[lasem] [clipPath] Begin to support objectBoundingBox for clip path units.
- From: Emmanuel Pacaud <emmanuel src gnome org>
- To: svn-commits-list gnome org
- Subject: [lasem] [clipPath] Begin to support objectBoundingBox for clip path units.
- Date: Fri, 5 Jun 2009 10:14:12 -0400 (EDT)
commit 3e862e93bca1eefd4f915178c1a2dc6120ef821b
Author: Emmanuel Pacaud <emmanuel pacaud lapp in2p3 fr>
Date: Fri Jun 5 16:13:11 2009 +0200
[clipPath] Begin to support objectBoundingBox for clip path units.
---
src/lsmdom.h | 7 +++++
src/lsmsvgclippathelement.c | 31 +++++++++++++++++++++-
src/lsmsvgelement.c | 24 +++++++++++++++++
src/lsmsvgelement.h | 18 +++++++------
src/lsmsvggraphic.c | 59 +++++++++++++++++++++++++++++++++++++++++-
src/lsmsvggraphic.h | 3 +-
src/lsmsvgmatrix.c | 40 +++++++++++++++++++++++++++++
src/lsmsvgmatrix.h | 26 +++++++++++--------
src/lsmsvgpatternelement.c | 9 +++---
src/lsmsvgrectelement.c | 19 ++++++++++++++
src/lsmsvgview.c | 31 +++++++++++++++++-----
src/lsmsvgview.h | 7 +++-
12 files changed, 237 insertions(+), 37 deletions(-)
diff --git a/src/lsmdom.h b/src/lsmdom.h
index 9c3b8ac..d9a131c 100644
--- a/src/lsmdom.h
+++ b/src/lsmdom.h
@@ -29,6 +29,13 @@
G_BEGIN_DECLS
typedef struct {
+ double x1;
+ double y1;
+ double x2;
+ double y2;
+} LsmExtents;
+
+typedef struct {
double x;
double y;
double width;
diff --git a/src/lsmsvgclippathelement.c b/src/lsmsvgclippathelement.c
index eaaff3c..0bbdcdf 100644
--- a/src/lsmsvgclippathelement.c
+++ b/src/lsmsvgclippathelement.c
@@ -42,12 +42,39 @@ _clip_path_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
LsmSvgClipPathElement *pattern = LSM_SVG_CLIP_PATH_ELEMENT (self);
LsmSvgPatternUnits units;
- units = LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX;
+ units = LSM_SVG_PATTERN_UNITS_USER_SPACE_ON_USE;
lsm_svg_pattern_units_attribute_parse (&pattern->units, &units);
LSM_SVG_ELEMENT_CLASS (parent_class)->update (self, parent_style);
}
+static void
+_clip_path_element_render_clip (LsmSvgElement *self, LsmSvgView *view)
+{
+ LsmSvgClipPathElement *clip = LSM_SVG_CLIP_PATH_ELEMENT (self);
+ gboolean is_object_bounding_box;
+
+ is_object_bounding_box = (clip->units.value == LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX);
+
+ if (is_object_bounding_box) {
+ LsmSvgMatrix matrix;
+ const LsmBox *viewbox;
+
+ viewbox = lsm_svg_view_get_clip_extents (view);
+ lsm_svg_matrix_init_translate (&matrix, viewbox->x, viewbox->y);
+ lsm_svg_matrix_scale (&matrix, viewbox->width, viewbox->height);
+ lsm_svg_view_push_viewbox (view, viewbox);
+ lsm_svg_view_push_matrix (view, &matrix);
+ }
+
+ LSM_SVG_ELEMENT_CLASS (parent_class)->render (self, view);
+
+ if (is_object_bounding_box) {
+ lsm_svg_view_pop_matrix (view);
+ lsm_svg_view_pop_viewbox (view);
+ }
+}
+
LsmDomNode *
lsm_svg_clip_path_element_new (void)
{
@@ -81,7 +108,7 @@ lsm_svg_clip_path_element_class_init (LsmSvgClipPathElementClass *klass)
d_node_class->get_node_name = _clip_path_element_get_node_name;
s_element_class->update = _clip_path_element_update;
- s_element_class->render_clip = s_element_class->render;
+ s_element_class->render_clip = _clip_path_element_render_clip;
s_element_class->render = NULL;
s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
diff --git a/src/lsmsvgelement.c b/src/lsmsvgelement.c
index c36e218..daeea96 100644
--- a/src/lsmsvgelement.c
+++ b/src/lsmsvgelement.c
@@ -182,6 +182,30 @@ lsm_svg_element_render_clip (LsmSvgElement *element, LsmSvgView *view)
}
}
+void
+lsm_svg_element_get_extents (LsmSvgElement *element, LsmSvgView *view, LsmExtents *extents)
+{
+ LsmSvgElementClass *element_class;
+
+ g_return_if_fail (LSM_IS_SVG_ELEMENT (element));
+ g_return_if_fail (LSM_IS_SVG_VIEW (view));
+ g_return_if_fail (extents != NULL);
+
+ element_class = LSM_SVG_ELEMENT_GET_CLASS (element);
+ if (element_class->get_extents != NULL) {
+ element_class->get_extents (element, view, extents);
+
+ lsm_debug ("LsmSvgElement::get_extents] Exents for '%s' = %g,%g %g,%g",
+ lsm_dom_node_get_node_name (LSM_DOM_NODE (element)),
+ extents->x1, extents->y1, extents->x2, extents->y2);
+ } else {
+ extents->x1 = 0.0;
+ extents->y1 = 0.0;
+ extents->x2 = 0.0;
+ extents->y2 = 0.0;
+ }
+}
+
static void
lsm_svg_element_init (LsmSvgElement *element)
{
diff --git a/src/lsmsvgelement.h b/src/lsmsvgelement.h
index 442d555..0a877c3 100644
--- a/src/lsmsvgelement.h
+++ b/src/lsmsvgelement.h
@@ -57,18 +57,20 @@ struct _LsmSvgElementClass {
LsmDomAttributeMap *attributes;
- void (*update) (LsmSvgElement *element, LsmSvgStyle *style);
- void (*render) (LsmSvgElement *element, LsmSvgView *view);
- void (*render_paint) (LsmSvgElement *element, LsmSvgView *view);
- void (*render_clip) (LsmSvgElement *element, LsmSvgView *view);
+ void (*update) (LsmSvgElement *element, LsmSvgStyle *style);
+ void (*render) (LsmSvgElement *element, LsmSvgView *view);
+ void (*render_paint) (LsmSvgElement *element, LsmSvgView *view);
+ void (*render_clip) (LsmSvgElement *element, LsmSvgView *view);
+ void (*get_extents) (LsmSvgElement *element, LsmSvgView *view, LsmExtents *extents);
};
GType lsm_svg_element_get_type (void);
-void lsm_svg_element_update (LsmSvgElement *element, const LsmSvgStyle *style);
-void lsm_svg_element_render (LsmSvgElement *element, LsmSvgView *view);
-void lsm_svg_element_render_paint (LsmSvgElement *element, LsmSvgView *view);
-void lsm_svg_element_render_clip (LsmSvgElement *element, LsmSvgView *view);
+void lsm_svg_element_update (LsmSvgElement *element, const LsmSvgStyle *style);
+void lsm_svg_element_render (LsmSvgElement *element, LsmSvgView *view);
+void lsm_svg_element_render_paint (LsmSvgElement *element, LsmSvgView *view);
+void lsm_svg_element_render_clip (LsmSvgElement *element, LsmSvgView *view);
+void lsm_svg_element_get_extents (LsmSvgElement *element, LsmSvgView *view, LsmExtents *extents);
G_END_DECLS
diff --git a/src/lsmsvggraphic.c b/src/lsmsvggraphic.c
index af55c92..e381e37 100644
--- a/src/lsmsvggraphic.c
+++ b/src/lsmsvggraphic.c
@@ -165,9 +165,13 @@ lsm_svg_graphic_render (LsmSvgElement *self, LsmSvgView *view)
if (graphic->fill != NULL) {
lsm_svg_view_push_fill_attributes (view, graphic->fill);
- if (graphic->fill->clip_path.value != NULL)
+ 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);
+ graphic->fill->clip_rule.value, &extents);
+ }
}
if (graphic->stroke != NULL)
lsm_svg_view_push_stroke_attributes (view, graphic->stroke);
@@ -193,6 +197,55 @@ lsm_svg_graphic_render (LsmSvgElement *self, LsmSvgView *view)
lsm_svg_view_pop_matrix (view);
}
+static void
+_graphic_get_extents (LsmSvgElement *self, LsmSvgView *view, LsmExtents *extents)
+{
+ LsmSvgGraphic *graphic = LSM_SVG_GRAPHIC (self);
+ LsmDomNode *node;
+ gboolean first_child = TRUE;
+ LsmExtents element_extents = {0.0, 0.0, 0.0, 0.0};
+
+ lsm_debug ("[LsmSvgGraphic::_graphic_get_extents]");
+
+ for (node = LSM_DOM_NODE (self)->first_child; node != NULL; node = node->next_sibling) {
+ if (LSM_IS_SVG_ELEMENT (node)) {
+ LsmExtents child_extents;
+
+ lsm_svg_element_get_extents (LSM_SVG_ELEMENT (node), view, &child_extents);
+
+ if (graphic->transform != NULL)
+ lsm_svg_matrix_transform_bounding_box (&graphic->transform->transform.matrix,
+ &child_extents.x1, &child_extents.y1,
+ &child_extents.x2, &child_extents.y2);
+ if (first_child) {
+ element_extents = child_extents;
+ first_child = FALSE;
+ } else {
+ element_extents.x1 = MIN (element_extents.x1, child_extents.x1);
+ element_extents.y1 = MIN (element_extents.y1, child_extents.y1);
+ element_extents.x2 = MAX (element_extents.x2, child_extents.x2);
+ element_extents.y2 = MAX (element_extents.y2, child_extents.y2);
+ }
+ }
+ }
+
+ *extents = element_extents;
+}
+
+static void
+lsm_svg_graphic_get_extents (LsmSvgElement *self, LsmSvgView *view, LsmExtents *extents)
+{
+ LsmSvgGraphic *graphic = LSM_SVG_GRAPHIC (self);
+
+ if (graphic->text != NULL)
+ lsm_svg_view_push_text_attributes (view, graphic->text);
+
+ LSM_SVG_GRAPHIC_GET_CLASS (graphic)->graphic_get_extents (self, view, extents);
+
+ if (graphic->text != NULL)
+ lsm_svg_view_pop_text_attributes (view);
+}
+
/* LsmSvgGraphic implementation */
static void
@@ -219,8 +272,10 @@ lsm_svg_graphic_class_init (LsmSvgGraphicClass *s_graphic_class)
s_element_class->update = lsm_svg_graphic_update;
s_element_class->render = lsm_svg_graphic_render;
+ s_element_class->get_extents = lsm_svg_graphic_get_extents;
s_graphic_class->graphic_render = _graphic_render;
+ s_graphic_class->graphic_get_extents = _graphic_get_extents;
s_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
diff --git a/src/lsmsvggraphic.h b/src/lsmsvggraphic.h
index 2a1ce6f..4c23a17 100644
--- a/src/lsmsvggraphic.h
+++ b/src/lsmsvggraphic.h
@@ -55,7 +55,8 @@ struct _LsmSvgGraphic {
struct _LsmSvgGraphicClass {
LsmSvgElementClass parent_class;
- void (*graphic_render) (LsmSvgElement *element, LsmSvgView *view);
+ void (*graphic_render) (LsmSvgElement *element, LsmSvgView *view);
+ void (*graphic_get_extents) (LsmSvgElement *element, LsmSvgView *view, LsmExtents *extents);
};
GType lsm_svg_graphic_get_type (void);
diff --git a/src/lsmsvgmatrix.c b/src/lsmsvgmatrix.c
index 16f2b81..99edea5 100644
--- a/src/lsmsvgmatrix.c
+++ b/src/lsmsvgmatrix.c
@@ -136,3 +136,43 @@ lsm_svg_matrix_multiply (LsmSvgMatrix *result, const LsmSvgMatrix *a, const LsmS
*result = r;
}
+
+void
+lsm_svg_matrix_transform_point (const LsmSvgMatrix *matrix, double *x, double *y)
+{
+ double new_x;
+ double new_y;
+
+ new_x = (matrix->a * *x + matrix->c * *y) + matrix->e;
+ new_y = (matrix->b * *x + matrix->d * *y) + matrix->f;
+
+ *x = new_x;
+ *y = new_y;
+}
+
+void
+lsm_svg_matrix_transform_bounding_box (const LsmSvgMatrix *matrix, double *x1, double *y1, double *x2, double *y2)
+{
+ double x12, y12, x21, y21;
+ double x_min, y_min, x_max, y_max;
+
+ x12 = *x1;
+ y12 = *y2;
+ x21 = *x2;
+ y21 = *y1;
+
+ lsm_svg_matrix_transform_point (matrix, x1, y1);
+ lsm_svg_matrix_transform_point (matrix, x2, y2);
+ lsm_svg_matrix_transform_point (matrix, &x12, &y12);
+ lsm_svg_matrix_transform_point (matrix, &x21, &y21);
+
+ x_min = MIN (MIN (*x1, *x2), MIN (x12, x21));
+ x_max = MAX (MAX (*x1, *x2), MAX (x12, x21));
+ y_min = MIN (MIN (*y1, *y2), MIN (y12, y21));
+ y_max = MAX (MAX (*y1, *y2), MAX (y12, y21));
+
+ *x1 = x_min;
+ *y1 = y_min;
+ *x2 = x_max;
+ *y2 = y_max;
+}
diff --git a/src/lsmsvgmatrix.h b/src/lsmsvgmatrix.h
index 52d5ec3..3a4cc5a 100644
--- a/src/lsmsvgmatrix.h
+++ b/src/lsmsvgmatrix.h
@@ -28,19 +28,23 @@ typedef struct {
double a, b, c, d, e, f;
} LsmSvgMatrix;
-void lsm_svg_matrix_init (LsmSvgMatrix *matrix, double a, double b,
- double c, double d, double e, double f);
-void lsm_svg_matrix_init_identity (LsmSvgMatrix *matrix);
+void lsm_svg_matrix_init (LsmSvgMatrix *matrix, double a, double b,
+ double c, double d,
+ double e, double f);
+void lsm_svg_matrix_init_identity (LsmSvgMatrix *matrix);
void lsm_svg_matrix_init_scale (LsmSvgMatrix *matrix, double sx, double sy);
-void lsm_svg_matrix_scale (LsmSvgMatrix *matrix, double sx, double sy);
-void lsm_svg_matrix_init_translate (LsmSvgMatrix *matrix, double tx, double ty);
+void lsm_svg_matrix_scale (LsmSvgMatrix *matrix, double sx, double sy);
+void lsm_svg_matrix_init_translate (LsmSvgMatrix *matrix, double tx, double ty);
void lsm_svg_matrix_translate (LsmSvgMatrix *matrix, double tx, double ty);
-void lsm_svg_matrix_init_rotate (LsmSvgMatrix *matrix, double radians);
-void lsm_svg_matrix_rotate (LsmSvgMatrix *matrix, double radians);
-void lsm_svg_matrix_init_skew_x (LsmSvgMatrix *matrix, double radians);
-void lsm_svg_matrix_skew_x (LsmSvgMatrix *matrix, double radians);
-void lsm_svg_matrix_init_skew_y (LsmSvgMatrix *matrix, double radians);
-void lsm_svg_matrix_skew_y (LsmSvgMatrix *matrix, double radians);
+void lsm_svg_matrix_init_rotate (LsmSvgMatrix *matrix, double radians);
+void lsm_svg_matrix_rotate (LsmSvgMatrix *matrix, double radians);
+void lsm_svg_matrix_init_skew_x (LsmSvgMatrix *matrix, double radians);
+void lsm_svg_matrix_skew_x (LsmSvgMatrix *matrix, double radians);
+void lsm_svg_matrix_init_skew_y (LsmSvgMatrix *matrix, double radians);
+void lsm_svg_matrix_skew_y (LsmSvgMatrix *matrix, double radians);
void lsm_svg_matrix_multiply (LsmSvgMatrix *result, const LsmSvgMatrix *a, const LsmSvgMatrix *b);
+void lsm_svg_matrix_transform_point (const LsmSvgMatrix *matrix, double *x, double *y);
+void lsm_svg_matrix_transform_bounding_box (const LsmSvgMatrix *matrix, double *x1, double *y1,
+ double *x2, double *y2);
#endif
diff --git a/src/lsmsvgpatternelement.c b/src/lsmsvgpatternelement.c
index 99590a2..0b78c95 100644
--- a/src/lsmsvgpatternelement.c
+++ b/src/lsmsvgpatternelement.c
@@ -115,12 +115,13 @@ _pattern_element_render_paint (LsmSvgElement *self, LsmSvgView *view)
is_object_bounding_box = (pattern->content_units.value == LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX);
if (is_object_bounding_box) {
- LsmBox extents;
LsmSvgMatrix matrix;
+ const LsmBox *viewbox;
- extents = lsm_svg_view_get_extents (view);
- lsm_svg_matrix_init_scale (&matrix, extents.width, extents.height);
- lsm_svg_view_push_viewbox (view, &extents);
+ viewbox = lsm_svg_view_get_pattern_extents (view);
+ lsm_svg_matrix_init_translate (&matrix, viewbox->x, viewbox->y);
+ lsm_svg_matrix_scale (&matrix, viewbox->width, viewbox->height);
+ lsm_svg_view_push_viewbox (view, viewbox);
lsm_svg_view_push_matrix (view, &matrix);
}
diff --git a/src/lsmsvgrectelement.c b/src/lsmsvgrectelement.c
index 3c2aa21..b039e9c 100644
--- a/src/lsmsvgrectelement.c
+++ b/src/lsmsvgrectelement.c
@@ -96,6 +96,24 @@ lsm_svg_rect_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
lsm_svg_view_show_rectangle (view, x, y, w, h, rx, ry);
}
+static void
+lsm_svg_rect_element_graphic_get_extents (LsmSvgElement *self, LsmSvgView *view, LsmExtents *extents)
+{
+ LsmSvgRectElement *rect = LSM_SVG_RECT_ELEMENT (self);
+ double x, y;
+ double w, h;
+
+ x = lsm_svg_view_normalize_length (view, &rect->x.length.base, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+ y = lsm_svg_view_normalize_length (view, &rect->y.length.base, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+ w = lsm_svg_view_normalize_length (view, &rect->width.length.base, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+ h = lsm_svg_view_normalize_length (view, &rect->height.length.base, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+
+ extents->x1 = x;
+ extents->y1 = y;
+ extents->x2 = x + w;
+ extents->y2 = y + h;
+}
+
/* LsmSvgRectElement implementation */
LsmDomNode *
@@ -133,6 +151,7 @@ lsm_svg_rect_element_class_init (LsmSvgRectElementClass *s_rect_class)
s_element_class->update = lsm_svg_rect_element_update;
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_element_class->attributes = lsm_dom_attribute_map_duplicate (s_element_class->attributes);
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index 0d18f79..ee00a31 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -49,15 +49,26 @@ struct _LsmSvgViewPatternData {
LsmSvgSpreadMethod spread_method;
};
-LsmBox
-lsm_svg_view_get_extents (LsmSvgView *view)
+const LsmBox *
+lsm_svg_view_get_pattern_extents (LsmSvgView *view)
{
- LsmBox null_box = {.x = 0.0, .y = 0.0, .width = 0.0, .height = 0.0};
+ static LsmBox null_extents = {.x = 0.0, .y = 0.0, .width = 0.0, .height = 0.0};
- g_return_val_if_fail (LSM_IS_SVG_VIEW (view), null_box);
- g_return_val_if_fail (view->pattern_data != NULL, null_box);
+ g_return_val_if_fail (LSM_IS_SVG_VIEW (view), &null_extents);
+ g_return_val_if_fail (view->pattern_data != NULL, &null_extents);
- return view->pattern_data->extents;
+ return &view->pattern_data->extents;
+}
+
+const LsmBox *
+lsm_svg_view_get_clip_extents (LsmSvgView *view)
+{
+ static LsmBox null_extents = {.x = 0.0, .y = 0.0, .width = 0.0, .height = 0.0};
+
+ g_return_val_if_fail (LSM_IS_SVG_VIEW (view), &null_extents);
+ g_return_val_if_fail (view->is_clipping, &null_extents);
+
+ return &view->clip_extents;
}
static void
@@ -826,13 +837,14 @@ lsm_svg_view_pop_matrix (LsmSvgView *view)
}
void
-lsm_svg_view_push_clip (LsmSvgView *view, char *clip_path, LsmSvgFillRule clip_rule)
+lsm_svg_view_push_clip (LsmSvgView *view, char *clip_path, LsmSvgFillRule clip_rule, const LsmExtents *extents)
{
LsmDomElement *element;
char *uri;
g_return_if_fail (LSM_IS_SVG_VIEW (view));
g_return_if_fail (!view->is_clipping);
+ g_return_if_fail (extents != NULL);
uri = clip_path;
@@ -840,6 +852,11 @@ 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;
+
if (strncmp (uri, "url(#", 5) ==0) {
char *end;
diff --git a/src/lsmsvgview.h b/src/lsmsvgview.h
index 920f884..0bff515 100644
--- a/src/lsmsvgview.h
+++ b/src/lsmsvgview.h
@@ -57,6 +57,7 @@ struct _LsmSvgView {
GSList *pattern_stack;
gboolean is_clipping;
+ LsmBox clip_extents;
};
struct _LsmSvgViewClass {
@@ -67,7 +68,8 @@ GType lsm_svg_view_get_type (void);
LsmSvgView * lsm_svg_view_new (LsmSvgDocument *document);
-LsmBox lsm_svg_view_get_extents (LsmSvgView *view);
+const LsmBox * lsm_svg_view_get_pattern_extents (LsmSvgView *view);
+const LsmBox * lsm_svg_view_get_clip_extents (LsmSvgView *view);
void lsm_svg_view_create_radial_gradient (LsmSvgView *view, double cx, double cy,
double r, double fx, double fy);
@@ -95,7 +97,8 @@ 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);
+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);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]