[lasem/wip/emmanuel/extents: 2/2] wip: svg ruler



commit b50fcd79b8a02ffd03bc51d9132efcda190607e1
Author: Emmanuel Pacaud <emmanuel gnome org>
Date:   Mon Jul 11 15:38:20 2016 +0200

    wip: svg ruler

 src/Makefile.am        |    2 +
 src/lsmdebug.c         |    6 +
 src/lsmdebug.h         |    5 +
 src/lsmsvg.h           |    1 +
 src/lsmsvgruler.c      |  239 +++++++++++++++++++++++++++++++++++++++++++++++
 src/lsmsvgruler.h      |   28 ++++++
 src/lsmsvgsvgelement.c |   23 +++--
 src/lsmsvgview.c       |  243 ++++++++++++++++++++----------------------------
 src/lsmsvgview.h       |    5 +-
 9 files changed, 401 insertions(+), 151 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index dbc5c87..9ccdcdd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -103,6 +103,7 @@ LASEM_SVG_SRCS =                            \
        lsmsvglength.c                          \
        lsmsvgview.c                            \
        lsmsvgmatrix.c                          \
+       lsmsvgruler.c                           \
        lsmsvgdocument.c                        \
        lsmsvgelement.c                         \
        lsmsvgtransformable.c                   \
@@ -227,6 +228,7 @@ LASEM_SVG_HDRS =                            \
        lsmsvglength.h                          \
        lsmsvgview.h                            \
        lsmsvgmatrix.h                          \
+       lsmsvgruler.h                           \
        lsmsvgdocument.h                        \
        lsmsvgelement.h                         \
        lsmsvgtransformable.h                   \
diff --git a/src/lsmdebug.c b/src/lsmdebug.c
index 02adaed..7dda251 100644
--- a/src/lsmdebug.c
+++ b/src/lsmdebug.c
@@ -56,6 +56,12 @@ LsmDebugCategory lsm_debug_category_render =
        .level = -1
 };
 
+LsmDebugCategory lsm_debug_category_ruler =
+{
+       .name = (char *) "ruler",
+       .level = -1
+};
+
 LsmDebugCategory lsm_debug_category_viewport =
 {
        .name = (char *) "viewport",
diff --git a/src/lsmdebug.h b/src/lsmdebug.h
index 85f2cfc..fbcfae1 100644
--- a/src/lsmdebug.h
+++ b/src/lsmdebug.h
@@ -42,6 +42,7 @@ extern LsmDebugCategory lsm_debug_category_dom;
 extern LsmDebugCategory lsm_debug_category_measure;
 extern LsmDebugCategory lsm_debug_category_update;
 extern LsmDebugCategory lsm_debug_category_render;
+extern LsmDebugCategory lsm_debug_category_ruler;
 extern LsmDebugCategory lsm_debug_category_viewport;
 
 #define lsm_debug_dom(...)             lsm_debug (&lsm_debug_category_dom, __VA_ARGS__)
@@ -60,6 +61,10 @@ extern LsmDebugCategory lsm_debug_category_viewport;
 #define lsm_log_render(...)            lsm_log (&lsm_debug_category_render, __VA_ARGS__)
 #define lsm_warning_render(...)                lsm_warning (&lsm_debug_category_render, __VA_ARGS__)
 
+#define lsm_debug_ruler(...)           lsm_debug (&lsm_debug_category_ruler, __VA_ARGS__)
+#define lsm_log_ruler(...)             lsm_log (&lsm_debug_category_ruler, __VA_ARGS__)
+#define lsm_warning_ruler(...)         lsm_warning (&lsm_debug_category_ruler, __VA_ARGS__)
+
 void           lsm_warning                     (LsmDebugCategory *category, const char *format, ...) 
G_GNUC_PRINTF(2,3);
 void           lsm_debug                       (LsmDebugCategory *category, const char *format, ...) 
G_GNUC_PRINTF(2,3);
 void           lsm_log                         (LsmDebugCategory *category, const char *format, ...) 
G_GNUC_PRINTF(2,3);
diff --git a/src/lsmsvg.h b/src/lsmsvg.h
index b08d328..149fc01 100644
--- a/src/lsmsvg.h
+++ b/src/lsmsvg.h
@@ -33,6 +33,7 @@
 #include <lsmsvgstyle.h>
 #include <lsmsvgcolors.h>
 #include <lsmsvglength.h>
+#include <lsmsvgruler.h>
 #include <lsmsvgview.h>
 #include <lsmsvgmatrix.h>
 #include <lsmsvgdocument.h>
diff --git a/src/lsmsvgruler.c b/src/lsmsvgruler.c
new file mode 100644
index 0000000..8a8ace4
--- /dev/null
+++ b/src/lsmsvgruler.c
@@ -0,0 +1,239 @@
+#include <lsmsvgruler.h>
+#include <lsmsvgmatrix.h>
+#include <lsmutils.h>
+
+struct _LsmSvgRuler {
+       double resolution_ppi;
+
+       LsmSvgStyle *style;
+       LsmSvgMatrix *matrix;
+       LsmSvgViewbox *viewbox;
+
+       GSList *style_stack;
+       GSList *matrix_stack;
+       GSList *viewbox_stack;
+
+       volatile gint ref_count;
+};
+
+LsmSvgRuler *
+lsm_svg_ruler_new (double resolution_ppi)
+{
+       LsmSvgRuler *ruler;
+
+       ruler = g_slice_new0 (LsmSvgRuler);
+       ruler->ref_count = 1;
+       ruler->resolution_ppi = resolution_ppi;
+       ruler->style = NULL;
+       ruler->matrix = g_slice_new (LsmSvgMatrix);
+       lsm_svg_matrix_init_identity (ruler->matrix);
+
+       return ruler;
+}
+
+LsmSvgRuler *
+lsm_svg_ruler_ref (LsmSvgRuler *ruler)
+{
+       g_return_val_if_fail (ruler != NULL, NULL);
+       g_return_val_if_fail (g_atomic_int_get (&ruler->ref_count) > 0, ruler);
+       g_atomic_int_inc (&ruler->ref_count);
+
+       return ruler;
+}
+
+static void
+_free_style (gpointer data, gpointer user_data)
+{
+       if (data != NULL)
+               lsm_svg_style_unref (data);
+}
+
+static void
+_free_matrix (gpointer data, gpointer user_data)
+{
+       if (data != NULL)
+               g_slice_free (LsmSvgMatrix, data);
+}
+
+static void
+_free_viewbox (gpointer data, gpointer user_data)
+{
+       if (data != NULL)
+               lsm_svg_viewbox_free (data);
+}
+
+void
+lsm_svg_ruler_unref (LsmSvgRuler *ruler)
+{
+       g_return_if_fail (g_atomic_int_get (&ruler->ref_count) > 0);
+       if (g_atomic_int_dec_and_test (&ruler->ref_count)) {
+               if (ruler->style_stack != NULL) {
+                       g_warning ("Dangling style in ruler stack");
+                       g_slist_foreach (ruler->style_stack, _free_style, NULL);
+                       g_clear_pointer (&ruler->style_stack, g_slist_free);
+               }
+               if (ruler->matrix_stack != NULL) {
+                       g_warning ("Dangling matrix in ruler stack");
+                       g_slist_foreach (ruler->matrix_stack, _free_matrix, NULL);
+                       g_clear_pointer (&ruler->matrix_stack, g_slist_free);
+               }
+               if (ruler->viewbox_stack != NULL) {
+                       g_warning ("Dangling viewbow in ruler stack");
+                       g_slist_foreach (ruler->viewbox_stack, _free_viewbox, NULL);
+                       g_clear_pointer (&ruler->viewbox_stack, g_slist_free);
+               }
+               _free_style (ruler->style, NULL);
+               _free_matrix (ruler->matrix, NULL);
+               _free_viewbox (ruler->viewbox, NULL);
+               g_slice_free (LsmSvgRuler, ruler);
+       }
+}
+
+void
+lsm_svg_ruler_push_style (LsmSvgRuler *ruler, LsmSvgStyle *style)
+{
+       g_return_if_fail (ruler != NULL);
+       g_return_if_fail (style != NULL);
+
+       lsm_log_ruler ("Push style");
+
+       /* FIXME Don't store current font_size_pixel in style */
+       if (ruler->style == NULL || (style->font_size != ruler->style->font_size)) {
+               LsmSvgViewbox font_viewbox;
+               LsmSvgViewbox *viewbox;
+               double current_font_size_px;
+
+               if (ruler->style != NULL)
+                       current_font_size_px = ruler->style->font_size_px;
+               else
+                       current_font_size_px = 0.0;
+
+               viewbox = ruler->viewbox;
+               font_viewbox.resolution_ppi = viewbox->resolution_ppi;
+               font_viewbox.viewbox.x = 0;
+               font_viewbox.viewbox.y = 0;
+               font_viewbox.viewbox.width = current_font_size_px;
+               font_viewbox.viewbox.height = current_font_size_px;
+
+               style->font_size_px = lsm_svg_length_normalize (&style->font_size->length, &font_viewbox,
+                                                               current_font_size_px, 
LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+
+               if (style->font_size_px < 0.0)
+                       style->font_size_px = 0.0;
+               lsm_log_ruler ("Font size = %g pixels", style->font_size_px);
+       } else
+               style->font_size_px = ruler->style->font_size_px;
+
+       ruler->style_stack = g_slist_prepend (ruler->style_stack, ruler->style);
+       ruler->style = lsm_svg_style_ref (style);
+}
+
+void
+lsm_svg_ruler_pop_style (LsmSvgRuler *ruler)
+{
+       g_return_if_fail (ruler != NULL);
+       g_return_if_fail (ruler->style_stack != NULL);
+
+       lsm_log_ruler ("Pop style");
+
+       lsm_svg_style_unref (ruler->style);
+       ruler->style = ruler->style_stack->data;
+       ruler->style_stack = g_slist_delete_link (ruler->style_stack, ruler->style_stack);
+}
+
+LsmSvgStyle *
+lsm_svg_ruler_get_style (LsmSvgRuler *ruler)
+{
+       g_return_val_if_fail (ruler != NULL, NULL);
+
+       return ruler->style;
+}
+
+gboolean
+lsm_svg_ruler_push_matrix (LsmSvgRuler *ruler, const LsmSvgMatrix *matrix)
+{
+       gboolean is_invertible;
+
+       g_return_val_if_fail (ruler != NULL, FALSE);
+       g_return_val_if_fail (matrix != NULL, FALSE);
+
+       ruler->matrix_stack = g_slist_prepend (ruler->matrix_stack, ruler->matrix);
+       ruler->matrix = g_slice_new (LsmSvgMatrix);
+
+       is_invertible = lsm_svg_matrix_is_invertible (matrix);
+       if (is_invertible)
+               lsm_svg_matrix_multiply (ruler->matrix, ruler->matrix, matrix); 
+       else
+               lsm_svg_matrix_init (ruler->matrix, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+
+       return is_invertible;
+}
+
+void
+lsm_svg_ruler_pop_matrix (LsmSvgRuler *ruler)
+{
+       g_return_if_fail (ruler != NULL);
+       g_return_if_fail (ruler->matrix_stack != NULL);
+
+       g_slice_free (LsmSvgMatrix, ruler->matrix);
+       ruler->matrix = ruler->matrix_stack->data;
+       ruler->matrix_stack = g_slist_delete_link (ruler->matrix_stack, ruler->matrix_stack);
+}
+
+void
+lsm_svg_ruler_push_viewbox (LsmSvgRuler *ruler, const LsmBox *viewbox)
+{
+       g_return_if_fail (ruler != NULL);
+       g_return_if_fail (viewbox != NULL);
+
+       lsm_debug_ruler ("Push viewbox = %g, %g, %g, %g",
+                        viewbox->x, viewbox->y, viewbox->width, viewbox->height);
+
+       ruler->viewbox_stack = g_slist_prepend (ruler->viewbox_stack, ruler->viewbox);
+       ruler->viewbox = lsm_svg_viewbox_new (ruler->resolution_ppi, viewbox);
+}
+
+void
+lsm_svg_ruler_pop_viewbox (LsmSvgRuler *ruler)
+{
+       g_return_if_fail (ruler != NULL);
+       g_return_if_fail (ruler->viewbox_stack != NULL);
+
+       lsm_debug_ruler ("Pop viewbox");
+
+       lsm_svg_viewbox_free (ruler->viewbox);
+       ruler->viewbox = ruler->viewbox_stack->data;
+       ruler->viewbox_stack = g_slist_delete_link (ruler->viewbox_stack, ruler->viewbox_stack);
+}
+
+double
+lsm_svg_ruler_normalize_length (LsmSvgRuler *ruler, const LsmSvgLength *length, LsmSvgLengthDirection 
direction)
+{
+       g_return_val_if_fail (ruler != NULL, 0.0);
+
+       return lsm_svg_length_normalize (length, ruler->viewbox, ruler->style->font_size_px, direction);
+}
+
+double *
+lsm_svg_ruler_normalize_length_list (LsmSvgRuler *ruler, const LsmSvgLengthList *list,
+                                    LsmSvgLengthDirection direction, unsigned int *n_data)
+{
+       double *data;
+       unsigned int i;
+
+       g_return_val_if_fail (n_data != NULL, NULL);
+       *n_data = 0;
+       g_return_val_if_fail (ruler != NULL, NULL);
+       g_return_val_if_fail (list != NULL, NULL);
+
+       if (list->n_lengths == 0)
+               return NULL;
+
+       *n_data = list->n_lengths;
+       data = g_new (double, list->n_lengths);
+       for (i = 0; i < list->n_lengths; i++)
+               data[i] = lsm_svg_ruler_normalize_length (ruler, &list->lengths[i], direction);
+
+       return data;
+}
+
diff --git a/src/lsmsvgruler.h b/src/lsmsvgruler.h
new file mode 100644
index 0000000..7229c13
--- /dev/null
+++ b/src/lsmsvgruler.h
@@ -0,0 +1,28 @@
+#include <lsmsvgstyle.h>
+
+#ifndef LSM_SVG_RULER
+#define LSM_SVG_RULER
+
+typedef struct _LsmSvgRuler LsmSvgRuler;
+
+LsmSvgRuler *          lsm_svg_ruler_new                       (double resolution_ppi);
+double                 lsm_svg_ruler_get_resolution_ppi        (LsmSvgRuler *ruler);
+
+LsmSvgRuler *          lsm_svg_ruler_ref                       (LsmSvgRuler *ruler);
+void                   lsm_svg_ruler_unref                     (LsmSvgRuler *ruler);
+void                   lsm_svg_ruler_push_style                (LsmSvgRuler *ruler, LsmSvgStyle *style);
+void                   lsm_svg_ruler_pop_style                 (LsmSvgRuler *ruler);
+LsmSvgStyle *          lsm_svg_ruler_get_style                 (LsmSvgRuler *ruler);
+gboolean               lsm_svg_ruler_push_matrix               (LsmSvgRuler *ruler, const LsmSvgMatrix 
*matrix);
+void                   lsm_svg_ruler_pop_matrix                (LsmSvgRuler *ruler);
+const LsmSvgMatrix *   lsm_svg_ruler_get_matrix                (LsmSvgRuler *ruler);
+void                   lsm_svg_ruler_push_viewbox              (LsmSvgRuler *ruler, const LsmBox *viewbox);
+void                   lsm_svg_ruler_pop_viewbox               (LsmSvgRuler *ruler);
+const LsmSvgViewbox *  lsm_svg_ruler_get_viewbox               (LsmSvgRuler *ruler);
+
+double                         lsm_svg_ruler_normalize_length          (LsmSvgRuler *ruler, const 
LsmSvgLength *length,
+                                                                LsmSvgLengthDirection direction);
+double *               lsm_svg_ruler_normalize_length_list     (LsmSvgRuler *ruler, const LsmSvgLengthList 
*list,
+                                                                LsmSvgLengthDirection direction, unsigned 
int *n_data);
+
+#endif
diff --git a/src/lsmsvgsvgelement.c b/src/lsmsvgsvgelement.c
index 29597a5..257c79d 100644
--- a/src/lsmsvgsvgelement.c
+++ b/src/lsmsvgsvgelement.c
@@ -47,6 +47,7 @@ lsm_svg_svg_element_measure (LsmSvgSvgElement *self, LsmSvgView *view, LsmDomVie
 {
        LsmSvgViewbox *svg_viewbox;
        LsmBox viewport;
+       LsmExtents extents = {0.0, 0.0, 0.0, 0.0};
        gboolean is_outermost_svg;
        double resolution_ppi;
        double svg_x;
@@ -99,14 +100,22 @@ lsm_svg_svg_element_measure (LsmSvgSvgElement *self, LsmSvgView *view, LsmDomVie
        self->svg_box.width = svg_width;
        self->svg_box.height = svg_height;
 
-       lsm_debug_measure ("[LsmSvgSvgElement::measure] Size = %g, %g, %g, %g",
-                          svg_x, svg_y, svg_width, svg_height);
-       lsm_svg_viewbox_free (svg_viewbox);
+       switch (measurement) {
+               case LSM_DOM_VIEW_MEASUREMENT_VIEWPORT:
+                       lsm_debug_measure ("[LsmSvgSvgElement::measure] Size = %g, %g, %g, %g",
+                                          svg_x, svg_y, svg_width, svg_height);
+
+                       if (x != NULL)
+                               *x = 0.0;
+                       if (y != NULL)
+                               *y = 0.0;
+                       break;
+               case LSM_DOM_VIEW_MEASUREMENT_EXTENTS:
+                       lsm_svg_element_get_extents (LSM_SVG_ELEMENT (self), view, &extents);
+                       break;
+       }
 
-       if (x != NULL)
-               *x = 0.0;
-       if (y != NULL)
-               *y = 0.0;
+       lsm_svg_viewbox_free (svg_viewbox);
 }
 
 /* LsmSvgGraphic implementation */
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index ab6d22e..4777310 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -117,29 +117,16 @@ double
 lsm_svg_view_normalize_length (LsmSvgView *view, const LsmSvgLength *length, LsmSvgLengthDirection direction)
 {
        g_return_val_if_fail (LSM_IS_SVG_VIEW (view), 0.0);
-
-       return lsm_svg_length_normalize (length, view->viewbox_stack->data, view->style->font_size_px, 
direction);
+       
+       return lsm_svg_ruler_normalize_length (view->ruler, length, direction);
 }
 
 double *
 lsm_svg_view_normalize_length_list (LsmSvgView *view, const LsmSvgLengthList *list, LsmSvgLengthDirection 
direction, unsigned int *n_data)
 {
-       double *data;
-       unsigned int i;
-
-       g_return_val_if_fail (n_data != NULL, NULL);
-       *n_data = 0;
        g_return_val_if_fail (LSM_IS_SVG_VIEW (view), NULL);
 
-       if (list->n_lengths == 0)
-               return NULL;
-
-       *n_data = list->n_lengths;
-       data = g_new (double, list->n_lengths);
-       for (i = 0; i < list->n_lengths; i++)
-               data[i] = lsm_svg_view_normalize_length (view, &list->lengths[i], direction);
-
-       return data;
+       return lsm_svg_ruler_normalize_length_list (view->ruler, list, direction, n_data);
 }
 
 static void
@@ -231,7 +218,7 @@ lsm_svg_view_add_gradient_color_stop (LsmSvgView *view, double offset)
        else
                view->last_stop_offset = offset;
 
-       style = view->style;
+       style = lsm_svg_ruler_get_style (view->ruler);
 
        lsm_debug_render ("[LsmSvgView::add_gradient_color_stop] opacity = %g", style->stop_opacity->value);
 
@@ -499,6 +486,7 @@ _set_color (LsmSvgView *view,
            const LsmSvgPaint *paint, double opacity)
 {
        cairo_t *cairo = view->dom_view.cairo;
+       LsmSvgStyle *style;
 
        switch (paint->type) {
                case LSM_SVG_PAINT_TYPE_NONE:
@@ -511,10 +499,11 @@ _set_color (LsmSvgView *view,
                                               opacity);
                        break;
                case LSM_SVG_PAINT_TYPE_CURRENT_COLOR:
+                       style = lsm_svg_ruler_get_style (view->ruler);
                        cairo_set_source_rgba (cairo,
-                                              view->style->color->value.red,
-                                              view->style->color->value.green,
-                                              view->style->color->value.blue,
+                                              style->color->value.red,
+                                              style->color->value.green,
+                                              style->color->value.blue,
                                               opacity);
                        break;
                case LSM_SVG_PAINT_TYPE_URI:
@@ -552,7 +541,7 @@ paint_markers (LsmSvgView *view)
        double angle;
        int i;
 
-       style = view->style;
+       style = lsm_svg_ruler_get_style (view->ruler);
 
        if ((style->marker->value == NULL ||       strcmp (style->marker->value, "none") == 0) &&
            (style->marker_mid->value == NULL ||   strcmp (style->marker_mid->value, "none") == 0) &&
@@ -570,8 +559,8 @@ paint_markers (LsmSvgView *view)
                                                          style->marker_mid->value);
        marker_end = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document),
                                                          style->marker_end->value);
-       stroke_width = lsm_svg_view_normalize_length (view, &view->style->stroke_width->length,
-                                                     LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
+       stroke_width = lsm_svg_ruler_normalize_length (view->ruler, &style->stroke_width->length,
+                                                      LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
 
        if (marker != NULL && lsm_svg_view_circular_reference_check (view, marker))
                return;
@@ -728,7 +717,7 @@ paint (LsmSvgView *view, LsmSvgViewPathInfos *path_infos)
        g_return_if_fail (LSM_IS_SVG_ELEMENT (element));
 
        cairo = view->dom_view.cairo;
-       style = view->style;
+       style = lsm_svg_ruler_get_style (view->ruler);
 
        if ((style->opacity != NULL ||
             style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER ) &&
@@ -802,8 +791,8 @@ paint (LsmSvgView *view, LsmSvgViewPathInfos *path_infos)
                                cairo_set_line_cap (cairo, CAIRO_LINE_CAP_SQUARE);
                }
 
-               line_width = lsm_svg_view_normalize_length (view, &style->stroke_width->length,
-                                                           LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
+               line_width = lsm_svg_ruler_normalize_length (view->ruler, &style->stroke_width->length,
+                                                            LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
 
                cairo_set_miter_limit (cairo, style->stroke_miter_limit->value);
                cairo_set_line_width (cairo, line_width);
@@ -813,13 +802,13 @@ paint (LsmSvgView *view, LsmSvgViewPathInfos *path_infos)
                        double *dashes;
                        unsigned int i;
 
-                       dash_offset = lsm_svg_view_normalize_length (view, &style->stroke_dash_offset->length,
-                                                                    LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
+                       dash_offset = lsm_svg_ruler_normalize_length (view->ruler, 
&style->stroke_dash_offset->length,
+                                                                     LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
                        dashes = g_new (double, style->stroke_dash_array->value.n_dashes);
                        for (i = 0; i < style->stroke_dash_array->value.n_dashes; i++)
-                               dashes[i] = lsm_svg_view_normalize_length (view,
-                                                                          
&style->stroke_dash_array->value.dashes[i],
-                                                                          LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
+                               dashes[i] = lsm_svg_ruler_normalize_length (view->ruler,
+                                                                           
&style->stroke_dash_array->value.dashes[i],
+                                                                           
LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
 
                        cairo_set_dash (cairo, dashes, style->stroke_dash_array->value.n_dashes, dash_offset);
                        g_free (dashes);
@@ -840,19 +829,23 @@ paint (LsmSvgView *view, LsmSvgViewPathInfos *path_infos)
                cairo_paint_with_alpha (cairo, group_opacity);
        }
 
-       if (view->style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER)
+       if (style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER)
                lsm_cairo_set_comp_op (cairo, LSM_SVG_COMP_OP_SRC_OVER);
 }
 
 static void
 process_path (LsmSvgView *view, LsmSvgViewPathInfos *path_infos)
 {
-       g_return_if_fail (view->style != NULL);
+       LsmSvgStyle *style;
+
+       style = lsm_svg_ruler_get_style (view->ruler);
+
+       g_return_if_fail (style != NULL);
 
        if (view->is_clipping) {
                if (path_infos->is_text_path)
                        pango_cairo_layout_path (view->dom_view.cairo, path_infos->pango_layout);
-               cairo_set_fill_rule (view->dom_view.cairo, view->style->clip_rule->value);
+               cairo_set_fill_rule (view->dom_view.cairo, style->clip_rule->value);
        } else
                paint (view, path_infos);
 }
@@ -861,11 +854,14 @@ void
 lsm_svg_view_show_viewport (LsmSvgView*view, const LsmBox *viewport)
 {
        LsmSvgPaint *paint;
+       LsmSvgStyle *style;
 
        g_return_if_fail (LSM_IS_SVG_VIEW (view));
        g_return_if_fail (viewport != NULL);
+       
+       style = lsm_svg_ruler_get_style (view->ruler);
 
-       paint = &view->style->viewport_fill->paint;
+       paint = &style->viewport_fill->paint;
 
        switch (paint->type) {
                case LSM_SVG_PAINT_TYPE_RGB_COLOR:
@@ -873,14 +869,14 @@ lsm_svg_view_show_viewport (LsmSvgView*view, const LsmBox *viewport)
                                               paint->color.red,
                                               paint->color.green,
                                               paint->color.blue,
-                                              view->style->viewport_fill_opacity->value);
+                                              style->viewport_fill_opacity->value);
                        break;
                case LSM_SVG_PAINT_TYPE_CURRENT_COLOR:
                        cairo_set_source_rgba (view->dom_view.cairo,
-                                              view->style->color->value.red,
-                                              view->style->color->value.green,
-                                              view->style->color->value.blue,
-                                              view->style->viewport_fill_opacity->value);
+                                              style->color->value.red,
+                                              style->color->value.green,
+                                              style->color->value.blue,
+                                              style->viewport_fill_opacity->value);
                default:
                        return;
        }
@@ -1089,7 +1085,7 @@ _update_pango_layout (LsmSvgView *view, unsigned int n, char const *string, doub
        int i;
        double x1, y1;
 
-       style = view->style;
+       style = lsm_svg_ruler_get_style (view->ruler);
 
        pango_layout = view->pango_layout;
        font_description = view->dom_view.font_description;
@@ -1267,7 +1263,7 @@ _show_text (LsmSvgView *view,
 
        cairo = view->dom_view.cairo;
 
-       style = view->style;
+       style = lsm_svg_ruler_get_style (view->ruler);
 
        lsm_debug_render ("[LsmSvgView::show_text] Show '%s' at %g,%g (%g px)", string,
                         x != NULL ? *x : 0, y != NULL ? *y : 0, style->font_size_px);
@@ -1448,28 +1444,17 @@ lsm_svg_view_show_pixbuf (LsmSvgView *view, GdkPixbuf *pixbuf)
 void
 lsm_svg_view_push_viewbox (LsmSvgView *view, const LsmBox *viewbox)
 {
-       LsmSvgViewbox *svg_viewbox;
-
        g_return_if_fail (LSM_IS_SVG_VIEW (view));
 
-       lsm_debug_render ("[LsmSvgView::push_viewbox] viewbox = %g, %g, %g, %g",
-                  viewbox->x, viewbox->y, viewbox->width, viewbox->height);
-
-       svg_viewbox = lsm_svg_viewbox_new (view->resolution_ppi, viewbox);
-
-       view->viewbox_stack = g_slist_prepend (view->viewbox_stack, svg_viewbox);
+       lsm_svg_ruler_push_viewbox (view->ruler, viewbox);
 }
 
 void
 lsm_svg_view_pop_viewbox (LsmSvgView *view)
 {
        g_return_if_fail (LSM_IS_SVG_VIEW (view));
-       g_return_if_fail (view->viewbox_stack != NULL);
-
-       lsm_debug_render ("[LsmSvgView::pop_viewbox]");
 
-       lsm_svg_viewbox_free (view->viewbox_stack->data);
-       view->viewbox_stack = g_slist_delete_link (view->viewbox_stack, view->viewbox_stack);
+       lsm_svg_ruler_pop_viewbox (view->ruler);
 }
 
 static const LsmBox *
@@ -1662,6 +1647,8 @@ lsm_svg_view_push_matrix (LsmSvgView *view, const LsmSvgMatrix *matrix)
                           current_ctm.x0, current_ctm.y0);
        }
 
+       lsm_svg_ruler_push_matrix (view->ruler, matrix);
+
        return TRUE;
 }
 
@@ -1670,6 +1657,8 @@ lsm_svg_view_pop_matrix (LsmSvgView *view)
 {
        g_return_if_fail (LSM_IS_SVG_VIEW (view));
 
+       lsm_svg_ruler_pop_matrix (view->ruler);
+
        if (view->matrix_stack != NULL) {
                cairo_matrix_t *ctm;
 
@@ -1691,6 +1680,7 @@ lsm_svg_view_push_clip (LsmSvgView *view)
 {
        LsmSvgElement *element;
        LsmExtents extents;
+       LsmSvgStyle *style;
        char *url;
 
        g_return_if_fail (LSM_IS_SVG_VIEW (view));
@@ -1698,7 +1688,8 @@ lsm_svg_view_push_clip (LsmSvgView *view)
 
        lsm_svg_element_get_extents (view->element_stack->data, view, &extents);
 
-       url = view->style->clip_path->value;
+       style = lsm_svg_ruler_get_style (view->ruler);
+       url = style->clip_path->value;
 
        lsm_debug_render ("[LsmSvgView::push_clip] Using '%s'", url);
 
@@ -1723,7 +1714,7 @@ lsm_svg_view_push_clip (LsmSvgView *view)
                cairo_clip (view->dom_view.cairo);
                view->is_clipping = FALSE;
        } else
-               lsm_warning_render ("[LsmSvgView::push_clip] Clip path not found: %s", 
view->style->clip_path->value);
+               lsm_warning_render ("[LsmSvgView::push_clip] Clip path not found: %s", 
style->clip_path->value);
 }
 
 static void
@@ -1746,11 +1737,13 @@ static void
 lsm_svg_view_pop_mask (LsmSvgView *view)
 {
        LsmSvgElement *mask_element;
+       LsmSvgStyle *style;
 
        g_return_if_fail (LSM_IS_SVG_VIEW (view));
 
+       style = lsm_svg_ruler_get_style (view->ruler);
        mask_element = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document),
-                                                           view->style->mask->value);
+                                                           style->mask->value);
 
        if (LSM_IS_SVG_MASK_ELEMENT (mask_element) &&
            !lsm_svg_view_circular_reference_check (view, mask_element)) {
@@ -1801,7 +1794,7 @@ lsm_svg_view_pop_mask (LsmSvgView *view)
                        if (view->debug_mask && view->dom_view.cairo != NULL) {
                                char *filename;
 
-                               filename = g_strdup_printf ("mask-%s.png", view->style->mask->value);
+                               filename = g_strdup_printf ("mask-%s.png", style->mask->value);
                                cairo_surface_write_to_png (cairo_get_target (view->dom_view.cairo), 
filename);
                                g_free (filename);
                        }
@@ -1813,7 +1806,7 @@ lsm_svg_view_pop_mask (LsmSvgView *view)
 
                _end_pattern (view);
        } else {
-               lsm_warning_render ("[LsmSvgView::pop_mask] Mask url nout found: %s", 
view->style->mask->value);
+               lsm_warning_render ("[LsmSvgView::pop_mask] Mask url nout found: %s", style->mask->value);
 
                cairo_pop_group_to_source (view->dom_view.cairo);
                cairo_paint (view->dom_view.cairo);
@@ -1827,11 +1820,13 @@ lsm_svg_view_push_filter (LsmSvgView *view)
        LsmBox object_extents;
        LsmBox effect_viewport;
        LsmSvgElement *filter_element;
+       LsmSvgStyle *style;
        gboolean success;
 
        g_return_if_fail (LSM_IS_SVG_VIEW (view));
        g_return_if_fail (view->element_stack != NULL);
 
+       style = lsm_svg_ruler_get_style (view->ruler);
        lsm_svg_element_get_extents (view->element_stack->data, view, &extents);
 
        object_extents.x = extents.x1;
@@ -1840,21 +1835,21 @@ lsm_svg_view_push_filter (LsmSvgView *view)
        object_extents.height = extents.y2 - extents.y1;
 
        filter_element = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document),
-                                                             view->style->filter->value);
+                                                             style->filter->value);
 
        if (LSM_IS_SVG_FILTER_ELEMENT (filter_element)) {
                effect_viewport = lsm_svg_filter_element_get_effect_viewport (LSM_SVG_FILTER_ELEMENT 
(filter_element),
                                                                              &object_extents, view);
 
                _start_pattern (view, &effect_viewport, &object_extents,
-                               view->style->opacity != NULL ? view->style->opacity->value : 1.0);
+                               style->opacity != NULL ? style->opacity->value : 1.0);
 
                success = lsm_svg_view_create_surface_pattern (view,
                                                              &effect_viewport,
                                                              NULL,
                                                              LSM_SVG_VIEW_SURFACE_TYPE_IMAGE);
        } else {
-               lsm_warning_render ("LsmSvgView::push_filter] Filter not found: %s", 
view->style->filter->value);
+               lsm_warning_render ("LsmSvgView::push_filter] Filter not found: %s", style->filter->value);
 
                _start_pattern (view, &object_extents, &object_extents, 0.0);
 
@@ -1873,13 +1868,15 @@ lsm_svg_view_pop_filter (LsmSvgView *view)
 {
        LsmSvgElement *filter_element;
        LsmSvgFilterSurface *filter_surface;
+       LsmSvgStyle *style;
        cairo_surface_t *surface;
        GSList *iter;
 
        g_return_if_fail (LSM_IS_SVG_VIEW (view));
 
+       style = lsm_svg_ruler_get_style (view->ruler);
        filter_element = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document),
-                                                             view->style->filter->value);
+                                                             style->filter->value);
 
        if (LSM_IS_SVG_FILTER_ELEMENT (filter_element) &&
            view->pattern_data->pattern != NULL) {
@@ -1910,7 +1907,7 @@ lsm_svg_view_pop_filter (LsmSvgView *view)
                                        LsmSvgFilterSurface *surface = iter->data;
 
                                        filename = g_strdup_printf ("filter-%04d-%s-%s.png", count++,
-                                                       view->style->filter->value,
+                                                       style->filter->value,
                                                        lsm_svg_filter_surface_get_name (surface));
                                        cairo_surface_write_to_png (lsm_svg_filter_surface_get_cairo_surface 
(surface), filename);
                                        g_free (filename);
@@ -1927,7 +1924,7 @@ lsm_svg_view_pop_filter (LsmSvgView *view)
                                cairo_pattern_set_matrix (pattern, &matrix);
                                cairo_set_source (view->pattern_data->old_cairo, pattern);
                                cairo_pattern_destroy (pattern);
-                               cairo_paint_with_alpha (view->pattern_data->old_cairo, 
view->style->opacity->value);
+                               cairo_paint_with_alpha (view->pattern_data->old_cairo, style->opacity->value);
                        }
 
                        for (iter = view->filter_surfaces; iter != NULL; iter = iter->next)
@@ -2096,6 +2093,7 @@ lsm_svg_view_apply_flood (LsmSvgView *view, const char *output, const LsmBox *su
 {
        LsmSvgFilterSurface *output_surface;
        LsmSvgFilterSurface *input_surface;
+       LsmSvgStyle *style;
        LsmBox subregion_px;
 
        g_return_if_fail (LSM_IS_SVG_VIEW (view));
@@ -2109,11 +2107,12 @@ lsm_svg_view_apply_flood (LsmSvgView *view, const char *output, const LsmBox *su
                        subregion_px.width, subregion_px.height,
                        subregion_px.x, subregion_px.y);
 
+       style = lsm_svg_ruler_get_style (view->ruler);
        lsm_svg_filter_surface_flood (output_surface,
-                                     view->style->flood_color->value.red,
-                                     view->style->flood_color->value.green,
-                                     view->style->flood_color->value.blue,
-                                     view->style->flood_opacity->value);
+                                     style->flood_color->value.red,
+                                     style->flood_color->value.green,
+                                     style->flood_color->value.blue,
+                                     style->flood_opacity->value);
 }
 
 void
@@ -2462,37 +2461,14 @@ lsm_svg_view_push_style (LsmSvgView *view, LsmSvgStyle *style)
        g_return_if_fail (LSM_IS_SVG_VIEW (view));
        g_return_if_fail (style != NULL);
 
-       lsm_log_render ("[SvgView::push_style]");
-
-       if (view->style == NULL || (style->font_size != view->style->font_size)) {
-               LsmSvgViewbox font_viewbox;
-               LsmSvgViewbox *viewbox;
-               double current_font_size_px;
-
-               if (view->style != NULL)
-                       current_font_size_px = view->style->font_size_px;
-               else
-                       current_font_size_px = 0.0;
-
-               viewbox = view->viewbox_stack->data;
-               font_viewbox.resolution_ppi = viewbox->resolution_ppi;
-               font_viewbox.viewbox.x = 0;
-               font_viewbox.viewbox.y = 0;
-               font_viewbox.viewbox.width = current_font_size_px;
-               font_viewbox.viewbox.height = current_font_size_px;
-
-               style->font_size_px = lsm_svg_length_normalize (&style->font_size->length, &font_viewbox,
-                                                               current_font_size_px, 
LSM_SVG_LENGTH_DIRECTION_VERTICAL);
-
-               if (style->font_size_px < 0.0)
-                       style->font_size_px = 0.0;
-               lsm_log_render ("[SvgView::push_style] Font size = %g pixels", style->font_size_px);
-       } else
-               style->font_size_px = view->style->font_size_px;
+       lsm_svg_ruler_push_style (view->ruler, style);
+}
 
-       view->style_stack = g_slist_prepend (view->style_stack, (void *) style);
-       view->style = style;
+void lsm_svg_view_pop_style (LsmSvgView *view)
+{
+       g_return_if_fail (LSM_IS_SVG_VIEW (view));
 
+       lsm_svg_ruler_pop_style (view->ruler);
 }
 
 void
@@ -2513,12 +2489,12 @@ 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 (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) &&
+       if (G_UNLIKELY((style->opacity->value < 1.0 ||
+                       style->enable_background->value == LSM_SVG_ENABLE_BACKGROUND_NEW ||
+                       style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER) &&
                       !do_filter &&
                       !view->is_clipping &&
-                      !view->style->ignore_group_opacity &&
+                      !style->ignore_group_opacity &&
                       view->dom_view.cairo != NULL)) {
                LsmSvgViewBackground *background;
 
@@ -2527,8 +2503,8 @@ lsm_svg_view_push_composition (LsmSvgView *view, LsmSvgStyle *style)
 
                background = g_slice_new (LsmSvgViewBackground);
                background->surface = cairo_get_group_target (view->dom_view.cairo);
-               background->group_opacity = view->style->opacity->value;
-               background->enable_background = view->style->enable_background->value == 
LSM_SVG_ENABLE_BACKGROUND_NEW;
+               background->group_opacity = style->opacity->value;
+               background->enable_background = style->enable_background->value == 
LSM_SVG_ENABLE_BACKGROUND_NEW;
 
                view->background_stack = g_list_prepend (view->background_stack, background);
        }
@@ -2552,32 +2528,25 @@ lsm_svg_view_push_composition (LsmSvgView *view, LsmSvgStyle *style)
        }
 }
 
-void lsm_svg_view_pop_style (LsmSvgView *view)
-{
-       g_return_if_fail (LSM_IS_SVG_VIEW (view));
-       g_return_if_fail (view->style_stack != NULL);
-
-       view->style_stack = g_slist_delete_link (view->style_stack, view->style_stack);
-       view->style = view->style_stack != NULL ? view->style_stack->data : NULL;
-
-       lsm_log_render ("[SvgView::pop_style]");
-}
-
 void lsm_svg_view_pop_composition (LsmSvgView *view)
 {
+       LsmSvgStyle *style;
        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);
+       g_return_if_fail (view->ruler != NULL);
+
+       style = lsm_svg_ruler_get_style (view->ruler);
+       g_return_if_fail (style != NULL);
 
        lsm_log_render ("[SvgView::pop_composition]");
 
-       do_clip = (g_strcmp0 (view->style->clip_path->value, "none") != 0);
-       do_mask = (g_strcmp0 (view->style->mask->value, "none") != 0);
-       do_filter = (g_strcmp0 (view->style->filter->value, "none") != 0);
+       do_clip = (g_strcmp0 (style->clip_path->value, "none") != 0);
+       do_mask = (g_strcmp0 (style->mask->value, "none") != 0);
+       do_filter = (g_strcmp0 (style->filter->value, "none") != 0);
 
        /* Don't do filtering during a clipping operation, as filter will
         * create a new subsurface, where clipping should occur with the path
@@ -2593,21 +2562,21 @@ void lsm_svg_view_pop_composition (LsmSvgView *view)
 
        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) &&
+       if (G_UNLIKELY ((style->opacity->value < 1.0 ||
+                        style->enable_background->value == LSM_SVG_ENABLE_BACKGROUND_NEW ||
+                        style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER) &&
                        !do_filter &&
                        !view->is_clipping &&
-                       !view->style->ignore_group_opacity &&
+                       !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);
-               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))
+               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, style->opacity->value);
+               if (G_UNLIKELY (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");
        }
@@ -2620,7 +2589,7 @@ lsm_svg_view_get_current_style (LsmSvgView *view)
 {
        g_return_val_if_fail (LSM_IS_SVG_VIEW (view), NULL);
 
-       return (LsmSvgStyle *) view->style;
+       return lsm_svg_ruler_get_style (view->ruler);
 }
 
 const LsmBox *
@@ -2683,9 +2652,9 @@ lsm_svg_view_render (LsmDomView *view)
        if (svg_element == NULL)
                return;
 
-       svg_view->style_stack = NULL;
+       svg_view->ruler = lsm_svg_ruler_new (view->resolution_ppi);
+
        svg_view->element_stack = NULL;
-       svg_view->viewbox_stack = NULL;
        svg_view->matrix_stack = NULL;
        svg_view->pango_layout_stack = NULL;
        svg_view->background_stack = NULL;
@@ -2715,26 +2684,18 @@ lsm_svg_view_render (LsmDomView *view)
                g_slist_free (svg_view->matrix_stack);
                svg_view->matrix_stack = NULL;
        }
-       if (svg_view->viewbox_stack != NULL) {
-               g_warning ("[LsmSvgView::render] Dangling viewport in stack");
-               g_slist_free (svg_view->viewbox_stack);
-               svg_view->viewbox_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;
        }
-       if (svg_view->style_stack != NULL) {
-               g_warning ("[LsmSvgView::render] Dangling style in stack");
-               g_slist_free (svg_view->style_stack);
-               svg_view->style_stack = NULL;
-       }
        if (svg_view->background_stack != NULL) {
                g_warning ("[LsmSvgView::render] Dangling background in stack");
                g_list_free (svg_view->background_stack);
                svg_view->background_stack = NULL;
        }
+
+       g_clear_pointer (&svg_view->ruler, lsm_svg_ruler_unref);
 }
 
 static void
diff --git a/src/lsmsvgview.h b/src/lsmsvgview.h
index 92ed6c6..87fa77f 100644
--- a/src/lsmsvgview.h
+++ b/src/lsmsvgview.h
@@ -26,6 +26,7 @@
 
 #include <lsmdom.h>
 #include <lsmsvgtypes.h>
+#include <lsmsvgruler.h>
 #include <lsmsvgelement.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
@@ -53,11 +54,9 @@ struct _LsmSvgView {
 
        double resolution_ppi;
 
-       const LsmSvgStyle *style;
+       LsmSvgRuler *ruler;
 
-       GSList *style_stack;
        GSList *element_stack;
-       GSList *viewbox_stack;
        GSList *matrix_stack;
        GSList *pango_layout_stack;
        GList *background_stack;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]