[lasem] [SVG] Implement preserveAspectRation attribute.
- From: Emmanuel Pacaud <emmanuel src gnome org>
- To: svn-commits-list gnome org
- Subject: [lasem] [SVG] Implement preserveAspectRation attribute.
- Date: Sun, 17 May 2009 12:27:27 -0400 (EDT)
commit 89524ec73e648de585c362e4cb338df9428c3761
Author: Emmanuel Pacaud <emmanuel pacaud lapp in2p3 fr>
Date: Sun May 17 18:27:03 2009 +0200
[SVG] Implement preserveAspectRation attribute.
---
src/lsmsvgattributes.c | 38 +++++++++++++++++++
src/lsmsvgattributes.h | 15 +++++++-
src/lsmsvgenums.c | 46 +++++++++++++++++++++++
src/lsmsvgenums.h | 26 +++++++++++++
src/lsmsvgsvgelement.c | 39 ++++++--------------
src/lsmsvgsvgelement.h | 3 +-
src/lsmsvgview.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++
src/lsmsvgview.h | 4 ++
8 files changed, 235 insertions(+), 31 deletions(-)
diff --git a/src/lsmsvgattributes.c b/src/lsmsvgattributes.c
index 8f98d6d..eb0485e 100644
--- a/src/lsmsvgattributes.c
+++ b/src/lsmsvgattributes.c
@@ -619,3 +619,41 @@ lsm_svg_transform_attribute_parse (LsmSvgTransformAttribute *attribute)
}
}
}
+
+void
+lsm_svg_preserve_aspect_ratio_attribute_parse (LsmSvgPreserveAspectRatioAttribute *attribute)
+{
+ char *string;
+
+ g_return_if_fail (attribute != NULL);
+
+ string = (char *) lsm_dom_attribute_get_value ((LsmDomAttribute *) attribute);
+ if (string != NULL) {
+ char **tokens;
+ unsigned int i = 0;
+
+ tokens = g_strsplit (string, " ", -1);
+
+ if (tokens[i] != NULL && strcmp (tokens[i], "defer") == 0) {
+ attribute->value.defer = TRUE;
+ i++;
+ } else
+ attribute->value.defer = FALSE;
+
+ if (tokens[i] != NULL) {
+ attribute->value.align = lsm_svg_align_from_string (tokens[i]);
+ i++;
+ if (tokens[i] != NULL)
+ attribute->value.meet_or_slice = lsm_svg_meet_or_slice_from_string (tokens[i]);
+ else
+ attribute->value.meet_or_slice = LSM_SVG_MEET_OR_SLICE_MEET;
+ } else attribute->value.align = LSM_SVG_ALIGN_X_MID_Y_MID;
+
+ g_strfreev (tokens);
+
+ } else {
+ attribute->value.defer = FALSE;
+ attribute->value.align = LSM_SVG_ALIGN_X_MID_Y_MID;
+ attribute->value.meet_or_slice = LSM_SVG_MEET_OR_SLICE_MEET;
+ }
+}
diff --git a/src/lsmsvgattributes.h b/src/lsmsvgattributes.h
index 65a204f..4db88ad 100644
--- a/src/lsmsvgattributes.h
+++ b/src/lsmsvgattributes.h
@@ -104,6 +104,16 @@ typedef struct {
LsmSvgMatrix matrix;
} LsmSvgTransformAttribute;
+typedef struct {
+ gboolean defer;
+ LsmSvgAlign align;
+ LsmSvgMeetOrSlice meet_or_slice;
+} LsmSvgPreserveAspectRatio;
+
+typedef struct {
+ LsmDomAttribute attr;
+ LsmSvgPreserveAspectRatio value;
+} LsmSvgPreserveAspectRatioAttribute;
/* Properties */
@@ -139,8 +149,9 @@ void lsm_svg_color_attribute_parse (LsmSvgColorAttribute *attribute,
/* Attributes */
-void lsm_svg_viewbox_attribute_parse (LsmSvgViewboxAttribute *attribute);
-void lsm_svg_transform_attribute_parse (LsmSvgTransformAttribute *attribute);
+void lsm_svg_viewbox_attribute_parse (LsmSvgViewboxAttribute *attribute);
+void lsm_svg_transform_attribute_parse (LsmSvgTransformAttribute *attribute);
+void lsm_svg_preserve_aspect_ratio_attribute_parse (LsmSvgPreserveAspectRatioAttribute *attribute);
G_END_DECLS
diff --git a/src/lsmsvgenums.c b/src/lsmsvgenums.c
index f2f8d63..1247354 100644
--- a/src/lsmsvgenums.c
+++ b/src/lsmsvgenums.c
@@ -156,3 +156,49 @@ lsm_svg_spread_method_from_string (const char *string)
return lsm_svg_value_from_string (string, lsm_svg_spread_method_strings,
G_N_ELEMENTS (lsm_svg_spread_method_strings));
}
+
+static const char *lsm_svg_align_strings[] = {
+ "",
+ "none",
+ "xMinYMin",
+ "xMidYMin",
+ "xMaxYMin",
+ "xMinYMid",
+ "xMidYMid",
+ "xMaxYMid",
+ "xMinYMax",
+ "xMidYMax",
+ "xMaxYMax"
+};
+
+const char *
+lsm_svg_align_to_string (LsmSvgAlign align)
+{
+ return lsm_svg_align_strings[CLAMP (align, 0, LSM_SVG_ALIGN_X_MAX_Y_MAX)];
+}
+
+LsmSvgAlign
+lsm_svg_align_from_string (const char *string)
+{
+ return lsm_svg_value_from_string (string, lsm_svg_align_strings,
+ G_N_ELEMENTS (lsm_svg_align_strings));
+}
+
+static const char *lsm_svg_meet_or_slice_strings[] = {
+ "",
+ "meet",
+ "slice"
+};
+
+const char *
+lsm_svg_meet_or_slice_to_string (LsmSvgMeetOrSlice meet_or_slice)
+{
+ return lsm_svg_meet_or_slice_strings[CLAMP (meet_or_slice, 0, LSM_SVG_MEET_OR_SLICE_SLICE)];
+}
+
+LsmSvgMeetOrSlice
+lsm_svg_meet_or_slice_from_string (const char *string)
+{
+ return lsm_svg_value_from_string (string, lsm_svg_meet_or_slice_strings,
+ G_N_ELEMENTS (lsm_svg_meet_or_slice_strings));
+}
diff --git a/src/lsmsvgenums.h b/src/lsmsvgenums.h
index 1a53db9..dd1e0cf 100644
--- a/src/lsmsvgenums.h
+++ b/src/lsmsvgenums.h
@@ -115,6 +115,32 @@ typedef enum {
const char * lsm_svg_spread_method_to_string (LsmSvgSpreadMethod method);
LsmSvgSpreadMethod lsm_svg_spread_method_from_string (const char *string);
+typedef enum {
+ LSM_SVG_ALIGN_UNKNOWN,
+ LSM_SVG_ALIGN_NONE,
+ LSM_SVG_ALIGN_X_MIN_Y_MIN,
+ LSM_SVG_ALIGN_X_MID_Y_MIN,
+ LSM_SVG_ALIGN_X_MAX_Y_MIN,
+ LSM_SVG_ALIGN_X_MIN_Y_MID,
+ LSM_SVG_ALIGN_X_MID_Y_MID,
+ LSM_SVG_ALIGN_X_MAX_Y_MID,
+ LSM_SVG_ALIGN_X_MIN_Y_MAX,
+ LSM_SVG_ALIGN_X_MID_Y_MAX,
+ LSM_SVG_ALIGN_X_MAX_Y_MAX
+} LsmSvgAlign;
+
+const char * lsm_svg_align_to_string (LsmSvgAlign align);
+LsmSvgAlign lsm_svg_align_from_string (const char *string);
+
+typedef enum {
+ LSM_SVG_MEET_OR_SLICE_UNKNOWN,
+ LSM_SVG_MEET_OR_SLICE_MEET,
+ LSM_SVG_MEET_OR_SLICE_SLICE
+} LsmSvgMeetOrSlice;
+
+const char * lsm_svg_meet_or_slice_to_string (LsmSvgMeetOrSlice meet_or_slice);
+LsmSvgMeetOrSlice lsm_svg_meet_or_slice_from_string (const char *string);
+
G_END_DECLS
#endif
diff --git a/src/lsmsvgsvgelement.c b/src/lsmsvgsvgelement.c
index 27b2f34..7ad8f89 100644
--- a/src/lsmsvgsvgelement.c
+++ b/src/lsmsvgsvgelement.c
@@ -62,6 +62,7 @@ _svg_element_update (LsmSvgElement *self, LsmSvgStyle *parent_style)
lsm_svg_length_attribute_parse (&svg->height, &length);
lsm_svg_viewbox_attribute_parse (&svg->viewbox);
+ lsm_svg_preserve_aspect_ratio_attribute_parse (&svg->preserve_aspect_ratio);
lsm_debug ("[LsmSvgSvgElement::update] view_bbox = %g, %g, %g, %g\n",
svg->viewbox.value.x,
@@ -130,16 +131,12 @@ lsm_svg_svg_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
{
LsmSvgSvgElement *svg = LSM_SVG_SVG_ELEMENT (self);
gboolean is_viewbox_defined;
- LsmSvgMatrix matrix;
- double svg_x;
- double svg_y;
- double svg_width;
- double svg_height;
+ LsmBox viewport;
- svg_x = lsm_svg_view_normalize_length (view, &svg->x.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
- svg_y = lsm_svg_view_normalize_length (view, &svg->y.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
- svg_width = lsm_svg_view_normalize_length (view, &svg->width.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
- svg_height = lsm_svg_view_normalize_length (view, &svg->height.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+ viewport.x = lsm_svg_view_normalize_length (view, &svg->x.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+ viewport.y = lsm_svg_view_normalize_length (view, &svg->y.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+ viewport.width = lsm_svg_view_normalize_length (view, &svg->width.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+ viewport.height = lsm_svg_view_normalize_length (view, &svg->height.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
is_viewbox_defined = lsm_dom_attribute_is_defined ((LsmDomAttribute *) &svg->viewbox);
@@ -147,28 +144,12 @@ lsm_svg_svg_element_graphic_render (LsmSvgElement *self, LsmSvgView *view)
svg->viewbox.value.height <= 0.0))
return;
- lsm_svg_matrix_init_translate (&matrix, svg_x, svg_y);
- lsm_svg_view_push_transform (view, &matrix);
-
- if (is_viewbox_defined) {
-
- lsm_svg_matrix_init (&matrix,
- svg_width / svg->viewbox.value.width, 0.0,
- 0.0 , svg_height / svg->viewbox.value.height,
- -svg->viewbox.value.x,-svg->viewbox.value.y);
-
- lsm_svg_view_push_transform (view, &matrix);
- lsm_svg_view_push_viewbox (view, &svg->viewbox.value);
- }
+ lsm_svg_view_push_viewport (view, &viewport, is_viewbox_defined ? &svg->viewbox.value : NULL,
+ &svg->preserve_aspect_ratio.value);
LSM_SVG_GRAPHIC_CLASS (parent_class)->graphic_render (self, view);
- if (is_viewbox_defined) {
- lsm_svg_view_pop_viewbox (view);
- lsm_svg_view_pop_transform (view);
- }
-
- lsm_svg_view_pop_transform (view);
+ lsm_svg_view_pop_viewport (view);
}
/* LsmSvgSvgElement implementation */
@@ -279,6 +260,8 @@ lsm_svg_svg_element_class_init (LsmSvgSvgElementClass *s_svg_class)
offsetof (LsmSvgSvgElement, height));
lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "viewBox",
offsetof (LsmSvgSvgElement, viewbox));
+ lsm_dom_attribute_map_add_attribute (s_element_class->attributes, "preserveAspectRatio",
+ offsetof (LsmSvgSvgElement, preserve_aspect_ratio));
}
G_DEFINE_TYPE (LsmSvgSvgElement, lsm_svg_svg_element, LSM_TYPE_SVG_GRAPHIC)
diff --git a/src/lsmsvgsvgelement.h b/src/lsmsvgsvgelement.h
index 2f0d95b..bfb9f75 100644
--- a/src/lsmsvgsvgelement.h
+++ b/src/lsmsvgsvgelement.h
@@ -46,7 +46,8 @@ struct _LsmSvgSvgElement {
LsmSvgLengthAttribute width;
LsmSvgLengthAttribute height;
- LsmSvgViewboxAttribute viewbox;
+ LsmSvgViewboxAttribute viewbox;
+ LsmSvgPreserveAspectRatioAttribute preserve_aspect_ratio;
LsmBox svg_box;
};
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index c91542c..7b03f83 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -686,6 +686,101 @@ lsm_svg_view_pop_viewbox (LsmSvgView *view)
}
void
+lsm_svg_view_push_viewport (LsmSvgView *view, const LsmBox *viewport, const LsmBox *viewbox,
+ const LsmSvgPreserveAspectRatio *aspect_ratio)
+{
+ cairo_t *cairo;
+ double x_ratio, x_scale;
+ double y_ratio, y_scale;
+ double x, y;
+
+ g_return_if_fail (LSM_IS_SVG_VIEW (view));
+ g_return_if_fail (viewport != NULL);
+ g_return_if_fail (aspect_ratio != NULL);
+
+ x = viewport->x;
+ y = viewport->y;
+
+ if (viewbox != NULL) {
+ x_ratio = viewbox->width > 0.0 ? viewport->width / viewbox->width : 0.0;
+ y_ratio = viewbox->height > 0.0 ? viewport->height / viewbox->height : 0.0;
+
+ if (aspect_ratio->align > LSM_SVG_ALIGN_NONE) {
+ if (aspect_ratio->meet_or_slice == LSM_SVG_MEET_OR_SLICE_MEET) {
+ x_scale = MIN (x_ratio, y_ratio);
+ y_scale = x_scale;
+ } else {
+ x_scale = MAX (x_ratio, y_ratio);
+ y_scale = x_scale;
+ }
+
+ x -= viewbox->x;
+ y -= viewbox->y;
+
+ switch (aspect_ratio->align) {
+ case LSM_SVG_ALIGN_X_MIN_Y_MIN:
+ break;
+ case LSM_SVG_ALIGN_X_MIN_Y_MID:
+ y += (viewport->height- viewbox->height * y_scale) * 0.5;
+ break;
+ case LSM_SVG_ALIGN_X_MIN_Y_MAX:
+ y += (viewport->height - viewbox->height * y_scale);
+ break;
+ case LSM_SVG_ALIGN_X_MID_Y_MIN:
+ x += (viewport->width - viewbox->width * x_scale) * 0.5;
+ break;
+ case LSM_SVG_ALIGN_X_MID_Y_MID:
+ x += (viewport->width - viewbox->width * x_scale) * 0.5;
+ y += (viewport->height- viewbox->height * y_scale) * 0.5;
+ break;
+ case LSM_SVG_ALIGN_X_MID_Y_MAX:
+ x += (viewport->width - viewbox->width * x_scale) * 0.5;
+ y += (viewport->height - viewbox->height * y_scale);
+ break;
+ case LSM_SVG_ALIGN_X_MAX_Y_MIN:
+ x += (viewport->width - viewbox->width * x_scale);
+ break;
+ case LSM_SVG_ALIGN_X_MAX_Y_MID:
+ x += (viewport->width - viewbox->width * x_scale);
+ y += (viewport->height- viewbox->height * y_scale) * 0.5;
+ break;
+ case LSM_SVG_ALIGN_X_MAX_Y_MAX:
+ x += (viewport->width - viewbox->width * x_scale);
+ y += (viewport->height - viewbox->height * y_scale);
+ break;
+ default:
+ break;
+ }
+ } else {
+ x_scale = x_ratio;
+ y_scale = y_ratio;
+ }
+
+ lsm_svg_view_push_viewbox (view, viewbox);
+
+ } else {
+ x_scale = y_scale = 1.0;
+ lsm_svg_view_push_viewbox (view, viewport);
+ }
+
+ cairo = view->dom_view.cairo;
+
+ cairo_save (cairo);
+ cairo_rectangle (cairo, viewport->x, viewport->y, viewport->width, viewport->height);
+ cairo_clip (cairo);
+ cairo_translate (cairo, x, y);
+ cairo_scale (cairo, x_scale, y_scale);
+}
+
+void
+lsm_svg_view_pop_viewport (LsmSvgView *view)
+{
+ cairo_restore (view->dom_view.cairo);
+
+ lsm_svg_view_pop_viewbox (view);
+}
+
+void
lsm_svg_view_push_transform (LsmSvgView *view, const LsmSvgMatrix *matrix)
{
cairo_matrix_t cr_matrix;
diff --git a/src/lsmsvgview.h b/src/lsmsvgview.h
index 10bae56..6aeb5d3 100644
--- a/src/lsmsvgview.h
+++ b/src/lsmsvgview.h
@@ -85,6 +85,10 @@ double lsm_svg_view_normalize_length (LsmSvgView *view, const LsmSvgLength *
LsmSvgLengthDirection direction);
void lsm_svg_view_push_viewbox (LsmSvgView *view, const LsmBox *viewbox);
void lsm_svg_view_pop_viewbox (LsmSvgView *view);
+void lsm_svg_view_push_viewport (LsmSvgView *view, const LsmBox *viewport,
+ const LsmBox *viewbox,
+ const LsmSvgPreserveAspectRatio *aspect_ratio);
+void lsm_svg_view_pop_viewport (LsmSvgView *view);
void lsm_svg_view_push_transform (LsmSvgView *view, const LsmSvgMatrix *matrix);
void lsm_svg_view_pop_transform (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]