diff options
| author | Krzysztof Kosi??ski <tweenk.pl@gmail.com> | 2011-07-10 03:33:59 +0000 |
|---|---|---|
| committer | Krzysztof KosiĆski <tweenk.pl@gmail.com> | 2011-07-10 03:33:59 +0000 |
| commit | 3099a49e82622b42547088666099f33d0d55b1ad (patch) | |
| tree | 5489f800f9f2444cbd2a976eec10c4cf3ca24242 /src | |
| parent | Redesign the rendering pipeline. Clipping paths are now rasterized. (diff) | |
| download | inkscape-3099a49e82622b42547088666099f33d0d55b1ad.tar.gz inkscape-3099a49e82622b42547088666099f33d0d55b1ad.zip | |
Implement handling of the clip-rule property. Partially based on
a patch by Andrew Lutomirski.
Fixed bugs:
- https://launchpad.net/bugs/171243
(bzr r10347.1.8)
Diffstat (limited to 'src')
| -rw-r--r-- | src/display/nr-arena-glyphs.cpp | 10 | ||||
| -rw-r--r-- | src/display/nr-arena-group.cpp | 14 | ||||
| -rw-r--r-- | src/display/nr-arena-shape.cpp | 12 | ||||
| -rw-r--r-- | src/sp-clippath.cpp | 11 | ||||
| -rw-r--r-- | src/style.cpp | 30 | ||||
| -rw-r--r-- | src/style.h | 4 |
6 files changed, 71 insertions, 10 deletions
diff --git a/src/display/nr-arena-glyphs.cpp b/src/display/nr-arena-glyphs.cpp index 185551d31..b76e87a78 100644 --- a/src/display/nr-arena-glyphs.cpp +++ b/src/display/nr-arena-glyphs.cpp @@ -360,6 +360,14 @@ static unsigned int nr_arena_glyphs_group_clip(cairo_t *ct, NRArenaItem *item, N NRArenaGroup *ggroup = NR_ARENA_GLYPHS_GROUP(item); cairo_save(ct); + // handle clip-rule + if (ggroup->style) { + if (ggroup->style->clip_rule.computed == SP_WIND_RULE_EVENODD) { + cairo_set_fill_rule(ct, CAIRO_FILL_RULE_EVEN_ODD); + } else { + cairo_set_fill_rule(ct, CAIRO_FILL_RULE_WINDING); + } + } ink_cairo_transform(ct, ggroup->ctm); for (NRArenaItem *child = ggroup->children; child != NULL; child = child->next) { @@ -369,9 +377,9 @@ static unsigned int nr_arena_glyphs_group_clip(cairo_t *ct, NRArenaItem *item, N cairo_save(ct); ink_cairo_transform(ct, g->g_transform); feed_pathvector_to_cairo(ct, pathv); - cairo_fill(ct); cairo_restore(ct); } + cairo_fill(ct); cairo_restore(ct); return item->state; diff --git a/src/display/nr-arena-group.cpp b/src/display/nr-arena-group.cpp index 5f11c1a6b..714c4ecff 100644 --- a/src/display/nr-arena-group.cpp +++ b/src/display/nr-arena-group.cpp @@ -12,6 +12,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include "display/canvas-bpath.h" #include "display/nr-arena-group.h" #include "display/nr-filter.h" #include "display/nr-filter-types.h" @@ -234,14 +235,25 @@ static unsigned int nr_arena_group_clip (cairo_t *ct, NRArenaItem *item, NRRectL *area) { NRArenaGroup *group = NR_ARENA_GROUP (item); - unsigned int ret = item->state; + cairo_save(ct); + + // handle clip-rule + if (group->style) { + if (group->style->clip_rule.computed == SP_WIND_RULE_EVENODD) { + cairo_set_fill_rule(ct, CAIRO_FILL_RULE_EVEN_ODD); + } else { + cairo_set_fill_rule(ct, CAIRO_FILL_RULE_WINDING); + } + } + for (NRArenaItem *child = group->children; child != NULL; child = child->next) { ret = nr_arena_item_invoke_clip (ct, child, area); if (ret & NR_ARENA_ITEM_STATE_INVALID) break; } + cairo_restore(ct); return ret; } diff --git a/src/display/nr-arena-shape.cpp b/src/display/nr-arena-shape.cpp index 9bece05b5..6d65611bf 100644 --- a/src/display/nr-arena-shape.cpp +++ b/src/display/nr-arena-shape.cpp @@ -21,6 +21,7 @@ #include <2geom/svg-path-parser.h> #include "display/cairo-utils.h" #include "display/canvas-arena.h" +#include "display/canvas-bpath.h" #include "display/curve.h" #include "display/nr-arena.h" #include "display/nr-arena-shape.h" @@ -401,10 +402,15 @@ static guint nr_arena_shape_clip(cairo_t *ct, NRArenaItem *item, NRRectL * /*are return item->state; } - // TODO: Handling of the clip-rule property / CSS attribute. - // Once the required bits are in SPStyle, this is as trivial as adding a single - // call to cairo_set_fill_rule() before cairo_fill(). cairo_save(ct); + // handle clip-rule + if (shape->style) { + if (shape->style->clip_rule.computed == SP_WIND_RULE_EVENODD) { + cairo_set_fill_rule(ct, CAIRO_FILL_RULE_EVEN_ODD); + } else { + cairo_set_fill_rule(ct, CAIRO_FILL_RULE_WINDING); + } + } ink_cairo_transform(ct, shape->ctm); feed_pathvector_to_cairo(ct, shape->curve->get_pathvector()); cairo_fill(ct); diff --git a/src/sp-clippath.cpp b/src/sp-clippath.cpp index 147ece167..48e466628 100644 --- a/src/sp-clippath.cpp +++ b/src/sp-clippath.cpp @@ -89,6 +89,7 @@ void SPClipPath::build(SPObject *object, SPDocument *document, Inkscape::XML::No if (((SPObjectClass *) SPClipPathClass::static_parent_class)->build) ((SPObjectClass *) SPClipPathClass::static_parent_class)->build(object, document, repr); + object->readAttr( "style" ); object->readAttr( "clipPathUnits" ); /* Register ourselves */ @@ -132,8 +133,13 @@ void SPClipPath::set(SPObject *object, unsigned int key, gchar const *value) object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); break; default: - if (((SPObjectClass *) SPClipPathClass::static_parent_class)->set) { - ((SPObjectClass *) SPClipPathClass::static_parent_class)->set(object, key, value); + if (SP_ATTRIBUTE_IS_CSS(key)) { + sp_style_read_from_object(object->style, object); + object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); + } else { + if (((SPObjectClass *) SPClipPathClass::static_parent_class)->set) { + ((SPObjectClass *) SPClipPathClass::static_parent_class)->set(object, key, value); + } } break; } @@ -258,6 +264,7 @@ NRArenaItem *SPClipPath::show(NRArena *arena, unsigned int key) t[5] = display->bbox.y0; nr_arena_group_set_child_transform(NR_ARENA_GROUP(ai), &t); } + nr_arena_group_set_style(NR_ARENA_GROUP(ai), this->style); return ai; } diff --git a/src/style.cpp b/src/style.cpp index 37a784e2a..e66c15494 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -335,6 +335,12 @@ static SPStyleEnum const enum_enable_background[] = { {NULL, -1} }; +static SPStyleEnum const enum_clip_rule[] = { + {"nonzero", SP_WIND_RULE_NONZERO}, + {"evenodd", SP_WIND_RULE_EVENODD}, + {NULL, -1} +}; + /** * Release callback. */ @@ -767,6 +773,9 @@ sp_style_read(SPStyle *style, SPObject *object, Inkscape::XML::Node *repr) SPS_READ_PENUM_IF_UNSET(&style->enable_background, repr, "enable-background", enum_enable_background, true); + /* clip-rule */ + SPS_READ_PENUM_IF_UNSET(&style->clip_rule, repr, "clip-rule", enum_clip_rule, true); + /* 3. Merge from parent */ if (object) { if (object->parent) { @@ -1020,7 +1029,9 @@ sp_style_merge_property(SPStyle *style, gint id, gchar const *val) style->object->getRepr()->setAttribute("clip-path", val); break; case SP_PROP_CLIP_RULE: - g_warning("Unimplemented style property SP_PROP_CLIP_RULE: value: %s", val); + if (!style->clip_rule.set) { + sp_style_read_ienum(&style->clip_rule, val, enum_clip_rule, true); + } break; case SP_PROP_MASK: /** \todo @@ -1645,6 +1656,11 @@ sp_style_merge_from_parent(SPStyle *const style, SPStyle const *const parent) if(style->enable_background.inherit) { style->enable_background.value = parent->enable_background.value; } + + /* Clipping */ + if (!style->clip_rule.set || style->clip_rule.inherit) { + style->clip_rule.computed = parent->clip_rule.computed; + } } template <typename T> @@ -1906,7 +1922,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[] = { - //nyi: SPStyle::clip_rule, + &SPStyle::clip_rule, //nyi: SPStyle::color_interpolation, //nyi: SPStyle::color_interpolation_filters, //nyi: SPStyle::color_rendering, @@ -2446,6 +2462,9 @@ sp_style_write_string(SPStyle const *const style, guint const flags) p += sp_style_write_ienum(p, c + BMAX - p, "enable-background", enum_enable_background, &style->enable_background, NULL, flags); + /* clipping */ + p += sp_style_write_ienum(p, c + BMAX - p, "clip-rule", enum_clip_rule, &style->clip_rule, NULL, flags); + /* fixme: */ p += sp_text_style_write(p, c + BMAX - p, style->text, flags); @@ -2592,6 +2611,8 @@ sp_style_write_difference(SPStyle const *const from, SPStyle const *const to) p += sp_text_style_write(p, c + BMAX - p, from->text, SP_STYLE_FLAG_IFDIFF); + p += sp_style_write_ienum(p, c + BMAX - p, "clip-rule", enum_clip_rule, &from->clip_rule, &to->clip_rule, SP_STYLE_FLAG_IFDIFF); + /** \todo * The reason we use IFSET rather than IFDIFF is the belief that the IFDIFF * flag is mainly only for attributes that don't handle explicit unset well. @@ -2783,6 +2804,8 @@ sp_style_clear(SPStyle *style) style->enable_background.value = SP_CSS_BACKGROUND_ACCUMULATE; style->enable_background.set = false; style->enable_background.inherit = false; + + style->clip_rule.value = style->clip_rule.computed = SP_WIND_RULE_NONZERO; } @@ -4178,6 +4201,9 @@ sp_style_unset_property_attrs(SPObject *o) if (style->enable_background.set) { repr->setAttribute("enable-background", NULL); } + if (style->clip_rule.set) { + repr->setAttribute("clip-rule", NULL); + } } /** diff --git a/src/style.h b/src/style.h index a12db388a..3ca1d4dbc 100644 --- a/src/style.h +++ b/src/style.h @@ -327,9 +327,11 @@ struct SPStyle { unsigned cursor_set : 1; unsigned overflow_set : 1; unsigned clip_path_set : 1; - unsigned clip_rule_set : 1; unsigned mask_set : 1; + /** clip-rule: 0 nonzero, 1 evenodd */ + SPIEnum clip_rule; + /** display */ SPIEnum display; |
