[lasem] <svg:mask> Start the implementation. Create a new mask attribute bag.
- From: Emmanuel Pacaud <emmanuel src gnome org>
- To: svn-commits-list gnome org
- Subject: [lasem] <svg:mask> Start the implementation. Create a new mask attribute bag.
- Date: Wed, 24 Jun 2009 15:29:10 +0000 (UTC)
commit 48ef6e70278997b28931e60d4ea8f5314a139832
Author: Emmanuel Pacaud <emmanuel pacaud lapp in2p3 fr>
Date: Wed Jun 24 17:27:53 2009 +0200
<svg:mask> Start the implementation. Create a new mask attribute bag.
The new mask attribute bag also contains the opacity property.
src/Makefile.am | 2 +
src/lsmsvg.h | 1 +
src/lsmsvgattributebags.c | 46 ++++++++--
src/lsmsvgattributebags.h | 9 ++-
src/lsmsvgcircleelement.c | 1 -
src/lsmsvgdocument.c | 3 +
src/lsmsvgelement.c | 5 +
src/lsmsvgellipseelement.c | 1 -
src/lsmsvggraphic.c | 46 +++++------
src/lsmsvggraphic.h | 4 +-
src/lsmsvglineelement.c | 1 -
src/lsmsvgmaskelement.c | 130 +++++++++++++++++++++++++++
src/lsmsvgmaskelement.h | 60 +++++++++++++
src/lsmsvgpathelement.c | 1 -
src/lsmsvgpolygonelement.c | 1 -
src/lsmsvgpolylineelement.c | 1 -
src/lsmsvgrectelement.c | 1 -
src/lsmsvgtextelement.c | 1 -
src/lsmsvgview.c | 202 +++++++++++++++++++++++++-----------------
src/lsmsvgview.h | 23 +++--
20 files changed, 401 insertions(+), 138 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 58d7bd1..dc76bd8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -83,6 +83,7 @@ liblasem_la_SOURCES = \
lsmsvgradialgradientelement.c \
lsmsvgstopelement.c \
lsmsvgpatternelement.c \
+ lsmsvgmaskelement.c \
lsmsvgenums.c \
lsmsvgattributes.c \
lsmsvgattributebags.c \
@@ -165,6 +166,7 @@ liblasem_la_HEADERS = \
lsmsvgradialgradientelement.h \
lsmsvgstopelement.h \
lsmsvgpatternelement.h \
+ lsmsvgmaskelement.h \
lsmsvgenums.h \
lsmsvgattributes.h \
lsmsvgattributebags.h \
diff --git a/src/lsmsvg.h b/src/lsmsvg.h
index 8277921..43bc421 100644
--- a/src/lsmsvg.h
+++ b/src/lsmsvg.h
@@ -49,6 +49,7 @@ typedef struct _LsmSvgLinearGradientElement LsmSvgLinearGradientElement;
typedef struct _LsmSvgRadialGradientElement LsmSvgRadialGradientElement;
typedef struct _LsmSvgStopElement LsmSvgStopElement;
typedef struct _LsmSvgPatternElement LsmSvgPatternElement;
+typedef struct _LsmSvgMaskElement LsmSvgMaskElement;
typedef struct _LsmSvgView LsmSvgView;
typedef struct _LsmSvgStyle LsmSvgStyle;
diff --git a/src/lsmsvgattributebags.c b/src/lsmsvgattributebags.c
index b34d68e..dfadb82 100644
--- a/src/lsmsvgattributebags.c
+++ b/src/lsmsvgattributebags.c
@@ -22,6 +22,44 @@
#include <lsmsvgattributebags.h>
static void *
+lsm_svg_mask_attribute_bag_init (void)
+{
+ LsmSvgMaskAttributeBag *mask;
+
+ mask = g_new0 (LsmSvgMaskAttributeBag, 1);
+ return mask;
+}
+
+static void
+lsm_svg_mask_attribute_bag_finalize (void *bag)
+{
+ g_free (bag);
+}
+
+static const LsmDomAttributeBagClass lsm_svg_mask_attribute_bag_class =
+{
+ .init = lsm_svg_mask_attribute_bag_init,
+ .finalize = lsm_svg_mask_attribute_bag_finalize
+};
+
+void
+lsm_dom_attribute_map_add_mask_attribute_bag (LsmDomAttributeMap *map, ptrdiff_t bag_offset)
+{
+ lsm_dom_attribute_map_add_bag_attribute (map, "opacity",
+ offsetof (LsmSvgMaskAttributeBag, opacity),
+ NULL,
+ bag_offset, &lsm_svg_mask_attribute_bag_class);
+ lsm_dom_attribute_map_add_bag_attribute (map, "clip-path",
+ offsetof (LsmSvgMaskAttributeBag, clip_path),
+ NULL,
+ bag_offset, &lsm_svg_mask_attribute_bag_class);
+ lsm_dom_attribute_map_add_bag_attribute (map, "clip-rule",
+ offsetof (LsmSvgMaskAttributeBag, clip_rule),
+ NULL,
+ bag_offset, &lsm_svg_mask_attribute_bag_class);
+}
+
+static void *
lsm_svg_fill_attribute_bag_init (void)
{
LsmSvgFillAttributeBag *fill;
@@ -61,14 +99,6 @@ lsm_dom_attribute_map_add_fill_attribute_bag (LsmDomAttributeMap *map, ptrdiff_t
offsetof (LsmSvgFillAttributeBag, opacity),
NULL,
bag_offset, &lsm_svg_fill_attribute_bag_class);
- lsm_dom_attribute_map_add_bag_attribute (map, "clip-path",
- offsetof (LsmSvgFillAttributeBag, clip_path),
- NULL,
- bag_offset, &lsm_svg_fill_attribute_bag_class);
- lsm_dom_attribute_map_add_bag_attribute (map, "clip-rule",
- offsetof (LsmSvgFillAttributeBag, clip_rule),
- NULL,
- bag_offset, &lsm_svg_fill_attribute_bag_class);
}
static void *
diff --git a/src/lsmsvgattributebags.h b/src/lsmsvgattributebags.h
index d7dfdd7..e84f07b 100644
--- a/src/lsmsvgattributebags.h
+++ b/src/lsmsvgattributebags.h
@@ -28,11 +28,15 @@
G_BEGIN_DECLS
typedef struct {
+ LsmDomAttribute clip_path;
+ LsmDomEnumAttribute clip_rule;
+ LsmSvgDoubleAttribute opacity;
+} LsmSvgMaskAttributeBag;
+
+typedef struct {
LsmSvgPaintAttribute paint;
LsmDomEnumAttribute rule;
LsmDomDoubleAttribute opacity;
- LsmDomAttribute clip_path;
- LsmDomEnumAttribute clip_rule;
} LsmSvgFillAttributeBag;
typedef struct {
@@ -60,6 +64,7 @@ typedef struct {
LsmSvgDoubleAttribute opacity;
} LsmSvgStopAttributeBag;
+void lsm_dom_attribute_map_add_mask_attribute_bag (LsmDomAttributeMap *map, ptrdiff_t bag_offset);
void lsm_dom_attribute_map_add_fill_attribute_bag (LsmDomAttributeMap *map, ptrdiff_t bag_offset);
void lsm_dom_attribute_map_add_stroke_attribute_bag (LsmDomAttributeMap *map, ptrdiff_t bag_offset);
void lsm_dom_attribute_map_add_transform_attribute_bag (LsmDomAttributeMap *map, ptrdiff_t bag_offset);
diff --git a/src/lsmsvgcircleelement.c b/src/lsmsvgcircleelement.c
index b0a333b..5371a7d 100644
--- a/src/lsmsvgcircleelement.c
+++ b/src/lsmsvgcircleelement.c
@@ -111,7 +111,6 @@ lsm_svg_circle_element_class_init (LsmSvgCircleElementClass *s_rect_class)
s_element_class->update = lsm_svg_circle_element_update;
s_graphic_class->graphic_render = lsm_svg_circle_element_graphic_render;
- s_graphic_class->late_opacity_handling = TRUE;
s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
diff --git a/src/lsmsvgdocument.c b/src/lsmsvgdocument.c
index 941b389..3c41c33 100644
--- a/src/lsmsvgdocument.c
+++ b/src/lsmsvgdocument.c
@@ -40,6 +40,7 @@
#include <lsmsvgradialgradientelement.h>
#include <lsmsvgstopelement.h>
#include <lsmsvgpatternelement.h>
+#include <lsmsvgmaskelement.h>
#include <lsmsvgview.h>
#include <string.h>
@@ -86,6 +87,8 @@ lsm_svg_document_create_element (LsmDomDocument *document, const char *tag_name)
node = lsm_svg_stop_element_new ();
else if (strcmp (tag_name, "pattern") == 0)
node = lsm_svg_pattern_element_new ();
+ else if (strcmp (tag_name, "mask") == 0)
+ node = lsm_svg_mask_element_new ();
else if (strcmp (tag_name, "use") == 0)
node = lsm_svg_use_element_new ();
else if (strcmp (tag_name, "image") == 0)
diff --git a/src/lsmsvgelement.c b/src/lsmsvgelement.c
index daeea96..26299b2 100644
--- a/src/lsmsvgelement.c
+++ b/src/lsmsvgelement.c
@@ -138,6 +138,9 @@ lsm_svg_element_render (LsmSvgElement *element, LsmSvgView *view)
g_return_if_fail (LSM_IS_SVG_ELEMENT (element));
+
+ lsm_svg_view_push_element (view, element);
+
element_class = LSM_SVG_ELEMENT_GET_CLASS (element);
if (element_class->render != NULL) {
lsm_debug ("[LsmSvgElement::render] Render %s (%s)",
@@ -146,6 +149,8 @@ lsm_svg_element_render (LsmSvgElement *element, LsmSvgView *view)
element_class->render (element, view);
}
+
+ lsm_svg_view_pop_element (view);
}
void
diff --git a/src/lsmsvgellipseelement.c b/src/lsmsvgellipseelement.c
index e26fc78..17f7783 100644
--- a/src/lsmsvgellipseelement.c
+++ b/src/lsmsvgellipseelement.c
@@ -112,7 +112,6 @@ lsm_svg_ellipse_element_class_init (LsmSvgEllipseElementClass *s_rect_class)
s_element_class->update = lsm_svg_ellipse_element_update;
s_graphic_class->graphic_render = lsm_svg_ellipse_element_graphic_render;
- s_graphic_class->late_opacity_handling = TRUE;
s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
diff --git a/src/lsmsvggraphic.c b/src/lsmsvggraphic.c
index d32abb8..75ec2c5 100644
--- a/src/lsmsvggraphic.c
+++ b/src/lsmsvggraphic.c
@@ -92,14 +92,19 @@ lsm_svg_graphic_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
lsm_svg_color_attribute_parse (&graphic->color, &parent_style->color, &parent_style->color);
- default_opacity = 1.0;
- lsm_svg_double_attribute_parse (&graphic->opacity, &default_opacity); /* FIXME handle inherit */
if (graphic->text != NULL) {
lsm_dom_string_attribute_parse (&graphic->text->font_family, &parent_style->text.font_family);
lsm_svg_length_attribute_parse (&graphic->text->font_size, &parent_style->text.font_size);
}
+ if (graphic->mask != NULL) {
+ lsm_svg_fill_rule_attribute_parse (&graphic->mask->clip_rule, &parent_style->clip.rule);
+ default_opacity = 1.0;
+ /* FIXME handle inherit */
+ lsm_svg_double_attribute_parse (&graphic->mask->opacity, &default_opacity);
+ }
+
if (graphic->fill != NULL) {
lsm_debug ("[LsmSvgGraphic::update] fill");
@@ -107,7 +112,6 @@ lsm_svg_graphic_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
&graphic->color.value);
lsm_svg_fill_rule_attribute_parse (&graphic->fill->rule, &parent_style->fill.rule);
lsm_dom_double_attribute_parse (&graphic->fill->opacity, &parent_style->fill.opacity);
- lsm_svg_fill_rule_attribute_parse (&graphic->fill->clip_rule, &parent_style->clip.rule);
}
if (graphic->stroke != NULL) {
@@ -141,14 +145,21 @@ lsm_svg_graphic_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
static void
_graphic_render (LsmSvgElement *self, LsmSvgView *view)
{
+ LsmSvgGraphic *graphic = LSM_SVG_GRAPHIC (self);
LsmDomNode *node;
lsm_debug ("[LsmSvgGraphic::_graphic_render]");
+ if (graphic->mask != NULL)
+ lsm_svg_view_push_group_opacity (view);
+
for (node = LSM_DOM_NODE (self)->first_child; node != NULL; node = node->next_sibling) {
if (LSM_IS_SVG_ELEMENT (node))
lsm_svg_element_render (LSM_SVG_ELEMENT (node), view);
}
+
+ if (graphic->mask != NULL)
+ lsm_svg_view_pop_group_opacity (view);
}
static void
@@ -159,20 +170,10 @@ lsm_svg_graphic_render (LsmSvgElement *self, LsmSvgView *view)
if (graphic->transform != NULL)
lsm_svg_view_push_matrix (view, &graphic->transform->transform.matrix);
- lsm_svg_view_push_opacity (view, graphic->opacity.value,
- LSM_SVG_GRAPHIC_GET_CLASS (graphic)->late_opacity_handling);
-
- if (graphic->fill != NULL) {
+ if (graphic->mask != NULL)
+ lsm_svg_view_push_mask_attributes (view, graphic->mask);
+ if (graphic->fill != NULL)
lsm_svg_view_push_fill_attributes (view, graphic->fill);
-
- if (graphic->fill->clip_path.value != NULL) {
- LsmExtents extents;
-
- lsm_svg_element_get_extents (self, view, &extents);
- lsm_svg_view_push_clip (view, graphic->fill->clip_path.value,
- graphic->fill->clip_rule.value, &extents);
- }
- }
if (graphic->stroke != NULL)
lsm_svg_view_push_stroke_attributes (view, graphic->stroke);
if (graphic->text != NULL)
@@ -184,13 +185,10 @@ lsm_svg_graphic_render (LsmSvgElement *self, LsmSvgView *view)
lsm_svg_view_pop_text_attributes (view);
if (graphic->stroke != NULL)
lsm_svg_view_pop_stroke_attributes (view);
- if (graphic->fill != NULL) {
- if (graphic->fill->clip_path.value != NULL)
- lsm_svg_view_pop_clip (view);
+ if (graphic->fill != NULL)
lsm_svg_view_pop_fill_attributes (view);
- }
-
- lsm_svg_view_pop_opacity (view);
+ if (graphic->mask != NULL)
+ lsm_svg_view_pop_mask_attributes (view);
if (graphic->transform != NULL)
lsm_svg_view_pop_matrix (view);
@@ -275,7 +273,6 @@ lsm_svg_graphic_class_init (LsmSvgGraphicClass *s_graphic_class)
s_graphic_class->graphic_render = _graphic_render;
s_graphic_class->graphic_get_extents = _graphic_get_extents;
- s_graphic_class->late_opacity_handling = FALSE;
s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
@@ -285,9 +282,8 @@ lsm_svg_graphic_class_init (LsmSvgGraphicClass *s_graphic_class)
offsetof (LsmSvgGraphic, style));
lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "color",
offsetof (LsmSvgGraphic, color));
- lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "opacity",
- offsetof (LsmSvgGraphic, opacity));
+ lsm_dom_attribute_map_add_mask_attribute_bag (s_element_class->attributes, offsetof (LsmSvgGraphic, mask));
lsm_dom_attribute_map_add_fill_attribute_bag (s_element_class->attributes, offsetof (LsmSvgGraphic, fill));
lsm_dom_attribute_map_add_stroke_attribute_bag (s_element_class->attributes, offsetof (LsmSvgGraphic, stroke));
lsm_dom_attribute_map_add_transform_attribute_bag (s_element_class->attributes,
diff --git a/src/lsmsvggraphic.h b/src/lsmsvggraphic.h
index 4127964..5750845 100644
--- a/src/lsmsvggraphic.h
+++ b/src/lsmsvggraphic.h
@@ -43,8 +43,8 @@ struct _LsmSvgGraphic {
LsmDomAttribute style;
LsmSvgColorAttribute color;
- LsmSvgDoubleAttribute opacity;
+ LsmSvgMaskAttributeBag *mask;
LsmSvgFillAttributeBag *fill;
LsmSvgStrokeAttributeBag *stroke;
LsmSvgTransformAttributeBag *transform;
@@ -57,8 +57,6 @@ struct _LsmSvgGraphicClass {
void (*graphic_render) (LsmSvgElement *element, LsmSvgView *view);
void (*graphic_get_extents) (LsmSvgElement *element, LsmSvgView *view, LsmExtents *extents);
-
- gboolean late_opacity_handling;
};
GType lsm_svg_graphic_get_type (void);
diff --git a/src/lsmsvglineelement.c b/src/lsmsvglineelement.c
index 3924c7d..a272bb3 100644
--- a/src/lsmsvglineelement.c
+++ b/src/lsmsvglineelement.c
@@ -107,7 +107,6 @@ lsm_svg_line_element_class_init (LsmSvgLineElementClass *s_rect_class)
s_element_class->update = lsm_svg_line_element_update;
s_graphic_class->graphic_render = lsm_svg_line_element_graphic_render;
- s_graphic_class->late_opacity_handling = TRUE;
s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
diff --git a/src/lsmsvgmaskelement.c b/src/lsmsvgmaskelement.c
new file mode 100644
index 0000000..d8a2a7a
--- /dev/null
+++ b/src/lsmsvgmaskelement.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright © 2009 Emmanuel Pacaud
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#include <lsmsvgmaskelement.h>
+#include <lsmsvgview.h>
+#include <lsmdebug.h>
+#include <stdio.h>
+
+static GObjectClass *parent_class;
+
+/* GdomNode implementation */
+
+static const char *
+_mask_element_get_node_name (LsmDomNode *node)
+{
+ return "mask";
+}
+
+/* LsmSvgElement implementation */
+
+static void
+_mask_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
+{
+ LsmSvgMaskElement *mask = LSM_SVG_MASK_ELEMENT (self);
+ LsmSvgPatternUnits units;
+ LsmSvgLength length;
+
+ units = LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX;
+ lsm_svg_pattern_units_attribute_parse (&mask->units, &units);
+
+ units = LSM_SVG_PATTERN_UNITS_USER_SPACE_ON_USE;
+ lsm_svg_pattern_units_attribute_parse (&mask->content_units, &units);
+
+ length.value_unit = 0.0;
+ length.type = LSM_SVG_LENGTH_TYPE_PX;
+ lsm_svg_animated_length_attribute_parse (&mask->x, &length);
+
+ length.value_unit = 0.0;
+ length.type = LSM_SVG_LENGTH_TYPE_PX;
+ lsm_svg_animated_length_attribute_parse (&mask->y, &length);
+
+ length.value_unit = 0.0;
+ length.type = LSM_SVG_LENGTH_TYPE_PX;
+ lsm_svg_animated_length_attribute_parse (&mask->width, &length);
+
+ length.value_unit = 0.0;
+ length.type = LSM_SVG_LENGTH_TYPE_PX;
+ lsm_svg_animated_length_attribute_parse (&mask->height, &length);
+
+ LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
+}
+
+static void
+_mask_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
+{
+}
+
+/* LsmSvgMaskElement implementation */
+
+LsmDomNode *
+lsm_svg_mask_element_new (void)
+{
+ return g_object_new (LSM_TYPE_SVG_MASK_ELEMENT, NULL);
+}
+
+static void
+lsm_svg_mask_element_init (LsmSvgMaskElement *self)
+{
+ /* Hack - Force the creation of the attribute bags,
+ making sure the properties will be inherited from the
+ mask element ancestor, not the referencing one. */
+
+ lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "fill", NULL);
+ lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "stroke", NULL);
+ lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "transform", NULL);
+ lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "font-family", NULL);
+ lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "stop-color", NULL);
+}
+
+/* LsmSvgMaskElement class */
+
+static void
+lsm_svg_mask_element_class_init (LsmSvgMaskElementClass *klass)
+{
+ LsmDomNodeClass *d_node_class = LSM_DOM_NODE_CLASS (klass);
+ LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ d_node_class->get_node_name = _mask_element_get_node_name;
+
+ s_element_class->update = _mask_element_update;
+ s_element_class->render_paint = _mask_element_render_paint;
+ s_element_class->render = NULL;
+
+ s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
+
+ lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "x",
+ offsetof (LsmSvgMaskElement, x));
+ lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "y",
+ offsetof (LsmSvgMaskElement, y));
+ lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "width",
+ offsetof (LsmSvgMaskElement, width));
+ lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "height",
+ offsetof (LsmSvgMaskElement, height));
+ lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "maskUnits",
+ offsetof (LsmSvgMaskElement, units));
+ lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "maskContentUnits",
+ offsetof (LsmSvgMaskElement, content_units));
+}
+
+G_DEFINE_TYPE (LsmSvgMaskElement, lsm_svg_mask_element, LSM_TYPE_SVG_GRAPHIC)
diff --git a/src/lsmsvgmaskelement.h b/src/lsmsvgmaskelement.h
new file mode 100644
index 0000000..c51338a
--- /dev/null
+++ b/src/lsmsvgmaskelement.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright © 2009 Emmanuel Pacaud
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_SVG_MASK_ELEMENT_H
+#define LSM_SVG_MASK_ELEMENT_H
+
+#include <lsmsvg.h>
+#include <lsmsvggraphic.h>
+
+G_BEGIN_DECLS
+
+#define LSM_TYPE_SVG_MASK_ELEMENT (lsm_svg_mask_element_get_type ())
+#define LSM_SVG_MASK_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LSM_TYPE_SVG_MASK_ELEMENT, LsmSvgMaskElement))
+#define LSM_SVG_MASK_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), LSM_TYPE_SVG_MASK_ELEMENT, LsmSvgMaskElementClass))
+#define LSM_IS_SVG_MASK_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LSM_TYPE_SVG_MASK_ELEMENT))
+#define LSM_IS_SVG_MASK_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), LSM_TYPE_SVG_MASK_ELEMENT))
+#define LSM_SVG_MASK_ELEMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), LSM_TYPE_SVG_MASK_ELEMENT, LsmSvgMaskElementClass))
+
+typedef struct _LsmSvgMaskElementClass LsmSvgMaskElementClass;
+
+struct _LsmSvgMaskElement {
+ LsmSvgGraphic graphic;
+
+ LsmSvgAnimatedLengthAttribute x;
+ LsmSvgAnimatedLengthAttribute y;
+ LsmSvgAnimatedLengthAttribute width;
+ LsmSvgAnimatedLengthAttribute height;
+ LsmDomEnumAttribute units;
+ LsmDomEnumAttribute content_units;
+};
+
+struct _LsmSvgMaskElementClass {
+ LsmSvgGraphicClass parent_class;
+};
+
+GType lsm_svg_mask_element_get_type (void);
+
+LsmDomNode * lsm_svg_mask_element_new (void);
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmsvgpathelement.c b/src/lsmsvgpathelement.c
index 408f8cb..e7e55d1 100644
--- a/src/lsmsvgpathelement.c
+++ b/src/lsmsvgpathelement.c
@@ -82,7 +82,6 @@ lsm_svg_path_element_class_init (LsmSvgPathElementClass *s_rect_class)
d_node_class->get_node_name = lsm_svg_path_element_get_node_name;
s_graphic_class->graphic_render = lsm_svg_path_element_graphic_render;
- s_graphic_class->late_opacity_handling = TRUE;
s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
diff --git a/src/lsmsvgpolygonelement.c b/src/lsmsvgpolygonelement.c
index b30071c..a560e6f 100644
--- a/src/lsmsvgpolygonelement.c
+++ b/src/lsmsvgpolygonelement.c
@@ -71,7 +71,6 @@ lsm_svg_polygon_element_class_init (LsmSvgPolygonElementClass *s_rect_class)
d_node_class->get_node_name = lsm_svg_polygon_element_get_node_name;
s_graphic_class->graphic_render = lsm_svg_polygon_element_graphic_render;
- s_graphic_class->late_opacity_handling = TRUE;
s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
diff --git a/src/lsmsvgpolylineelement.c b/src/lsmsvgpolylineelement.c
index 37ff4f4..0facb9a 100644
--- a/src/lsmsvgpolylineelement.c
+++ b/src/lsmsvgpolylineelement.c
@@ -71,7 +71,6 @@ lsm_svg_polyline_element_class_init (LsmSvgPolylineElementClass *s_rect_class)
d_node_class->get_node_name = lsm_svg_polyline_element_get_node_name;
s_graphic_class->graphic_render = lsm_svg_polyline_element_graphic_render;
- s_graphic_class->late_opacity_handling = TRUE;
s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
diff --git a/src/lsmsvgrectelement.c b/src/lsmsvgrectelement.c
index 4e1388b..b039e9c 100644
--- a/src/lsmsvgrectelement.c
+++ b/src/lsmsvgrectelement.c
@@ -152,7 +152,6 @@ lsm_svg_rect_element_class_init (LsmSvgRectElementClass *s_rect_class)
s_graphic_class->graphic_render = lsm_svg_rect_element_graphic_render;
s_graphic_class->graphic_get_extents = lsm_svg_rect_element_graphic_get_extents;
- s_graphic_class->late_opacity_handling = TRUE;
s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
diff --git a/src/lsmsvgtextelement.c b/src/lsmsvgtextelement.c
index 845c552..f89c44e 100644
--- a/src/lsmsvgtextelement.c
+++ b/src/lsmsvgtextelement.c
@@ -124,7 +124,6 @@ lsm_svg_text_element_class_init (LsmSvgTextElementClass *s_rect_class)
s_element_class->update = lsm_svg_text_element_update;
s_graphic_class->graphic_render = lsm_svg_text_element_graphic_render;
- s_graphic_class->late_opacity_handling = TRUE;
s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index 03a6d66..59792d8 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -36,11 +36,6 @@
static GObjectClass *parent_class;
-typedef struct {
- double opacity;
- gboolean late_opacity_handling;
-} LsmSvgViewOpacityData;
-
struct _LsmSvgViewPatternData {
cairo_t *old_cairo;
@@ -861,14 +856,34 @@ lsm_svg_view_pop_matrix (LsmSvgView *view)
}
void
-lsm_svg_view_push_clip (LsmSvgView *view, char *clip_path, LsmSvgFillRule clip_rule, const LsmExtents *extents)
+lsm_svg_view_push_element (LsmSvgView *view, const LsmSvgElement *element)
+{
+ g_return_if_fail (LSM_IS_SVG_VIEW (view));
+ g_return_if_fail (LSM_IS_SVG_ELEMENT (element));
+
+ view->element_stack = g_slist_prepend (view->element_stack, (void *) element);
+}
+
+void
+lsm_svg_view_pop_element (LsmSvgView *view)
+{
+ g_return_if_fail (LSM_IS_SVG_VIEW (view));
+ g_return_if_fail (view->element_stack != NULL);
+
+ view->element_stack = g_slist_delete_link (view->element_stack, view->element_stack);
+}
+
+static void
+lsm_svg_view_push_clip (LsmSvgView *view, char *clip_path, LsmSvgFillRule clip_rule)
{
LsmDomElement *element;
+ LsmExtents extents;
char *uri;
g_return_if_fail (LSM_IS_SVG_VIEW (view));
g_return_if_fail (!view->is_clipping);
- g_return_if_fail (extents != NULL);
+
+ lsm_svg_element_get_extents (view->element_stack->data, view, &extents);
uri = clip_path;
@@ -876,10 +891,10 @@ lsm_svg_view_push_clip (LsmSvgView *view, char *clip_path, LsmSvgFillRule clip_r
cairo_save (view->dom_view.cairo);
- view->clip_extents.x = extents->x1;
- view->clip_extents.y = extents->y1;
- view->clip_extents.width = extents->x2 - extents->x1;
- view->clip_extents.height = extents->y2 - extents->y1;
+ view->clip_extents.x = extents.x1;
+ view->clip_extents.y = extents.y1;
+ view->clip_extents.width = extents.x2 - extents.x1;
+ view->clip_extents.height = extents.y2 - extents.y1;
if (strncmp (uri, "url(#", 5) ==0) {
char *end;
@@ -901,7 +916,7 @@ lsm_svg_view_push_clip (LsmSvgView *view, char *clip_path, LsmSvgFillRule clip_r
}
}
-void
+static void
lsm_svg_view_pop_clip (LsmSvgView *view)
{
lsm_debug ("[LsmSvgView::pop_clip");
@@ -909,21 +924,71 @@ lsm_svg_view_pop_clip (LsmSvgView *view)
cairo_restore (view->dom_view.cairo);
}
-gboolean
-lsm_svg_view_is_clipping (LsmSvgView *view)
+void
+lsm_svg_view_push_group_opacity (LsmSvgView *view)
+{
+ LsmSvgMaskAttributeBag *mask;
+
+ g_return_if_fail (LSM_IS_SVG_VIEW (view));
+ g_return_if_fail (view->mask_stack != NULL);
+
+ mask = view->mask_stack->data;
+
+ if (mask->opacity.value < 1.0)
+ cairo_push_group (view->dom_view.cairo);
+}
+
+void
+lsm_svg_view_pop_group_opacity (LsmSvgView *view)
{
- g_return_val_if_fail (LSM_IS_SVG_VIEW (view), FALSE);
+ LsmSvgMaskAttributeBag *mask;
+
+ g_return_if_fail (LSM_IS_SVG_VIEW (view));
+ g_return_if_fail (view->mask_stack != NULL);
- return view->is_clipping;
+ mask = view->mask_stack->data;
+
+ if (mask->opacity.value < 1.0) {
+ cairo_pop_group_to_source (view->dom_view.cairo);
+ cairo_paint_with_alpha (view->dom_view.cairo, mask->opacity.value);
+ }
}
void
-lsm_svg_view_push_fill_attributes (LsmSvgView *view, LsmSvgFillAttributeBag *fill)
+lsm_svg_view_push_mask_attributes (LsmSvgView *view, const LsmSvgMaskAttributeBag *mask)
+{
+ g_return_if_fail (LSM_IS_SVG_VIEW (view));
+ g_return_if_fail (mask != NULL);
+
+ view->mask_stack = g_slist_prepend (view->mask_stack, (void *) mask);
+
+ if (mask->clip_path.value != NULL)
+ lsm_svg_view_push_clip (view, mask->clip_path.value, mask->clip_rule.value);
+}
+
+void
+lsm_svg_view_pop_mask_attributes (LsmSvgView *view)
+{
+ LsmSvgMaskAttributeBag *mask;
+
+ g_return_if_fail (LSM_IS_SVG_VIEW (view));
+ g_return_if_fail (view->mask_stack != NULL);
+
+ mask = view->mask_stack->data;
+
+ if (mask->clip_path.value != NULL)
+ lsm_svg_view_pop_clip (view);
+
+ view->mask_stack = g_slist_delete_link (view->mask_stack, view->mask_stack);
+}
+
+void
+lsm_svg_view_push_fill_attributes (LsmSvgView *view, const LsmSvgFillAttributeBag *fill)
{
g_return_if_fail (LSM_IS_SVG_VIEW (view));
g_return_if_fail (fill != NULL);
- view->fill_stack = g_slist_prepend (view->fill_stack, fill);
+ view->fill_stack = g_slist_prepend (view->fill_stack, (void *) fill);
}
void
@@ -936,12 +1001,12 @@ lsm_svg_view_pop_fill_attributes (LsmSvgView *view)
}
void
-lsm_svg_view_push_stroke_attributes (LsmSvgView *view, LsmSvgStrokeAttributeBag *stroke)
+lsm_svg_view_push_stroke_attributes (LsmSvgView *view, const LsmSvgStrokeAttributeBag *stroke)
{
g_return_if_fail (LSM_IS_SVG_VIEW (view));
g_return_if_fail (stroke != NULL);
- view->stroke_stack = g_slist_prepend (view->stroke_stack, stroke);
+ view->stroke_stack = g_slist_prepend (view->stroke_stack, (void *) stroke);
}
void
@@ -954,12 +1019,12 @@ lsm_svg_view_pop_stroke_attributes (LsmSvgView *view)
}
void
-lsm_svg_view_push_text_attributes (LsmSvgView *view, LsmSvgTextAttributeBag *text)
+lsm_svg_view_push_text_attributes (LsmSvgView *view, const LsmSvgTextAttributeBag *text)
{
g_return_if_fail (LSM_IS_SVG_VIEW (view));
g_return_if_fail (text != NULL);
- view->text_stack = g_slist_prepend (view->text_stack, text);
+ view->text_stack = g_slist_prepend (view->text_stack, (void *) text);
}
void
@@ -1078,33 +1143,35 @@ paint (LsmSvgView *view)
{
LsmSvgFillAttributeBag *fill;
LsmSvgStrokeAttributeBag *stroke;
+ LsmSvgGraphic *graphic;
cairo_t *cairo;
gboolean use_group;
- double global_opacity;
+ double group_opacity;
g_return_if_fail (view->fill_stack != NULL);
g_return_if_fail (view->stroke_stack != NULL);
+ g_return_if_fail (view->element_stack != NULL);
+
+ graphic = view->element_stack->data;
+
+ g_return_if_fail (LSM_IS_SVG_GRAPHIC (graphic));
cairo = view->dom_view.cairo;
fill = view->fill_stack->data;
stroke = view->stroke_stack->data;
- if (view->opacity_stack != NULL) {
- LsmSvgViewOpacityData *opacity_data;
+ if (view->mask_stack != NULL && view->mask_stack->data == graphic->mask) {
+ LsmSvgMaskAttributeBag *mask;
- opacity_data = view->opacity_stack->data;
- global_opacity = opacity_data->opacity;
+ mask = view->mask_stack->data;
+ group_opacity = mask->opacity.value;
use_group = fill->paint.paint.type != LSM_SVG_PAINT_TYPE_NONE &&
stroke->paint.paint.type != LSM_SVG_PAINT_TYPE_NONE &&
- global_opacity < 1.0;
-
- if (!opacity_data->late_opacity_handling)
- g_warning ("[LsmSvgView::paint] Missing late_opacity_handling declaration in"
- " caller element");
+ group_opacity < 1.0;
} else {
use_group = FALSE;
- global_opacity = 1.0;
+ group_opacity = 1.0;
}
/* FIXME Instead of push_group, restrict to the current path bounding box */
@@ -1112,14 +1179,14 @@ paint (LsmSvgView *view)
cairo_push_group (cairo);
if (_set_color (view, LSM_SVG_VIEW_PAINT_OPERATION_FILL,
- &fill->paint.paint, fill->opacity.value * global_opacity)) {
+ &fill->paint.paint, fill->opacity.value * group_opacity)) {
cairo_set_fill_rule (cairo, fill->rule.value == LSM_SVG_FILL_RULE_EVEN_ODD ?
CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
cairo_fill_preserve (cairo);
}
if (_set_color (view, LSM_SVG_VIEW_PAINT_OPERATION_STROKE,
- &stroke->paint.paint, stroke->opacity.value * global_opacity)) {
+ &stroke->paint.paint, stroke->opacity.value * group_opacity)) {
double line_width;
switch (stroke->line_join.value) {
@@ -1180,7 +1247,7 @@ paint (LsmSvgView *view)
if (use_group) {
cairo_pop_group_to_source (cairo);
- cairo_paint_with_alpha (cairo, global_opacity);
+ cairo_paint_with_alpha (cairo, group_opacity);
}
}
@@ -1188,10 +1255,10 @@ static void
process_path (LsmSvgView *view)
{
if (view->is_clipping) {
- LsmSvgFillAttributeBag *fill;
+ LsmSvgMaskAttributeBag *mask;
- fill = view->fill_stack->data;
- cairo_set_fill_rule (view->dom_view.cairo, fill->clip_rule.value);
+ mask = view->mask_stack->data;
+ cairo_set_fill_rule (view->dom_view.cairo, mask->clip_rule.value);
} else
paint (view);
}
@@ -1395,41 +1462,6 @@ lsm_svg_view_show_pixbuf (LsmSvgView *view, GdkPixbuf *pixbuf)
cairo_paint (view->dom_view.cairo);
}
-void
-lsm_svg_view_push_opacity (LsmSvgView *view, double opacity, gboolean late_opacity_handling)
-{
- LsmSvgViewOpacityData *opacity_data;
-
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
-
- opacity_data = g_new (LsmSvgViewOpacityData, 1);
- opacity_data->opacity = opacity;
- opacity_data->late_opacity_handling = late_opacity_handling;
-
- if (opacity < 1.0 && !late_opacity_handling)
- cairo_push_group (view->dom_view.cairo);
-
- view->opacity_stack = g_slist_prepend (view->opacity_stack, opacity_data);
-}
-
-void
-lsm_svg_view_pop_opacity (LsmSvgView *view)
-{
- LsmSvgViewOpacityData *opacity_data;
-
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
- g_return_if_fail (view->opacity_stack != NULL);
-
- opacity_data = view->opacity_stack->data;
-
- if (opacity_data->opacity < 1.0 && !opacity_data->late_opacity_handling) {
- cairo_pop_group_to_source (view->dom_view.cairo);
- cairo_paint_with_alpha (view->dom_view.cairo, opacity_data->opacity);
- }
-
- view->opacity_stack = g_slist_delete_link (view->opacity_stack, view->opacity_stack);
-}
-
static void
lsm_svg_view_measure (LsmDomView *view, double *width, double *height)
{
@@ -1458,10 +1490,11 @@ lsm_svg_view_render (LsmDomView *view)
lsm_svg_svg_element_update (svg_element);
+ svg_view->element_stack = NULL;
svg_view->viewbox_stack = NULL;
+ svg_view->mask_stack = NULL;
svg_view->fill_stack = NULL;
svg_view->stroke_stack = NULL;
- svg_view->opacity_stack = NULL;
svg_view->text_stack = NULL;
svg_view->matrix_stack = NULL;
@@ -1484,26 +1517,31 @@ lsm_svg_view_render (LsmDomView *view)
g_slist_free (svg_view->viewbox_stack);
svg_view->viewbox_stack = NULL;
}
- if (svg_view->opacity_stack != NULL) {
- g_warning ("[LsmSvgView::render] Dangling opacity data in stack");
- g_slist_free (svg_view->opacity_stack);
- svg_view->opacity_stack = NULL;
- }
if (svg_view->fill_stack != NULL) {
- g_warning ("[LsmSvgView::render] Dangling fill attribute in stack");
+ g_warning ("[LsmSvgView::render] Dangling fill attributes in stack");
g_slist_free (svg_view->fill_stack);
svg_view->fill_stack = NULL;
}
if (svg_view->stroke_stack != NULL) {
- g_warning ("[LsmSvgView::render] Dangling stroke attribute in stack");
+ g_warning ("[LsmSvgView::render] Dangling stroke attributes in stack");
g_slist_free (svg_view->stroke_stack);
svg_view->stroke_stack = NULL;
}
+ if (svg_view->mask_stack != NULL) {
+ g_warning ("[LsmSvgView::render] Dangling mask attributes in stack");
+ g_slist_free (svg_view->mask_stack);
+ svg_view->mask_stack = NULL;
+ }
if (svg_view->text_stack != NULL) {
g_warning ("[LsmSvgView::render] Dangling text attribute in stack");
g_slist_free (svg_view->text_stack);
svg_view->text_stack = NULL;
}
+ if (svg_view->element_stack != NULL) {
+ g_warning ("[LsmSvgView::render] Dangling element in stack");
+ g_slist_free (svg_view->element_stack);
+ svg_view->element_stack = NULL;
+ }
}
LsmSvgView *
diff --git a/src/lsmsvgview.h b/src/lsmsvgview.h
index 72a0b3a..63f6925 100644
--- a/src/lsmsvgview.h
+++ b/src/lsmsvgview.h
@@ -46,10 +46,11 @@ struct _LsmSvgView {
double resolution_ppi;
+ GSList *element_stack;
GSList *viewbox_stack;
+ GSList *mask_stack;
GSList *fill_stack;
GSList *stroke_stack;
- GSList *opacity_stack;
GSList *text_stack;
GSList *matrix_stack;
@@ -98,15 +99,17 @@ void lsm_svg_view_push_viewport (LsmSvgView *view, const LsmBox *viewport,
void lsm_svg_view_pop_viewport (LsmSvgView *view);
void lsm_svg_view_push_matrix (LsmSvgView *view, LsmSvgMatrix *matrix);
void lsm_svg_view_pop_matrix (LsmSvgView *view);
-void lsm_svg_view_push_clip (LsmSvgView *view, char *clip_path,
- LsmSvgFillRule clip_rule, const LsmExtents *extents);
-void lsm_svg_view_pop_clip (LsmSvgView *view);
-gboolean lsm_svg_view_is_clipping (LsmSvgView *view);
-void lsm_svg_view_push_fill_attributes (LsmSvgView *view, LsmSvgFillAttributeBag *fill);
+
+void lsm_svg_view_push_element (LsmSvgView *view, const LsmSvgElement *element);
+void lsm_svg_view_pop_element (LsmSvgView *view);
+
+void lsm_svg_view_push_mask_attributes (LsmSvgView *view, const LsmSvgMaskAttributeBag *mask);
+void lsm_svg_view_pop_mask_attributes (LsmSvgView *view);
+void lsm_svg_view_push_fill_attributes (LsmSvgView *view, const LsmSvgFillAttributeBag *fill);
void lsm_svg_view_pop_fill_attributes (LsmSvgView *view);
-void lsm_svg_view_push_stroke_attributes (LsmSvgView *view, LsmSvgStrokeAttributeBag *stroke);
+void lsm_svg_view_push_stroke_attributes (LsmSvgView *view, const LsmSvgStrokeAttributeBag *stroke);
void lsm_svg_view_pop_stroke_attributes (LsmSvgView *view);
-void lsm_svg_view_push_text_attributes (LsmSvgView *view, LsmSvgTextAttributeBag *text);
+void lsm_svg_view_push_text_attributes (LsmSvgView *view, const LsmSvgTextAttributeBag *text);
void lsm_svg_view_pop_text_attributes (LsmSvgView *view);
void lsm_svg_view_show_rectangle (LsmSvgView *view, double x, double y,
@@ -121,8 +124,8 @@ void lsm_svg_view_show_polygon (LsmSvgView *view, const char *points);
void lsm_svg_view_show_text (LsmSvgView *view, char const *text, double x, double y);
void lsm_svg_view_show_pixbuf (LsmSvgView *view, GdkPixbuf *pixbuf);
-void lsm_svg_view_push_opacity (LsmSvgView *view, double opacity, gboolean late_opacity_handling);
-void lsm_svg_view_pop_opacity (LsmSvgView *view);
+void lsm_svg_view_push_group_opacity (LsmSvgView *view);
+void lsm_svg_view_pop_group_opacity (LsmSvgView *view);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]