[lasem] svg: add support for comp-op attribute (svg1.2)
- From: Emmanuel Pacaud <emmanuel src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [lasem] svg: add support for comp-op attribute (svg1.2)
- Date: Mon, 29 Oct 2012 13:55:29 +0000 (UTC)
commit 18fc0faa6ac4b0ee090c52df6a409c44a48dded7
Author: Emmanuel Pacaud <emmanuel gnome org>
Date: Sun Oct 28 09:39:50 2012 +0100
svg: add support for comp-op attribute (svg1.2)
src/lsmcairo.c | 1 +
src/lsmcairo.h | 1 +
src/lsmsvgstyle.c | 6 +++
src/lsmsvgstyle.h | 6 +++
src/lsmsvgtraits.c | 24 +++++++++++++
src/lsmsvgtraits.h | 1 +
src/lsmsvgview.c | 93 ++++++++++++++++++++++++++++++++++++++++-----------
7 files changed, 112 insertions(+), 20 deletions(-)
---
diff --git a/src/lsmcairo.c b/src/lsmcairo.c
index 980d951..c568fd5 100644
--- a/src/lsmcairo.c
+++ b/src/lsmcairo.c
@@ -595,3 +595,4 @@ lsm_cairo_set_source_pixbuf (cairo_t *cairo,
cairo_set_source_surface (cairo, surface, pixbuf_x, pixbuf_y);
cairo_surface_destroy (surface);
}
+
diff --git a/src/lsmcairo.h b/src/lsmcairo.h
index d6f895b..eed4148 100644
--- a/src/lsmcairo.h
+++ b/src/lsmcairo.h
@@ -45,6 +45,7 @@ void lsm_cairo_box_user_to_device (cairo_t *cairo, LsmBox *to, const LsmBox
void lsm_cairo_box_device_to_user (cairo_t *cairo, LsmBox *to, const LsmBox *from);
void lsm_cairo_set_source_pixbuf (cairo_t *cairo, const GdkPixbuf *pixbuf,
double pixbuf_x, double pixbuf_y);
+
G_END_DECLS
#endif
diff --git a/src/lsmsvgstyle.c b/src/lsmsvgstyle.c
index 8c0cf77..1f6df04 100644
--- a/src/lsmsvgstyle.c
+++ b/src/lsmsvgstyle.c
@@ -54,6 +54,12 @@ static const LsmPropertyInfos lsm_svg_property_infos[] = {
.trait_default = "none"
},
{
+ .name = "comp-op",
+ .id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, comp_op),
+ .trait_class = &lsm_svg_comp_op_trait_class,
+ .trait_default = "src-over"
+ },
+ {
.name = "dominant-baseline",
.id = LSM_PROPERTY_OFFSET_TO_ID (LsmSvgStyle, dominant_baseline),
.trait_class = &lsm_null_trait_class,
diff --git a/src/lsmsvgstyle.h b/src/lsmsvgstyle.h
index 8197d49..e76bad5 100644
--- a/src/lsmsvgstyle.h
+++ b/src/lsmsvgstyle.h
@@ -31,6 +31,11 @@ G_BEGIN_DECLS
typedef struct {
LsmProperty base;
+ LsmSvgCompOp value;
+} LsmSvgCompOpProperty;
+
+typedef struct {
+ LsmProperty base;
double value;
} LsmSvgDoubleProperty;
@@ -126,6 +131,7 @@ struct _LsmSvgStyle {
LsmProperty * baseline_shift;
LsmProperty * clip;
LsmProperty * clip_path;
+ LsmSvgCompOpProperty * comp_op;
LsmProperty * dominant_baseline;
LsmSvgEnableBackgroundProperty *enable_background;
LsmProperty * filter;
diff --git a/src/lsmsvgtraits.c b/src/lsmsvgtraits.c
index 9db4bea..053467e 100644
--- a/src/lsmsvgtraits.c
+++ b/src/lsmsvgtraits.c
@@ -56,6 +56,30 @@ const LsmTraitClass lsm_svg_blending_mode_trait_class = {
};
static gboolean
+lsm_svg_comp_op_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+ LsmSvgCompOp *trait = (LsmSvgCompOp *) abstract_trait;
+
+ *trait = lsm_svg_comp_op_from_string (string);
+
+ return *trait >= 0;
+}
+
+char *
+lsm_svg_comp_op_trait_to_string (LsmTrait *abstract_trait)
+{
+ LsmSvgCompOp *trait = (LsmSvgCompOp *) abstract_trait;
+
+ return g_strdup (lsm_svg_comp_op_to_string (*trait));
+}
+
+const LsmTraitClass lsm_svg_comp_op_trait_class = {
+ .size = sizeof (LsmSvgCompOp),
+ .from_string = lsm_svg_comp_op_trait_from_string,
+ .to_string = lsm_svg_comp_op_trait_to_string
+};
+
+static gboolean
lsm_svg_enable_background_trait_from_string (LsmTrait *abstract_trait, char *string)
{
LsmSvgEnableBackground *trait = (LsmSvgEnableBackground *) abstract_trait;
diff --git a/src/lsmsvgtraits.h b/src/lsmsvgtraits.h
index c51f9f2..7fb2644 100644
--- a/src/lsmsvgtraits.h
+++ b/src/lsmsvgtraits.h
@@ -76,6 +76,7 @@ extern const LsmTraitClass lsm_svg_angle_trait_class;
extern const LsmTraitClass lsm_svg_blending_mode_trait_class;
extern const LsmTraitClass lsm_svg_enable_background_trait_class;
extern const LsmTraitClass lsm_svg_color_trait_class;
+extern const LsmTraitClass lsm_svg_comp_op_trait_class;
extern const LsmTraitClass lsm_svg_dash_array_trait_class;
extern const LsmTraitClass lsm_svg_display_trait_class;
extern const LsmTraitClass lsm_svg_fill_rule_trait_class;
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index f72123a..c2fcbc2 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -77,6 +77,40 @@ typedef struct {
gboolean enable_background;
} LsmSvgViewBackground;
+cairo_operator_t cairo_operators[] = {
+ CAIRO_OPERATOR_CLEAR,
+ CAIRO_OPERATOR_SOURCE,
+ CAIRO_OPERATOR_DEST,
+ CAIRO_OPERATOR_OVER,
+ CAIRO_OPERATOR_DEST_OVER,
+ CAIRO_OPERATOR_IN,
+ CAIRO_OPERATOR_DEST_IN,
+ CAIRO_OPERATOR_OUT,
+ CAIRO_OPERATOR_DEST_OUT,
+ CAIRO_OPERATOR_ATOP,
+ CAIRO_OPERATOR_DEST_ATOP,
+ CAIRO_OPERATOR_XOR,
+ CAIRO_OPERATOR_ADD,
+ CAIRO_OPERATOR_MULTIPLY,
+ CAIRO_OPERATOR_SCREEN,
+ CAIRO_OPERATOR_OVERLAY,
+ CAIRO_OPERATOR_DARKEN,
+ CAIRO_OPERATOR_LIGHTEN,
+ CAIRO_OPERATOR_COLOR_DODGE,
+ CAIRO_OPERATOR_COLOR_BURN,
+ CAIRO_OPERATOR_HARD_LIGHT,
+ CAIRO_OPERATOR_SOFT_LIGHT,
+ CAIRO_OPERATOR_DIFFERENCE,
+ CAIRO_OPERATOR_EXCLUSION
+};
+
+void
+lsm_cairo_set_comp_op (cairo_t *cairo, LsmSvgCompOp comp_op)
+{
+ if (G_LIKELY (cairo != NULL && comp_op >= LSM_SVG_COMP_OP_CLEAR && comp_op <= LSM_SVG_COMP_OP_EXCLUSION))
+ cairo_set_operator (cairo, cairo_operators[comp_op]);
+}
+
double
lsm_svg_view_normalize_length (LsmSvgView *view, const LsmSvgLength *length, LsmSvgLengthDirection direction)
{
@@ -660,7 +694,8 @@ paint (LsmSvgView *view, LsmSvgViewPathInfos *path_infos)
cairo = view->dom_view.cairo;
style = view->style;
- if (style->opacity != NULL &&
+ if ((style->opacity != NULL ||
+ style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER ) &&
style->ignore_group_opacity &&
g_strcmp0 (style->filter->value, "none") == 0) {
group_opacity = style->opacity->value;
@@ -671,15 +706,17 @@ paint (LsmSvgView *view, LsmSvgViewPathInfos *path_infos)
style->stroke->paint.type == LSM_SVG_PAINT_TYPE_URI_RGB_COLOR ||
style->fill->paint.type == LSM_SVG_PAINT_TYPE_URI_RGB_COLOR ||
style->fill->paint.type == LSM_SVG_PAINT_TYPE_URI) &&
- group_opacity < 1.0;
+ (group_opacity < 1.0 || style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER );
} else {
use_group = FALSE;
group_opacity = 1.0;
}
/* Instead of push_group, we should restrict to the current path bounding box */
- if (use_group)
+ if (use_group) {
cairo_push_group (cairo);
+ } else if (style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER)
+ lsm_cairo_set_comp_op (cairo, style->comp_op->value);
if (_set_color (view,
path_infos,
@@ -762,8 +799,13 @@ paint (LsmSvgView *view, LsmSvgViewPathInfos *path_infos)
if (use_group) {
cairo_pop_group_to_source (cairo);
+ if (G_UNLIKELY (style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER))
+ lsm_cairo_set_comp_op (cairo, style->comp_op->value);
cairo_paint_with_alpha (cairo, group_opacity);
}
+
+ if (view->style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER)
+ lsm_cairo_set_comp_op (cairo, LSM_SVG_COMP_OP_SRC_OVER);
}
static void
@@ -2076,11 +2118,13 @@ lsm_svg_view_push_composition (LsmSvgView *view, LsmSvgStyle *style)
do_mask = (g_strcmp0 (style->mask->value, "none") != 0);
do_filter = (g_strcmp0 (style->filter->value, "none") != 0);
- if ((view->style->opacity->value < 1.0 ||
- view->style->enable_background->value == LSM_SVG_ENABLE_BACKGROUND_NEW) &&
- !do_filter &&
- !view->is_clipping &&
- !view->style->ignore_group_opacity) {
+ if (G_UNLIKELY((view->style->opacity->value < 1.0 ||
+ view->style->enable_background->value == LSM_SVG_ENABLE_BACKGROUND_NEW ||
+ view->style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER) &&
+ !do_filter &&
+ !view->is_clipping &&
+ !view->style->ignore_group_opacity &&
+ view->dom_view.cairo != NULL)) {
LsmSvgViewBackground *background;
lsm_debug_render ("[LsmSvgView::push_composition] Push group");
@@ -2094,12 +2138,12 @@ lsm_svg_view_push_composition (LsmSvgView *view, LsmSvgStyle *style)
view->background_stack = g_list_prepend (view->background_stack, background);
}
- if (do_clip) {
+ if (G_UNLIKELY (do_clip)) {
lsm_debug_render ("[LsmSvgView::push_style] Start clip '%s'", style->clip_path->value);
lsm_svg_view_push_clip (view);
}
- if (do_mask) {
+ if (G_UNLIKELY (do_mask)) {
lsm_debug_render ("[LsmSvgView::push_style] Start mask '%s'", style->mask->value);
lsm_svg_view_push_mask (view);
}
@@ -2107,7 +2151,7 @@ lsm_svg_view_push_composition (LsmSvgView *view, LsmSvgStyle *style)
/* Don't do filtering during a clipping operation, as filter will
* create a new subsurface, where clipping should occur with the path
* of the clip-path element. */
- if (do_filter && !view->is_clipping) {
+ if (G_UNLIKELY (do_filter && !view->is_clipping)) {
lsm_debug_render ("[LsmSvgView::push_style] Start filter '%s'", style->filter->value);
lsm_svg_view_push_filter (view);
}
@@ -2129,6 +2173,7 @@ void lsm_svg_view_pop_composition (LsmSvgView *view)
gboolean do_filter;
gboolean do_mask;
gboolean do_clip;
+ cairo_t *cairo;
g_return_if_fail (LSM_IS_SVG_VIEW (view));
g_return_if_fail (view->style != NULL);
@@ -2142,25 +2187,33 @@ void lsm_svg_view_pop_composition (LsmSvgView *view)
/* Don't do filtering during a clipping operation, as filter will
* create a new subsurface, where clipping should occur with the path
* of the clip-path element. */
- if (do_filter && !view->is_clipping)
+ if (G_UNLIKELY (do_filter && !view->is_clipping))
lsm_svg_view_pop_filter (view);
- if (do_mask)
+ if (G_UNLIKELY (do_mask))
lsm_svg_view_pop_mask (view);
- if (do_clip)
+ if (G_UNLIKELY (do_clip))
lsm_svg_view_pop_clip (view);
- if ((view->style->opacity->value < 1.0 ||
- view->style->enable_background->value == LSM_SVG_ENABLE_BACKGROUND_NEW) &&
- !do_filter &&
- !view->is_clipping &&
- !view->style->ignore_group_opacity) {
+ cairo = view->dom_view.cairo;
+
+ if (G_UNLIKELY ((view->style->opacity->value < 1.0 ||
+ view->style->enable_background->value == LSM_SVG_ENABLE_BACKGROUND_NEW ||
+ view->style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER) &&
+ !do_filter &&
+ !view->is_clipping &&
+ !view->style->ignore_group_opacity &&
+ cairo != NULL)) {
g_slice_free (LsmSvgViewBackground, view->background_stack->data);
view->background_stack = g_list_delete_link (view->background_stack, view->background_stack);
cairo_pop_group_to_source (view->dom_view.cairo);
- cairo_paint_with_alpha (view->dom_view.cairo, view->style->opacity->value);
+ if (G_UNLIKELY (view->style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER))
+ lsm_cairo_set_comp_op (cairo, view->style->comp_op->value);
+ cairo_paint_with_alpha (cairo, view->style->opacity->value);
+ if (G_UNLIKELY (view->style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER))
+ lsm_cairo_set_comp_op (cairo, LSM_SVG_COMP_OP_SRC_OVER);
lsm_debug_render ("[LsmSvgView::pop_composition] Pop group");
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]