From e35ae24fbf03f60ff3efb70d88e67967599af484 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Sun, 28 Oct 2018 11:46:33 +0100 Subject: [PATCH 01/20] Add filter rendering in 1 tile --- src/display/sp-canvas.cpp | 48 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index bc22f1a5a0..6008fceaf3 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -32,6 +32,7 @@ #include "display/sp-canvas.h" #include "display/sp-canvas-group.h" #include "display/rendermode.h" +#include "display/drawing-item.h" #include "display/cairo-utils.h" #include "preferences.h" #include "inkscape.h" @@ -1592,6 +1593,7 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect cairo_set_source(buf.ct, _background); cairo_set_operator(buf.ct, CAIRO_OPERATOR_SOURCE); cairo_paint(buf.ct); + cairo_restore(buf.ct); // cairo_surface_write_to_png( imgs, "debug1.png" ); @@ -1600,6 +1602,17 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect } // cairo_surface_write_to_png( imgs, "debug2.png" ); + // Start of visible tile rendering + cairo_set_operator(buf.ct, CAIRO_OPERATOR_OVER); + cairo_set_source_rgb (buf.ct, 0, 0, 0); + cairo_move_to (buf.ct, 0, 0); + cairo_line_to (buf.ct, paint_rect.width() * _device_scale, paint_rect.height() * _device_scale); + cairo_move_to (buf.ct, paint_rect.width() * _device_scale, 0); + cairo_line_to (buf.ct, 0, paint_rect.height() * _device_scale); + cairo_set_line_width (buf.ct, 1); + cairo_stroke (buf.ct); + // End + // output to X cairo_destroy(buf.ct); @@ -1946,8 +1959,26 @@ int SPCanvas::paint() gtk_widget_get_allocation(GTK_WIDGET(this), &allocation); cairo_rectangle_int_t crect = { _x0, _y0, allocation.width, allocation.height }; cairo_region_t *to_draw = cairo_region_create_rectangle(&crect); + cairo_region_t *filtered_region = cairo_region_create(); + SPDesktop * desktop = SP_ACTIVE_DESKTOP; + if (desktop) { + Geom::Rect box = Geom::Rect(_x0 , _y0, _x0 + allocation.width, _y0 + allocation.height) * desktop->dt2doc(); + box *= Geom::Scale(desktop->current_zoom()).inverse(); + std::vector items = desktop->getDocument()->getItemsPartiallyInBox(desktop->dkey, box, true, true); + for (auto item:items) { + if (item->isFiltered()) { + Geom::OptRect optarea = item->get_arenaitem(desktop->dkey)->visualBounds(); + if (optarea) { + Geom::Rect area = (*optarea) * desktop->doc2dt() ; + Geom::IntRect render_rect = area.roundOutwards(); + cairo_rectangle_int_t crect = { render_rect.left(), render_rect.top(), render_rect.width(), render_rect.height() }; + cairo_region_union_rectangle(filtered_region, &crect); + } + } + } + } cairo_region_subtract(to_draw, _clean_region); - + cairo_region_subtract(to_draw, filtered_region); int n_rects = cairo_region_num_rectangles(to_draw); for (int i = 0; i < n_rects; ++i) { cairo_rectangle_int_t crect; @@ -1958,7 +1989,20 @@ int SPCanvas::paint() return FALSE; }; } - + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + unsigned tile_multiplier = prefs->getIntLimited("/options/rendering/tile-multiplier", 16, 1, 512); + prefs->setInt("/options/rendering/tile-multiplier",512); + n_rects = cairo_region_num_rectangles(filtered_region); + for (int i = 0; i < n_rects; ++i) { + cairo_rectangle_int_t crect; + cairo_region_get_rectangle(filtered_region, i, &crect); + if (!paintRect(crect.x, crect.y, crect.x + crect.width, crect.y + crect.height)) { + // Aborted + cairo_region_destroy(filtered_region); + return FALSE; + }; + } + prefs->setInt("/options/rendering/tile-multiplier", tile_multiplier); // we've had a full unaborted redraw, reset the full redraw counter if (_forced_redraw_limit != -1) { _forced_redraw_count = 0; -- GitLab From 3339c9818673a142bd8e84fd3f74de4609f678bb Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Sun, 28 Oct 2018 13:28:54 +0100 Subject: [PATCH 02/20] Fix rendering errors and move to Desktop --- src/desktop.cpp | 13 +++++++++++++ src/desktop.h | 2 +- src/display/sp-canvas.cpp | 24 ++++++++++++------------ 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/desktop.cpp b/src/desktop.cpp index 335afa17d1..2e1a972b7b 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -726,6 +726,19 @@ SPItem *SPDesktop::getGroupAtPoint(Geom::Point const &p) const g_return_val_if_fail (doc() != nullptr, NULL); return doc()->getGroupAtPoint(dkey, p); } +/** + * Returns a vector of visible items in a desktop + */ +std::vector SPDesktop::getVisibleItems(bool isFiltered) { + std::vector result; + for(auto item:getDocument()->getItemsPartiallyInBox(dkey, get_display_area(), true, true)) { + if(isFiltered && !item->isFiltered()) { + continue; + } + result.push_back(item); + } + return result; +} /** * Returns the mouse point in document coordinates; if mouse is diff --git a/src/desktop.h b/src/desktop.h index b4e5da35d6..8e83b16b92 100644 --- a/src/desktop.h +++ b/src/desktop.h @@ -436,7 +436,7 @@ public: void mouseover() override {} void mouseout() override {} - + std::vector getVisibleItems(bool isFiltered = false); virtual bool onDeleteUI (GdkEventAny*); virtual bool onWindowStateEvent (GdkEventWindowState* event); diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 6008fceaf3..fa1981dff6 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -1602,7 +1602,7 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect } // cairo_surface_write_to_png( imgs, "debug2.png" ); - // Start of visible tile rendering + // Start of visible tile rendering comment for hide X tiles cairo_set_operator(buf.ct, CAIRO_OPERATOR_OVER); cairo_set_source_rgb (buf.ct, 0, 0, 0); cairo_move_to (buf.ct, 0, 0); @@ -1962,18 +1962,18 @@ int SPCanvas::paint() cairo_region_t *filtered_region = cairo_region_create(); SPDesktop * desktop = SP_ACTIVE_DESKTOP; if (desktop) { - Geom::Rect box = Geom::Rect(_x0 , _y0, _x0 + allocation.width, _y0 + allocation.height) * desktop->dt2doc(); - box *= Geom::Scale(desktop->current_zoom()).inverse(); - std::vector items = desktop->getDocument()->getItemsPartiallyInBox(desktop->dkey, box, true, true); + std::vector items = desktop->getVisibleItems(true); for (auto item:items) { - if (item->isFiltered()) { - Geom::OptRect optarea = item->get_arenaitem(desktop->dkey)->visualBounds(); - if (optarea) { - Geom::Rect area = (*optarea) * desktop->doc2dt() ; - Geom::IntRect render_rect = area.roundOutwards(); - cairo_rectangle_int_t crect = { render_rect.left(), render_rect.top(), render_rect.width(), render_rect.height() }; - cairo_region_union_rectangle(filtered_region, &crect); - } + Geom::OptRect optarea = item->get_arenaitem(desktop->dkey)->visualBounds(); + if (optarea) { + Geom::Rect area = (*optarea) * desktop->doc2dt(); + Geom::IntRect render_rect = area.roundOutwards(); + render_rect.setLeft(std::max(render_rect.left(),_x0)); + render_rect.setTop(std::max(render_rect.top(),_y0)); + render_rect.setRight(std::max(render_rect.right(), (allocation.width +_x0))); + render_rect.setBottom(std::max(render_rect.bottom(),(allocation.height +_y0))); + cairo_rectangle_int_t crect = {_x0, _y0, render_rect.width(), render_rect.height() }; + cairo_region_union_rectangle(filtered_region, &crect); } } } -- GitLab From 66db0912401280a4aea0fc303ea9a47594ab4d02 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Sun, 28 Oct 2018 17:44:09 +0100 Subject: [PATCH 03/20] Remove relay over preferences and minor fixes --- src/display/sp-canvas.cpp | 23 +++++++++++------------ src/display/sp-canvas.h | 2 +- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index fa1981dff6..371f9054fb 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "helper/sp-marshal.h" #include <2geom/rect.h> @@ -1768,7 +1769,7 @@ The default for now is the strips mode. } -bool SPCanvas::paintRect(int xx0, int yy0, int xx1, int yy1) +bool SPCanvas::paintRect(int xx0, int yy0, int xx1, int yy1, bool paint_as_one) { GtkAllocation allocation; g_return_val_if_fail (!_need_update, false); @@ -1808,8 +1809,9 @@ bool SPCanvas::paintRect(int xx0, int yy0, int xx1, int yy1) Inkscape::Preferences *prefs = Inkscape::Preferences::get(); unsigned tile_multiplier = prefs->getIntLimited("/options/rendering/tile-multiplier", 16, 1, 512); - - if (_rendermode != Inkscape::RENDERMODE_OUTLINE) { + if (paint_as_one) { + setup.max_pixels = std::numeric_limits::max(); // Geom::Infinity() dont work + } else if (_rendermode != Inkscape::RENDERMODE_OUTLINE) { // use 256K as a compromise to not slow down gradients // 256K is the cached buffer and we need 4 channels setup.max_pixels = 65536 * tile_multiplier; // 256K/4 @@ -1970,10 +1972,10 @@ int SPCanvas::paint() Geom::IntRect render_rect = area.roundOutwards(); render_rect.setLeft(std::max(render_rect.left(),_x0)); render_rect.setTop(std::max(render_rect.top(),_y0)); - render_rect.setRight(std::max(render_rect.right(), (allocation.width +_x0))); - render_rect.setBottom(std::max(render_rect.bottom(),(allocation.height +_y0))); - cairo_rectangle_int_t crect = {_x0, _y0, render_rect.width(), render_rect.height() }; - cairo_region_union_rectangle(filtered_region, &crect); + render_rect.setRight(std::min(render_rect.right(), (allocation.width +_x0))); + render_rect.setBottom(std::min(render_rect.bottom(),(allocation.height +_y0))); + cairo_rectangle_int_t item_crect = {render_rect.left(), render_rect.top(), render_rect.width(), render_rect.height() }; + cairo_region_union_rectangle(filtered_region, &item_crect); } } } @@ -1989,25 +1991,22 @@ int SPCanvas::paint() return FALSE; }; } - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - unsigned tile_multiplier = prefs->getIntLimited("/options/rendering/tile-multiplier", 16, 1, 512); - prefs->setInt("/options/rendering/tile-multiplier",512); n_rects = cairo_region_num_rectangles(filtered_region); for (int i = 0; i < n_rects; ++i) { cairo_rectangle_int_t crect; cairo_region_get_rectangle(filtered_region, i, &crect); - if (!paintRect(crect.x, crect.y, crect.x + crect.width, crect.y + crect.height)) { + if (!paintRect(crect.x, crect.y, crect.x + crect.width, crect.y + crect.height, true)) { // Aborted cairo_region_destroy(filtered_region); return FALSE; }; } - prefs->setInt("/options/rendering/tile-multiplier", tile_multiplier); // we've had a full unaborted redraw, reset the full redraw counter if (_forced_redraw_limit != -1) { _forced_redraw_count = 0; } + cairo_region_destroy(filtered_region); cairo_region_destroy(to_draw); return TRUE; diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index ef2df22923..cc8b2274cb 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -128,7 +128,7 @@ private: /// Draws a specific rectangular part of the canvas. /// @return true if the rectangle painting succeeds. - bool paintRect(int xx0, int yy0, int xx1, int yy1); + bool paintRect(int xx0, int yy0, int xx1, int yy1, bool paint_as_one = false); /// Repaints the areas in the canvas that need it. /// @return true if all the dirty parts have been redrawn -- GitLab From 2bc1b9820a63a2d08947a80e04d918ef08b73878 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Sun, 28 Oct 2018 20:09:01 +0100 Subject: [PATCH 04/20] Add render improvements to not force split when unnecesary --- src/display/sp-canvas.cpp | 64 +++++++++++++++++++++++++++++++++++++-- src/display/sp-canvas.h | 1 + 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 371f9054fb..db47b87d83 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -1658,6 +1658,49 @@ struct PaintRectSetup { Geom::Point mouse_loc; }; +bool SPCanvas::itemInsideTile(Geom::IntRect const &this_rect, Geom::IntRect const &item_bbox) +{ + int bw = this_rect.width(); + int bh = this_rect.height(); + if ((bw < 1) || (bh < 1)) + return false; + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + unsigned tile_multiplier = prefs->getIntLimited("/options/rendering/tile-multiplier", 16, 1, 512); + gint max_pixels = 0; + if (_rendermode != Inkscape::RENDERMODE_OUTLINE) { + // use 256K as a compromise to not slow down gradients + // 256K is the cached buffer and we need 4 channels + max_pixels = 65536 * tile_multiplier; // 256K/4 + } else { + // paths only, so 1M works faster + // 1M is the cached buffer and we need 4 channels + max_pixels = 262144; + } + + if (bw * bh < max_pixels) { + return this_rect.contains(item_bbox); + } + Geom::IntRect lo, hi; + if (bw < bh || bh < 2 * TILE_SIZE) { + int mid = this_rect[Geom::X].middle(); + // Make sure that mid lies on a tile boundary + mid = (mid / TILE_SIZE) * TILE_SIZE; + + lo = Geom::IntRect(this_rect.left(), this_rect.top(), mid, this_rect.bottom()); + hi = Geom::IntRect(mid, this_rect.top(), this_rect.right(), this_rect.bottom()); + return itemInsideTile(hi, item_bbox) || itemInsideTile(lo, item_bbox); + } else { + int mid = this_rect[Geom::Y].middle(); + // Make sure that mid lies on a tile boundary + mid = (mid / TILE_SIZE) * TILE_SIZE; + + lo = Geom::IntRect(this_rect.left(), this_rect.top(), this_rect.right(), mid); + hi = Geom::IntRect(this_rect.left(), mid, this_rect.right(), this_rect.bottom()); + + return itemInsideTile(lo, item_bbox) || itemInsideTile(hi, item_bbox); + } +} + int SPCanvas::paintRectInternal(PaintRectSetup const *setup, Geom::IntRect const &this_rect) { GTimeVal now; @@ -1968,14 +2011,31 @@ int SPCanvas::paint() for (auto item:items) { Geom::OptRect optarea = item->get_arenaitem(desktop->dkey)->visualBounds(); if (optarea) { - Geom::Rect area = (*optarea) * desktop->doc2dt(); + Geom::Rect area = (*optarea) * desktop->doc2dt(); Geom::IntRect render_rect = area.roundOutwards(); render_rect.setLeft(std::max(render_rect.left(),_x0)); render_rect.setTop(std::max(render_rect.top(),_y0)); render_rect.setRight(std::min(render_rect.right(), (allocation.width +_x0))); render_rect.setBottom(std::min(render_rect.bottom(),(allocation.height +_y0))); cairo_rectangle_int_t item_crect = {render_rect.left(), render_rect.top(), render_rect.width(), render_rect.height() }; - cairo_region_union_rectangle(filtered_region, &item_crect); + int n_rects = cairo_region_num_rectangles(to_draw); + for (int i = 0; i < n_rects; ++i) { + cairo_rectangle_int_t crect; + cairo_region_get_rectangle(to_draw, i, &crect); + Geom::IntRect to_draw_rect = render_rect; + to_draw_rect.setLeft(crect.x); + to_draw_rect.setTop(crect.y); + to_draw_rect.setRight(crect.x + crect.width); + to_draw_rect.setBottom(crect.y + crect.height); + // This optimice the rendering, rendering only appart + // If a tile dont contain the whole + // std::cout << itemInsideTile(to_draw_rect, render_rect) << std::endl; + // std::cout << to_draw_rect << std::endl; + // std::cout << render_rect << std::endl; + if (!itemInsideTile(to_draw_rect, render_rect)) { + cairo_region_union_rectangle(filtered_region, &item_crect); + }; + } } } } diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index cc8b2274cb..fe805fdbba 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -118,6 +118,7 @@ private: void paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect const &canvas_rect, int sw); + bool itemInsideTile(Geom::IntRect const &this_rect, Geom::IntRect const &item_bbox); /** * Paint the given rect, recursively subdividing the region until it is the size of a single * buffer. -- GitLab From 2e16e40904fa608c1d5b723fa262c7c6df796db8 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Sun, 28 Oct 2018 22:17:23 +0100 Subject: [PATCH 05/20] More speed improvements --- src/display/sp-canvas.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index db47b87d83..752aaa1056 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -2032,35 +2032,36 @@ int SPCanvas::paint() // std::cout << itemInsideTile(to_draw_rect, render_rect) << std::endl; // std::cout << to_draw_rect << std::endl; // std::cout << render_rect << std::endl; - if (!itemInsideTile(to_draw_rect, render_rect)) { + if (!itemInsideTile(to_draw_rect, render_rect)) { cairo_region_union_rectangle(filtered_region, &item_crect); }; } } } } - cairo_region_subtract(to_draw, _clean_region); - cairo_region_subtract(to_draw, filtered_region); - int n_rects = cairo_region_num_rectangles(to_draw); + cairo_region_subtract(filtered_region, _clean_region); + int n_rects = cairo_region_num_rectangles(filtered_region); for (int i = 0; i < n_rects; ++i) { cairo_rectangle_int_t crect; - cairo_region_get_rectangle(to_draw, i, &crect); - if (!paintRect(crect.x, crect.y, crect.x + crect.width, crect.y + crect.height)) { + cairo_region_get_rectangle(filtered_region, i, &crect); + if (!paintRect(crect.x, crect.y, crect.x + crect.width, crect.y + crect.height, true)) { // Aborted - cairo_region_destroy(to_draw); + cairo_region_destroy(filtered_region); return FALSE; }; } - n_rects = cairo_region_num_rectangles(filtered_region); + cairo_region_subtract(to_draw, _clean_region); + n_rects = cairo_region_num_rectangles(to_draw); for (int i = 0; i < n_rects; ++i) { cairo_rectangle_int_t crect; - cairo_region_get_rectangle(filtered_region, i, &crect); - if (!paintRect(crect.x, crect.y, crect.x + crect.width, crect.y + crect.height, true)) { + cairo_region_get_rectangle(to_draw, i, &crect); + if (!paintRect(crect.x, crect.y, crect.x + crect.width, crect.y + crect.height)) { // Aborted - cairo_region_destroy(filtered_region); + cairo_region_destroy(to_draw); return FALSE; }; } + // we've had a full unaborted redraw, reset the full redraw counter if (_forced_redraw_limit != -1) { _forced_redraw_count = 0; -- GitLab From 67616992e1b1a98bd0bc383cd9220cb59aa3fe7c Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Sun, 28 Oct 2018 23:11:30 +0100 Subject: [PATCH 06/20] Allow select groups and his elements on region --- src/desktop.cpp | 2 +- src/document.cpp | 27 ++++++++++++++++----------- src/document.h | 6 +++--- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/desktop.cpp b/src/desktop.cpp index 2e1a972b7b..076f0b7329 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -731,7 +731,7 @@ SPItem *SPDesktop::getGroupAtPoint(Geom::Point const &p) const */ std::vector SPDesktop::getVisibleItems(bool isFiltered) { std::vector result; - for(auto item:getDocument()->getItemsPartiallyInBox(dkey, get_display_area(), true, true)) { + for(auto item:getDocument()->getItemsPartiallyInBox(dkey, get_display_area(), true, true, true)) { if(isFiltered && !item->isFiltered()) { continue; } diff --git a/src/document.cpp b/src/document.cpp index 35e57871f8..7a7dbc99dc 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1382,19 +1382,23 @@ static bool overlaps(Geom::Rect const &area, Geom::Rect const &box) } static std::vector &find_items_in_area(std::vector &s, SPGroup *group, unsigned int dkey, Geom::Rect const &area, - bool (*test)(Geom::Rect const &, Geom::Rect const &), bool take_insensitive = false, bool into_groups = false) + bool (*test)(Geom::Rect const &, Geom::Rect const &), bool take_insensitive = false, bool into_groups = false, bool with_groups = true) { g_return_val_if_fail(SP_IS_GROUP(group), s); for (auto& o: group->children) { if ( SP_IS_ITEM(&o) ) { - if (SP_IS_GROUP(&o) && (SP_GROUP(&o)->effectiveLayerMode(dkey) == SPGroup::LAYER || into_groups)) { - s = find_items_in_area(s, SP_GROUP(&o), dkey, area, test, take_insensitive, into_groups); + SPItem *item = SP_ITEM(&o); + bool is_layer = SP_IS_GROUP(item) && SP_GROUP(item)->effectiveLayerMode(dkey) == SPGroup::LAYER; + if (SP_IS_GROUP(item) && (is_layer || into_groups)) { + s = find_items_in_area(s, SP_GROUP(item), dkey, area, test, take_insensitive, into_groups, with_groups); + if(with_groups && !is_layer) { + s.push_back(item); + } } else { - SPItem *child = SP_ITEM(&o); - Geom::OptRect box = child->desktopVisualBounds(); - if ( box && test(area, *box) && (take_insensitive || child->isVisibleAndUnlocked(dkey))) { - s.push_back(child); + Geom::OptRect box = item->desktopVisualBounds(); + if ( box && test(area, *box) && (take_insensitive || item->isVisibleAndUnlocked(dkey))) { + s.push_back(item); } } } @@ -1456,6 +1460,7 @@ SPItem *SPDocument::getItemFromListAtPointBottom(unsigned int dkey, SPGroup *gro Turn the SVG DOM into a flat list of nodes that can be searched from top-down. The list can be persisted, which improves "find at multiple points" speed. */ +// TODO: study add `gboolean with_groups = false` as parameter. void SPDocument::build_flat_item_list(unsigned int dkey, SPGroup *group, gboolean into_groups) const { for (auto& o: group->children) { @@ -1554,10 +1559,10 @@ static SPItem *find_group_at_point(unsigned int dkey, SPGroup *group, Geom::Poin * Assumes box is normalized (and g_asserts it!) * */ -std::vector SPDocument::getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive, bool into_groups) const +std::vector SPDocument::getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive, bool into_groups, bool with_groups) const { std::vector x; - return find_items_in_area(x, SP_GROUP(this->root), dkey, box, is_within, take_insensitive, into_groups); + return find_items_in_area(x, SP_GROUP(this->root), dkey, box, is_within, take_insensitive, into_groups, with_groups); } /* @@ -1567,10 +1572,10 @@ std::vector SPDocument::getItemsInBox(unsigned int dkey, Geom::Rect con * */ -std::vector SPDocument::getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive, bool into_groups) const +std::vector SPDocument::getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive, bool into_groups, bool with_groups) const { std::vector x; - return find_items_in_area(x, SP_GROUP(this->root), dkey, box, overlaps, take_insensitive, into_groups); + return find_items_in_area(x, SP_GROUP(this->root), dkey, box, overlaps, take_insensitive, into_groups, with_groups); } std::vector SPDocument::getItemsAtPoints(unsigned const key, std::vector points, bool all_layers, size_t limit) const diff --git a/src/document.h b/src/document.h index 5b93261de9..c0f9664696 100644 --- a/src/document.h +++ b/src/document.h @@ -287,9 +287,9 @@ public: int ensureUpToDate(); bool addResource(char const *key, SPObject *object); bool removeResource(char const *key, SPObject *object); - std::vector const getResourceList(char const *key); - std::vector getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive = false, bool into_groups = false) const; - std::vector getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive = false, bool into_groups = false) const; + std::vector const getResourceList(char const *key) const; + std::vector getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive = false, bool into_groups = false, bool with_groups = false) const; + std::vector getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive = false, bool into_groups = false, bool with_groups = false) const; SPItem *getItemAtPoint(unsigned int key, Geom::Point const &p, bool into_groups, SPItem *upto = nullptr) const; std::vector getItemsAtPoints(unsigned const key, std::vector points, bool all_layers = true, size_t limit = 0) const ; SPItem *getGroupAtPoint(unsigned int key, Geom::Point const &p) const; -- GitLab From 3d144207c65b62efff5cbf80ef54b94a06a34b8a Mon Sep 17 00:00:00 2001 From: Jabiertxof Date: Mon, 29 Oct 2018 17:21:22 +0100 Subject: [PATCH 07/20] Fix compiling bug --- src/document.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/document.h b/src/document.h index c0f9664696..49196b9835 100644 --- a/src/document.h +++ b/src/document.h @@ -287,7 +287,7 @@ public: int ensureUpToDate(); bool addResource(char const *key, SPObject *object); bool removeResource(char const *key, SPObject *object); - std::vector const getResourceList(char const *key) const; + std::vector const getResourceList(char const *key); std::vector getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive = false, bool into_groups = false, bool with_groups = false) const; std::vector getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive = false, bool into_groups = false, bool with_groups = false) const; SPItem *getItemAtPoint(unsigned int key, Geom::Point const &p, bool into_groups, SPItem *upto = nullptr) const; -- GitLab From 6f2702e3571902b0c8f0708716c71ab7468577d1 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Thu, 1 Nov 2018 21:32:48 +0100 Subject: [PATCH 08/20] fixing commits --- src/desktop.cpp | 2 +- src/display/drawing-item.cpp | 21 ++-- src/display/drawing-item.h | 4 +- src/display/sp-canvas.cpp | 226 +++++++++++++++------------------- src/display/sp-canvas.h | 4 +- src/document.cpp | 21 ++-- src/document.h | 4 +- src/ui/contextmenu.cpp | 2 +- src/ui/tools/measure-tool.cpp | 2 +- 9 files changed, 139 insertions(+), 147 deletions(-) diff --git a/src/desktop.cpp b/src/desktop.cpp index 076f0b7329..7846599c77 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -731,7 +731,7 @@ SPItem *SPDesktop::getGroupAtPoint(Geom::Point const &p) const */ std::vector SPDesktop::getVisibleItems(bool isFiltered) { std::vector result; - for(auto item:getDocument()->getItemsPartiallyInBox(dkey, get_display_area(), true, true, true)) { + for(auto item:getDocument()->getItemsPartiallyInBox(dkey, get_display_area(), false, true, true, false, true)) { if(isFiltered && !item->isFiltered()) { continue; } diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp index aa27939080..1e7f8a2ce9 100644 --- a/src/display/drawing-item.cpp +++ b/src/display/drawing-item.cpp @@ -127,6 +127,7 @@ DrawingItem::DrawingItem(Drawing &drawing) , _visible(true) , _sensitive(true) , _cached(0) + , _cache_insensitive(0) , _cached_persistent(0) , _has_cache_iterator(0) , _propagate(0) @@ -261,7 +262,7 @@ DrawingItem::clearChildren() /// Set the incremental transform for this item void -DrawingItem::setTransform(Geom::Affine const &new_trans) +DrawingItem::setTransform(Geom::Affine const &new_trans, bool markForUpdate) { Geom::Affine current; if (_transform) { @@ -277,7 +278,9 @@ DrawingItem::setTransform(Geom::Affine const &new_trans) } else { _transform = new Geom::Affine(new_trans); } - _markForUpdate(STATE_ALL, true); + if (markForUpdate) { + _markForUpdate(STATE_ALL, true); + } } } @@ -340,7 +343,7 @@ DrawingItem::setCached(bool cached, bool persistent) { static const char *cache_env = getenv("_INKSCAPE_DISABLE_CACHE"); if (cache_env) return; - + if (_cache_insensitive) return; if (_cached_persistent && !persistent) return; @@ -680,7 +683,7 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag { bool outline = _drawing.outline(); bool render_filters = _drawing.renderFilters(); - + std::cout << "111111111111111111" << std::endl; // stop_at is handled in DrawingGroup, but this check is required to handle the case // where a filtered item with background-accessing filter has enable-background: new if (this == stop_at) return RENDER_STOP; @@ -688,7 +691,7 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag // If we are invisible, return immediately if (!_visible) return RENDER_OK; if (_ctm.isSingular(1e-18)) return RENDER_OK; - +std::cout << "222222222222222222222222" << std::endl; // TODO convert outline rendering to a separate virtual function if (outline) { _renderOutline(dc, area, flags); @@ -698,7 +701,7 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag // carea is the area to paint Geom::OptIntRect carea = Geom::intersect(area, _drawbox); if (!carea) return RENDER_OK; - +std::cout << "13333333333333333333333" << std::endl; // Device scale for HiDPI screens (typically 1 or 2) int device_scale = dc.surface()->device_scale(); @@ -718,9 +721,9 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag default: // should not happen g_assert_not_reached(); } - +std::cout << render_filters << "ññññññññññññññññññññññññññ" << std::endl; // render from cache if possible - if (_cached) { + if (_cached && !_cache_insensitive) { if (_cache) { _cache->prepare(); set_cairo_blend_operator( dc, _mix_blend_mode ); @@ -741,6 +744,8 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag // if our caching was turned off after the last update, it was already // deleted in setCached() } + _cache_insensitive = false; + std::cout << render_filters << "wwwwwwwwwwwwwwwwwwwwwwwww" << std::endl; // determine whether this shape needs intermediate rendering. bool needs_intermediate_rendering = false; diff --git a/src/display/drawing-item.h b/src/display/drawing-item.h index 5cd6c987f3..c24272b4bd 100644 --- a/src/display/drawing-item.h +++ b/src/display/drawing-item.h @@ -111,6 +111,7 @@ public: void setSensitive(bool v); bool cached() const { return _cached; } void setCached(bool c, bool persistent = false); + void setCacheInsensitive() { _cache_insensitive = true; } virtual void setStyle(SPStyle *style, SPStyle *context_style = nullptr); virtual void setChildrenStyle(SPStyle *context_style); @@ -118,7 +119,7 @@ public: void setAntialiasing(unsigned a); void setIsolation(unsigned isolation); // CSS Compositing and Blending void setBlendMode(unsigned blend_mode); - void setTransform(Geom::Affine const &trans); + void setTransform(Geom::Affine const &trans, bool markForUpdate = true); void setClip(DrawingItem *item); void setMask(DrawingItem *item); void setFillPattern(DrawingPattern *pattern); @@ -216,6 +217,7 @@ protected: unsigned _visible : 1; unsigned _sensitive : 1; ///< Whether this item responds to events unsigned _cached : 1; ///< Whether the rendering is stored for reuse + unsigned _cache_insensitive: 1; // If set cache is not changed for a temporary item change unsigned _cached_persistent : 1; ///< If set, will always be cached regardless of score unsigned _has_cache_iterator : 1; ///< If set, _cache_iterator is valid unsigned _propagate : 1; ///< Whether to call update for all children on next update diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 752aaa1056..b7c4c35dcb 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -32,9 +32,12 @@ #include <2geom/affine.h> #include "display/sp-canvas.h" #include "display/sp-canvas-group.h" +#include "display/drawing-item.h" +#include "display/canvas-arena.h" #include "display/rendermode.h" #include "display/drawing-item.h" #include "display/cairo-utils.h" +#include "object/sp-root.h" #include "preferences.h" #include "inkscape.h" #include "sodipodi-ctrlrect.h" @@ -51,7 +54,7 @@ using Inkscape::Debug::GdkEventLatencyTracker; // gtk_check_version returns non-NULL on failure static bool const HAS_BROKEN_MOTION_HINTS = - true || gtk_check_version(2, 12, 0) != nullptr; + TRUE || gtk_check_version(2, 12, 0) != nullptr; // Define this to visualize the regions to be redrawn //#define DEBUG_REDRAW 1; @@ -192,7 +195,7 @@ static guint object_signals[LAST_SIGNAL] = { 0 }; void sp_canvas_item_construct(SPCanvasItem *item, SPCanvasGroup *parent, gchar const *first_arg_name, va_list args); /** - * Helper that returns true iff item is descendant of parent. + * Helper that returns TRUE iff item is descendant of parent. */ bool is_descendant(SPCanvasItem const *item, SPCanvasItem const *parent); @@ -242,8 +245,8 @@ sp_canvas_item_init(SPCanvasItem *item) // that should be initially invisible; examples of such items: node handles, the CtrlRect // used for rubberbanding, path outline, etc. item->visible = TRUE; - item->in_destruction = false; - item->pickable = true; + item->in_destruction = FALSE; + item->pickable = TRUE; } SPCanvasItem *sp_canvas_item_new(SPCanvasGroup *parent, GType type, gchar const *first_arg_name, ...) @@ -317,7 +320,7 @@ void sp_canvas_item_dispose(GObject *object) */ if (!item->in_destruction) { - item->in_destruction=true; + item->in_destruction=TRUE; // Hack: if this is a ctrlrect, move it to 0,0; // this redraws only the stroke of the rect to be deleted, @@ -354,7 +357,7 @@ void sp_canvas_item_dispose(GObject *object) } g_signal_emit (object, object_signals[DESTROY], 0); - item->in_destruction = false; + item->in_destruction = FALSE; } G_OBJECT_CLASS(sp_canvas_item_parent_class)->dispose(object); @@ -705,12 +708,12 @@ bool is_descendant(SPCanvasItem const *item, SPCanvasItem const *parent) { while (item) { if (item == parent) { - return true; + return TRUE; } item = item->parent; } - return false; + return FALSE; } } // namespace @@ -966,23 +969,25 @@ static void sp_canvas_init(SPCanvas *canvas) canvas->_need_repick = TRUE; // See comment at in sp-canvas.h. - canvas->_gen_all_enter_events = false; + canvas->_gen_all_enter_events = FALSE; - canvas->_drawing_disabled = false; + canvas->_drawing_disabled = FALSE; canvas->_backing_store = nullptr; #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 12, 0) canvas->_surface_for_similar = nullptr; #endif canvas->_clean_region = cairo_region_create(); + canvas->_filtered_region = cairo_region_create(); canvas->_background = cairo_pattern_create_rgb(1, 1, 1); - canvas->_background_is_checkerboard = false; + canvas->_background_is_checkerboard = FALSE; + canvas->_filtering = FALSE; canvas->_forced_redraw_count = 0; canvas->_forced_redraw_limit = -1; #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - canvas->_enable_cms_display_adj = false; + canvas->_enable_cms_display_adj = FALSE; new (&canvas->_cms_key) Glib::ustring(""); #endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) } @@ -1021,6 +1026,10 @@ void SPCanvas::dispose(GObject *object) cairo_region_destroy(canvas->_clean_region); canvas->_clean_region = nullptr; } + if (canvas->_filtered_region) { + cairo_region_destroy(canvas->_filtered_region); + canvas->_filtered_region = nullptr; + } if (canvas->_background) { cairo_pattern_destroy(canvas->_background); canvas->_background = nullptr; @@ -1091,7 +1100,7 @@ void SPCanvas::handle_realize(GtkWidget *widget) gdk_window_set_user_data (window, widget); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - if (prefs->getBool("/options/useextinput/value", true)) { + if (prefs->getBool("/options/useextinput/value", TRUE)) { gtk_widget_set_events(widget, attributes.event_mask); } @@ -1261,9 +1270,9 @@ int SPCanvas::emitEvent(GdkEvent *event) } // Block Undo and Redo while we drag /anything/ if(event->type == GDK_BUTTON_PRESS && event->button.button == 1) - _is_dragging = true; + _is_dragging = TRUE; else if(event->type == GDK_BUTTON_RELEASE) - _is_dragging = false; + _is_dragging = FALSE; // Choose where we send the event @@ -1313,7 +1322,7 @@ int SPCanvas::pickCurrentItem(GdkEvent *event) int retval = FALSE; - if (_gen_all_enter_events == false) { + if (_gen_all_enter_events == FALSE) { // If a button is down, we'll perform enter and leave events on the // current item, but not enter on any other item. This is more or // less like X pointer grabbing for canvas items. @@ -1411,7 +1420,7 @@ int SPCanvas::pickCurrentItem(GdkEvent *event) _in_repick = FALSE; } - if (_gen_all_enter_events == false) { + if (_gen_all_enter_events == FALSE) { // new_current_item may have been set to NULL during the call to // emitEvent() above if ((_new_current_item != _current_item) && button_down) { @@ -1546,14 +1555,13 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect // initialized. if (_backing_store == nullptr) return; - SPCanvasBuf buf; buf.buf = nullptr; buf.buf_rowstride = 0; buf.rect = paint_rect; buf.canvas_rect = canvas_rect; buf.device_scale = _device_scale; - buf.is_empty = true; + buf.is_empty = TRUE; // Make sure the following code does not go outside of _backing_store's data // FIXME for device_scale. @@ -1562,7 +1570,6 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect assert(paint_rect.top() - _y0 >= 0); assert(paint_rect.right() - _x0 <= cairo_image_surface_get_width(_backing_store)); assert(paint_rect.bottom() - _y0 <= cairo_image_surface_get_height(_backing_store)); - // Create a temporary surface that draws directly to _backing_store cairo_surface_flush(_backing_store); // cairo_surface_write_to_png( _backing_store, "debug0.png" ); @@ -1575,7 +1582,6 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect cairo_surface_get_device_scale(_backing_store, &x_scale, &y_scale); assert (_device_scale == (int)x_scale); assert (_device_scale == (int)y_scale); - // Move to the right row data += stride * (paint_rect.top() - _y0) * (int)y_scale; // Move to the right pixel inside of that row @@ -1598,11 +1604,10 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect cairo_restore(buf.ct); // cairo_surface_write_to_png( imgs, "debug1.png" ); - if (_root->visible) { + if (_root->visible) { SP_CANVAS_ITEM_GET_CLASS(_root)->render(_root, &buf); } // cairo_surface_write_to_png( imgs, "debug2.png" ); - // Start of visible tile rendering comment for hide X tiles cairo_set_operator(buf.ct, CAIRO_OPERATOR_OVER); cairo_set_source_rgb (buf.ct, 0, 0, 0); @@ -1646,7 +1651,6 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect // Mark the painted rectangle clean markRect(paint_rect, 0); - gtk_widget_queue_draw_area(GTK_WIDGET(this), paint_rect.left() -_x0, paint_rect.top() - _y0, paint_rect.width(), paint_rect.height()); } @@ -1658,49 +1662,6 @@ struct PaintRectSetup { Geom::Point mouse_loc; }; -bool SPCanvas::itemInsideTile(Geom::IntRect const &this_rect, Geom::IntRect const &item_bbox) -{ - int bw = this_rect.width(); - int bh = this_rect.height(); - if ((bw < 1) || (bh < 1)) - return false; - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - unsigned tile_multiplier = prefs->getIntLimited("/options/rendering/tile-multiplier", 16, 1, 512); - gint max_pixels = 0; - if (_rendermode != Inkscape::RENDERMODE_OUTLINE) { - // use 256K as a compromise to not slow down gradients - // 256K is the cached buffer and we need 4 channels - max_pixels = 65536 * tile_multiplier; // 256K/4 - } else { - // paths only, so 1M works faster - // 1M is the cached buffer and we need 4 channels - max_pixels = 262144; - } - - if (bw * bh < max_pixels) { - return this_rect.contains(item_bbox); - } - Geom::IntRect lo, hi; - if (bw < bh || bh < 2 * TILE_SIZE) { - int mid = this_rect[Geom::X].middle(); - // Make sure that mid lies on a tile boundary - mid = (mid / TILE_SIZE) * TILE_SIZE; - - lo = Geom::IntRect(this_rect.left(), this_rect.top(), mid, this_rect.bottom()); - hi = Geom::IntRect(mid, this_rect.top(), this_rect.right(), this_rect.bottom()); - return itemInsideTile(hi, item_bbox) || itemInsideTile(lo, item_bbox); - } else { - int mid = this_rect[Geom::Y].middle(); - // Make sure that mid lies on a tile boundary - mid = (mid / TILE_SIZE) * TILE_SIZE; - - lo = Geom::IntRect(this_rect.left(), this_rect.top(), this_rect.right(), mid); - hi = Geom::IntRect(this_rect.left(), mid, this_rect.right(), this_rect.bottom()); - - return itemInsideTile(lo, item_bbox) || itemInsideTile(hi, item_bbox); - } -} - int SPCanvas::paintRectInternal(PaintRectSetup const *setup, Geom::IntRect const &this_rect) { GTimeVal now; @@ -1731,7 +1692,7 @@ int SPCanvas::paintRectInternal(PaintRectSetup const *setup, Geom::IntRect const _forced_redraw_count++; } - return false; + return FALSE; } } @@ -1753,7 +1714,7 @@ int SPCanvas::paintRectInternal(PaintRectSetup const *setup, Geom::IntRect const GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(setup->canvas)); gdk_window_begin_paint_rect(window, &r); */ - + std::cout << "canvas_rect, bw); //gdk_window_end_paint(window); return 1; @@ -1815,7 +1776,7 @@ The default for now is the strips mode. bool SPCanvas::paintRect(int xx0, int yy0, int xx1, int yy1, bool paint_as_one) { GtkAllocation allocation; - g_return_val_if_fail (!_need_update, false); + g_return_val_if_fail (!_need_update, FALSE); gtk_widget_get_allocation(GTK_WIDGET(this), &allocation); @@ -1825,7 +1786,7 @@ bool SPCanvas::paintRect(int xx0, int yy0, int xx1, int yy1, bool paint_as_one) Geom::IntRect paint_rect(xx0, yy0, xx1, yy1); Geom::OptIntRect area = paint_rect & canvas_rect; - if (!area || area->hasZeroArea()) return false; + if (!area || area->hasZeroArea()) return FALSE; paint_rect = *area; PaintRectSetup setup; @@ -1995,79 +1956,91 @@ gint SPCanvas::handle_focus_out(GtkWidget *widget, GdkEventFocus *event) int SPCanvas::paint() { + bool need_update = _need_update; if (_need_update) { sp_canvas_item_invoke_update(_root, Geom::identity(), 0); _need_update = FALSE; } - GtkAllocation allocation; gtk_widget_get_allocation(GTK_WIDGET(this), &allocation); cairo_rectangle_int_t crect = { _x0, _y0, allocation.width, allocation.height }; cairo_region_t *to_draw = cairo_region_create_rectangle(&crect); - cairo_region_t *filtered_region = cairo_region_create(); SPDesktop * desktop = SP_ACTIVE_DESKTOP; + Inkscape::DrawingItem *rootarena; + size_t nitems = 0; if (desktop) { - std::vector items = desktop->getVisibleItems(true); - for (auto item:items) { - Geom::OptRect optarea = item->get_arenaitem(desktop->dkey)->visualBounds(); - if (optarea) { - Geom::Rect area = (*optarea) * desktop->doc2dt(); - Geom::IntRect render_rect = area.roundOutwards(); - render_rect.setLeft(std::max(render_rect.left(),_x0)); - render_rect.setTop(std::max(render_rect.top(),_y0)); - render_rect.setRight(std::min(render_rect.right(), (allocation.width +_x0))); - render_rect.setBottom(std::min(render_rect.bottom(),(allocation.height +_y0))); - cairo_rectangle_int_t item_crect = {render_rect.left(), render_rect.top(), render_rect.width(), render_rect.height() }; - int n_rects = cairo_region_num_rectangles(to_draw); - for (int i = 0; i < n_rects; ++i) { - cairo_rectangle_int_t crect; - cairo_region_get_rectangle(to_draw, i, &crect); - Geom::IntRect to_draw_rect = render_rect; - to_draw_rect.setLeft(crect.x); - to_draw_rect.setTop(crect.y); - to_draw_rect.setRight(crect.x + crect.width); - to_draw_rect.setBottom(crect.y + crect.height); - // This optimice the rendering, rendering only appart - // If a tile dont contain the whole - // std::cout << itemInsideTile(to_draw_rect, render_rect) << std::endl; - // std::cout << to_draw_rect << std::endl; - // std::cout << render_rect << std::endl; - if (!itemInsideTile(to_draw_rect, render_rect)) { - cairo_region_union_rectangle(filtered_region, &item_crect); - }; - } + rootarena = desktop->getDocument()->getRoot()->get_arenaitem(desktop->dkey); + if (!_filtering && _rendermode == Inkscape::RENDERMODE_NORMAL) { + std::vector items = desktop->getVisibleItems(TRUE); + nitems = items.size(); + for (auto item:items) { + Inkscape::DrawingItem *ditem = item->get_arenaitem(desktop->dkey); + //ditem->setCacheInsensitive(); //toggle back on render + Geom::OptRect optarea = ditem->visualBounds(); + if (optarea) { + Geom::Rect area = (*optarea) * desktop->doc2dt(); + Geom::IntRect render_rect = area.roundOutwards(); + render_rect.setLeft(std::max(render_rect.left(),_x0)); + render_rect.setTop(std::max(render_rect.top(),_y0)); + render_rect.setRight(std::min(render_rect.right(), (allocation.width +_x0))); + render_rect.setBottom(std::min(render_rect.bottom(),(allocation.height +_y0))); + cairo_rectangle_int_t crect = {render_rect.left(), render_rect.top(), render_rect.width(), render_rect.height() }; + std::cout << _filtering << "---" << 1 << "---" << crect.x << "---" << crect.y << "---" << crect.width << "---" << crect.height << std::endl; + cairo_region_union_rectangle(_filtered_region, &crect); + } + } + if (nitems) { + cairo_region_subtract(_filtered_region, _clean_region); + desktop->_display_mode = Inkscape::RENDERMODE_NO_FILTERS; + rootarena->drawing().setRenderMode(desktop->_display_mode); + _rendermode = desktop->_display_mode; } } } - cairo_region_subtract(filtered_region, _clean_region); - int n_rects = cairo_region_num_rectangles(filtered_region); - for (int i = 0; i < n_rects; ++i) { - cairo_rectangle_int_t crect; - cairo_region_get_rectangle(filtered_region, i, &crect); - if (!paintRect(crect.x, crect.y, crect.x + crect.width, crect.y + crect.height, true)) { - // Aborted - cairo_region_destroy(filtered_region); - return FALSE; - }; - } cairo_region_subtract(to_draw, _clean_region); - n_rects = cairo_region_num_rectangles(to_draw); + int n_rects = cairo_region_num_rectangles(to_draw); for (int i = 0; i < n_rects; ++i) { cairo_rectangle_int_t crect; cairo_region_get_rectangle(to_draw, i, &crect); - if (!paintRect(crect.x, crect.y, crect.x + crect.width, crect.y + crect.height)) { + std::cout << _filtering << "---" << 2 << "---" << crect.x << "---" << crect.y << "---" << crect.width << "---" << crect.height << std::endl; + if (!paintRect(crect.x, crect.y, crect.x + crect.width, crect.y + crect.height, _filtering)) { // Aborted cairo_region_destroy(to_draw); + if (nitems) { + desktop->_display_mode = Inkscape::RENDERMODE_NORMAL; + rootarena->drawing().setRenderMode(desktop->_display_mode); + _rendermode = desktop->_display_mode; + nitems = 0; + } + _filtering = FALSE; return FALSE; }; } - - // we've had a full unaborted redraw, reset the full redraw counter - if (_forced_redraw_limit != -1) { - _forced_redraw_count = 0; - } - cairo_region_destroy(filtered_region); + if (nitems) { + std::cout << _filtering << "wwwwwwwwwwwwwwwww" << std::endl; + _filtering = TRUE; + /* for (auto item:items) { + sp_canvas_item_request_update(SP_CANVAS_ITEM(this)); + } */ + //_need_update = need_update?TRUE:FALSE; + desktop->_display_mode = Inkscape::RENDERMODE_NORMAL; + rootarena->drawing().setRenderMode(desktop->_display_mode); + _rendermode = desktop->_display_mode; + + cairo_region_subtract(_clean_region, _filtered_region); + if(!paint()) { + return FALSE; + } + cairo_region_subtract(_filtered_region, _filtered_region); + //_need_update = FALSE; + _filtering = FALSE; + } else { + // we've had a full unaborted redraw, reset the full redraw counter + } + if (_forced_redraw_limit != -1) { + _forced_redraw_count = 0; + } cairo_region_destroy(to_draw); return TRUE; @@ -2119,6 +2092,7 @@ void SPCanvas::addIdle() _idle_id = gdk_threads_add_idle_full(UPDATE_PRIORITY, idle_handler, this, nullptr); } } + void SPCanvas::removeIdle() { if (_idle_id) { @@ -2270,7 +2244,7 @@ void SPCanvas::setBackgroundColor(guint32 rgba) { cairo_pattern_destroy(_background); } _background = cairo_pattern_create_rgb(new_r, new_g, new_b); - _background_is_checkerboard = false; + _background_is_checkerboard = FALSE; dirtyAll(); addIdle(); } @@ -2281,7 +2255,7 @@ void SPCanvas::setBackgroundCheckerboard() { cairo_pattern_destroy(_background); } _background = ink_cairo_pattern_create_checkerboard(); - _background_is_checkerboard = true; + _background_is_checkerboard = TRUE; dirtyAll(); addIdle(); } @@ -2333,7 +2307,7 @@ Geom::Point sp_canvas_world_to_window(SPCanvas const *canvas, Geom::Point const } /** - * Returns true if point given in world coordinates is inside window. + * Returns TRUE if point given in world coordinates is inside window. */ bool sp_canvas_world_pt_inside_window(SPCanvas const *canvas, Geom::Point const &world) { @@ -2396,6 +2370,10 @@ void SPCanvas::dirtyAll() { cairo_region_destroy(_clean_region); _clean_region = cairo_region_create(); } + if (_filtered_region && !cairo_region_is_empty(_filtered_region)) { + cairo_region_destroy(_filtered_region); + _filtered_region = cairo_region_create(); + } } void SPCanvas::markRect(Geom::IntRect const &area, uint8_t val) diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index fe805fdbba..cb70a3ba96 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -118,7 +118,6 @@ private: void paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect const &canvas_rect, int sw); - bool itemInsideTile(Geom::IntRect const &this_rect, Geom::IntRect const &item_bbox); /** * Paint the given rect, recursively subdividing the region until it is the size of a single * buffer. @@ -189,12 +188,15 @@ public: #endif /// Area of the widget that has up-to-date content cairo_region_t *_clean_region; + /// Area of the widget that has filtered to render + cairo_region_t *_filtered_region; /// Widget background, defaults to white cairo_pattern_t *_background; bool _background_is_checkerboard; /// Last known modifier state, for deferred repick when a button is down. int _state; + bool _filtering; /** The item containing the mouse pointer, or NULL if none. */ SPCanvasItem *_current_item; diff --git a/src/document.cpp b/src/document.cpp index 7a7dbc99dc..646ed26bdb 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1382,7 +1382,7 @@ static bool overlaps(Geom::Rect const &area, Geom::Rect const &box) } static std::vector &find_items_in_area(std::vector &s, SPGroup *group, unsigned int dkey, Geom::Rect const &area, - bool (*test)(Geom::Rect const &, Geom::Rect const &), bool take_insensitive = false, bool into_groups = false, bool with_groups = true) + bool (*test)(Geom::Rect const &, Geom::Rect const &), bool take_hidden = false, bool take_insensitive = false, bool into_groups = false, bool into_filtered_groups = true, bool with_groups = true) { g_return_val_if_fail(SP_IS_GROUP(group), s); @@ -1391,13 +1391,18 @@ static std::vector &find_items_in_area(std::vector &s, SPGroup SPItem *item = SP_ITEM(&o); bool is_layer = SP_IS_GROUP(item) && SP_GROUP(item)->effectiveLayerMode(dkey) == SPGroup::LAYER; if (SP_IS_GROUP(item) && (is_layer || into_groups)) { - s = find_items_in_area(s, SP_GROUP(item), dkey, area, test, take_insensitive, into_groups, with_groups); + if(!item->isFiltered() || into_filtered_groups) { + s = find_items_in_area(s, SP_GROUP(item), dkey, area, test, take_insensitive, into_groups, into_filtered_groups, with_groups); + } if(with_groups && !is_layer) { - s.push_back(item); + Geom::OptRect box = item->desktopVisualBounds(); + if ( box && test(area, *box) && (!item->isLocked() || take_insensitive) && (!item->isHidden() || take_hidden) ) { + s.push_back(item); + } } } else { Geom::OptRect box = item->desktopVisualBounds(); - if ( box && test(area, *box) && (take_insensitive || item->isVisibleAndUnlocked(dkey))) { + if ( box && test(area, *box) && (!item->isLocked() || take_insensitive) && (!item->isHidden() || take_hidden) ) { s.push_back(item); } } @@ -1559,10 +1564,10 @@ static SPItem *find_group_at_point(unsigned int dkey, SPGroup *group, Geom::Poin * Assumes box is normalized (and g_asserts it!) * */ -std::vector SPDocument::getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive, bool into_groups, bool with_groups) const +std::vector SPDocument::getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool take_hidden, bool take_insensitive, bool into_groups, bool into_filtered_groups,bool with_groups) const { std::vector x; - return find_items_in_area(x, SP_GROUP(this->root), dkey, box, is_within, take_insensitive, into_groups, with_groups); + return find_items_in_area(x, SP_GROUP(this->root), dkey, box, is_within, take_hidden, take_insensitive, into_groups, into_filtered_groups, with_groups); } /* @@ -1572,10 +1577,10 @@ std::vector SPDocument::getItemsInBox(unsigned int dkey, Geom::Rect con * */ -std::vector SPDocument::getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive, bool into_groups, bool with_groups) const +std::vector SPDocument::getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool take_hidden, bool take_insensitive, bool into_groups, bool into_filtered_groups, bool with_groups) const { std::vector x; - return find_items_in_area(x, SP_GROUP(this->root), dkey, box, overlaps, take_insensitive, into_groups, with_groups); + return find_items_in_area(x, SP_GROUP(this->root), dkey, box, overlaps, take_hidden, take_insensitive, into_groups, into_filtered_groups, with_groups); } std::vector SPDocument::getItemsAtPoints(unsigned const key, std::vector points, bool all_layers, size_t limit) const diff --git a/src/document.h b/src/document.h index 49196b9835..e045719b13 100644 --- a/src/document.h +++ b/src/document.h @@ -288,8 +288,8 @@ public: bool addResource(char const *key, SPObject *object); bool removeResource(char const *key, SPObject *object); std::vector const getResourceList(char const *key); - std::vector getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive = false, bool into_groups = false, bool with_groups = false) const; - std::vector getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive = false, bool into_groups = false, bool with_groups = false) const; + std::vector getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool take_hidden = false, bool take_insensitive = false, bool into_groups = false, bool into_filtered_groups = true, bool with_groups = false) const; + std::vector getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool take_hidden = false, bool take_insensitive = false, bool into_groups = false, bool into_filtered_groups = true, bool with_groups = false) const; SPItem *getItemAtPoint(unsigned int key, Geom::Point const &p, bool into_groups, SPItem *upto = nullptr) const; std::vector getItemsAtPoints(unsigned const key, std::vector points, bool all_layers = true, size_t limit = 0) const ; SPItem *getGroupAtPoint(unsigned int key, Geom::Point const &p) const; diff --git a/src/ui/contextmenu.cpp b/src/ui/contextmenu.cpp index a3e9e9e78f..4ce30406bd 100644 --- a/src/ui/contextmenu.cpp +++ b/src/ui/contextmenu.cpp @@ -81,7 +81,7 @@ ContextMenu::ContextMenu(SPDesktop *desktop, SPItem *item) : AddSeparator(); /* Lock/Unock Hide/Unhide*/ Geom::Rect b(_desktop->point(),_desktop->point() + Geom::Point(1,1)); - std::vector< SPItem * > down_items = _desktop->getDocument()->getItemsPartiallyInBox( _desktop->dkey, b, true, true); + std::vector< SPItem * > down_items = _desktop->getDocument()->getItemsPartiallyInBox( _desktop->dkey, b, true, true, true, true); bool has_down_hidden = false; bool has_down_locked = false; for(std::vector< SPItem * >::iterator down = down_items.begin(); down != down_items.end(); ++down){ diff --git a/src/ui/tools/measure-tool.cpp b/src/ui/tools/measure-tool.cpp index 3863d99d2e..80ba90398e 100644 --- a/src/ui/tools/measure-tool.cpp +++ b/src/ui/tools/measure-tool.cpp @@ -1300,7 +1300,7 @@ void MeasureTool::showCanvasItems(bool to_guides, bool to_item, bool to_phantom, std::vector items; SPDocument *doc = desktop->getDocument(); Geom::Rect rect(start_p, end_p); - items = doc->getItemsPartiallyInBox(desktop->dkey, rect, false, true); + items = doc->getItemsPartiallyInBox(desktop->dkey, rect, false, false, true, true); Inkscape::LayerModel *layer_model = nullptr; SPObject *current_layer = nullptr; if(desktop){ -- GitLab From 86594f2fe58dabae49377559275670cad6003987 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Fri, 2 Nov 2018 02:18:17 +0100 Subject: [PATCH 09/20] Improbe rendering of filters from cache --- -.orig | 0 src/display/drawing-item.cpp | 70 ++++++++------ src/display/drawing-item.h | 4 +- src/display/drawing-surface.cpp | 3 +- src/display/sp-canvas.cpp | 157 +++++++++----------------------- src/display/sp-canvas.h | 5 +- 6 files changed, 87 insertions(+), 152 deletions(-) create mode 100644 -.orig diff --git a/-.orig b/-.orig new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp index 1e7f8a2ce9..de4ffe0d92 100644 --- a/src/display/drawing-item.cpp +++ b/src/display/drawing-item.cpp @@ -127,7 +127,6 @@ DrawingItem::DrawingItem(Drawing &drawing) , _visible(true) , _sensitive(true) , _cached(0) - , _cache_insensitive(0) , _cached_persistent(0) , _has_cache_iterator(0) , _propagate(0) @@ -262,7 +261,7 @@ DrawingItem::clearChildren() /// Set the incremental transform for this item void -DrawingItem::setTransform(Geom::Affine const &new_trans, bool markForUpdate) +DrawingItem::setTransform(Geom::Affine const &new_trans) { Geom::Affine current; if (_transform) { @@ -278,9 +277,7 @@ DrawingItem::setTransform(Geom::Affine const &new_trans, bool markForUpdate) } else { _transform = new Geom::Affine(new_trans); } - if (markForUpdate) { - _markForUpdate(STATE_ALL, true); - } + _markForUpdate(STATE_ALL, true); } } @@ -343,7 +340,7 @@ DrawingItem::setCached(bool cached, bool persistent) { static const char *cache_env = getenv("_INKSCAPE_DISABLE_CACHE"); if (cache_env) return; - if (_cache_insensitive) return; + if (_cached_persistent && !persistent) return; @@ -683,7 +680,7 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag { bool outline = _drawing.outline(); bool render_filters = _drawing.renderFilters(); - std::cout << "111111111111111111" << std::endl; + // stop_at is handled in DrawingGroup, but this check is required to handle the case // where a filtered item with background-accessing filter has enable-background: new if (this == stop_at) return RENDER_STOP; @@ -691,7 +688,7 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag // If we are invisible, return immediately if (!_visible) return RENDER_OK; if (_ctm.isSingular(1e-18)) return RENDER_OK; -std::cout << "222222222222222222222222" << std::endl; + // TODO convert outline rendering to a separate virtual function if (outline) { _renderOutline(dc, area, flags); @@ -701,7 +698,7 @@ std::cout << "222222222222222222222222" << std::endl; // carea is the area to paint Geom::OptIntRect carea = Geom::intersect(area, _drawbox); if (!carea) return RENDER_OK; -std::cout << "13333333333333333333333" << std::endl; + // Device scale for HiDPI screens (typically 1 or 2) int device_scale = dc.surface()->device_scale(); @@ -721,31 +718,37 @@ std::cout << "13333333333333333333333" << std::endl; default: // should not happen g_assert_not_reached(); } -std::cout << render_filters << "ññññññññññññññññññññññññññ" << std::endl; + // render from cache if possible - if (_cached && !_cache_insensitive) { + Geom::IntRect canvas_bbox = dc.targetLogicalBounds().roundOutwards(); + if (_cached) { if (_cache) { _cache->prepare(); set_cairo_blend_operator( dc, _mix_blend_mode ); - _cache->paintFromCache(dc, carea); - if (!carea) return RENDER_OK; - } else { - // There is no cache. This could be because caching of this item - // was just turned on after the last update phase, or because - // we were previously outside of the canvas. - Geom::OptIntRect cl = _drawing.cacheLimit(); - cl.intersectWith(_drawbox); - if (cl) { - _cache = new DrawingCache(*cl, device_scale); + if (!carea) { + return RENDER_OK; } + delete _cache; + _cache = nullptr; + } + // There is no cache. This could be because caching of this item + // was just turned on after the last update phase, or because + // we were previously outside of the canvas. + Geom::OptIntRect cl = _drawing.cacheLimit(); + cl.intersectWith(_drawbox); + if (_filter && render_filters) { + cl.intersectWith(canvas_bbox); + } else { + cl.intersectWith(carea); + } + if (cl) { + _cache = new DrawingCache(*cl, device_scale); } } else { // if our caching was turned off after the last update, it was already // deleted in setCached() } - _cache_insensitive = false; - std::cout << render_filters << "wwwwwwwwwwwwwwwwwwwwwwwww" << std::endl; // determine whether this shape needs intermediate rendering. bool needs_intermediate_rendering = false; @@ -862,12 +865,21 @@ std::cout << render_filters << "ññññññññññññññññññññññññ // 6. Paint the completed rendering onto the base context (or into cache) if (_cached && _cache) { - DrawingContext cachect(*_cache); - cachect.rectangle(*carea); - cachect.setOperator(CAIRO_OPERATOR_SOURCE); - cachect.setSource(&intermediate); - cachect.fill(); - _cache->markClean(*carea); + Geom::OptIntRect cl = _drawing.cacheLimit(); + cl.intersectWith(_drawbox); + if (_filter && render_filters) { + cl.intersectWith(canvas_bbox); + } else { + cl.intersectWith(carea); + } + if (cl) { + DrawingContext cachect(*_cache); + cachect.rectangle(*cl); + cachect.setOperator(CAIRO_OPERATOR_SOURCE); + cachect.setSource(&intermediate); + cachect.fill(); + _cache->markClean(*cl); + } } dc.rectangle(*carea); dc.setSource(&intermediate); diff --git a/src/display/drawing-item.h b/src/display/drawing-item.h index c24272b4bd..5cd6c987f3 100644 --- a/src/display/drawing-item.h +++ b/src/display/drawing-item.h @@ -111,7 +111,6 @@ public: void setSensitive(bool v); bool cached() const { return _cached; } void setCached(bool c, bool persistent = false); - void setCacheInsensitive() { _cache_insensitive = true; } virtual void setStyle(SPStyle *style, SPStyle *context_style = nullptr); virtual void setChildrenStyle(SPStyle *context_style); @@ -119,7 +118,7 @@ public: void setAntialiasing(unsigned a); void setIsolation(unsigned isolation); // CSS Compositing and Blending void setBlendMode(unsigned blend_mode); - void setTransform(Geom::Affine const &trans, bool markForUpdate = true); + void setTransform(Geom::Affine const &trans); void setClip(DrawingItem *item); void setMask(DrawingItem *item); void setFillPattern(DrawingPattern *pattern); @@ -217,7 +216,6 @@ protected: unsigned _visible : 1; unsigned _sensitive : 1; ///< Whether this item responds to events unsigned _cached : 1; ///< Whether the rendering is stored for reuse - unsigned _cache_insensitive: 1; // If set cache is not changed for a temporary item change unsigned _cached_persistent : 1; ///< If set, will always be cached regardless of score unsigned _has_cache_iterator : 1; ///< If set, _cache_iterator is valid unsigned _propagate : 1; ///< Whether to call update for all children on next update diff --git a/src/display/drawing-surface.cpp b/src/display/drawing-surface.cpp index 0616410153..97f7e868d9 100644 --- a/src/display/drawing-surface.cpp +++ b/src/display/drawing-surface.cpp @@ -240,7 +240,6 @@ DrawingCache::prepare() Geom::IntRect old_area = pixelArea(); bool is_identity = _pending_transform.isIdentity(); if (is_identity && _pending_area == old_area) return; // no change - bool is_integer_translation = is_identity; if (!is_identity && _pending_transform.isTranslation()) { Geom::IntPoint t = _pending_transform.translation().round(); @@ -306,7 +305,7 @@ DrawingCache::paintFromCache(DrawingContext &dc, Geom::OptIntRect &area) // by the item. // Then we subtract the area that needs to be repainted from the // original area and paint the resulting region from cache. - cairo_rectangle_int_t area_c = _convertRect(*area); + cairo_rectangle_int_t area_c = _convertRect(pixelArea()); cairo_region_t *dirty_region = cairo_region_create_rectangle(&area_c); cairo_region_t *cache_region = cairo_region_copy(dirty_region); cairo_region_subtract(dirty_region, _clean_region); diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index b7c4c35dcb..376361e3c5 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -25,19 +25,14 @@ #include #include #include -#include #include "helper/sp-marshal.h" #include <2geom/rect.h> #include <2geom/affine.h> #include "display/sp-canvas.h" #include "display/sp-canvas-group.h" -#include "display/drawing-item.h" -#include "display/canvas-arena.h" #include "display/rendermode.h" -#include "display/drawing-item.h" #include "display/cairo-utils.h" -#include "object/sp-root.h" #include "preferences.h" #include "inkscape.h" #include "sodipodi-ctrlrect.h" @@ -54,7 +49,7 @@ using Inkscape::Debug::GdkEventLatencyTracker; // gtk_check_version returns non-NULL on failure static bool const HAS_BROKEN_MOTION_HINTS = - TRUE || gtk_check_version(2, 12, 0) != nullptr; + true || gtk_check_version(2, 12, 0) != nullptr; // Define this to visualize the regions to be redrawn //#define DEBUG_REDRAW 1; @@ -195,7 +190,7 @@ static guint object_signals[LAST_SIGNAL] = { 0 }; void sp_canvas_item_construct(SPCanvasItem *item, SPCanvasGroup *parent, gchar const *first_arg_name, va_list args); /** - * Helper that returns TRUE iff item is descendant of parent. + * Helper that returns true iff item is descendant of parent. */ bool is_descendant(SPCanvasItem const *item, SPCanvasItem const *parent); @@ -245,8 +240,8 @@ sp_canvas_item_init(SPCanvasItem *item) // that should be initially invisible; examples of such items: node handles, the CtrlRect // used for rubberbanding, path outline, etc. item->visible = TRUE; - item->in_destruction = FALSE; - item->pickable = TRUE; + item->in_destruction = false; + item->pickable = true; } SPCanvasItem *sp_canvas_item_new(SPCanvasGroup *parent, GType type, gchar const *first_arg_name, ...) @@ -320,7 +315,7 @@ void sp_canvas_item_dispose(GObject *object) */ if (!item->in_destruction) { - item->in_destruction=TRUE; + item->in_destruction=true; // Hack: if this is a ctrlrect, move it to 0,0; // this redraws only the stroke of the rect to be deleted, @@ -357,7 +352,7 @@ void sp_canvas_item_dispose(GObject *object) } g_signal_emit (object, object_signals[DESTROY], 0); - item->in_destruction = FALSE; + item->in_destruction = false; } G_OBJECT_CLASS(sp_canvas_item_parent_class)->dispose(object); @@ -708,12 +703,12 @@ bool is_descendant(SPCanvasItem const *item, SPCanvasItem const *parent) { while (item) { if (item == parent) { - return TRUE; + return true; } item = item->parent; } - return FALSE; + return false; } } // namespace @@ -969,25 +964,23 @@ static void sp_canvas_init(SPCanvas *canvas) canvas->_need_repick = TRUE; // See comment at in sp-canvas.h. - canvas->_gen_all_enter_events = FALSE; + canvas->_gen_all_enter_events = false; - canvas->_drawing_disabled = FALSE; + canvas->_drawing_disabled = false; canvas->_backing_store = nullptr; #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 12, 0) canvas->_surface_for_similar = nullptr; #endif canvas->_clean_region = cairo_region_create(); - canvas->_filtered_region = cairo_region_create(); canvas->_background = cairo_pattern_create_rgb(1, 1, 1); - canvas->_background_is_checkerboard = FALSE; - canvas->_filtering = FALSE; + canvas->_background_is_checkerboard = false; canvas->_forced_redraw_count = 0; canvas->_forced_redraw_limit = -1; #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - canvas->_enable_cms_display_adj = FALSE; + canvas->_enable_cms_display_adj = false; new (&canvas->_cms_key) Glib::ustring(""); #endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) } @@ -1026,10 +1019,6 @@ void SPCanvas::dispose(GObject *object) cairo_region_destroy(canvas->_clean_region); canvas->_clean_region = nullptr; } - if (canvas->_filtered_region) { - cairo_region_destroy(canvas->_filtered_region); - canvas->_filtered_region = nullptr; - } if (canvas->_background) { cairo_pattern_destroy(canvas->_background); canvas->_background = nullptr; @@ -1100,7 +1089,7 @@ void SPCanvas::handle_realize(GtkWidget *widget) gdk_window_set_user_data (window, widget); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - if (prefs->getBool("/options/useextinput/value", TRUE)) { + if (prefs->getBool("/options/useextinput/value", true)) { gtk_widget_set_events(widget, attributes.event_mask); } @@ -1270,9 +1259,9 @@ int SPCanvas::emitEvent(GdkEvent *event) } // Block Undo and Redo while we drag /anything/ if(event->type == GDK_BUTTON_PRESS && event->button.button == 1) - _is_dragging = TRUE; + _is_dragging = true; else if(event->type == GDK_BUTTON_RELEASE) - _is_dragging = FALSE; + _is_dragging = false; // Choose where we send the event @@ -1322,7 +1311,7 @@ int SPCanvas::pickCurrentItem(GdkEvent *event) int retval = FALSE; - if (_gen_all_enter_events == FALSE) { + if (_gen_all_enter_events == false) { // If a button is down, we'll perform enter and leave events on the // current item, but not enter on any other item. This is more or // less like X pointer grabbing for canvas items. @@ -1420,7 +1409,7 @@ int SPCanvas::pickCurrentItem(GdkEvent *event) _in_repick = FALSE; } - if (_gen_all_enter_events == FALSE) { + if (_gen_all_enter_events == false) { // new_current_item may have been set to NULL during the call to // emitEvent() above if ((_new_current_item != _current_item) && button_down) { @@ -1555,13 +1544,14 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect // initialized. if (_backing_store == nullptr) return; + SPCanvasBuf buf; buf.buf = nullptr; buf.buf_rowstride = 0; buf.rect = paint_rect; buf.canvas_rect = canvas_rect; buf.device_scale = _device_scale; - buf.is_empty = TRUE; + buf.is_empty = true; // Make sure the following code does not go outside of _backing_store's data // FIXME for device_scale. @@ -1570,6 +1560,7 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect assert(paint_rect.top() - _y0 >= 0); assert(paint_rect.right() - _x0 <= cairo_image_surface_get_width(_backing_store)); assert(paint_rect.bottom() - _y0 <= cairo_image_surface_get_height(_backing_store)); + // Create a temporary surface that draws directly to _backing_store cairo_surface_flush(_backing_store); // cairo_surface_write_to_png( _backing_store, "debug0.png" ); @@ -1582,6 +1573,7 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect cairo_surface_get_device_scale(_backing_store, &x_scale, &y_scale); assert (_device_scale == (int)x_scale); assert (_device_scale == (int)y_scale); + // Move to the right row data += stride * (paint_rect.top() - _y0) * (int)y_scale; // Move to the right pixel inside of that row @@ -1600,15 +1592,15 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect cairo_set_source(buf.ct, _background); cairo_set_operator(buf.ct, CAIRO_OPERATOR_SOURCE); cairo_paint(buf.ct); - cairo_restore(buf.ct); // cairo_surface_write_to_png( imgs, "debug1.png" ); - if (_root->visible) { + if (_root->visible) { SP_CANVAS_ITEM_GET_CLASS(_root)->render(_root, &buf); } // cairo_surface_write_to_png( imgs, "debug2.png" ); - // Start of visible tile rendering comment for hide X tiles + + // Start of visible tile rendering comment for hide X tiles cairo_set_operator(buf.ct, CAIRO_OPERATOR_OVER); cairo_set_source_rgb (buf.ct, 0, 0, 0); cairo_move_to (buf.ct, 0, 0); @@ -1618,7 +1610,7 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect cairo_set_line_width (buf.ct, 1); cairo_stroke (buf.ct); // End - + // output to X cairo_destroy(buf.ct); @@ -1651,6 +1643,7 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect // Mark the painted rectangle clean markRect(paint_rect, 0); + gtk_widget_queue_draw_area(GTK_WIDGET(this), paint_rect.left() -_x0, paint_rect.top() - _y0, paint_rect.width(), paint_rect.height()); } @@ -1692,7 +1685,7 @@ int SPCanvas::paintRectInternal(PaintRectSetup const *setup, Geom::IntRect const _forced_redraw_count++; } - return FALSE; + return false; } } @@ -1714,7 +1707,7 @@ int SPCanvas::paintRectInternal(PaintRectSetup const *setup, Geom::IntRect const GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(setup->canvas)); gdk_window_begin_paint_rect(window, &r); */ - std::cout << "canvas_rect, bw); //gdk_window_end_paint(window); return 1; @@ -1773,10 +1766,10 @@ The default for now is the strips mode. } -bool SPCanvas::paintRect(int xx0, int yy0, int xx1, int yy1, bool paint_as_one) +bool SPCanvas::paintRect(int xx0, int yy0, int xx1, int yy1) { GtkAllocation allocation; - g_return_val_if_fail (!_need_update, FALSE); + g_return_val_if_fail (!_need_update, false); gtk_widget_get_allocation(GTK_WIDGET(this), &allocation); @@ -1786,7 +1779,7 @@ bool SPCanvas::paintRect(int xx0, int yy0, int xx1, int yy1, bool paint_as_one) Geom::IntRect paint_rect(xx0, yy0, xx1, yy1); Geom::OptIntRect area = paint_rect & canvas_rect; - if (!area || area->hasZeroArea()) return FALSE; + if (!area || area->hasZeroArea()) return false; paint_rect = *area; PaintRectSetup setup; @@ -1813,9 +1806,8 @@ bool SPCanvas::paintRect(int xx0, int yy0, int xx1, int yy1, bool paint_as_one) Inkscape::Preferences *prefs = Inkscape::Preferences::get(); unsigned tile_multiplier = prefs->getIntLimited("/options/rendering/tile-multiplier", 16, 1, 512); - if (paint_as_one) { - setup.max_pixels = std::numeric_limits::max(); // Geom::Infinity() dont work - } else if (_rendermode != Inkscape::RENDERMODE_OUTLINE) { + + if (_rendermode != Inkscape::RENDERMODE_OUTLINE) { // use 256K as a compromise to not slow down gradients // 256K is the cached buffer and we need 4 channels setup.max_pixels = 65536 * tile_multiplier; // 256K/4 @@ -1956,91 +1948,33 @@ gint SPCanvas::handle_focus_out(GtkWidget *widget, GdkEventFocus *event) int SPCanvas::paint() { - bool need_update = _need_update; if (_need_update) { sp_canvas_item_invoke_update(_root, Geom::identity(), 0); _need_update = FALSE; } + GtkAllocation allocation; gtk_widget_get_allocation(GTK_WIDGET(this), &allocation); cairo_rectangle_int_t crect = { _x0, _y0, allocation.width, allocation.height }; cairo_region_t *to_draw = cairo_region_create_rectangle(&crect); - SPDesktop * desktop = SP_ACTIVE_DESKTOP; - Inkscape::DrawingItem *rootarena; - size_t nitems = 0; - if (desktop) { - rootarena = desktop->getDocument()->getRoot()->get_arenaitem(desktop->dkey); - if (!_filtering && _rendermode == Inkscape::RENDERMODE_NORMAL) { - std::vector items = desktop->getVisibleItems(TRUE); - nitems = items.size(); - for (auto item:items) { - Inkscape::DrawingItem *ditem = item->get_arenaitem(desktop->dkey); - //ditem->setCacheInsensitive(); //toggle back on render - Geom::OptRect optarea = ditem->visualBounds(); - if (optarea) { - Geom::Rect area = (*optarea) * desktop->doc2dt(); - Geom::IntRect render_rect = area.roundOutwards(); - render_rect.setLeft(std::max(render_rect.left(),_x0)); - render_rect.setTop(std::max(render_rect.top(),_y0)); - render_rect.setRight(std::min(render_rect.right(), (allocation.width +_x0))); - render_rect.setBottom(std::min(render_rect.bottom(),(allocation.height +_y0))); - cairo_rectangle_int_t crect = {render_rect.left(), render_rect.top(), render_rect.width(), render_rect.height() }; - std::cout << _filtering << "---" << 1 << "---" << crect.x << "---" << crect.y << "---" << crect.width << "---" << crect.height << std::endl; - cairo_region_union_rectangle(_filtered_region, &crect); - } - } - if (nitems) { - cairo_region_subtract(_filtered_region, _clean_region); - desktop->_display_mode = Inkscape::RENDERMODE_NO_FILTERS; - rootarena->drawing().setRenderMode(desktop->_display_mode); - _rendermode = desktop->_display_mode; - } - } - } cairo_region_subtract(to_draw, _clean_region); + int n_rects = cairo_region_num_rectangles(to_draw); for (int i = 0; i < n_rects; ++i) { cairo_rectangle_int_t crect; cairo_region_get_rectangle(to_draw, i, &crect); - std::cout << _filtering << "---" << 2 << "---" << crect.x << "---" << crect.y << "---" << crect.width << "---" << crect.height << std::endl; - if (!paintRect(crect.x, crect.y, crect.x + crect.width, crect.y + crect.height, _filtering)) { + if (!paintRect(crect.x, crect.y, crect.x + crect.width, crect.y + crect.height)) { // Aborted cairo_region_destroy(to_draw); - if (nitems) { - desktop->_display_mode = Inkscape::RENDERMODE_NORMAL; - rootarena->drawing().setRenderMode(desktop->_display_mode); - _rendermode = desktop->_display_mode; - nitems = 0; - } - _filtering = FALSE; return FALSE; }; } - if (nitems) { - std::cout << _filtering << "wwwwwwwwwwwwwwwww" << std::endl; - _filtering = TRUE; - /* for (auto item:items) { - sp_canvas_item_request_update(SP_CANVAS_ITEM(this)); - } */ - //_need_update = need_update?TRUE:FALSE; - desktop->_display_mode = Inkscape::RENDERMODE_NORMAL; - rootarena->drawing().setRenderMode(desktop->_display_mode); - _rendermode = desktop->_display_mode; - - cairo_region_subtract(_clean_region, _filtered_region); - if(!paint()) { - return FALSE; - } - cairo_region_subtract(_filtered_region, _filtered_region); - //_need_update = FALSE; - _filtering = FALSE; - } else { - // we've had a full unaborted redraw, reset the full redraw counter + // we've had a full unaborted redraw, reset the full redraw counter + if (_forced_redraw_limit != -1) { + _forced_redraw_count = 0; } - if (_forced_redraw_limit != -1) { - _forced_redraw_count = 0; - } + cairo_region_destroy(to_draw); return TRUE; @@ -2092,7 +2026,6 @@ void SPCanvas::addIdle() _idle_id = gdk_threads_add_idle_full(UPDATE_PRIORITY, idle_handler, this, nullptr); } } - void SPCanvas::removeIdle() { if (_idle_id) { @@ -2244,7 +2177,7 @@ void SPCanvas::setBackgroundColor(guint32 rgba) { cairo_pattern_destroy(_background); } _background = cairo_pattern_create_rgb(new_r, new_g, new_b); - _background_is_checkerboard = FALSE; + _background_is_checkerboard = false; dirtyAll(); addIdle(); } @@ -2255,7 +2188,7 @@ void SPCanvas::setBackgroundCheckerboard() { cairo_pattern_destroy(_background); } _background = ink_cairo_pattern_create_checkerboard(); - _background_is_checkerboard = TRUE; + _background_is_checkerboard = true; dirtyAll(); addIdle(); } @@ -2307,7 +2240,7 @@ Geom::Point sp_canvas_world_to_window(SPCanvas const *canvas, Geom::Point const } /** - * Returns TRUE if point given in world coordinates is inside window. + * Returns true if point given in world coordinates is inside window. */ bool sp_canvas_world_pt_inside_window(SPCanvas const *canvas, Geom::Point const &world) { @@ -2370,10 +2303,6 @@ void SPCanvas::dirtyAll() { cairo_region_destroy(_clean_region); _clean_region = cairo_region_create(); } - if (_filtered_region && !cairo_region_is_empty(_filtered_region)) { - cairo_region_destroy(_filtered_region); - _filtered_region = cairo_region_create(); - } } void SPCanvas::markRect(Geom::IntRect const &area, uint8_t val) diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index cb70a3ba96..ef2df22923 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -128,7 +128,7 @@ private: /// Draws a specific rectangular part of the canvas. /// @return true if the rectangle painting succeeds. - bool paintRect(int xx0, int yy0, int xx1, int yy1, bool paint_as_one = false); + bool paintRect(int xx0, int yy0, int xx1, int yy1); /// Repaints the areas in the canvas that need it. /// @return true if all the dirty parts have been redrawn @@ -188,15 +188,12 @@ public: #endif /// Area of the widget that has up-to-date content cairo_region_t *_clean_region; - /// Area of the widget that has filtered to render - cairo_region_t *_filtered_region; /// Widget background, defaults to white cairo_pattern_t *_background; bool _background_is_checkerboard; /// Last known modifier state, for deferred repick when a button is down. int _state; - bool _filtering; /** The item containing the mouse pointer, or NULL if none. */ SPCanvasItem *_current_item; -- GitLab From d16eeaf15378e9c45e7c9a149f23176017f55e24 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Fri, 2 Nov 2018 02:46:36 +0100 Subject: [PATCH 10/20] Improve also cache for non fileered elements --- src/display/drawing-item.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp index de4ffe0d92..28f5237875 100644 --- a/src/display/drawing-item.cpp +++ b/src/display/drawing-item.cpp @@ -737,11 +737,7 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag // we were previously outside of the canvas. Geom::OptIntRect cl = _drawing.cacheLimit(); cl.intersectWith(_drawbox); - if (_filter && render_filters) { - cl.intersectWith(canvas_bbox); - } else { - cl.intersectWith(carea); - } + cl.intersectWith(canvas_bbox); if (cl) { _cache = new DrawingCache(*cl, device_scale); } @@ -867,11 +863,7 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag if (_cached && _cache) { Geom::OptIntRect cl = _drawing.cacheLimit(); cl.intersectWith(_drawbox); - if (_filter && render_filters) { - cl.intersectWith(canvas_bbox); - } else { - cl.intersectWith(carea); - } + cl.intersectWith(canvas_bbox); if (cl) { DrawingContext cachect(*_cache); cachect.rectangle(*cl); -- GitLab From 7b63970486db93e8f094cb19690f9fbba87e662b Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Fri, 2 Nov 2018 03:55:17 +0100 Subject: [PATCH 11/20] Fixes to rendering --- src/display/drawing-item.cpp | 30 ++++++++++++------------------ src/display/drawing-item.h | 1 + 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp index 28f5237875..07b1e6233f 100644 --- a/src/display/drawing-item.cpp +++ b/src/display/drawing-item.cpp @@ -135,6 +135,7 @@ DrawingItem::DrawingItem(Drawing &drawing) , _antialias(2) , _isolation(SP_CSS_ISOLATION_AUTO) , _mix_blend_mode(SP_CSS_BLEND_NORMAL) + , _canvas_bbox(Geom::IntRect::infinite()) {} DrawingItem::~DrawingItem() @@ -720,26 +721,21 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag } // render from cache if possible - Geom::IntRect canvas_bbox = dc.targetLogicalBounds().roundOutwards(); + _canvas_bbox = dc.targetLogicalBounds().roundOutwards(); if (_cached) { if (_cache) { _cache->prepare(); set_cairo_blend_operator( dc, _mix_blend_mode ); _cache->paintFromCache(dc, carea); - if (!carea) { - return RENDER_OK; + if (!carea) return RENDER_OK; + } else { + // There is no cache. This could be because caching of this item + // was just turned on after the last update phase, or because + // we were previously outside of the canvas. + Geom::OptIntRect cl = _cacheRect(); + if (cl) { + _cache = new DrawingCache(*cl, device_scale); } - delete _cache; - _cache = nullptr; - } - // There is no cache. This could be because caching of this item - // was just turned on after the last update phase, or because - // we were previously outside of the canvas. - Geom::OptIntRect cl = _drawing.cacheLimit(); - cl.intersectWith(_drawbox); - cl.intersectWith(canvas_bbox); - if (cl) { - _cache = new DrawingCache(*cl, device_scale); } } else { // if our caching was turned off after the last update, it was already @@ -861,9 +857,7 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag // 6. Paint the completed rendering onto the base context (or into cache) if (_cached && _cache) { - Geom::OptIntRect cl = _drawing.cacheLimit(); - cl.intersectWith(_drawbox); - cl.intersectWith(canvas_bbox); + Geom::OptIntRect cl = _cacheRect(); if (cl) { DrawingContext cachect(*_cache); cachect.rectangle(*cl); @@ -1164,7 +1158,7 @@ DrawingItem::_cacheScore() Geom::OptIntRect DrawingItem::_cacheRect() { - Geom::OptIntRect r = _drawbox & _drawing.cacheLimit(); + Geom::OptIntRect r = _drawbox & _canvas_bbox & _drawing.cacheLimit(); return r; } diff --git a/src/display/drawing-item.h b/src/display/drawing-item.h index 5cd6c987f3..af6349e98e 100644 --- a/src/display/drawing-item.h +++ b/src/display/drawing-item.h @@ -193,6 +193,7 @@ protected: Geom::Affine _ctm; ///< Total transform from item coords to display coords Geom::OptIntRect _bbox; ///< Bounding box in display (pixel) coords including stroke Geom::OptIntRect _drawbox; ///< Full visual bounding box - enlarged by filters, shrunk by clips and masks + Geom::IntRect _canvas_bbox; ///< Canvas bounding box Geom::OptRect _item_bbox; ///< Geometric bounding box in item's user space. /// This is used to compute the filter effect region and render in /// objectBoundingBox units. -- GitLab From 70e1054c48d6df475f3fb5841ef73de4a4b1fa50 Mon Sep 17 00:00:00 2001 From: Jabiertxof Date: Fri, 2 Nov 2018 11:23:34 +0100 Subject: [PATCH 12/20] Fixing gaps rendering bug --- src/display/drawing-item.cpp | 10 +++++++--- src/display/drawing-item.h | 1 - 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp index 07b1e6233f..eea74df1c1 100644 --- a/src/display/drawing-item.cpp +++ b/src/display/drawing-item.cpp @@ -135,7 +135,6 @@ DrawingItem::DrawingItem(Drawing &drawing) , _antialias(2) , _isolation(SP_CSS_ISOLATION_AUTO) , _mix_blend_mode(SP_CSS_BLEND_NORMAL) - , _canvas_bbox(Geom::IntRect::infinite()) {} DrawingItem::~DrawingItem() @@ -721,7 +720,7 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag } // render from cache if possible - _canvas_bbox = dc.targetLogicalBounds().roundOutwards(); + Geom::IntRect _canvas_bbox = dc.targetLogicalBounds().roundOutwards(); if (_cached) { if (_cache) { _cache->prepare(); @@ -858,6 +857,11 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag // 6. Paint the completed rendering onto the base context (or into cache) if (_cached && _cache) { Geom::OptIntRect cl = _cacheRect(); + if (_filter && render_filters) { + cl.intersects(_canvas_bbox); + } else { + cl.intersects(*carea); + } if (cl) { DrawingContext cachect(*_cache); cachect.rectangle(*cl); @@ -1158,7 +1162,7 @@ DrawingItem::_cacheScore() Geom::OptIntRect DrawingItem::_cacheRect() { - Geom::OptIntRect r = _drawbox & _canvas_bbox & _drawing.cacheLimit(); + Geom::OptIntRect r = _drawbox & _drawing.cacheLimit(); return r; } diff --git a/src/display/drawing-item.h b/src/display/drawing-item.h index af6349e98e..5cd6c987f3 100644 --- a/src/display/drawing-item.h +++ b/src/display/drawing-item.h @@ -193,7 +193,6 @@ protected: Geom::Affine _ctm; ///< Total transform from item coords to display coords Geom::OptIntRect _bbox; ///< Bounding box in display (pixel) coords including stroke Geom::OptIntRect _drawbox; ///< Full visual bounding box - enlarged by filters, shrunk by clips and masks - Geom::IntRect _canvas_bbox; ///< Canvas bounding box Geom::OptRect _item_bbox; ///< Geometric bounding box in item's user space. /// This is used to compute the filter effect region and render in /// objectBoundingBox units. -- GitLab From 2366fb89df0604870128ef2428279a8254be72ac Mon Sep 17 00:00:00 2001 From: Jabiertxof Date: Fri, 2 Nov 2018 14:21:26 +0100 Subject: [PATCH 13/20] Fixing rendering --- src/display/drawing-item.cpp | 7 ++++--- src/display/drawing-surface.cpp | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp index eea74df1c1..94b039777b 100644 --- a/src/display/drawing-item.cpp +++ b/src/display/drawing-item.cpp @@ -731,7 +731,8 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag // There is no cache. This could be because caching of this item // was just turned on after the last update phase, or because // we were previously outside of the canvas. - Geom::OptIntRect cl = _cacheRect(); + Geom::OptIntRect cl = _drawing.cacheLimit(); + cl.intersectWith(_drawbox); if (cl) { _cache = new DrawingCache(*cl, device_scale); } @@ -856,9 +857,9 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag // 6. Paint the completed rendering onto the base context (or into cache) if (_cached && _cache) { - Geom::OptIntRect cl = _cacheRect(); + Geom::OptIntRect cl = _drawing.cacheLimit(); if (_filter && render_filters) { - cl.intersects(_canvas_bbox); + cl.intersectWith(_drawbox); } else { cl.intersects(*carea); } diff --git a/src/display/drawing-surface.cpp b/src/display/drawing-surface.cpp index 97f7e868d9..40f251a85c 100644 --- a/src/display/drawing-surface.cpp +++ b/src/display/drawing-surface.cpp @@ -305,7 +305,7 @@ DrawingCache::paintFromCache(DrawingContext &dc, Geom::OptIntRect &area) // by the item. // Then we subtract the area that needs to be repainted from the // original area and paint the resulting region from cache. - cairo_rectangle_int_t area_c = _convertRect(pixelArea()); + cairo_rectangle_int_t area_c = _convertRect(*area); cairo_region_t *dirty_region = cairo_region_create_rectangle(&area_c); cairo_region_t *cache_region = cairo_region_copy(dirty_region); cairo_region_subtract(dirty_region, _clean_region); -- GitLab From eb8735ec1d35c87585d86534c2791373de09b25e Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Fri, 2 Nov 2018 15:11:49 +0100 Subject: [PATCH 14/20] Fixing rendering --- src/display/drawing-item.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp index 94b039777b..6f7f62f13c 100644 --- a/src/display/drawing-item.cpp +++ b/src/display/drawing-item.cpp @@ -721,6 +721,7 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag // render from cache if possible Geom::IntRect _canvas_bbox = dc.targetLogicalBounds().roundOutwards(); + std::cout << _canvas_bbox << std::endl; if (_cached) { if (_cache) { _cache->prepare(); -- GitLab From 9c77d5e55b9d863574afaadc3bde5cbd8027d1e1 Mon Sep 17 00:00:00 2001 From: Jabiertxof Date: Fri, 2 Nov 2018 21:08:58 +0100 Subject: [PATCH 15/20] Improving cache oversize display --- src/display/drawing-item.cpp | 46 ++++++++++++++------------------- src/display/drawing-surface.cpp | 38 +++++++++++++++++---------- src/display/drawing-surface.h | 2 +- 3 files changed, 44 insertions(+), 42 deletions(-) diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp index 6f7f62f13c..94330355a6 100644 --- a/src/display/drawing-item.cpp +++ b/src/display/drawing-item.cpp @@ -699,6 +699,10 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag Geom::OptIntRect carea = Geom::intersect(area, _drawbox); if (!carea) return RENDER_OK; + //if (!(_filter && render_filters)) { + //cachearea.intersectWith(carea); + //} + carea = _cacheRect(); // Device scale for HiDPI screens (typically 1 or 2) int device_scale = dc.surface()->device_scale(); @@ -719,25 +723,21 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag g_assert_not_reached(); } - // render from cache if possible - Geom::IntRect _canvas_bbox = dc.targetLogicalBounds().roundOutwards(); - std::cout << _canvas_bbox << std::endl; if (_cached) { if (_cache) { - _cache->prepare(); + _cache->prepare(carea); set_cairo_blend_operator( dc, _mix_blend_mode ); _cache->paintFromCache(dc, carea); + std::cout << "bbbbbbbbbbbbb" << std::endl; if (!carea) return RENDER_OK; - } else { - // There is no cache. This could be because caching of this item - // was just turned on after the last update phase, or because - // we were previously outside of the canvas. - Geom::OptIntRect cl = _drawing.cacheLimit(); - cl.intersectWith(_drawbox); - if (cl) { - _cache = new DrawingCache(*cl, device_scale); - } + std::cout << "aaaaaaaaaaaaaaaaa" << std::endl; + delete _cache; + _cache = nullptr; } + // There is no cache. This could be because caching of this item + // was just turned on after the last update phase, or because + // we were previously outside of the canvas. + _cache = new DrawingCache(*carea, device_scale); } else { // if our caching was turned off after the last update, it was already // deleted in setCached() @@ -858,20 +858,12 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag // 6. Paint the completed rendering onto the base context (or into cache) if (_cached && _cache) { - Geom::OptIntRect cl = _drawing.cacheLimit(); - if (_filter && render_filters) { - cl.intersectWith(_drawbox); - } else { - cl.intersects(*carea); - } - if (cl) { - DrawingContext cachect(*_cache); - cachect.rectangle(*cl); - cachect.setOperator(CAIRO_OPERATOR_SOURCE); - cachect.setSource(&intermediate); - cachect.fill(); - _cache->markClean(*cl); - } + DrawingContext cachect(*_cache); + cachect.rectangle(*carea); + cachect.setOperator(CAIRO_OPERATOR_SOURCE); + cachect.setSource(&intermediate); + cachect.fill(); + _cache->markClean(*carea); } dc.rectangle(*carea); dc.setSource(&intermediate); diff --git a/src/display/drawing-surface.cpp b/src/display/drawing-surface.cpp index 40f251a85c..e8c7101fb1 100644 --- a/src/display/drawing-surface.cpp +++ b/src/display/drawing-surface.cpp @@ -235,7 +235,7 @@ DrawingCache::scheduleTransform(Geom::IntRect const &new_area, Geom::Affine cons /// Transforms the cache according to the transform specified during the update phase. /// Call this during render phase, before painting. void -DrawingCache::prepare() +DrawingCache::prepare(Geom::OptIntRect cachearea) { Geom::IntRect old_area = pixelArea(); bool is_identity = _pending_transform.isIdentity(); @@ -265,21 +265,28 @@ DrawingCache::prepare() _surface = nullptr; _pixels = _pending_area.dimensions(); _origin = _pending_area.min(); - + Geom::IntRect expanded = _pending_area; + Geom::IntPoint expansion(_pending_area.width()/2, _pending_area.height()/2); + expanded.expandBy(expansion); if (is_integer_translation) { - // transform the cache only for integer translations and identities - cairo_t *ct = createRawContext(); - if (!is_identity) { - ink_cairo_transform(ct, _pending_transform); + if (expanded.contains(cachearea) && 1 > 2) { + cairo_rectangle_int_t cache_t = _convertRect(*cachearea); + cairo_region_subtract_rectangle(_clean_region, &cache_t); + } else { + // transform the cache only for integer translations and identities + cairo_t *ct = createRawContext(); + if (!is_identity) { + ink_cairo_transform(ct, _pending_transform); + } + cairo_set_source_surface(ct, old_surface, old_origin[X], old_origin[Y]); + cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE); + cairo_pattern_set_filter(cairo_get_source(ct), CAIRO_FILTER_NEAREST); + cairo_paint(ct); + cairo_destroy(ct); + + cairo_rectangle_int_t limit = _convertRect(_pending_area); + cairo_region_intersect_rectangle(_clean_region, &limit); } - cairo_set_source_surface(ct, old_surface, old_origin[X], old_origin[Y]); - cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE); - cairo_pattern_set_filter(cairo_get_source(ct), CAIRO_FILTER_NEAREST); - cairo_paint(ct); - cairo_destroy(ct); - - cairo_rectangle_int_t limit = _convertRect(_pending_area); - cairo_region_intersect_rectangle(_clean_region, &limit); } else { // dirty everything cairo_region_destroy(_clean_region); @@ -310,6 +317,9 @@ DrawingCache::paintFromCache(DrawingContext &dc, Geom::OptIntRect &area) cairo_region_t *cache_region = cairo_region_copy(dirty_region); cairo_region_subtract(dirty_region, _clean_region); + + cairo_region_subtract(dirty_region, _clean_region); + if (cairo_region_is_empty(dirty_region)) { area = Geom::OptIntRect(); } else { diff --git a/src/display/drawing-surface.h b/src/display/drawing-surface.h index ae9a576e71..0cef72f059 100644 --- a/src/display/drawing-surface.h +++ b/src/display/drawing-surface.h @@ -70,7 +70,7 @@ public: void markDirty(Geom::IntRect const &area = Geom::IntRect::infinite()); void markClean(Geom::IntRect const &area = Geom::IntRect::infinite()); void scheduleTransform(Geom::IntRect const &new_area, Geom::Affine const &trans); - void prepare(); + void prepare(Geom::OptIntRect cachearea = Geom::OptIntRect()); void paintFromCache(DrawingContext &dc, Geom::OptIntRect &area); protected: -- GitLab From 9a8ab28ec05fdc7616787a9850ba48dd35ba343c Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Sat, 3 Nov 2018 00:13:16 +0100 Subject: [PATCH 16/20] Working on cache --- -.orig | 0 src/display/drawing-item.cpp | 2 +- src/display/drawing-surface.cpp | 36 +++++++++++---------------------- src/display/drawing-surface.h | 2 +- 4 files changed, 14 insertions(+), 26 deletions(-) delete mode 100644 -.orig diff --git a/-.orig b/-.orig deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp index 94330355a6..d316624217 100644 --- a/src/display/drawing-item.cpp +++ b/src/display/drawing-item.cpp @@ -627,7 +627,7 @@ DrawingItem::update(Geom::IntRect const &area, UpdateContext const &ctx, unsigne Geom::OptIntRect cl = _cacheRect(); if (_visible && cl) { // never create cache for invisible items // this takes care of invalidation on transform - _cache->scheduleTransform(*cl, ctm_change); + _cache->scheduleTransform(*_drawbox, ctm_change); } else { // Destroy cache for this item - outside of canvas or invisible. // The opposite transition (invisible -> visible or object diff --git a/src/display/drawing-surface.cpp b/src/display/drawing-surface.cpp index e8c7101fb1..2f0d1d2e98 100644 --- a/src/display/drawing-surface.cpp +++ b/src/display/drawing-surface.cpp @@ -235,7 +235,7 @@ DrawingCache::scheduleTransform(Geom::IntRect const &new_area, Geom::Affine cons /// Transforms the cache according to the transform specified during the update phase. /// Call this during render phase, before painting. void -DrawingCache::prepare(Geom::OptIntRect cachearea) +DrawingCache::prepare() { Geom::IntRect old_area = pixelArea(); bool is_identity = _pending_transform.isIdentity(); @@ -265,28 +265,19 @@ DrawingCache::prepare(Geom::OptIntRect cachearea) _surface = nullptr; _pixels = _pending_area.dimensions(); _origin = _pending_area.min(); - Geom::IntRect expanded = _pending_area; - Geom::IntPoint expansion(_pending_area.width()/2, _pending_area.height()/2); - expanded.expandBy(expansion); if (is_integer_translation) { - if (expanded.contains(cachearea) && 1 > 2) { - cairo_rectangle_int_t cache_t = _convertRect(*cachearea); - cairo_region_subtract_rectangle(_clean_region, &cache_t); - } else { - // transform the cache only for integer translations and identities - cairo_t *ct = createRawContext(); - if (!is_identity) { - ink_cairo_transform(ct, _pending_transform); - } - cairo_set_source_surface(ct, old_surface, old_origin[X], old_origin[Y]); - cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE); - cairo_pattern_set_filter(cairo_get_source(ct), CAIRO_FILTER_NEAREST); - cairo_paint(ct); - cairo_destroy(ct); - - cairo_rectangle_int_t limit = _convertRect(_pending_area); - cairo_region_intersect_rectangle(_clean_region, &limit); + cairo_t *ct = createRawContext(); + if (!is_identity) { + ink_cairo_transform(ct, _pending_transform); } + cairo_set_source_surface(ct, old_surface, old_origin[X], old_origin[Y]); + cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE); + cairo_pattern_set_filter(cairo_get_source(ct), CAIRO_FILTER_NEAREST); + cairo_paint(ct); + cairo_destroy(ct); + + cairo_rectangle_int_t limit = _convertRect(_pending_area); + cairo_region_intersect_rectangle(_clean_region, &limit); } else { // dirty everything cairo_region_destroy(_clean_region); @@ -317,9 +308,6 @@ DrawingCache::paintFromCache(DrawingContext &dc, Geom::OptIntRect &area) cairo_region_t *cache_region = cairo_region_copy(dirty_region); cairo_region_subtract(dirty_region, _clean_region); - - cairo_region_subtract(dirty_region, _clean_region); - if (cairo_region_is_empty(dirty_region)) { area = Geom::OptIntRect(); } else { diff --git a/src/display/drawing-surface.h b/src/display/drawing-surface.h index 0cef72f059..ae9a576e71 100644 --- a/src/display/drawing-surface.h +++ b/src/display/drawing-surface.h @@ -70,7 +70,7 @@ public: void markDirty(Geom::IntRect const &area = Geom::IntRect::infinite()); void markClean(Geom::IntRect const &area = Geom::IntRect::infinite()); void scheduleTransform(Geom::IntRect const &new_area, Geom::Affine const &trans); - void prepare(Geom::OptIntRect cachearea = Geom::OptIntRect()); + void prepare(); void paintFromCache(DrawingContext &dc, Geom::OptIntRect &area); protected: -- GitLab From ef23d54c6fed745f5915a8a6523d804314a6a160 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Sat, 3 Nov 2018 00:19:42 +0100 Subject: [PATCH 17/20] Reset to no working code --- src/display/drawing-item.cpp | 27 +++++++++++++-------------- src/display/drawing-surface.cpp | 3 +++ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp index d316624217..aa27939080 100644 --- a/src/display/drawing-item.cpp +++ b/src/display/drawing-item.cpp @@ -627,7 +627,7 @@ DrawingItem::update(Geom::IntRect const &area, UpdateContext const &ctx, unsigne Geom::OptIntRect cl = _cacheRect(); if (_visible && cl) { // never create cache for invisible items // this takes care of invalidation on transform - _cache->scheduleTransform(*_drawbox, ctm_change); + _cache->scheduleTransform(*cl, ctm_change); } else { // Destroy cache for this item - outside of canvas or invisible. // The opposite transition (invisible -> visible or object @@ -699,10 +699,6 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag Geom::OptIntRect carea = Geom::intersect(area, _drawbox); if (!carea) return RENDER_OK; - //if (!(_filter && render_filters)) { - //cachearea.intersectWith(carea); - //} - carea = _cacheRect(); // Device scale for HiDPI screens (typically 1 or 2) int device_scale = dc.surface()->device_scale(); @@ -723,21 +719,24 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag g_assert_not_reached(); } + // render from cache if possible if (_cached) { if (_cache) { - _cache->prepare(carea); + _cache->prepare(); set_cairo_blend_operator( dc, _mix_blend_mode ); + _cache->paintFromCache(dc, carea); - std::cout << "bbbbbbbbbbbbb" << std::endl; if (!carea) return RENDER_OK; - std::cout << "aaaaaaaaaaaaaaaaa" << std::endl; - delete _cache; - _cache = nullptr; + } else { + // There is no cache. This could be because caching of this item + // was just turned on after the last update phase, or because + // we were previously outside of the canvas. + Geom::OptIntRect cl = _drawing.cacheLimit(); + cl.intersectWith(_drawbox); + if (cl) { + _cache = new DrawingCache(*cl, device_scale); + } } - // There is no cache. This could be because caching of this item - // was just turned on after the last update phase, or because - // we were previously outside of the canvas. - _cache = new DrawingCache(*carea, device_scale); } else { // if our caching was turned off after the last update, it was already // deleted in setCached() diff --git a/src/display/drawing-surface.cpp b/src/display/drawing-surface.cpp index 2f0d1d2e98..0616410153 100644 --- a/src/display/drawing-surface.cpp +++ b/src/display/drawing-surface.cpp @@ -240,6 +240,7 @@ DrawingCache::prepare() Geom::IntRect old_area = pixelArea(); bool is_identity = _pending_transform.isIdentity(); if (is_identity && _pending_area == old_area) return; // no change + bool is_integer_translation = is_identity; if (!is_identity && _pending_transform.isTranslation()) { Geom::IntPoint t = _pending_transform.translation().round(); @@ -265,7 +266,9 @@ DrawingCache::prepare() _surface = nullptr; _pixels = _pending_area.dimensions(); _origin = _pending_area.min(); + if (is_integer_translation) { + // transform the cache only for integer translations and identities cairo_t *ct = createRawContext(); if (!is_identity) { ink_cairo_transform(ct, _pending_transform); -- GitLab From c0a9b47c0c3ab44433d6889c09df5799ecc322d7 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Sat, 3 Nov 2018 23:00:20 +0100 Subject: [PATCH 18/20] Better fix for the problem --- src/desktop.cpp | 13 ------------- src/desktop.h | 2 +- src/display/drawing-item.cpp | 8 +++++--- src/display/drawing-surface.cpp | 4 ++-- src/display/sp-canvas.cpp | 2 +- src/document.cpp | 32 +++++++++++--------------------- src/document.h | 4 ++-- src/ui/contextmenu.cpp | 2 +- src/ui/tools/measure-tool.cpp | 8 ++------ 9 files changed, 25 insertions(+), 50 deletions(-) diff --git a/src/desktop.cpp b/src/desktop.cpp index 7846599c77..335afa17d1 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -726,19 +726,6 @@ SPItem *SPDesktop::getGroupAtPoint(Geom::Point const &p) const g_return_val_if_fail (doc() != nullptr, NULL); return doc()->getGroupAtPoint(dkey, p); } -/** - * Returns a vector of visible items in a desktop - */ -std::vector SPDesktop::getVisibleItems(bool isFiltered) { - std::vector result; - for(auto item:getDocument()->getItemsPartiallyInBox(dkey, get_display_area(), false, true, true, false, true)) { - if(isFiltered && !item->isFiltered()) { - continue; - } - result.push_back(item); - } - return result; -} /** * Returns the mouse point in document coordinates; if mouse is diff --git a/src/desktop.h b/src/desktop.h index 8e83b16b92..b4e5da35d6 100644 --- a/src/desktop.h +++ b/src/desktop.h @@ -436,7 +436,7 @@ public: void mouseover() override {} void mouseout() override {} - std::vector getVisibleItems(bool isFiltered = false); + virtual bool onDeleteUI (GdkEventAny*); virtual bool onWindowStateEvent (GdkEventWindowState* event); diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp index aa27939080..3ba4f49aca 100644 --- a/src/display/drawing-item.cpp +++ b/src/display/drawing-item.cpp @@ -699,6 +699,11 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag Geom::OptIntRect carea = Geom::intersect(area, _drawbox); if (!carea) return RENDER_OK; + // expand render on filtered items + Geom::OptIntRect cl = _cacheRect(); + if (_filter && render_filters) { + carea = cl; + } // Device scale for HiDPI screens (typically 1 or 2) int device_scale = dc.surface()->device_scale(); @@ -724,15 +729,12 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag if (_cache) { _cache->prepare(); set_cairo_blend_operator( dc, _mix_blend_mode ); - _cache->paintFromCache(dc, carea); if (!carea) return RENDER_OK; } else { // There is no cache. This could be because caching of this item // was just turned on after the last update phase, or because // we were previously outside of the canvas. - Geom::OptIntRect cl = _drawing.cacheLimit(); - cl.intersectWith(_drawbox); if (cl) { _cache = new DrawingCache(*cl, device_scale); } diff --git a/src/display/drawing-surface.cpp b/src/display/drawing-surface.cpp index 0616410153..bcbc269932 100644 --- a/src/display/drawing-surface.cpp +++ b/src/display/drawing-surface.cpp @@ -240,7 +240,7 @@ DrawingCache::prepare() Geom::IntRect old_area = pixelArea(); bool is_identity = _pending_transform.isIdentity(); if (is_identity && _pending_area == old_area) return; // no change - + bool is_integer_translation = is_identity; if (!is_identity && _pending_transform.isTranslation()) { Geom::IntPoint t = _pending_transform.translation().round(); @@ -289,7 +289,7 @@ DrawingCache::prepare() //std::cout << _pending_transform << old_area << _pending_area << std::endl; cairo_surface_destroy(old_surface); - _pending_transform.setIdentity(); + _pending_transform.setIdentity(); } /** diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 376361e3c5..186196f5e0 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -1610,7 +1610,7 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect cairo_set_line_width (buf.ct, 1); cairo_stroke (buf.ct); // End - + // output to X cairo_destroy(buf.ct); diff --git a/src/document.cpp b/src/document.cpp index 646ed26bdb..35e57871f8 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1382,28 +1382,19 @@ static bool overlaps(Geom::Rect const &area, Geom::Rect const &box) } static std::vector &find_items_in_area(std::vector &s, SPGroup *group, unsigned int dkey, Geom::Rect const &area, - bool (*test)(Geom::Rect const &, Geom::Rect const &), bool take_hidden = false, bool take_insensitive = false, bool into_groups = false, bool into_filtered_groups = true, bool with_groups = true) + bool (*test)(Geom::Rect const &, Geom::Rect const &), bool take_insensitive = false, bool into_groups = false) { g_return_val_if_fail(SP_IS_GROUP(group), s); for (auto& o: group->children) { if ( SP_IS_ITEM(&o) ) { - SPItem *item = SP_ITEM(&o); - bool is_layer = SP_IS_GROUP(item) && SP_GROUP(item)->effectiveLayerMode(dkey) == SPGroup::LAYER; - if (SP_IS_GROUP(item) && (is_layer || into_groups)) { - if(!item->isFiltered() || into_filtered_groups) { - s = find_items_in_area(s, SP_GROUP(item), dkey, area, test, take_insensitive, into_groups, into_filtered_groups, with_groups); - } - if(with_groups && !is_layer) { - Geom::OptRect box = item->desktopVisualBounds(); - if ( box && test(area, *box) && (!item->isLocked() || take_insensitive) && (!item->isHidden() || take_hidden) ) { - s.push_back(item); - } - } + if (SP_IS_GROUP(&o) && (SP_GROUP(&o)->effectiveLayerMode(dkey) == SPGroup::LAYER || into_groups)) { + s = find_items_in_area(s, SP_GROUP(&o), dkey, area, test, take_insensitive, into_groups); } else { - Geom::OptRect box = item->desktopVisualBounds(); - if ( box && test(area, *box) && (!item->isLocked() || take_insensitive) && (!item->isHidden() || take_hidden) ) { - s.push_back(item); + SPItem *child = SP_ITEM(&o); + Geom::OptRect box = child->desktopVisualBounds(); + if ( box && test(area, *box) && (take_insensitive || child->isVisibleAndUnlocked(dkey))) { + s.push_back(child); } } } @@ -1465,7 +1456,6 @@ SPItem *SPDocument::getItemFromListAtPointBottom(unsigned int dkey, SPGroup *gro Turn the SVG DOM into a flat list of nodes that can be searched from top-down. The list can be persisted, which improves "find at multiple points" speed. */ -// TODO: study add `gboolean with_groups = false` as parameter. void SPDocument::build_flat_item_list(unsigned int dkey, SPGroup *group, gboolean into_groups) const { for (auto& o: group->children) { @@ -1564,10 +1554,10 @@ static SPItem *find_group_at_point(unsigned int dkey, SPGroup *group, Geom::Poin * Assumes box is normalized (and g_asserts it!) * */ -std::vector SPDocument::getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool take_hidden, bool take_insensitive, bool into_groups, bool into_filtered_groups,bool with_groups) const +std::vector SPDocument::getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive, bool into_groups) const { std::vector x; - return find_items_in_area(x, SP_GROUP(this->root), dkey, box, is_within, take_hidden, take_insensitive, into_groups, into_filtered_groups, with_groups); + return find_items_in_area(x, SP_GROUP(this->root), dkey, box, is_within, take_insensitive, into_groups); } /* @@ -1577,10 +1567,10 @@ std::vector SPDocument::getItemsInBox(unsigned int dkey, Geom::Rect con * */ -std::vector SPDocument::getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool take_hidden, bool take_insensitive, bool into_groups, bool into_filtered_groups, bool with_groups) const +std::vector SPDocument::getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive, bool into_groups) const { std::vector x; - return find_items_in_area(x, SP_GROUP(this->root), dkey, box, overlaps, take_hidden, take_insensitive, into_groups, into_filtered_groups, with_groups); + return find_items_in_area(x, SP_GROUP(this->root), dkey, box, overlaps, take_insensitive, into_groups); } std::vector SPDocument::getItemsAtPoints(unsigned const key, std::vector points, bool all_layers, size_t limit) const diff --git a/src/document.h b/src/document.h index e045719b13..5b93261de9 100644 --- a/src/document.h +++ b/src/document.h @@ -288,8 +288,8 @@ public: bool addResource(char const *key, SPObject *object); bool removeResource(char const *key, SPObject *object); std::vector const getResourceList(char const *key); - std::vector getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool take_hidden = false, bool take_insensitive = false, bool into_groups = false, bool into_filtered_groups = true, bool with_groups = false) const; - std::vector getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool take_hidden = false, bool take_insensitive = false, bool into_groups = false, bool into_filtered_groups = true, bool with_groups = false) const; + std::vector getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive = false, bool into_groups = false) const; + std::vector getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool take_insensitive = false, bool into_groups = false) const; SPItem *getItemAtPoint(unsigned int key, Geom::Point const &p, bool into_groups, SPItem *upto = nullptr) const; std::vector getItemsAtPoints(unsigned const key, std::vector points, bool all_layers = true, size_t limit = 0) const ; SPItem *getGroupAtPoint(unsigned int key, Geom::Point const &p) const; diff --git a/src/ui/contextmenu.cpp b/src/ui/contextmenu.cpp index 4ce30406bd..a3e9e9e78f 100644 --- a/src/ui/contextmenu.cpp +++ b/src/ui/contextmenu.cpp @@ -81,7 +81,7 @@ ContextMenu::ContextMenu(SPDesktop *desktop, SPItem *item) : AddSeparator(); /* Lock/Unock Hide/Unhide*/ Geom::Rect b(_desktop->point(),_desktop->point() + Geom::Point(1,1)); - std::vector< SPItem * > down_items = _desktop->getDocument()->getItemsPartiallyInBox( _desktop->dkey, b, true, true, true, true); + std::vector< SPItem * > down_items = _desktop->getDocument()->getItemsPartiallyInBox( _desktop->dkey, b, true, true); bool has_down_hidden = false; bool has_down_locked = false; for(std::vector< SPItem * >::iterator down = down_items.begin(); down != down_items.end(); ++down){ diff --git a/src/ui/tools/measure-tool.cpp b/src/ui/tools/measure-tool.cpp index 80ba90398e..7dce42d219 100644 --- a/src/ui/tools/measure-tool.cpp +++ b/src/ui/tools/measure-tool.cpp @@ -847,11 +847,7 @@ void MeasureTool::toMarkDimension() totallengthval = Inkscape::Util::Quantity::convert(totallengthval, "px", unit_name); double scale = prefs->getDouble("/tools/measure/scale", 100.0) / 100.0; gchar *totallength_str = g_strdup_printf(precision_str.str().c_str(), totallengthval * scale, unit_name.c_str()); - double textangle = Geom::rad_from_deg(180) - ray.angle(); - if (desktop->is_yaxisdown()) { - textangle = ray.angle() - Geom::rad_from_deg(180); - } - setLabelText(totallength_str, middle, fontsize, textangle, color); + setLabelText(totallength_str, middle, fontsize, Geom::rad_from_deg(180) - ray.angle(), color); g_free(totallength_str); doc->ensureUpToDate(); DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MEASURE,_("Add global measure line")); @@ -1300,7 +1296,7 @@ void MeasureTool::showCanvasItems(bool to_guides, bool to_item, bool to_phantom, std::vector items; SPDocument *doc = desktop->getDocument(); Geom::Rect rect(start_p, end_p); - items = doc->getItemsPartiallyInBox(desktop->dkey, rect, false, false, true, true); + items = doc->getItemsPartiallyInBox(desktop->dkey, rect, false, true); Inkscape::LayerModel *layer_model = nullptr; SPObject *current_layer = nullptr; if(desktop){ -- GitLab From 3bac2312ec7d91b34dded222f3e51eaa89e2ee00 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Sat, 3 Nov 2018 23:39:09 +0100 Subject: [PATCH 19/20] cleanup branch --- src/display/drawing-item.cpp | 2 ++ src/display/drawing-surface.cpp | 4 ++-- src/ui/tools/measure-tool.cpp | 6 +++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp index 3ba4f49aca..f83d0eaeb9 100644 --- a/src/display/drawing-item.cpp +++ b/src/display/drawing-item.cpp @@ -704,6 +704,7 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag if (_filter && render_filters) { carea = cl; } + // Device scale for HiDPI screens (typically 1 or 2) int device_scale = dc.surface()->device_scale(); @@ -729,6 +730,7 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag if (_cache) { _cache->prepare(); set_cairo_blend_operator( dc, _mix_blend_mode ); + _cache->paintFromCache(dc, carea); if (!carea) return RENDER_OK; } else { diff --git a/src/display/drawing-surface.cpp b/src/display/drawing-surface.cpp index bcbc269932..0616410153 100644 --- a/src/display/drawing-surface.cpp +++ b/src/display/drawing-surface.cpp @@ -240,7 +240,7 @@ DrawingCache::prepare() Geom::IntRect old_area = pixelArea(); bool is_identity = _pending_transform.isIdentity(); if (is_identity && _pending_area == old_area) return; // no change - + bool is_integer_translation = is_identity; if (!is_identity && _pending_transform.isTranslation()) { Geom::IntPoint t = _pending_transform.translation().round(); @@ -289,7 +289,7 @@ DrawingCache::prepare() //std::cout << _pending_transform << old_area << _pending_area << std::endl; cairo_surface_destroy(old_surface); - _pending_transform.setIdentity(); + _pending_transform.setIdentity(); } /** diff --git a/src/ui/tools/measure-tool.cpp b/src/ui/tools/measure-tool.cpp index 7dce42d219..3863d99d2e 100644 --- a/src/ui/tools/measure-tool.cpp +++ b/src/ui/tools/measure-tool.cpp @@ -847,7 +847,11 @@ void MeasureTool::toMarkDimension() totallengthval = Inkscape::Util::Quantity::convert(totallengthval, "px", unit_name); double scale = prefs->getDouble("/tools/measure/scale", 100.0) / 100.0; gchar *totallength_str = g_strdup_printf(precision_str.str().c_str(), totallengthval * scale, unit_name.c_str()); - setLabelText(totallength_str, middle, fontsize, Geom::rad_from_deg(180) - ray.angle(), color); + double textangle = Geom::rad_from_deg(180) - ray.angle(); + if (desktop->is_yaxisdown()) { + textangle = ray.angle() - Geom::rad_from_deg(180); + } + setLabelText(totallength_str, middle, fontsize, textangle, color); g_free(totallength_str); doc->ensureUpToDate(); DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MEASURE,_("Add global measure line")); -- GitLab From 727d394da45461754365baea4eadc0777484826c Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Mon, 5 Nov 2018 22:51:27 +0100 Subject: [PATCH 20/20] Remove helper lines --- src/display/sp-canvas.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 186196f5e0..bc22f1a5a0 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -1600,17 +1600,6 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect } // cairo_surface_write_to_png( imgs, "debug2.png" ); - // Start of visible tile rendering comment for hide X tiles - cairo_set_operator(buf.ct, CAIRO_OPERATOR_OVER); - cairo_set_source_rgb (buf.ct, 0, 0, 0); - cairo_move_to (buf.ct, 0, 0); - cairo_line_to (buf.ct, paint_rect.width() * _device_scale, paint_rect.height() * _device_scale); - cairo_move_to (buf.ct, paint_rect.width() * _device_scale, 0); - cairo_line_to (buf.ct, 0, paint_rect.height() * _device_scale); - cairo_set_line_width (buf.ct, 1); - cairo_stroke (buf.ct); - // End - // output to X cairo_destroy(buf.ct); -- GitLab