diff options
Diffstat (limited to 'src/display')
| -rw-r--r-- | src/display/cairo-utils.cpp | 123 | ||||
| -rw-r--r-- | src/display/cairo-utils.h | 3 | ||||
| -rw-r--r-- | src/display/drawing-context.h | 1 | ||||
| -rw-r--r-- | src/display/drawing-group.cpp | 82 | ||||
| -rw-r--r-- | src/display/drawing-item.cpp | 88 | ||||
| -rw-r--r-- | src/display/drawing-item.h | 6 | ||||
| -rw-r--r-- | src/display/sp-canvas.cpp | 2 |
7 files changed, 209 insertions, 96 deletions
diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp index d3ca85f7e..f560b9f19 100644 --- a/src/display/cairo-utils.cpp +++ b/src/display/cairo-utils.cpp @@ -1252,6 +1252,129 @@ private: /* None */ }; +unsigned ink_cairo_operator_to_css_blend(cairo_operator_t cairo_operator) +{ + // All of the blend modes are implemented in Cairo as of 1.10. + // For a detailed description, see: + // http://cairographics.org/operators/ + unsigned res = SP_CSS_BLEND_NORMAL; + switch (cairo_operator) { + case CAIRO_OPERATOR_MULTIPLY: + res = SP_CSS_BLEND_MULTIPLY; + break; + case CAIRO_OPERATOR_SCREEN: + res = SP_CSS_BLEND_SCREEN; + break; + case CAIRO_OPERATOR_DARKEN: + res = SP_CSS_BLEND_DARKEN; + break; + case CAIRO_OPERATOR_LIGHTEN: + res = SP_CSS_BLEND_LIGHTEN; + break; + case CAIRO_OPERATOR_OVERLAY: + res = SP_CSS_BLEND_OVERLAY; + break; + case CAIRO_OPERATOR_COLOR_DODGE: + res = SP_CSS_BLEND_COLORDODGE; + break; + case CAIRO_OPERATOR_COLOR_BURN: + res = SP_CSS_BLEND_COLORBURN; + break; + case CAIRO_OPERATOR_HARD_LIGHT: + res = SP_CSS_BLEND_HARDLIGHT; + break; + case CAIRO_OPERATOR_SOFT_LIGHT: + res = SP_CSS_BLEND_SOFTLIGHT; + break; + case CAIRO_OPERATOR_DIFFERENCE: + res = SP_CSS_BLEND_DIFFERENCE; + break; + case CAIRO_OPERATOR_EXCLUSION: + res = SP_CSS_BLEND_EXCLUSION; + break; + case CAIRO_OPERATOR_HSL_HUE: + res = SP_CSS_BLEND_HUE; + break; + case CAIRO_OPERATOR_HSL_SATURATION: + res = SP_CSS_BLEND_SATURATION; + break; + case CAIRO_OPERATOR_HSL_COLOR: + res = SP_CSS_BLEND_COLOR; + break; + case CAIRO_OPERATOR_HSL_LUMINOSITY: + res = SP_CSS_BLEND_LUMINOSITY; + break; + case CAIRO_OPERATOR_OVER: + default: + res = SP_CSS_BLEND_NORMAL; + break; + } + return res; +} + +cairo_operator_t ink_css_blend_to_cairo_operator(unsigned css_blend) +{ + // All of the blend modes are implemented in Cairo as of 1.10. + // For a detailed description, see: + // http://cairographics.org/operators/ + + cairo_operator_t res = CAIRO_OPERATOR_OVER; + switch (css_blend) { + case SP_CSS_BLEND_MULTIPLY: + res = CAIRO_OPERATOR_MULTIPLY; + break; + case SP_CSS_BLEND_SCREEN: + res = CAIRO_OPERATOR_SCREEN; + break; + case SP_CSS_BLEND_DARKEN: + res = CAIRO_OPERATOR_DARKEN; + break; + case SP_CSS_BLEND_LIGHTEN: + res = CAIRO_OPERATOR_LIGHTEN; + break; + case SP_CSS_BLEND_OVERLAY: + res = CAIRO_OPERATOR_OVERLAY; + break; + case SP_CSS_BLEND_COLORDODGE: + res = CAIRO_OPERATOR_COLOR_DODGE; + break; + case SP_CSS_BLEND_COLORBURN: + res = CAIRO_OPERATOR_COLOR_BURN; + break; + case SP_CSS_BLEND_HARDLIGHT: + res = CAIRO_OPERATOR_HARD_LIGHT; + break; + case SP_CSS_BLEND_SOFTLIGHT: + res = CAIRO_OPERATOR_SOFT_LIGHT; + break; + case SP_CSS_BLEND_DIFFERENCE: + res = CAIRO_OPERATOR_DIFFERENCE; + break; + case SP_CSS_BLEND_EXCLUSION: + res = CAIRO_OPERATOR_EXCLUSION; + break; + case SP_CSS_BLEND_HUE: + res = CAIRO_OPERATOR_HSL_HUE; + break; + case SP_CSS_BLEND_SATURATION: + res = CAIRO_OPERATOR_HSL_SATURATION; + break; + case SP_CSS_BLEND_COLOR: + res = CAIRO_OPERATOR_HSL_COLOR; + break; + case SP_CSS_BLEND_LUMINOSITY: + res = CAIRO_OPERATOR_HSL_LUMINOSITY; + break; + case SP_CSS_BLEND_NORMAL: + default: + res = CAIRO_OPERATOR_OVER; + break; + } + return res; +} + + + int ink_cairo_surface_linear_to_srgb(cairo_surface_t *surface) { cairo_surface_flush(surface); diff --git a/src/display/cairo-utils.h b/src/display/cairo-utils.h index fbcee5413..36800f699 100644 --- a/src/display/cairo-utils.h +++ b/src/display/cairo-utils.h @@ -156,7 +156,8 @@ void ink_cairo_pattern_set_matrix(cairo_pattern_t *cp, Geom::Affine const &m); void ink_matrix_to_2geom(Geom::Affine &, cairo_matrix_t const &); void ink_matrix_to_cairo(cairo_matrix_t &, Geom::Affine const &); - +cairo_operator_t ink_css_blend_to_cairo_operator(unsigned blend_mode); +unsigned ink_cairo_operator_to_css_blend(cairo_operator_t cairo_operator); cairo_surface_t *ink_cairo_surface_copy(cairo_surface_t *s); cairo_surface_t *ink_cairo_surface_create_identical(cairo_surface_t *s); cairo_surface_t *ink_cairo_surface_create_same_size(cairo_surface_t *s, cairo_content_t c); diff --git a/src/display/drawing-context.h b/src/display/drawing-context.h index 1095fa1a3..aedb87ea2 100644 --- a/src/display/drawing-context.h +++ b/src/display/drawing-context.h @@ -101,6 +101,7 @@ public: void setMiterLimit(double miter) { cairo_set_miter_limit(_ct, miter); } void setFillRule(cairo_fill_rule_t rule) { cairo_set_fill_rule(_ct, rule); } void setOperator(cairo_operator_t op) { cairo_set_operator(_ct, op); } + cairo_operator_t getOperator() { return cairo_get_operator(_ct); } void setTolerance(double tol) { cairo_set_tolerance(_ct, tol); } void setSource(cairo_pattern_t *source) { cairo_set_source(_ct, source); } void setSource(cairo_surface_t *surface, double x, double y) { diff --git a/src/display/drawing-group.cpp b/src/display/drawing-group.cpp index 0d6a2edfc..4fe84d7eb 100644 --- a/src/display/drawing-group.cpp +++ b/src/display/drawing-group.cpp @@ -10,10 +10,13 @@ * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ -#include "display/drawing.h" -#include "display/drawing-item.h" #include "display/drawing-group.h" - +#include "display/cairo-utils.h" +#include "display/drawing-context.h" +#include "display/drawing-item.h" +#include "display/drawing-surface.h" +#include "display/drawing.h" +#include "style.h" namespace Inkscape { @@ -90,29 +93,70 @@ DrawingGroup::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, u unsigned DrawingGroup::_renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigned flags, DrawingItem *stop_at) { - if (stop_at == nullptr) { - // normal rendering - for (auto & i : _children) { - i.setAntialiasing(_antialias); - i.render(dc, area, flags, stop_at); + if (!parent() || (_isolation == SP_CSS_ISOLATION_ISOLATE && !_mix_blend_mode)) { + int device_scale = dc.surface()->device_scale(); + DrawingSurface intermediate(area, device_scale); + DrawingContext ict(intermediate); + ict.setOperator(CAIRO_OPERATOR_OVER); + if (parent()) { + flags = flags | RENDER_FILTER_BACKGROUND; } - } else { - // background rendering - for (auto & i : _children) { - if (&i == stop_at) return RENDER_OK; // do not render the stop_at item at all - if (i.isAncestorOf(stop_at)) { - // render its ancestors without masks, opacity or filters + if (stop_at == nullptr) { + // normal rendering + for (auto &i : _children) { i.setAntialiasing(_antialias); - i.render(dc, area, flags | RENDER_FILTER_BACKGROUND, stop_at); - // stop further rendering - return RENDER_OK; - } else { + i.render(ict, area, flags, stop_at); + } + } else { + // background rendering + for (auto &i : _children) { + if (&i == stop_at) + return RENDER_OK; // do not render the stop_at item at all + if (i.isAncestorOf(stop_at)) { + // render its ancestors without masks, opacity or filters + i.setAntialiasing(_antialias); + i.render(ict, area, flags | RENDER_FILTER_BACKGROUND, stop_at); + break; + } else { + i.setAntialiasing(_antialias); + i.render(ict, area, flags, stop_at); + } + } + } + dc.rectangle(area); + dc.setSource(&intermediate); + dc.setOperator(CAIRO_OPERATOR_OVER); + dc.fill(); + return RENDER_OK; + } else { + /* cairo_operator_t current_op = CAIRO_OPERATOR_OVER; + if (parent()->_isolation == SP_CSS_ISOLATION_ISOLATE && !parent()->_mix_blend_mode) { + dc.setOperator(CAIRO_OPERATOR_OVER); + } */ + if (stop_at == nullptr) { + // normal rendering + for (auto &i : _children) { i.setAntialiasing(_antialias); i.render(dc, area, flags, stop_at); } + } else { + // background rendering + for (auto &i : _children) { + if (&i == stop_at) + return RENDER_OK; // do not render the stop_at item at all + if (i.isAncestorOf(stop_at)) { + // render its ancestors without masks, opacity or filters + i.setAntialiasing(_antialias); + i.render(dc, area, flags | RENDER_FILTER_BACKGROUND, stop_at); + break; + } else { + i.setAntialiasing(_antialias); + i.render(dc, area, flags, stop_at); + } + } } + return RENDER_OK; } - return RENDER_OK; } void diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp index 81d01846e..52939e301 100644 --- a/src/display/drawing-item.cpp +++ b/src/display/drawing-item.cpp @@ -28,65 +28,6 @@ #include "object/sp-item.h" namespace Inkscape { - -void set_cairo_blend_operator( DrawingContext &dc, unsigned blend_mode ) { - - // All of the blend modes are implemented in Cairo as of 1.10. - // For a detailed description, see: - // http://cairographics.org/operators/ - switch (blend_mode) { - case SP_CSS_BLEND_MULTIPLY: - dc.setOperator(CAIRO_OPERATOR_MULTIPLY); - break; - case SP_CSS_BLEND_SCREEN: - dc.setOperator(CAIRO_OPERATOR_SCREEN); - break; - case SP_CSS_BLEND_DARKEN: - dc.setOperator(CAIRO_OPERATOR_DARKEN); - break; - case SP_CSS_BLEND_LIGHTEN: - dc.setOperator(CAIRO_OPERATOR_LIGHTEN); - break; - case SP_CSS_BLEND_OVERLAY: - dc.setOperator(CAIRO_OPERATOR_OVERLAY); - break; - case SP_CSS_BLEND_COLORDODGE: - dc.setOperator(CAIRO_OPERATOR_COLOR_DODGE); - break; - case SP_CSS_BLEND_COLORBURN: - dc.setOperator(CAIRO_OPERATOR_COLOR_BURN); - break; - case SP_CSS_BLEND_HARDLIGHT: - dc.setOperator(CAIRO_OPERATOR_HARD_LIGHT); - break; - case SP_CSS_BLEND_SOFTLIGHT: - dc.setOperator(CAIRO_OPERATOR_SOFT_LIGHT); - break; - case SP_CSS_BLEND_DIFFERENCE: - dc.setOperator(CAIRO_OPERATOR_DIFFERENCE); - break; - case SP_CSS_BLEND_EXCLUSION: - dc.setOperator(CAIRO_OPERATOR_EXCLUSION); - break; - case SP_CSS_BLEND_HUE: - dc.setOperator(CAIRO_OPERATOR_HSL_HUE); - break; - case SP_CSS_BLEND_SATURATION: - dc.setOperator(CAIRO_OPERATOR_HSL_SATURATION); - break; - case SP_CSS_BLEND_COLOR: - dc.setOperator(CAIRO_OPERATOR_HSL_COLOR); - break; - case SP_CSS_BLEND_LUMINOSITY: - dc.setOperator(CAIRO_OPERATOR_HSL_LUMINOSITY); - break; - case SP_CSS_BLEND_NORMAL: - default: - dc.setOperator(CAIRO_OPERATOR_OVER); - break; - } -} - /** * @class DrawingItem * SVG drawing item for display. @@ -629,7 +570,6 @@ DrawingItem::update(Geom::IntRect const &area, UpdateContext const &ctx, unsigne } } } - if (to_update & STATE_CACHE) { // Update cache score for this item if (_has_cache_iterator) { @@ -773,8 +713,7 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag if (_cached && !(flags & RENDER_BYPASS_CACHE)) { if (_cache) { _cache->prepare(); - set_cairo_blend_operator( dc, _mix_blend_mode ); - + dc.setOperator(ink_css_blend_to_cairo_operator(_mix_blend_mode)); _cache->paintFromCache(dc, carea); if (!carea) { return RENDER_OK; @@ -798,13 +737,13 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag bool needs_opacity = (_opacity < 0.995); // this item needs an intermediate rendering if: - nir |= (_clip != nullptr); // 1. it has a clipping path - nir |= (_mask != nullptr); // 2. it has a mask - nir |= (_filter != nullptr && render_filters); // 3. it has a filter - nir |= needs_opacity; // 4. it is non-opaque - nir |= (_cache != nullptr); // 5. it is to be cached - nir |= (_mix_blend_mode != SP_CSS_BLEND_NORMAL); // 6. Blend mode not normal - nir |= (_isolation == SP_CSS_ISOLATION_ISOLATE); // 7. Explicit isolatiom + nir |= (_clip != nullptr); // 1. it has a clipping path + nir |= (_mask != nullptr); // 2. it has a mask + nir |= (_filter != nullptr && render_filters); // 3. it has a filter + nir |= needs_opacity; // 4. it is non-opaque + nir |= (_cache != nullptr); // 5. it is to be cached + nir |= (_mix_blend_mode != SP_CSS_BLEND_NORMAL); // 6. Blend mode not normal + // Isolation is handled by the drawing-group /* How the rendering is done. * @@ -817,12 +756,12 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag * the entire intermediate surface is painted with alpha corresponding * to the opacity value. */ - // Short-circuit the simple case. // We also use this path for filter background rendering, because masking, clipping, // filters and opacity do not apply when rendering the ancestors of the filtered // element if ((flags & RENDER_FILTER_BACKGROUND) || !needs_intermediate_rendering) { + dc.setOperator(ink_css_blend_to_cairo_operator(_mix_blend_mode)); return _renderItem(dc, *carea, flags & ~RENDER_FILTER_BACKGROUND, stop_at); } @@ -925,11 +864,16 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag cachect.fill(); _cache->markClean(*carea); } + dc.rectangle(*carea); dc.setSource(&intermediate); - set_cairo_blend_operator( dc, _mix_blend_mode ); + // 7. Render blend mode + dc.setOperator(ink_css_blend_to_cairo_operator(_mix_blend_mode)); dc.fill(); dc.setSource(0,0,0,0); + // Web isolation only works if parent doesnt have transform + + // the call above is to clear a ref on the intermediate surface held by dc return render_result; @@ -1115,7 +1059,7 @@ DrawingItem::_markForRendering() bkg_root = i; } } - + if (bkg_root) { bkg_root->_invalidateFilterBackground(*dirty); } diff --git a/src/display/drawing-item.h b/src/display/drawing-item.h index f0107cdc7..809d6ae72 100644 --- a/src/display/drawing-item.h +++ b/src/display/drawing-item.h @@ -94,6 +94,9 @@ public: DrawingItem(Drawing &drawing); virtual ~DrawingItem(); + unsigned _isolation : 1; + unsigned _mix_blend_mode : 4; + Geom::OptIntRect geometricBounds() const { return _bbox; } Geom::OptIntRect visualBounds() const { return _drawbox; } Geom::OptRect itemBounds() const { return _item_bbox; } @@ -227,9 +230,6 @@ protected: /// otherwise the group is returned unsigned _antialias : 2; ///< antialiasing level (NONE/FAST/GOOD(DEFAULT)/BEST) - unsigned _isolation : 1; - unsigned _mix_blend_mode : 4; - friend class Drawing; }; diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index b33dd20b6..216c8437f 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -1838,7 +1838,6 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect cairo_surface_set_device_scale(imgs, _device_scale, _device_scale); buf.ct = cairo_create(imgs); - cairo_save(buf.ct); cairo_translate(buf.ct, -paint_rect.left(), -paint_rect.top()); cairo_set_source(buf.ct, _background); @@ -1850,6 +1849,7 @@ void SPCanvas::paintSingleBuffer(Geom::IntRect const &paint_rect, Geom::IntRect if (_root->visible) { SP_CANVAS_ITEM_GET_CLASS(_root)->render(_root, &buf); } + // cairo_surface_write_to_png( imgs, "debug2.png" ); // output to X |
