summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJabier Arraiza <jabier.arraiza@marker.es>2019-10-19 04:33:22 +0000
committerJabier Arraiza <jabier.arraiza@marker.es>2019-10-19 04:33:22 +0000
commit2d7e690eb6a2add552b84370d56d56ec1b1fbfd4 (patch)
treef5b76e1fbe3e2cf144d24697ce37018bf0401b86
parentUpdate hr.po for Inkscape 1.0 (diff)
downloadinkscape-2d7e690eb6a2add552b84370d56d56ec1b1fbfd4.tar.gz
inkscape-2d7e690eb6a2add552b84370d56d56ec1b1fbfd4.zip
Add export/import PDF blend modes and add isolation modifier
-rw-r--r--src/desktop-style.cpp52
-rw-r--r--src/desktop-style.h1
-rw-r--r--src/display/cairo-utils.cpp123
-rw-r--r--src/display/cairo-utils.h3
-rw-r--r--src/display/drawing-context.h1
-rw-r--r--src/display/drawing-group.cpp82
-rw-r--r--src/display/drawing-item.cpp88
-rw-r--r--src/display/drawing-item.h6
-rw-r--r--src/display/sp-canvas.cpp2
-rw-r--r--src/extension/internal/cairo-render-context.cpp15
-rw-r--r--src/extension/internal/pdfinput/svg-builder.cpp66
-rw-r--r--src/extension/internal/pdfinput/svg-builder.h2
-rw-r--r--src/ui/dialog/fill-and-stroke.cpp1
-rw-r--r--src/ui/dialog/layers.cpp1
-rw-r--r--src/ui/dialog/objects.cpp61
-rw-r--r--src/ui/dialog/objects.h10
-rw-r--r--src/ui/tools/node-tool.cpp5
-rw-r--r--src/ui/tools/select-tool.cpp1
-rw-r--r--src/ui/widget/filter-effect-chooser.cpp50
-rw-r--r--src/ui/widget/filter-effect-chooser.h38
-rw-r--r--src/ui/widget/object-composite-settings.cpp70
-rw-r--r--src/ui/widget/object-composite-settings.h3
22 files changed, 504 insertions, 177 deletions
diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp
index 092c48ec3..160000a78 100644
--- a/src/desktop-style.cpp
+++ b/src/desktop-style.cpp
@@ -1750,6 +1750,54 @@ objects_query_blend (const std::vector<SPItem*> &objects, SPStyle *style_res)
}
}
+int objects_query_isolation(const std::vector<SPItem *> &objects, SPStyle *style_res)
+{
+ const int empty_prev = -2;
+ int isolation = 0;
+ float isolation_prev = empty_prev;
+ bool same_isolation = true;
+ guint items = 0;
+
+ for (auto obj : objects) {
+ if (!obj) {
+ continue;
+ }
+ SPStyle *style = obj->style;
+ if (!style || !dynamic_cast<SPItem *>(obj)) {
+ continue;
+ }
+
+ items++;
+
+ if (style->isolation.set) {
+ isolation = style->isolation.value;
+ }
+ // defaults to blend mode = "normal"
+ else {
+ isolation = 0;
+ }
+
+ if (isolation_prev != empty_prev && isolation_prev != isolation)
+ same_isolation = false;
+ isolation_prev = isolation;
+ }
+
+ if (items > 0) {
+ style_res->isolation.value = isolation;
+ }
+
+ if (items == 0) {
+ return QUERY_STYLE_NOTHING;
+ } else if (items == 1) {
+ return QUERY_STYLE_SINGLE;
+ } else {
+ if (same_isolation)
+ return QUERY_STYLE_MULTIPLE_SAME;
+ else
+ return QUERY_STYLE_MULTIPLE_DIFFERENT;
+ }
+}
+
/**
* Write to style_res the average blurring of a list of objects.
*/
@@ -1873,6 +1921,8 @@ sp_desktop_query_style_from_list (const std::vector<SPItem*> &list, SPStyle *sty
} else if (property == QUERY_STYLE_PROPERTY_BLEND) {
return objects_query_blend (list, style);
+ } else if (property == QUERY_STYLE_PROPERTY_ISOLATION) {
+ return objects_query_isolation(list, style);
} else if (property == QUERY_STYLE_PROPERTY_BLUR) {
return objects_query_blur (list, style);
}
@@ -1924,6 +1974,7 @@ sp_desktop_query_style_all (SPDesktop *desktop, SPStyle *query)
int result_opacity = sp_desktop_query_style (desktop, query, QUERY_STYLE_PROPERTY_MASTEROPACITY);
int result_blur = sp_desktop_query_style (desktop, query, QUERY_STYLE_PROPERTY_BLUR);
int result_blend = sp_desktop_query_style (desktop, query, QUERY_STYLE_PROPERTY_BLEND);
+ int result_isolation = sp_desktop_query_style (desktop, query, QUERY_STYLE_PROPERTY_ISOLATION);
return (result_family != QUERY_STYLE_NOTHING ||
result_fstyle != QUERY_STYLE_NOTHING ||
@@ -1937,6 +1988,7 @@ sp_desktop_query_style_all (SPDesktop *desktop, SPStyle *query)
result_strokejoin != QUERY_STYLE_NOTHING ||
result_paintorder != QUERY_STYLE_NOTHING ||
result_blur != QUERY_STYLE_NOTHING ||
+ result_isolation != QUERY_STYLE_NOTHING ||
result_blend != QUERY_STYLE_NOTHING);
}
diff --git a/src/desktop-style.h b/src/desktop-style.h
index b2e076400..c32bc2447 100644
--- a/src/desktop-style.h
+++ b/src/desktop-style.h
@@ -59,6 +59,7 @@ enum { // which property was queried (add when you need more)
QUERY_STYLE_PROPERTY_BASELINES, // baseline-shift
QUERY_STYLE_PROPERTY_WRITINGMODES, // writing-mode, text-orientation
QUERY_STYLE_PROPERTY_MASTEROPACITY, // opacity
+ QUERY_STYLE_PROPERTY_ISOLATION, // isolation
QUERY_STYLE_PROPERTY_BLEND, // blend
QUERY_STYLE_PROPERTY_BLUR // blur
};
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
diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp
index adc4f1eb5..a1e5b91a8 100644
--- a/src/extension/internal/cairo-render-context.cpp
+++ b/src/extension/internal/cairo-render-context.cpp
@@ -1569,6 +1569,9 @@ CairoRenderContext::renderPathVector(Geom::PathVector const & pathv, SPStyle con
} else {
cairo_set_fill_rule(_cr, CAIRO_FILL_RULE_WINDING);
}
+ if (style->mix_blend_mode.set && style->mix_blend_mode.value) {
+ cairo_set_operator(_cr, ink_css_blend_to_cairo_operator(style->mix_blend_mode.value));
+ }
cairo_fill(_cr);
TEST(cairo_surface_write_to_png (_surface, "pathmask.png"));
}
@@ -1599,6 +1602,10 @@ CairoRenderContext::renderPathVector(Geom::PathVector const & pathv, SPStyle con
}
}
+ if (style->mix_blend_mode.set && style->mix_blend_mode.value) {
+ cairo_set_operator(_cr, ink_css_blend_to_cairo_operator(style->mix_blend_mode.value));
+ }
+
setPathVector(pathv);
if (!no_fill && (order == STROKE_OVER_FILL || order == FILL_ONLY)) {
@@ -1695,6 +1702,10 @@ bool CairoRenderContext::renderImage(Inkscape::Pixbuf *pb,
}
}
+ if (style->mix_blend_mode.set && style->mix_blend_mode.value) {
+ cairo_set_operator(_cr, ink_css_blend_to_cairo_operator(style->mix_blend_mode.value));
+ }
+
cairo_paint(_cr);
cairo_restore(_cr);
@@ -1825,6 +1836,10 @@ CairoRenderContext::renderGlyphtext(PangoFont *font, Geom::Affine const &font_ma
stroke = true;
}
+ if (style->mix_blend_mode.set && style->mix_blend_mode.value) {
+ cairo_set_operator(_cr, (cairo_operator_t)style->mix_blend_mode.value);
+ }
+
// Text never has markers
bool stroke_over_fill = true;
if ( (style->paint_order.layer[0] == SP_CSS_PAINT_ORDER_STROKE &&
diff --git a/src/extension/internal/pdfinput/svg-builder.cpp b/src/extension/internal/pdfinput/svg-builder.cpp
index 9b4b55e21..14727eba5 100644
--- a/src/extension/internal/pdfinput/svg-builder.cpp
+++ b/src/extension/internal/pdfinput/svg-builder.cpp
@@ -409,6 +409,26 @@ void SvgBuilder::_setFillStyle(SPCSSAttr *css, GfxState *state, bool even_odd) {
}
/**
+ * \brief Sets blend style properties from poppler's GfxState data structure
+ * \update a SPCSSAttr with all mix-blend-mode set
+ */
+void SvgBuilder::_setBlendMode(Inkscape::XML::Node *node, GfxState *state)
+{
+ SPCSSAttr *css = sp_repr_css_attr(node, "style");
+ GfxBlendMode blendmode = state->getBlendMode();
+ if (blendmode) {
+ sp_repr_css_set_property(css, "mix-blend-mode", enum_blend_mode[blendmode].key);
+ }
+ Glib::ustring value;
+ sp_repr_css_write_string(css, value);
+ if (value.empty()) {
+ node->setAttribute("style", nullptr);
+ } else {
+ node->setAttribute("style", value.c_str());
+ }
+ sp_repr_css_attr_unref(css);
+}
+/**
* \brief Sets style properties from poppler's GfxState data structure
* \return SPCSSAttr with all the relevant properties set
*/
@@ -447,7 +467,7 @@ void SvgBuilder::addPath(GfxState *state, bool fill, bool stroke, bool even_odd)
SPCSSAttr *css = _setStyle(state, fill, stroke, even_odd);
sp_repr_css_change(path, css, "style");
sp_repr_css_attr_unref(css);
-
+ _setBlendMode(path, state);
_container->appendChild(path);
Inkscape::GC::release(path);
}
@@ -1427,6 +1447,11 @@ void SvgBuilder::addChar(GfxState *state, double x, double y,
bool has_fill = !( render_mode & 1 );
bool has_stroke = ( render_mode & 3 ) == 1 || ( render_mode & 3 ) == 2;
new_glyph.style = _setStyle(state, has_fill, has_stroke);
+ // Find a way to handle blend modes on text
+ /* GfxBlendMode blendmode = state->getBlendMode();
+ if (blendmode) {
+ sp_repr_css_set_property(new_glyph.style, "mix-blend-mode", enum_blend_mode[blendmode].key);
+ } */
new_glyph.render_mode = render_mode;
sp_repr_css_merge(new_glyph.style, _font_style); // Merge with font style
_invalidated_style = false;
@@ -1435,6 +1460,10 @@ void SvgBuilder::addChar(GfxState *state, double x, double y,
// Point to previous glyph's style information
const SvgGlyph& prev_glyph = _glyphs.back();
new_glyph.style = prev_glyph.style;
+ /* GfxBlendMode blendmode = state->getBlendMode();
+ if (blendmode) {
+ sp_repr_css_set_property(new_glyph.style, "mix-blend-mode", enum_blend_mode[blendmode].key);
+ } */
new_glyph.render_mode = prev_glyph.render_mode;
}
new_glyph.font_specification = _font_specification;
@@ -1710,14 +1739,16 @@ Inkscape::XML::Node *SvgBuilder::_createMask(double width, double height) {
}
}
-void SvgBuilder::addImage(GfxState * /*state*/, Stream *str, int width, int height,
- GfxImageColorMap *color_map, bool interpolate, int *mask_colors) {
+void SvgBuilder::addImage(GfxState *state, Stream *str, int width, int height, GfxImageColorMap *color_map,
+ bool interpolate, int *mask_colors)
+{
- Inkscape::XML::Node *image_node = _createImage(str, width, height, color_map, interpolate, mask_colors);
- if (image_node) {
- _container->appendChild(image_node);
+ Inkscape::XML::Node *image_node = _createImage(str, width, height, color_map, interpolate, mask_colors);
+ if (image_node) {
+ _setBlendMode(image_node, state);
+ _container->appendChild(image_node);
Inkscape::GC::release(image_node);
- }
+ }
}
void SvgBuilder::addImageMask(GfxState *state, Stream *str, int width, int height,
@@ -1735,6 +1766,7 @@ void SvgBuilder::addImageMask(GfxState *state, Stream *str, int width, int heigh
_setFillStyle(css, state, false);
sp_repr_css_change(rect, css, "style");
sp_repr_css_attr_unref(css);
+ _setBlendMode(rect, state);
// Scaling 1x1 surfaces might not work so skip setting a mask with this size
if ( width > 1 || height > 1 ) {
@@ -1758,10 +1790,10 @@ void SvgBuilder::addImageMask(GfxState *state, Stream *str, int width, int heigh
Inkscape::GC::release(rect);
}
-void SvgBuilder::addMaskedImage(GfxState * /*state*/, Stream *str, int width, int height,
- GfxImageColorMap *color_map, bool interpolate,
- Stream *mask_str, int mask_width, int mask_height,
- bool invert_mask, bool mask_interpolate) {
+void SvgBuilder::addMaskedImage(GfxState *state, Stream *str, int width, int height, GfxImageColorMap *color_map,
+ bool interpolate, Stream *mask_str, int mask_width, int mask_height, bool invert_mask,
+ bool mask_interpolate)
+{
Inkscape::XML::Node *mask_image_node = _createImage(mask_str, mask_width, mask_height,
nullptr, mask_interpolate, nullptr, true, invert_mask);
@@ -1787,14 +1819,15 @@ void SvgBuilder::addMaskedImage(GfxState * /*state*/, Stream *str, int width, in
Inkscape::GC::release(mask_image_node);
}
if (image_node) {
+ _setBlendMode(image_node, state);
Inkscape::GC::release(image_node);
}
}
-
-void SvgBuilder::addSoftMaskedImage(GfxState * /*state*/, Stream *str, int width, int height,
- GfxImageColorMap *color_map, bool interpolate,
- Stream *mask_str, int mask_width, int mask_height,
- GfxImageColorMap *mask_color_map, bool mask_interpolate) {
+
+void SvgBuilder::addSoftMaskedImage(GfxState *state, Stream *str, int width, int height, GfxImageColorMap *color_map,
+ bool interpolate, Stream *mask_str, int mask_width, int mask_height,
+ GfxImageColorMap *mask_color_map, bool mask_interpolate)
+{
Inkscape::XML::Node *mask_image_node = _createImage(mask_str, mask_width, mask_height,
mask_color_map, mask_interpolate, nullptr, true);
@@ -1815,6 +1848,7 @@ void SvgBuilder::addSoftMaskedImage(GfxState * /*state*/, Stream *str, int width
Inkscape::GC::release(mask_image_node);
}
if (image_node) {
+ _setBlendMode(image_node, state);
Inkscape::GC::release(image_node);
}
}
diff --git a/src/extension/internal/pdfinput/svg-builder.h b/src/extension/internal/pdfinput/svg-builder.h
index 8168617f6..c42d694de 100644
--- a/src/extension/internal/pdfinput/svg-builder.h
+++ b/src/extension/internal/pdfinput/svg-builder.h
@@ -189,7 +189,7 @@ private:
SPCSSAttr *_setStyle(GfxState *state, bool fill, bool stroke, bool even_odd=false);
void _setStrokeStyle(SPCSSAttr *css, GfxState *state);
void _setFillStyle(SPCSSAttr *css, GfxState *state, bool even_odd);
-
+ void _setBlendMode(Inkscape::XML::Node *node, GfxState *state);
void _flushText(); // Write buffered text into doc
std::string _BestMatchingFont(std::string PDFname);
diff --git a/src/ui/dialog/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp
index 22dd407e7..fd28cbc87 100644
--- a/src/ui/dialog/fill-and-stroke.cpp
+++ b/src/ui/dialog/fill-and-stroke.cpp
@@ -46,6 +46,7 @@ FillAndStroke::FillAndStroke()
, _page_stroke_paint(Gtk::manage(new UI::Widget::NotebookPage(1, 1, true, true)))
, _page_stroke_style(Gtk::manage(new UI::Widget::NotebookPage(1, 1, true, true)))
, _composite_settings(SP_VERB_DIALOG_FILL_STROKE, "fillstroke",
+ UI::Widget::SimpleFilterModifier::ISOLATION |
UI::Widget::SimpleFilterModifier::BLEND |
UI::Widget::SimpleFilterModifier::BLUR |
UI::Widget::SimpleFilterModifier::OPACITY)
diff --git a/src/ui/dialog/layers.cpp b/src/ui/dialog/layers.cpp
index e2aa4e2c9..06af29a6e 100644
--- a/src/ui/dialog/layers.cpp
+++ b/src/ui/dialog/layers.cpp
@@ -740,6 +740,7 @@ LayersPanel::LayersPanel() :
_pending(nullptr),
_toggleEvent(nullptr),
_compositeSettings(SP_VERB_DIALOG_LAYERS, "layers",
+ UI::Widget::SimpleFilterModifier::ISOLATION |
UI::Widget::SimpleFilterModifier::BLEND |
UI::Widget::SimpleFilterModifier::OPACITY |
UI::Widget::SimpleFilterModifier::BLUR),
diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp
index 272d98595..8682cfd0c 100644
--- a/src/ui/dialog/objects.cpp
+++ b/src/ui/dialog/objects.cpp
@@ -577,17 +577,20 @@ void ObjectsPanel::_objectsSelected( Selection *sel ) {
void ObjectsPanel::_setCompositingValues(SPItem *item)
{
// Block the connections to avoid interference
+ _isolationConnection.block();
_opacityConnection.block();
_blendConnection.block();
_blurConnection.block();
+ // Set the isolation
+ int isolation = item->style->isolation.set ? item->style->isolation.value : SP_CSS_ISOLATION_AUTO;
+ _filter_modifier.set_isolation_mode(isolation, true);
// Set the opacity
double opacity = (item->style->opacity.set ? SP_SCALE24_TO_FLOAT(item->style->opacity.value) : 1);
opacity *= 100; // Display in percent.
_filter_modifier.set_opacity_value(opacity);
// Set the blend mode
- _filter_modifier.set_blend_mode(item->style->mix_blend_mode.set ? item->style->mix_blend_mode.value
- : SP_CSS_BLEND_NORMAL);
+ _filter_modifier.set_blend_mode(item->style->mix_blend_mode.value, true);
SPGaussianBlur *spblur = nullptr;
if (item->style->getFilter()) {
for (auto& primitive_obj: item->style->getFilter()->children) {
@@ -613,6 +616,7 @@ void ObjectsPanel::_setCompositingValues(SPItem *item)
_filter_modifier.set_blur_value(blur_value);
//Unblock connections
+ _isolationConnection.unblock();
_blurConnection.unblock();
_blendConnection.unblock();
_opacityConnection.unblock();
@@ -1185,6 +1189,7 @@ void ObjectsPanel::_blockAllSignals(bool should_block = true) {
// incoming signals
_documentChangedCurrentLayer.block(should_block);
+ _isolationConnection.block(should_block);
_opacityConnection.block(should_block);
_blendConnection.block(should_block);
_blurConnection.block(should_block);
@@ -1600,14 +1605,38 @@ void ObjectsPanel::_opacityChangedIter(const Gtk::TreeIter& iter)
}
/**
+ * Callback for when the isolation value is changed
+ */
+void ObjectsPanel::_isolationValueChanged()
+{
+ _blockCompositeUpdate = true;
+ _tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &ObjectsPanel::_isolationChangedIter));
+ DocumentUndo::maybeDone(_document, "isolation", SP_VERB_DIALOG_OBJECTS, _("Set object isolation"));
+ _blockCompositeUpdate = false;
+}
+
+/**
+ * Change the isolation of the selected items in the tree
+ * @param iter Current tree item
+ */
+void ObjectsPanel::_isolationChangedIter(const Gtk::TreeIter &iter)
+{
+ Gtk::TreeModel::Row row = *iter;
+ SPItem *item = row[_model->_colObject];
+ if (item) {
+ item->style->isolation.set = TRUE;
+ item->style->isolation.value = _filter_modifier.get_isolation_mode();
+ item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
+ }
+}
+
+/**
* Callback for when the blend mode is changed
*/
void ObjectsPanel::_blendValueChanged()
{
_blockCompositeUpdate = true;
- const Glib::ustring blendmode = _filter_modifier.get_blend_mode();
-
- _tree.get_selection()->selected_foreach_iter(sigc::bind<Glib::ustring>(sigc::mem_fun(*this, &ObjectsPanel::_blendChangedIter), blendmode));
+ _tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &ObjectsPanel::_blendChangedIter));
DocumentUndo::done(_document, SP_VERB_DIALOG_OBJECTS, _("Set object blend mode"));
_blockCompositeUpdate = false;
}
@@ -1617,23 +1646,15 @@ void ObjectsPanel::_blendValueChanged()
* @param iter Current tree item
* @param blendmode Blend mode to set
*/
-void ObjectsPanel::_blendChangedIter(const Gtk::TreeIter& iter, Glib::ustring blendmode)
+void ObjectsPanel::_blendChangedIter(const Gtk::TreeIter &iter)
{
Gtk::TreeModel::Row row = *iter;
SPItem* item = row[_model->_colObject];
if (item)
{
- //Since blur and blend are both filters, we need to set both at the same time
- SPStyle *style = item->style;
- g_assert(style != nullptr);
- SPCSSAttr *css = sp_css_attr_from_style(style, SP_STYLE_FLAG_ALWAYS | SP_STYLE_FLAG_IFSRC);
- if (blendmode == "normal") {
- sp_repr_css_unset_property(css, "mix-blend-mode");
- } else {
- sp_repr_css_set_property(css, "mix-blend-mode", blendmode.c_str());
- }
- sp_repr_css_change(item->getRepr(), css, "style");
- sp_repr_css_attr_unref(css);
+ item->style->mix_blend_mode.set = TRUE;
+ item->style->mix_blend_mode.value = _filter_modifier.get_blend_mode();
+ item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
}
}
@@ -1717,7 +1738,8 @@ ObjectsPanel::ObjectsPanel() :
_clipmaskHeader(C_("Clip and mask", "CM")),
_highlightHeader(C_("Highlight", "HL")),
_nameHeader(_("Label")),
- _filter_modifier( UI::Widget::SimpleFilterModifier::BLEND |
+ _filter_modifier( UI::Widget::SimpleFilterModifier::ISOLATION |
+ UI::Widget::SimpleFilterModifier::BLEND |
UI::Widget::SimpleFilterModifier::BLUR |
UI::Widget::SimpleFilterModifier::OPACITY ),
_colorSelectorDialog("dialogs.colorpickerwindow")
@@ -1859,7 +1881,8 @@ ObjectsPanel::ObjectsPanel() :
_blendConnection = _filter_modifier.signal_blend_changed().connect(sigc::mem_fun(*this, &ObjectsPanel::_blendValueChanged));
_blurConnection = _filter_modifier.signal_blur_changed().connect(sigc::mem_fun(*this, &ObjectsPanel::_blurValueChanged));
_opacityConnection = _filter_modifier.signal_opacity_changed().connect( sigc::mem_fun(*this, &ObjectsPanel::_opacityValueChanged));
-
+ _isolationConnection = _filter_modifier.signal_isolation_changed().connect(
+ sigc::mem_fun(*this, &ObjectsPanel::_isolationValueChanged));
//Pack the compositing functions and the button row
_page.pack_end(_filter_modifier, Gtk::PACK_SHRINK);
_page.pack_end(_buttonsRow, Gtk::PACK_SHRINK);
diff --git a/src/ui/dialog/objects.h b/src/ui/dialog/objects.h
index 3800b2da5..155303374 100644
--- a/src/ui/dialog/objects.h
+++ b/src/ui/dialog/objects.h
@@ -85,6 +85,7 @@ private:
sigc::connection _selectedConnection;
//Connections for when the opacity/blend/blur of the active selection in the document changes
+ sigc::connection _isolationConnection;
sigc::connection _opacityConnection;
sigc::connection _blendConnection;
sigc::connection _blurConnection;
@@ -217,11 +218,14 @@ private:
void _objectsChangedWrapper(SPObject *obj);
void _objectsChanged(SPObject *obj);
void _addObject( SPObject* obj, Gtk::TreeModel::Row* parentRow );
-
+
+ void _isolationChangedIter(const Gtk::TreeIter &iter);
+ void _isolationValueChanged();
+
void _opacityChangedIter(const Gtk::TreeIter& iter);
void _opacityValueChanged();
-
- void _blendChangedIter(const Gtk::TreeIter& iter, Glib::ustring blendmode);
+
+ void _blendChangedIter(const Gtk::TreeIter &iter);
void _blendValueChanged();
void _blurChangedIter(const Gtk::TreeIter& iter, double blur);
diff --git a/src/ui/tools/node-tool.cpp b/src/ui/tools/node-tool.cpp
index 931e08d15..f994f85cf 100644
--- a/src/ui/tools/node-tool.cpp
+++ b/src/ui/tools/node-tool.cpp
@@ -31,6 +31,8 @@
#include "live_effects/effect.h"
#include "live_effects/lpeobject.h"
+#include "include/macros.h"
+
#include "object/sp-clippath.h"
#include "object/sp-item-group.h"
#include "object/sp-mask.h"
@@ -498,7 +500,8 @@ bool NodeTool::root_handler(GdkEvent* event) {
case GDK_MOTION_NOTIFY: {
sp_update_helperpath();
SPItem *over_item = nullptr;
- if (!desktop->canvas->_scrooling) {
+ if (!desktop->canvas->_scrooling || MOD__CTRL(event) || MOD__SHIFT(event) || MOD__ALT(event)) {
+ desktop->canvas->_scrooling = false;
combine_motion_events(desktop->canvas, event->motion, 0);
over_item = sp_event_context_find_item(desktop, event_point(event->button), FALSE, TRUE);
}
diff --git a/src/ui/tools/select-tool.cpp b/src/ui/tools/select-tool.cpp
index 9bd97fabc..6d5fdd2b9 100644
--- a/src/ui/tools/select-tool.cpp
+++ b/src/ui/tools/select-tool.cpp
@@ -554,7 +554,6 @@ bool SelectTool::root_handler(GdkEvent* event) {
if ((event->motion.state & GDK_BUTTON1_MASK) && !this->space_panning) {
Geom::Point const motion_pt(event->motion.x, event->motion.y);
Geom::Point const p(desktop->w2d(motion_pt));
-
if ( within_tolerance
&& ( abs( (gint) event->motion.x - xp ) < tolerance )
&& ( abs( (gint) event->motion.y - yp ) < tolerance ) ) {
diff --git a/src/ui/widget/filter-effect-chooser.cpp b/src/ui/widget/filter-effect-chooser.cpp
index 98074d354..08a3a3750 100644
--- a/src/ui/widget/filter-effect-chooser.cpp
+++ b/src/ui/widget/filter-effect-chooser.cpp
@@ -54,9 +54,11 @@ namespace Widget {
SimpleFilterModifier::SimpleFilterModifier(int flags)
: _flags(flags)
, _lb_blend(_("Blend mode:"))
+ , _lb_isolation("Isolate") // Translate for 1.1
, _blend(SPBlendModeConverter, SP_ATTR_INVALID, false)
, _blur(_("Blur (%)"), 0, 0, 100, 1, 0.1, 1)
, _opacity(_("Opacity (%)"), 0, 0, 100, 1, 0.1, 1)
+ , _notify(true)
{
set_name("SimpleFilterModifier");
@@ -72,6 +74,13 @@ SimpleFilterModifier::SimpleFilterModifier(int flags)
_lb_blend.set_mnemonic_widget(_blend);
_hb_blend.pack_start(_lb_blend, false, false, 5);
_hb_blend.pack_start(_blend, false, false, 5);
+ if (flags & ISOLATION) {
+ _isolation.property_active() = false;
+ _hb_blend.pack_start(_isolation, false, false, 5);
+ _hb_blend.pack_start(_lb_isolation, false, false, 5);
+ }
+ _hb_blend.pack_start(_lb_blend, false, false, 5);
+ _hb_blend.pack_start(_blend, false, false, 5);
Gtk::Separator *separator = Gtk::manage(new Gtk::Separator());
separator->set_margin_top(8);
separator->set_margin_bottom(8);
@@ -90,34 +99,63 @@ SimpleFilterModifier::SimpleFilterModifier(int flags)
_blend.signal_changed().connect(signal_blend_changed());
_blur.signal_value_changed().connect(signal_blur_changed());
_opacity.signal_value_changed().connect(signal_opacity_changed());
+ _isolation.signal_toggled().connect(signal_isolation_changed());
+}
+
+sigc::signal<void> &SimpleFilterModifier::signal_isolation_changed()
+{
+ if (_notify) {
+ return _signal_isolation_changed;
+ }
+ _notify = true;
+ return _signal_null;
}
sigc::signal<void>& SimpleFilterModifier::signal_blend_changed()
{
- return _signal_blend_changed;
+ if (_notify) {
+ return _signal_blend_changed;
+ }
+ _notify = true;
+ return _signal_null;
}
sigc::signal<void>& SimpleFilterModifier::signal_blur_changed()
{
+ // we dont use notifi to block use aberaje for multiple
return _signal_blur_changed;
}
sigc::signal<void>& SimpleFilterModifier::signal_opacity_changed()
{
+ // we dont use notifi to block use averaje for multiple
return _signal_opacity_changed;
}
-const Glib::ustring SimpleFilterModifier::get_blend_mode()
+int SimpleFilterModifier::get_isolation_mode()
+{
+ return _isolation.get_active() ? SP_CSS_ISOLATION_ISOLATE : SP_CSS_ISOLATION_AUTO;
+}
+
+void SimpleFilterModifier::set_isolation_mode(const int val, bool notify)
+{
+ _notify = notify;
+ _isolation.set_active(val == SP_CSS_ISOLATION_ISOLATE);
+}
+
+int SimpleFilterModifier::get_blend_mode()
{
const Util::EnumData<SPBlendMode> *d = _blend.get_active_data();
if (d) {
- return _blend.get_active_data()->key;
- } else
- return "normal";
+ return _blend.get_active_data()->id;
+ } else {
+ return SP_CSS_BLEND_NORMAL;
+ }
}
-void SimpleFilterModifier::set_blend_mode(const int val)
+void SimpleFilterModifier::set_blend_mode(const int val, bool notify)
{
+ _notify = notify;
_blend.set_active(val);
}
diff --git a/src/ui/widget/filter-effect-chooser.h b/src/ui/widget/filter-effect-chooser.h
index 9d5953739..21b8e7c7f 100644
--- a/src/ui/widget/filter-effect-chooser.h
+++ b/src/ui/widget/filter-effect-chooser.h
@@ -15,6 +15,7 @@
*/
#include <gtkmm/box.h>
+#include <gtkmm/checkbutton.h>
#include <gtkmm/combobox.h>
#include <gtkmm/separator.h>
@@ -32,41 +33,44 @@ namespace Widget {
class SimpleFilterModifier : public Gtk::VBox
{
public:
- enum Flags {
- NONE = 0,
- BLUR = 1,
- OPACITY= 2,
- BLEND = 4
- };
+ enum Flags { NONE = 0, BLUR = 1, OPACITY = 2, BLEND = 4, ISOLATION = 16 };
- SimpleFilterModifier(int flags);
+ SimpleFilterModifier(int flags);
- sigc::signal<void>& signal_blend_changed();
- sigc::signal<void>& signal_blur_changed();
- sigc::signal<void>& signal_opacity_changed();
+ sigc::signal<void> &signal_blend_changed();
+ sigc::signal<void> &signal_blur_changed();
+ sigc::signal<void> &signal_opacity_changed();
+ sigc::signal<void> &signal_isolation_changed();
- const Glib::ustring get_blend_mode();
- // Uses blend mode enum values, or -1 for a complex filter
- void set_blend_mode(const int);
+ int get_isolation_mode();
+ void set_isolation_mode(const int, bool notifi);
- double get_blur_value() const;
- void set_blur_value(const double);
+ int get_blend_mode();
+ void set_blend_mode(const int, bool notifi);
- double get_opacity_value() const;
- void set_opacity_value(const double);
+ double get_blur_value() const;
+ void set_blur_value(const double);
+
+ double get_opacity_value() const;
+ void set_opacity_value(const double);
private:
int _flags;
+ bool _notify;
Gtk::HBox _hb_blend;
Gtk::Label _lb_blend;
+ Gtk::Label _lb_isolation;
ComboBoxEnum<SPBlendMode> _blend;
SpinScale _blur;
SpinScale _opacity;
+ Gtk::CheckButton _isolation;
+ sigc::signal<void> _signal_null;
sigc::signal<void> _signal_blend_changed;
sigc::signal<void> _signal_blur_changed;
sigc::signal<void> _signal_opacity_changed;
+ sigc::signal<void> _signal_isolation_changed;
};
}
diff --git a/src/ui/widget/object-composite-settings.cpp b/src/ui/widget/object-composite-settings.cpp
index 4052e1d38..785cb589a 100644
--- a/src/ui/widget/object-composite-settings.cpp
+++ b/src/ui/widget/object-composite-settings.cpp
@@ -37,6 +37,7 @@ ObjectCompositeSettings::ObjectCompositeSettings(unsigned int verb_code, char co
_blend_tag(Glib::ustring(history_prefix) + ":blend"),
_blur_tag(Glib::ustring(history_prefix) + ":blur"),
_opacity_tag(Glib::ustring(history_prefix) + ":opacity"),
+ _isolation_tag(Glib::ustring(history_prefix) + ":isolation"),
_filter_modifier(flags),
_blocked(false)
{
@@ -48,6 +49,8 @@ ObjectCompositeSettings::ObjectCompositeSettings(unsigned int verb_code, char co
_filter_modifier.signal_blend_changed().connect(sigc::mem_fun(*this, &ObjectCompositeSettings::_blendBlurValueChanged));
_filter_modifier.signal_blur_changed().connect(sigc::mem_fun(*this, &ObjectCompositeSettings::_blendBlurValueChanged));
_filter_modifier.signal_opacity_changed().connect(sigc::mem_fun(*this, &ObjectCompositeSettings::_opacityValueChanged));
+ _filter_modifier.signal_isolation_changed().connect(
+ sigc::mem_fun(*this, &ObjectCompositeSettings::_isolationValueChanged));
show_all_children();
}
@@ -100,8 +103,6 @@ ObjectCompositeSettings::_blendBlurValueChanged()
radius = 0;
}
- const Glib::ustring blendmode = _filter_modifier.get_blend_mode();
-
//apply created filter to every selected item
std::vector<SPObject*> sel = _subject->list();
for (std::vector<SPObject*>::const_iterator i = sel.begin() ; i != sel.end() ; ++i ) {
@@ -112,18 +113,9 @@ ObjectCompositeSettings::_blendBlurValueChanged()
SPItem * item = SP_ITEM(*i);
SPStyle *style = item->style;
g_assert(style != nullptr);
-
- SPCSSAttr *css = sp_repr_css_attr_new();
-
- if (blendmode == "normal") {
- sp_repr_css_unset_property(css, "mix-blend-mode");
- } else {
- sp_repr_css_set_property(css, "mix-blend-mode", blendmode.c_str());
- }
-
- _subject->setCSS(css);
-
- sp_repr_css_attr_unref(css);
+ item->style->mix_blend_mode.set = TRUE;
+ item->style->mix_blend_mode.value = _filter_modifier.get_blend_mode();
+ item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
if (radius == 0 && item->style->filter.set
&& filter_is_single_gaussian_blur(SP_FILTER(item->style->getFilter()))) {
@@ -183,6 +175,35 @@ ObjectCompositeSettings::_opacityValueChanged()
_blocked = false;
}
+void ObjectCompositeSettings::_isolationValueChanged()
+{
+ if (!_subject) {
+ return;
+ }
+
+ SPDesktop *desktop = _subject->getDesktop();
+ if (!desktop) {
+ return;
+ }
+
+ if (_blocked)
+ return;
+ _blocked = true;
+
+ for (auto item : _subject->list()) {
+ item->style->isolation.set = TRUE;
+ item->style->isolation.value = _filter_modifier.get_isolation_mode();
+ item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
+ }
+
+ DocumentUndo::maybeDone(desktop->getDocument(), _isolation_tag.c_str(), _verb_code, _("Change isolation"));
+
+ // resume interruptibility
+ // sp_canvas_end_forced_full_redraws(desktop->getCanvas());
+
+ _blocked = false;
+}
+
void
ObjectCompositeSettings::_subjectChanged() {
if (!_subject) {
@@ -211,16 +232,33 @@ ObjectCompositeSettings::_subjectChanged() {
}
//query now for current filter mode and average blurring of selection
+ const int isolation_result = _subject->queryStyle(&query, QUERY_STYLE_PROPERTY_ISOLATION);
+ switch (isolation_result) {
+ case QUERY_STYLE_NOTHING:
+ _filter_modifier.set_isolation_mode(SP_CSS_ISOLATION_AUTO, false);
+ break;
+ case QUERY_STYLE_SINGLE:
+ case QUERY_STYLE_MULTIPLE_SAME:
+ _filter_modifier.set_isolation_mode(query.isolation.value, true); // here dont work mix_blend_mode.set
+ break;
+ case QUERY_STYLE_MULTIPLE_DIFFERENT:
+ _filter_modifier.set_isolation_mode(SP_CSS_ISOLATION_AUTO, false);
+ // TODO: set text
+ break;
+ }
+
+ // query now for current filter mode and average blurring of selection
const int blend_result = _subject->queryStyle(&query, QUERY_STYLE_PROPERTY_BLEND);
switch(blend_result) {
case QUERY_STYLE_NOTHING:
+ _filter_modifier.set_blend_mode(0, false);
break;
case QUERY_STYLE_SINGLE:
case QUERY_STYLE_MULTIPLE_SAME:
- _filter_modifier.set_blend_mode(query.mix_blend_mode.value); // here dont work mix_blend_mode.set
+ _filter_modifier.set_blend_mode(query.mix_blend_mode.value, true); // here dont work mix_blend_mode.set
break;
case QUERY_STYLE_MULTIPLE_DIFFERENT:
- // TODO: set text
+ _filter_modifier.set_blend_mode(0, false);
break;
}
diff --git a/src/ui/widget/object-composite-settings.h b/src/ui/widget/object-composite-settings.h
index 8e57bbf0c..96501185a 100644
--- a/src/ui/widget/object-composite-settings.h
+++ b/src/ui/widget/object-composite-settings.h
@@ -45,6 +45,7 @@ private:
Glib::ustring _blend_tag;
Glib::ustring _blur_tag;
Glib::ustring _opacity_tag;
+ Glib::ustring _isolation_tag;
StyleSubject *_subject;
@@ -59,7 +60,7 @@ private:
void _subjectChanged();
void _blendBlurValueChanged();
void _opacityValueChanged();
-
+ void _isolationValueChanged();
};
}