diff options
| author | Tavmjong Bah <tavmjong@free.fr> | 2013-12-10 12:40:42 +0000 |
|---|---|---|
| committer | tavmjong-free <tavmjong@free.fr> | 2013-12-10 12:40:42 +0000 |
| commit | cd9fae530b0cf7e48a7b8cb41ef5efb7e99717fe (patch) | |
| tree | 9835ce4a35ad3ff6d0f9b073f08a3f6aefc463cb | |
| parent | Add JessyInk namespace. (diff) | |
| download | inkscape-cd9fae530b0cf7e48a7b8cb41ef5efb7e99717fe.tar.gz inkscape-cd9fae530b0cf7e48a7b8cb41ef5efb7e99717fe.zip | |
New CSS blending modes (outside of filters).
Define WITH_CSSBLEND to try out.
Note: The modes are defined in CSS Compositing and Blending Level 1.
To do: GUI. Isolate SVG drawing from Inkscape background (i.e. page border).
(bzr r12845)
| -rw-r--r-- | src/attributes.cpp | 2 | ||||
| -rw-r--r-- | src/attributes.h | 2 | ||||
| -rw-r--r-- | src/display/drawing-item.cpp | 88 | ||||
| -rw-r--r-- | src/display/drawing-item.h | 5 | ||||
| -rw-r--r-- | src/sp-item.cpp | 5 | ||||
| -rw-r--r-- | src/style.cpp | 51 | ||||
| -rw-r--r-- | src/style.h | 29 |
7 files changed, 182 insertions, 0 deletions
diff --git a/src/attributes.cpp b/src/attributes.cpp index b93bcfd57..40e11b023 100644 --- a/src/attributes.cpp +++ b/src/attributes.cpp @@ -440,6 +440,8 @@ static SPStyleProp const props[] = { {SP_PROP_DISPLAY, "display"}, {SP_PROP_OVERFLOW, "overflow"}, {SP_PROP_VISIBILITY, "visibility"}, + {SP_PROP_BLEND_MODE, "mix-blend-mode"}, // CSS Blending and Compositing + {SP_PROP_ISOLATION, "isolation"}, /* SVG */ /* Clip/Mask */ {SP_PROP_CLIP_PATH, "clip-path"}, diff --git a/src/attributes.h b/src/attributes.h index 24244c237..ecf7ce966 100644 --- a/src/attributes.h +++ b/src/attributes.h @@ -441,6 +441,8 @@ enum SPAttributeEnum { SP_PROP_DISPLAY, SP_PROP_OVERFLOW, SP_PROP_VISIBILITY, + SP_PROP_BLEND_MODE, + SP_PROP_ISOLATION, /* SVG */ /* Clip/Mask */ SP_PROP_CLIP_PATH, diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp index a8257e6e5..a9b07bb6e 100644 --- a/src/display/drawing-item.cpp +++ b/src/display/drawing-item.cpp @@ -23,6 +23,66 @@ namespace Inkscape { +#ifdef WITH_CSSBLEND +void set_cairo_blend_operator( DrawingContext &ct, 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: + ct.setOperator(CAIRO_OPERATOR_MULTIPLY); + break; + case SP_CSS_BLEND_SCREEN: + ct.setOperator(CAIRO_OPERATOR_SCREEN); + break; + case SP_CSS_BLEND_DARKEN: + ct.setOperator(CAIRO_OPERATOR_DARKEN); + break; + case SP_CSS_BLEND_LIGHTEN: + ct.setOperator(CAIRO_OPERATOR_LIGHTEN); + break; + case SP_CSS_BLEND_OVERLAY: + ct.setOperator(CAIRO_OPERATOR_OVERLAY); + break; + case SP_CSS_BLEND_COLORDODGE: + ct.setOperator(CAIRO_OPERATOR_COLOR_DODGE); + break; + case SP_CSS_BLEND_COLORBURN: + ct.setOperator(CAIRO_OPERATOR_COLOR_BURN); + break; + case SP_CSS_BLEND_HARDLIGHT: + ct.setOperator(CAIRO_OPERATOR_HARD_LIGHT); + break; + case SP_CSS_BLEND_SOFTLIGHT: + ct.setOperator(CAIRO_OPERATOR_SOFT_LIGHT); + break; + case SP_CSS_BLEND_DIFFERENCE: + ct.setOperator(CAIRO_OPERATOR_DIFFERENCE); + break; + case SP_CSS_BLEND_EXCLUSION: + ct.setOperator(CAIRO_OPERATOR_EXCLUSION); + break; + case SP_CSS_BLEND_HUE: + ct.setOperator(CAIRO_OPERATOR_HSL_HUE); + break; + case SP_CSS_BLEND_SATURATION: + ct.setOperator(CAIRO_OPERATOR_HSL_SATURATION); + break; + case SP_CSS_BLEND_COLOR: + ct.setOperator(CAIRO_OPERATOR_HSL_COLOR); + break; + case SP_CSS_BLEND_LUMINOSITY: + ct.setOperator(CAIRO_OPERATOR_HSL_LUMINOSITY); + break; + case SP_CSS_BLEND_NORMAL: + default: + ct.setOperator(CAIRO_OPERATOR_OVER); + break; + } +} +#endif + /** * @class DrawingItem * SVG drawing item for display. @@ -67,6 +127,8 @@ DrawingItem::DrawingItem(Drawing &drawing) , _propagate(0) // , _renders_opacity(0) , _pick_children(0) + , _isolation(SP_CSS_ISOLATION_AUTO) + , _blend_mode(SP_CSS_BLEND_NORMAL) {} DrawingItem::~DrawingItem() @@ -209,6 +271,22 @@ DrawingItem::setOpacity(float opacity) } void +DrawingItem::setIsolation(unsigned isolation) +{ + _isolation = isolation; + //if( isolation != 0 ) std::cout << "isolation: " << isolation << std::endl; + _markForRendering(); +} + +void +DrawingItem::setBlendMode(unsigned blend_mode) +{ + _blend_mode = blend_mode; + //if( blend_mode != 0 ) std::cout << "setBlendMode: " << blend_mode << std::endl; + _markForRendering(); +} + +void DrawingItem::setVisible(bool v) { _visible = v; @@ -494,6 +572,9 @@ DrawingItem::render(DrawingContext &ct, Geom::IntRect const &area, unsigned flag if (_cached) { if (_cache) { _cache->prepare(); +#ifdef WITH_CSSBLEND + set_cairo_blend_operator( ct, _blend_mode ); +#endif _cache->paintFromCache(ct, carea); if (!carea) return RENDER_OK; } else { @@ -522,6 +603,10 @@ DrawingItem::render(DrawingContext &ct, Geom::IntRect const &area, unsigned flag nir |= (_filter != NULL && render_filters); // 3. it has a filter nir |= needs_opacity; // 4. it is non-opaque nir |= (_cache != NULL); // 5. it is cached +#ifdef WITH_CSSBLEND + nir |= (_blend_mode != SP_CSS_BLEND_NORMAL); // 6. Blend mode not normal + nir |= (_isolation == SP_CSS_ISOLATION_ISOLATE); // 7. Explicit isolatiom +#endif /* How the rendering is done. * @@ -633,6 +718,9 @@ DrawingItem::render(DrawingContext &ct, Geom::IntRect const &area, unsigned flag } ct.rectangle(*carea); ct.setSource(&intermediate); +#ifdef WITH_CSSBLEND + set_cairo_blend_operator( ct, _blend_mode ); +#endif ct.fill(); ct.setSource(0,0,0,0); // the call above is to clear a ref on the intermediate surface held by ct diff --git a/src/display/drawing-item.h b/src/display/drawing-item.h index e03bbd0f7..1796d29d6 100644 --- a/src/display/drawing-item.h +++ b/src/display/drawing-item.h @@ -108,6 +108,8 @@ public: void setCached(bool c, bool persistent = false); void setOpacity(float opacity); + void setIsolation(unsigned isolation); // CSS Compositing and Blending + void setBlendMode(unsigned blend_mode); void setTransform(Geom::Affine const &trans); void setClip(DrawingItem *item); void setMask(DrawingItem *item); @@ -204,6 +206,9 @@ protected: unsigned _pick_children : 1; ///< For groups: if true, children are returned from pick(), /// otherwise the group is returned + unsigned _isolation : 1; + unsigned _blend_mode : 4; + friend class Drawing; }; diff --git a/src/sp-item.cpp b/src/sp-item.cpp index c6daa853c..5e126f486 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -599,6 +599,8 @@ void SPItem::update(SPCtx* /*ctx*/, guint flags) { if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { for (SPItemView *v = item->display; v != NULL; v = v->next) { v->arenaitem->setOpacity(SP_SCALE24_TO_FLOAT(object->style->opacity.value)); + v->arenaitem->setIsolation( object->style->isolation.value ); + v->arenaitem->setBlendMode( object->style->blend_mode.value ); v->arenaitem->setVisible(!item->isHidden()); } } @@ -1023,6 +1025,9 @@ Inkscape::DrawingItem *SPItem::invoke_show(Inkscape::Drawing &drawing, unsigned display = sp_item_view_new_prepend(display, this, flags, key, ai); ai->setTransform(transform); ai->setOpacity(SP_SCALE24_TO_FLOAT(style->opacity.value)); + ai->setIsolation( style->isolation.value ); + ai->setBlendMode( style->blend_mode.value ); + //ai->setCompositeOperator( style->composite_op.value ); ai->setVisible(!isHidden()); ai->setSensitive(sensitive); if (clip_ref->getObject()) { diff --git a/src/style.cpp b/src/style.cpp index fc0c97c15..bb5603f1c 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -303,6 +303,33 @@ static SPStyleEnum const enum_overflow[] = { {NULL, -1} }; +// CSS Compositing and Blending Level 1 +static SPStyleEnum const enum_isolation[] = { + {"auto", SP_CSS_ISOLATION_AUTO}, + {"isolate", SP_CSS_ISOLATION_ISOLATE}, + {NULL, -1} +}; + +static SPStyleEnum const enum_blend_mode[] = { + {"normal", SP_CSS_BLEND_NORMAL}, + {"multiply", SP_CSS_BLEND_MULTIPLY}, + {"screen", SP_CSS_BLEND_SCREEN}, + {"darken", SP_CSS_BLEND_DARKEN}, + {"lighten", SP_CSS_BLEND_LIGHTEN}, + {"overlay", SP_CSS_BLEND_OVERLAY}, + {"color-dodge", SP_CSS_BLEND_COLORDODGE}, + {"color-burn", SP_CSS_BLEND_COLORBURN}, + {"hard-light", SP_CSS_BLEND_HARDLIGHT}, + {"soft-light", SP_CSS_BLEND_SOFTLIGHT}, + {"difference", SP_CSS_BLEND_DIFFERENCE}, + {"exclusion", SP_CSS_BLEND_EXCLUSION}, + {"hue", SP_CSS_BLEND_HUE}, + {"saturation", SP_CSS_BLEND_SATURATION}, + {"color", SP_CSS_BLEND_COLOR}, + {"luminosity", SP_CSS_BLEND_LUMINOSITY}, + {NULL, -1} +}; + static SPStyleEnum const enum_display[] = { {"none", SP_CSS_DISPLAY_NONE}, {"inline", SP_CSS_DISPLAY_INLINE}, @@ -643,6 +670,11 @@ sp_style_read(SPStyle *style, SPObject *object, Inkscape::XML::Node *repr) SPS_READ_PENUM_IF_UNSET(&style->visibility, repr, "visibility", enum_visibility, true); SPS_READ_PENUM_IF_UNSET(&style->display, repr, "display", enum_display, true); SPS_READ_PENUM_IF_UNSET(&style->overflow, repr, "overflow", enum_overflow, true); + + /* CSS Compositing and Blending Level 1 */ + SPS_READ_PENUM_IF_UNSET(&style->isolation, repr, "isolation", enum_isolation, true); + SPS_READ_PENUM_IF_UNSET(&style->blend_mode, repr, "mix_blend_mode", enum_blend_mode, true); + /* Font */ SPS_READ_PFONTSIZE_IF_UNSET(&style->font_size, repr, "font-size"); SPS_READ_PENUM_IF_UNSET(&style->font_style, repr, "font-style", enum_font_style, true); @@ -1207,6 +1239,13 @@ sp_style_merge_property(SPStyle *style, gint id, gchar const *val) case SP_PROP_VISIBILITY: SPS_READ_IENUM_IF_UNSET(&style->visibility, val, enum_visibility, true); break; + case SP_PROP_ISOLATION: + SPS_READ_IENUM_IF_UNSET(&style->isolation, val, enum_isolation, true); + break; + case SP_PROP_BLEND_MODE: + SPS_READ_IENUM_IF_UNSET(&style->blend_mode, val, enum_blend_mode, true); + break; + /* SVG */ /* Clip/Mask */ case SP_PROP_CLIP_PATH: @@ -2180,6 +2219,7 @@ sp_style_merge_from_dying_parent(SPStyle *const style, SPStyle const *const pare /* Enum values that don't have any relative settings (other than `inherit'). */ { SPIEnum SPStyle::*const fields[] = { + &SPStyle::blend_mode, &SPStyle::clip_rule, &SPStyle::color_interpolation, &SPStyle::color_interpolation_filters, @@ -2189,6 +2229,7 @@ sp_style_merge_from_dying_parent(SPStyle *const style, SPStyle const *const pare &SPStyle::font_style, &SPStyle::font_variant, &SPStyle::image_rendering, + &SPStyle::isolation, //nyi: SPStyle::pointer_events, &SPStyle::shape_rendering, &SPStyle::stroke_linecap, @@ -2791,6 +2832,8 @@ sp_style_write_string(SPStyle const *const style, guint const flags) p += sp_style_write_ienum(p, c + BMAX - p, "visibility", enum_visibility, &style->visibility, NULL, flags); p += sp_style_write_ienum(p, c + BMAX - p, "display", enum_display, &style->display, NULL, flags); p += sp_style_write_ienum(p, c + BMAX - p, "overflow", enum_overflow, &style->overflow, NULL, flags); + p += sp_style_write_ienum(p, c + BMAX - p, "isolation", enum_isolation, &style->isolation, NULL, flags); + p += sp_style_write_ienum(p, c + BMAX - p, "mix-blend-mode", enum_blend_mode, &style->blend_mode, NULL, flags); /* filter: */ p += sp_style_write_ifilter(p, c + BMAX - p, "filter", &style->filter, NULL, flags); @@ -2949,6 +2992,8 @@ sp_style_write_difference(SPStyle const *const from, SPStyle const *const to) p += sp_style_write_ienum(p, c + BMAX - p, "visibility", enum_visibility, &from->visibility, &to->visibility, SP_STYLE_FLAG_IFSET); p += sp_style_write_ienum(p, c + BMAX - p, "display", enum_display, &from->display, &to->display, SP_STYLE_FLAG_IFSET); p += sp_style_write_ienum(p, c + BMAX - p, "overflow", enum_overflow, &from->overflow, &to->overflow, SP_STYLE_FLAG_IFSET); + p += sp_style_write_ienum(p, c + BMAX - p, "isolation", enum_isolation, &from->isolation, &to->isolation, SP_STYLE_FLAG_IFSET); + p += sp_style_write_ienum(p, c + BMAX - p, "mix-blend-mode", enum_blend_mode, &from->blend_mode, &to->blend_mode, SP_STYLE_FLAG_IFSET); /* filter: */ p += sp_style_write_ifilter(p, c + BMAX - p, "filter", &from->filter, &to->filter, SP_STYLE_FLAG_IFDIFF); @@ -3168,6 +3213,12 @@ sp_style_clear(SPStyle *style) style->overflow.set = FALSE; style->overflow.inherit = FALSE; style->overflow.value = style->overflow.computed = SP_CSS_OVERFLOW_VISIBLE; + style->isolation.set = FALSE; + style->isolation.inherit = FALSE; + style->isolation.value = style->isolation.computed = SP_CSS_ISOLATION_AUTO; + style->blend_mode.set = FALSE; + style->blend_mode.inherit = FALSE; + style->blend_mode.value = style->blend_mode.computed = SP_CSS_BLEND_NORMAL; style->color.clear(); style->color.setColor(0.0, 0.0, 0.0); diff --git a/src/style.h b/src/style.h index bc4df96e2..014d2b72f 100644 --- a/src/style.h +++ b/src/style.h @@ -364,6 +364,11 @@ struct SPStyle { /** opacity */ SPIScale24 opacity; + /** mix-blend-mode: CSS Compositing and Blending Level 1 */ + SPIEnum isolation; + // Could be shared with Filter blending mode + SPIEnum blend_mode; + /** color */ SPIPaint color; /** color-interpolation */ @@ -606,6 +611,30 @@ enum SPCSSDisplay { SP_CSS_DISPLAY_TABLE_CAPTION }; +enum SPIsolation { + SP_CSS_ISOLATION_AUTO, + SP_CSS_ISOLATION_ISOLATE +}; + +enum SPBlendMode { + SP_CSS_BLEND_NORMAL, + SP_CSS_BLEND_MULTIPLY, + SP_CSS_BLEND_SCREEN, + SP_CSS_BLEND_DARKEN, + SP_CSS_BLEND_LIGHTEN, + SP_CSS_BLEND_OVERLAY, + SP_CSS_BLEND_COLORDODGE, + SP_CSS_BLEND_COLORBURN, + SP_CSS_BLEND_HARDLIGHT, + SP_CSS_BLEND_SOFTLIGHT, + SP_CSS_BLEND_DIFFERENCE, + SP_CSS_BLEND_EXCLUSION, + SP_CSS_BLEND_HUE, + SP_CSS_BLEND_SATURATION, + SP_CSS_BLEND_COLOR, + SP_CSS_BLEND_LUMINOSITY +}; + enum SPEnableBackground { SP_CSS_BACKGROUND_ACCUMULATE, SP_CSS_BACKGROUND_NEW |
