summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKrzysztof Kosi??ski <tweenk.pl@gmail.com>2011-07-10 03:33:59 +0000
committerKrzysztof KosiƄski <tweenk.pl@gmail.com>2011-07-10 03:33:59 +0000
commit3099a49e82622b42547088666099f33d0d55b1ad (patch)
tree5489f800f9f2444cbd2a976eec10c4cf3ca24242 /src
parentRedesign the rendering pipeline. Clipping paths are now rasterized. (diff)
downloadinkscape-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.cpp10
-rw-r--r--src/display/nr-arena-group.cpp14
-rw-r--r--src/display/nr-arena-shape.cpp12
-rw-r--r--src/sp-clippath.cpp11
-rw-r--r--src/style.cpp30
-rw-r--r--src/style.h4
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;