From 328fad57dbfb65e3bd31062021d5cc3081e68515 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Fri, 22 Jul 2011 04:09:27 +0200 Subject: Replace direct use of Cairo contexts and surfaces in the rendering tree with wrappers which keep some extra information about the surface, amd NRRect and NRRectL use with Geom::Rect and Geom::IntRect. Should simplify implementing filter primitive subregions. (bzr r10347.1.17) --- src/display/drawing-surface.cpp | 149 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 src/display/drawing-surface.cpp (limited to 'src/display/drawing-surface.cpp') diff --git a/src/display/drawing-surface.cpp b/src/display/drawing-surface.cpp new file mode 100644 index 000000000..e50a732c6 --- /dev/null +++ b/src/display/drawing-surface.cpp @@ -0,0 +1,149 @@ +/** + * @file + * @brief Cairo surface that remembers its origin + *//* + * Authors: + * Krzysztof KosiƄski + * + * Copyright (C) 2011 Authors + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "display/drawing-surface.h" +#include "display/cairo-utils.h" + +namespace Inkscape { + +using Geom::X; +using Geom::Y; + + +/** @class DrawingSurface + * @brief Drawing surface that remembers its origin. + * + * This is a very minimalistic wrapper over cairo_surface_t. The main + * extra functionality provided by this class is that it automates + * the mapping from "logical space" (coordinates in the rendering) + * and the "physical space" (surface pixels). For example, patterns + * have to be rendered on surfaces which have possibly non-integer + * widths and heights. + */ + +/** @brief Creates a surface with the given physical extents. + * When a drawing context is created for this surface, its pixels + * will cover the area under the given rectangle. */ +DrawingSurface::DrawingSurface(Geom::IntRect const &area) + : _surface(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, area.width(), area.height())) + , _origin(area.min()) + , _scale(1, 1) +{} + +/** @brief Creates a surface with the given logical extents. + * When a drawing context is created for this surface, its pixels + * will cover the area under the given rectangle. If the rectangle + * has non-integer width, there will be slightly more than 1 pixel + * per logical unit. */ +DrawingSurface::DrawingSurface(Geom::Rect const &area) + : _surface(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, ceil(area.width()), ceil(area.height()))) + , _origin(area.min()) + , _scale(ceil(area.width()) / area.width(), ceil(area.height()) / area.height()) +{} + +/** @brief Creates a surface with the given logical and physical extents. + * When a drawing context is created for this surface, its pixels + * will cover the area under the given rectangle. IT will contain + * the number of pixels specified by the second argument. + * @param logbox Logical extents of the surface + * @param pixdims Pixel dimensions of the surface. */ +DrawingSurface::DrawingSurface(Geom::Rect const &logbox, Geom::IntPoint const &pixdims) + : _surface(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, pixdims[X], pixdims[Y])) + , _origin(logbox.min()) + , _scale(pixdims[X] / logbox.width(), pixdims[Y] / logbox.height()) +{} + +/** @brief Wrap a cairo_surface_t. + * This constructor will take an extra reference on @a surface, which will + * be released on destruction. */ +DrawingSurface::DrawingSurface(cairo_surface_t *surface, Geom::Point const &origin) + : _surface(surface) + , _origin(origin) + , _scale(1, 1) +{ + cairo_surface_reference(surface); +} + +DrawingSurface::~DrawingSurface() +{ + cairo_surface_destroy(_surface); +} + +/// Get the logical extents of the surface. +Geom::Rect +DrawingSurface::area() const +{ + Geom::Rect r = Geom::Rect::from_xywh(_origin, dimensions()); + return r; +} + +/// Get the logical width and weight of the surface as a point. +Geom::Point +DrawingSurface::dimensions() const +{ + double w = cairo_image_surface_get_width(_surface); + double h = cairo_image_surface_get_height(_surface); + Geom::Point logical_dims(w / _scale[X], h / _scale[Y]); + return logical_dims; +} + +Geom::Point +DrawingSurface::origin() const +{ + return _origin; +} + +Geom::Scale +DrawingSurface::scale() const +{ + return _scale; +} + +/// Get the transformation applied to the drawing context on construction. +Geom::Affine +DrawingSurface::drawingTransform() const +{ + Geom::Affine ret = _scale * Geom::Translate(-_origin); + return ret; +} + +cairo_surface_type_t +DrawingSurface::type() const +{ + // currently hardcoded + return CAIRO_SURFACE_TYPE_IMAGE; +} + +/** @brief Create a drawing context for this surface. + * It's better to use the surface constructor of DrawingContext. */ +cairo_t * +DrawingSurface::createRawContext() +{ + cairo_t *ct = cairo_create(_surface); + if (_scale != Geom::Scale::identity()) { + cairo_scale(ct, _scale[X], _scale[Y]); + } + cairo_translate(ct, -_origin[X], -_origin[Y]); + return ct; +} + +} // end namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : -- cgit v1.2.3 From c1ad04d91b5cac237f184c3c6943ab520dd21cf7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Tue, 26 Jul 2011 00:03:48 +0200 Subject: Add deferred allocation functionality to DrawingSurface (bzr r10347.1.19) --- src/display/drawing-surface.cpp | 45 +++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 8 deletions(-) (limited to 'src/display/drawing-surface.cpp') diff --git a/src/display/drawing-surface.cpp b/src/display/drawing-surface.cpp index e50a732c6..41ff14167 100644 --- a/src/display/drawing-surface.cpp +++ b/src/display/drawing-surface.cpp @@ -25,17 +25,22 @@ using Geom::Y; * extra functionality provided by this class is that it automates * the mapping from "logical space" (coordinates in the rendering) * and the "physical space" (surface pixels). For example, patterns - * have to be rendered on surfaces which have possibly non-integer + * have to be rendered on tiles which have possibly non-integer * widths and heights. + * + * This class has delayed allocation functionality - it creates + * the Cairo surface it wraps on the first call to createRawContext() + * of when a DrawingContext is constructed. */ /** @brief Creates a surface with the given physical extents. * When a drawing context is created for this surface, its pixels * will cover the area under the given rectangle. */ DrawingSurface::DrawingSurface(Geom::IntRect const &area) - : _surface(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, area.width(), area.height())) + : _surface(NULL) , _origin(area.min()) , _scale(1, 1) + , _pixels(area.dimensions()) {} /** @brief Creates a surface with the given logical extents. @@ -44,9 +49,10 @@ DrawingSurface::DrawingSurface(Geom::IntRect const &area) * has non-integer width, there will be slightly more than 1 pixel * per logical unit. */ DrawingSurface::DrawingSurface(Geom::Rect const &area) - : _surface(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, ceil(area.width()), ceil(area.height()))) + : _surface(NULL) , _origin(area.min()) , _scale(ceil(area.width()) / area.width(), ceil(area.height()) / area.height()) + , _pixels(area.dimensions().ceil()) {} /** @brief Creates a surface with the given logical and physical extents. @@ -56,9 +62,10 @@ DrawingSurface::DrawingSurface(Geom::Rect const &area) * @param logbox Logical extents of the surface * @param pixdims Pixel dimensions of the surface. */ DrawingSurface::DrawingSurface(Geom::Rect const &logbox, Geom::IntPoint const &pixdims) - : _surface(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, pixdims[X], pixdims[Y])) + : _surface(NULL) , _origin(logbox.min()) , _scale(pixdims[X] / logbox.width(), pixdims[Y] / logbox.height()) + , _pixels(pixdims) {} /** @brief Wrap a cairo_surface_t. @@ -70,11 +77,14 @@ DrawingSurface::DrawingSurface(cairo_surface_t *surface, Geom::Point const &orig , _scale(1, 1) { cairo_surface_reference(surface); + _pixels[X] = cairo_image_surface_get_width(surface); + _pixels[Y] = cairo_image_surface_get_height(surface); } DrawingSurface::~DrawingSurface() { - cairo_surface_destroy(_surface); + if (_surface) + cairo_surface_destroy(_surface); } /// Get the logical extents of the surface. @@ -85,13 +95,18 @@ DrawingSurface::area() const return r; } +/// Get the pixel dimensions of the surface +Geom::IntPoint +DrawingSurface::pixels() const +{ + return _pixels; +} + /// Get the logical width and weight of the surface as a point. Geom::Point DrawingSurface::dimensions() const { - double w = cairo_image_surface_get_width(_surface); - double h = cairo_image_surface_get_height(_surface); - Geom::Point logical_dims(w / _scale[X], h / _scale[Y]); + Geom::Point logical_dims(_pixels[X] / _scale[X], _pixels[Y] / _scale[Y]); return logical_dims; } @@ -122,11 +137,25 @@ DrawingSurface::type() const return CAIRO_SURFACE_TYPE_IMAGE; } +/// Drop contents of the surface and release the underlying Cairo object. +void +DrawingSurface::dropContents() +{ + if (_surface) { + cairo_surface_destroy(_surface); + _surface = NULL; + } +} + /** @brief Create a drawing context for this surface. * It's better to use the surface constructor of DrawingContext. */ cairo_t * DrawingSurface::createRawContext() { + // deferred allocation + if (!_surface) { + _surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, _pixels[X], _pixels[Y]); + } cairo_t *ct = cairo_create(_surface); if (_scale != Geom::Scale::identity()) { cairo_scale(ct, _scale[X], _scale[Y]); -- cgit v1.2.3 From 905b8a96963f78358abfd109c0c49758c6fe4e9d Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Thu, 28 Jul 2011 07:04:08 +0200 Subject: Per-item render cache. Cache some offscreen data to facilitate smoother navigation. (bzr r10347.1.20) --- src/display/drawing-surface.cpp | 137 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 125 insertions(+), 12 deletions(-) (limited to 'src/display/drawing-surface.cpp') diff --git a/src/display/drawing-surface.cpp b/src/display/drawing-surface.cpp index 41ff14167..28bdc1f3c 100644 --- a/src/display/drawing-surface.cpp +++ b/src/display/drawing-surface.cpp @@ -10,6 +10,7 @@ */ #include "display/drawing-surface.h" +#include "display/drawing-context.h" #include "display/cairo-utils.h" namespace Inkscape { @@ -43,18 +44,6 @@ DrawingSurface::DrawingSurface(Geom::IntRect const &area) , _pixels(area.dimensions()) {} -/** @brief Creates a surface with the given logical extents. - * When a drawing context is created for this surface, its pixels - * will cover the area under the given rectangle. If the rectangle - * has non-integer width, there will be slightly more than 1 pixel - * per logical unit. */ -DrawingSurface::DrawingSurface(Geom::Rect const &area) - : _surface(NULL) - , _origin(area.min()) - , _scale(ceil(area.width()) / area.width(), ceil(area.height()) / area.height()) - , _pixels(area.dimensions().ceil()) -{} - /** @brief Creates a surface with the given logical and physical extents. * When a drawing context is created for this surface, its pixels * will cover the area under the given rectangle. IT will contain @@ -164,6 +153,130 @@ DrawingSurface::createRawContext() return ct; } +Geom::IntRect +DrawingSurface::pixelArea() const +{ + Geom::IntRect ret = Geom::IntRect::from_xywh(_origin.round(), _pixels); + return ret; +} + +////////////////////////////////////////////////////////////////////////////// + +DrawingCache::DrawingCache(Geom::IntRect const &area) + : DrawingSurface(area) + , _clean_region(cairo_region_create()) +{} + +DrawingCache::~DrawingCache() +{ + cairo_region_destroy(_clean_region); +} + +void +DrawingCache::markDirty(Geom::IntRect const &area) +{ + cairo_rectangle_int_t dirty = _convertRect(area); + cairo_region_subtract_rectangle(_clean_region, &dirty); +} +void +DrawingCache::markClean(Geom::IntRect const &area) +{ + Geom::OptIntRect r = Geom::intersect(area, pixelArea()); + if (!r) return; + cairo_rectangle_int_t clean = _convertRect(*r); + cairo_region_union_rectangle(_clean_region, &clean); +} +bool +DrawingCache::isClean(Geom::IntRect const &area) const +{ + cairo_rectangle_int_t test = _convertRect(area); + if (cairo_region_contains_rectangle(_clean_region, &test) == CAIRO_REGION_OVERLAP_IN) { + return true; + } else { + return false; + } +} +void +DrawingCache::resizeAndTransform(Geom::IntRect const &new_area, Geom::Affine const &trans) +{ + Geom::IntRect old_area = pixelArea(); + bool is_identity = false; + bool is_integer_translation = false; + if (trans.isIdentity()) { + is_identity = true; + if (new_area == old_area) return; + } + if (!is_identity && trans.isTranslation()) { + Geom::IntPoint t = trans.translation().round(); + if (Geom::are_near(Geom::Point(t), trans.translation())) { + // integer translation or identity with change of area + is_integer_translation = true; + cairo_region_translate(_clean_region, t[X], t[Y]); + if (old_area + t == new_area) { + // if the areas match, the only thing to do + // is to ensure that the clean area is not too large + cairo_rectangle_int_t limit = _convertRect(new_area); + cairo_region_intersect_rectangle(_clean_region, &limit); + _origin += t; + return; + } + } + } + // otherwise, we need to transform the cache + Geom::IntPoint old_origin = old_area.min(); + cairo_surface_t *old_surface = _surface; + _surface = NULL; + _pixels = new_area.dimensions(); + _origin = new_area.min(); + + cairo_t *ct = createRawContext(); + if (!is_identity) { + ink_cairo_transform(ct, trans); + } + cairo_set_source_surface(ct, old_surface, old_origin[X], old_origin[Y]); + cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE); + cairo_paint(ct); + + cairo_surface_destroy(old_surface); + cairo_destroy(ct); + + if (!is_identity && !is_integer_translation) { + // dirty everything + cairo_region_destroy(_clean_region); + _clean_region = cairo_region_create(); + } else { + cairo_rectangle_int_t limit = _convertRect(new_area); + cairo_region_intersect_rectangle(_clean_region, &limit); + } +} + +/** @brief Paints the clean area from cache and returns the remaining part */ +bool +DrawingCache::paintFromCache(DrawingContext &ct, Geom::IntRect const &area) +{ + if (!isClean(area)) + return false; + + Inkscape::DrawingContext::Save save(ct); + ct.rectangle(area); + ct.clip(); + ct.setSource(this); + ct.paint(); + + return true; +} + +cairo_rectangle_int_t +DrawingCache::_convertRect(Geom::IntRect const &area) +{ + cairo_rectangle_int_t ret; + ret.x = area.left(); + ret.y = area.top(); + ret.width = area.width(); + ret.height = area.height(); + return ret; +} + } // end namespace Inkscape /* -- cgit v1.2.3 From f336c94939e9740501835b2584ad9a3160ac6d51 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Tue, 9 Aug 2011 03:14:07 +0200 Subject: Initial autocache work (bzr r10347.1.26) --- src/display/drawing-surface.cpp | 47 ++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 15 deletions(-) (limited to 'src/display/drawing-surface.cpp') diff --git a/src/display/drawing-surface.cpp b/src/display/drawing-surface.cpp index 28bdc1f3c..1faa3151e 100644 --- a/src/display/drawing-surface.cpp +++ b/src/display/drawing-surface.cpp @@ -9,6 +9,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include #include "display/drawing-surface.h" #include "display/drawing-context.h" #include "display/cairo-utils.h" @@ -165,6 +166,7 @@ DrawingSurface::pixelArea() const DrawingCache::DrawingCache(Geom::IntRect const &area) : DrawingSurface(area) , _clean_region(cairo_region_create()) + , _pending_area(area) {} DrawingCache::~DrawingCache() @@ -196,28 +198,41 @@ DrawingCache::isClean(Geom::IntRect const &area) const return false; } } + +/// Call this during the update phase to schedule a transformation of the cache. +void +DrawingCache::scheduleTransform(Geom::IntRect const &new_area, Geom::Affine const &trans) +{ + if (new_area.hasZeroArea() && trans.isIdentity()) return; + _pending_area = new_area; + _pending_transform *= trans; +} + +/// Transforms the cache according to the transform specified during the update phase. +/// Call this during render phase, before painting. void -DrawingCache::resizeAndTransform(Geom::IntRect const &new_area, Geom::Affine const &trans) +DrawingCache::prepare() { Geom::IntRect old_area = pixelArea(); - bool is_identity = false; - bool is_integer_translation = false; - if (trans.isIdentity()) { - is_identity = true; - if (new_area == old_area) return; + bool is_identity = _pending_transform.isIdentity(); + if (is_identity) { + if (_pending_area == old_area) return; } - if (!is_identity && trans.isTranslation()) { - Geom::IntPoint t = trans.translation().round(); - if (Geom::are_near(Geom::Point(t), trans.translation())) { + + bool is_integer_translation = false; + if (!is_identity && _pending_transform.isTranslation()) { + Geom::IntPoint t = _pending_transform.translation().round(); + if (Geom::are_near(Geom::Point(t), _pending_transform.translation())) { // integer translation or identity with change of area is_integer_translation = true; cairo_region_translate(_clean_region, t[X], t[Y]); - if (old_area + t == new_area) { + if (old_area + t == _pending_area) { // if the areas match, the only thing to do // is to ensure that the clean area is not too large - cairo_rectangle_int_t limit = _convertRect(new_area); + cairo_rectangle_int_t limit = _convertRect(_pending_area); cairo_region_intersect_rectangle(_clean_region, &limit); _origin += t; + _pending_transform.setIdentity(); return; } } @@ -226,12 +241,12 @@ DrawingCache::resizeAndTransform(Geom::IntRect const &new_area, Geom::Affine con Geom::IntPoint old_origin = old_area.min(); cairo_surface_t *old_surface = _surface; _surface = NULL; - _pixels = new_area.dimensions(); - _origin = new_area.min(); + _pixels = _pending_area.dimensions(); + _origin = _pending_area.min(); cairo_t *ct = createRawContext(); if (!is_identity) { - ink_cairo_transform(ct, trans); + 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); @@ -245,9 +260,11 @@ DrawingCache::resizeAndTransform(Geom::IntRect const &new_area, Geom::Affine con cairo_region_destroy(_clean_region); _clean_region = cairo_region_create(); } else { - cairo_rectangle_int_t limit = _convertRect(new_area); + cairo_rectangle_int_t limit = _convertRect(_pending_area); cairo_region_intersect_rectangle(_clean_region, &limit); } + std::cout << _pending_transform << old_area << _pending_area << std::endl; + _pending_transform.setIdentity(); } /** @brief Paints the clean area from cache and returns the remaining part */ -- cgit v1.2.3 From 16c067ffe728e848bd555b1607d766ccd4162ac5 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Tue, 9 Aug 2011 06:02:34 +0200 Subject: Turn off debug message spam (bzr r10347.1.27) --- src/display/drawing-surface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/display/drawing-surface.cpp') diff --git a/src/display/drawing-surface.cpp b/src/display/drawing-surface.cpp index 1faa3151e..39a622fe7 100644 --- a/src/display/drawing-surface.cpp +++ b/src/display/drawing-surface.cpp @@ -9,7 +9,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include +//#include #include "display/drawing-surface.h" #include "display/drawing-context.h" #include "display/cairo-utils.h" @@ -263,7 +263,7 @@ DrawingCache::prepare() cairo_rectangle_int_t limit = _convertRect(_pending_area); cairo_region_intersect_rectangle(_clean_region, &limit); } - std::cout << _pending_transform << old_area << _pending_area << std::endl; + //std::cout << _pending_transform << old_area << _pending_area << std::endl; _pending_transform.setIdentity(); } -- cgit v1.2.3 From 74b91362758052e0f03bb819663a4606f08e4c69 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Tue, 9 Aug 2011 07:51:45 +0200 Subject: Use cache even if only part of the redraw region is clean (bzr r10347.1.28) --- src/display/drawing-surface.cpp | 71 ++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 23 deletions(-) (limited to 'src/display/drawing-surface.cpp') diff --git a/src/display/drawing-surface.cpp b/src/display/drawing-surface.cpp index 39a622fe7..43cf50b88 100644 --- a/src/display/drawing-surface.cpp +++ b/src/display/drawing-surface.cpp @@ -188,16 +188,6 @@ DrawingCache::markClean(Geom::IntRect const &area) cairo_rectangle_int_t clean = _convertRect(*r); cairo_region_union_rectangle(_clean_region, &clean); } -bool -DrawingCache::isClean(Geom::IntRect const &area) const -{ - cairo_rectangle_int_t test = _convertRect(area); - if (cairo_region_contains_rectangle(_clean_region, &test) == CAIRO_REGION_OVERLAP_IN) { - return true; - } else { - return false; - } -} /// Call this during the update phase to schedule a transformation of the cache. void @@ -267,20 +257,46 @@ DrawingCache::prepare() _pending_transform.setIdentity(); } -/** @brief Paints the clean area from cache and returns the remaining part */ -bool -DrawingCache::paintFromCache(DrawingContext &ct, Geom::IntRect const &area) +/** @brief Paints the clean area from cache and modifies the @a area + * parameter to the bounds of the region that must be repainted. */ +void +DrawingCache::paintFromCache(DrawingContext &ct, Geom::OptIntRect &area) { - if (!isClean(area)) - return false; - - Inkscape::DrawingContext::Save save(ct); - ct.rectangle(area); - ct.clip(); - ct.setSource(this); - ct.paint(); - - return true; + if (!area) return; + + // We subtract the clean region from the area, then get the bounds + // of the resulting region. This is the area that needs to be repainted + // 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_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); + + if (cairo_region_is_empty(dirty_region)) { + area = Geom::OptIntRect(); + } else { + cairo_rectangle_int_t to_repaint; + cairo_region_get_extents(dirty_region, &to_repaint); + *area = _convertRect(to_repaint); + cairo_region_subtract_rectangle(cache_region, &to_repaint); + } + cairo_region_destroy(dirty_region); + + if (!cairo_region_is_empty(cache_region)) { + Inkscape::DrawingContext::Save save(ct); + int nr = cairo_region_num_rectangles(cache_region); + cairo_rectangle_int_t tmp; + for (int i = 0; i < nr; ++i) { + cairo_region_get_rectangle(cache_region, i, &tmp); + ct.rectangle(_convertRect(tmp)); + } + ct.clip(); + ct.setSource(this); + ct.paint(); + } + cairo_region_destroy(cache_region); } cairo_rectangle_int_t @@ -294,6 +310,15 @@ DrawingCache::_convertRect(Geom::IntRect const &area) return ret; } +Geom::IntRect +DrawingCache::_convertRect(cairo_rectangle_int_t const &r) +{ + Geom::IntRect ret = Geom::IntRect::from_xywh( + r.x, r.y, + r.width, r.height); + return ret; +} + } // end namespace Inkscape /* -- cgit v1.2.3 From 52d06f53a4efef7c6880e34cad9de0c770fc13ad Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Tue, 9 Aug 2011 10:01:41 +0200 Subject: Fix invalidation on scrolling (bzr r10347.1.29) --- src/display/drawing-surface.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src/display/drawing-surface.cpp') diff --git a/src/display/drawing-surface.cpp b/src/display/drawing-surface.cpp index 43cf50b88..e5564f2b3 100644 --- a/src/display/drawing-surface.cpp +++ b/src/display/drawing-surface.cpp @@ -193,7 +193,6 @@ DrawingCache::markClean(Geom::IntRect const &area) void DrawingCache::scheduleTransform(Geom::IntRect const &new_area, Geom::Affine const &trans) { - if (new_area.hasZeroArea() && trans.isIdentity()) return; _pending_area = new_area; _pending_transform *= trans; } @@ -205,15 +204,12 @@ DrawingCache::prepare() { Geom::IntRect old_area = pixelArea(); bool is_identity = _pending_transform.isIdentity(); - if (is_identity) { - if (_pending_area == old_area) return; - } + if (is_identity && _pending_area == old_area) return; // no change bool is_integer_translation = false; if (!is_identity && _pending_transform.isTranslation()) { Geom::IntPoint t = _pending_transform.translation().round(); if (Geom::are_near(Geom::Point(t), _pending_transform.translation())) { - // integer translation or identity with change of area is_integer_translation = true; cairo_region_translate(_clean_region, t[X], t[Y]); if (old_area + t == _pending_area) { -- cgit v1.2.3 From a49c525365ff86ea1e22281d3a3b66d7ef0087c1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Fri, 19 Aug 2011 09:33:48 +0200 Subject: Fix rendering glitches appearing when filtered, cached groups have filtered, cached children (bzr r10347.1.36) --- src/display/drawing-surface.cpp | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) (limited to 'src/display/drawing-surface.cpp') diff --git a/src/display/drawing-surface.cpp b/src/display/drawing-surface.cpp index e5564f2b3..5cbfaa3fe 100644 --- a/src/display/drawing-surface.cpp +++ b/src/display/drawing-surface.cpp @@ -275,26 +275,51 @@ DrawingCache::paintFromCache(DrawingContext &ct, Geom::OptIntRect &area) } else { cairo_rectangle_int_t to_repaint; cairo_region_get_extents(dirty_region, &to_repaint); - *area = _convertRect(to_repaint); + area = _convertRect(to_repaint); cairo_region_subtract_rectangle(cache_region, &to_repaint); } cairo_region_destroy(dirty_region); if (!cairo_region_is_empty(cache_region)) { - Inkscape::DrawingContext::Save save(ct); int nr = cairo_region_num_rectangles(cache_region); cairo_rectangle_int_t tmp; for (int i = 0; i < nr; ++i) { cairo_region_get_rectangle(cache_region, i, &tmp); ct.rectangle(_convertRect(tmp)); } - ct.clip(); ct.setSource(this); - ct.paint(); + ct.fill(); } cairo_region_destroy(cache_region); } +// debugging utility +void +DrawingCache::_dumpCache(Geom::OptIntRect const &area) +{ + static int dumpnr = 0; + cairo_surface_t *surface = ink_cairo_surface_copy(_surface); + DrawingContext ct(surface, _origin); + if (!cairo_region_is_empty(_clean_region)) { + Inkscape::DrawingContext::Save save(ct); + int nr = cairo_region_num_rectangles(_clean_region); + cairo_rectangle_int_t tmp; + for (int i = 0; i < nr; ++i) { + cairo_region_get_rectangle(_clean_region, i, &tmp); + ct.rectangle(_convertRect(tmp)); + } + ct.setSource(0,1,0,0.1); + ct.fill(); + } + ct.rectangle(*area); + ct.setSource(1,0,0,0.1); + ct.fill(); + char *fn = g_strdup_printf("dump%d.png", dumpnr++); + cairo_surface_write_to_png(surface, fn); + cairo_surface_destroy(surface); + g_free(fn); +} + cairo_rectangle_int_t DrawingCache::_convertRect(Geom::IntRect const &area) { -- cgit v1.2.3