[lasem] svg_convolve_matrix: import algorithm from librsvg



commit da70256156cc325011282b558f6fb5f29aaec007
Author: Emmanuel Pacaud <emmanuel gnome org>
Date:   Sun Aug 2 21:21:33 2015 +0200

    svg_convolve_matrix: import algorithm from librsvg

 docs/reference/lasem/Makefile.am |    3 +-
 src/Makefile.am                  |    2 +
 src/lsmsvgattributes.h           |   10 +++
 src/lsmsvgdocument.c             |    5 +-
 src/lsmsvgenums.c                |   22 +++++++
 src/lsmsvgenums.h                |   10 +++
 src/lsmsvgfilterconvolvematrix.c |  125 ++++++++++++++++++++++++++++++++++++++
 src/lsmsvgfilterconvolvematrix.h |   59 ++++++++++++++++++
 src/lsmsvgfiltersurface.c        |  123 +++++++++++++++++++++++++++++++++++++
 src/lsmsvgfiltersurface.h        |    4 +
 src/lsmsvgtraits.c               |   65 ++++++++++++++++++++
 src/lsmsvgtraits.h               |    9 +++-
 src/lsmsvgtypes.h                |    1 +
 src/lsmsvgview.c                 |   23 +++++++
 src/lsmsvgview.h                 |    3 +
 15 files changed, 461 insertions(+), 3 deletions(-)
---
diff --git a/docs/reference/lasem/Makefile.am b/docs/reference/lasem/Makefile.am
index a88e1c3..2b272bf 100644
--- a/docs/reference/lasem/Makefile.am
+++ b/docs/reference/lasem/Makefile.am
@@ -152,8 +152,9 @@ IGNORE_HFILES=\
        lsmsvgfilterelement.h                   \
        lsmsvgfilterprimitive.h                 \
        lsmsvgfilterblend.h                     \
-       lsmsvgfiltercomposite.h                 \
        lsmsvgfiltercolormatrix.h               \
+       lsmsvgfiltercomposite.h                 \
+       lsmsvgfilterconvolvematrix.h            \
        lsmsvgfilterflood.h                     \
        lsmsvgfiltergaussianblur.h              \
        lsmsvgfilterimage.h                     \
diff --git a/src/Makefile.am b/src/Makefile.am
index 98640b8..14139da 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -136,6 +136,7 @@ LASEM_SVG_SRCS =                            \
        lsmsvgfilterblend.c                     \
        lsmsvgfiltercolormatrix.c               \
        lsmsvgfiltercomposite.c                 \
+       lsmsvgfilterconvolvematrix.c            \
        lsmsvgfilterflood.c                     \
        lsmsvgfiltergaussianblur.c              \
        lsmsvgfilterimage.c                     \
@@ -257,6 +258,7 @@ LASEM_SVG_HDRS =                            \
        lsmsvgfilterblend.h                     \
        lsmsvgfiltercolormatrix.h               \
        lsmsvgfiltercomposite.h                 \
+       lsmsvgfilterconvolvematrix.h            \
        lsmsvgfilterflood.h                     \
        lsmsvgfiltergaussianblur.h              \
        lsmsvgfilterimage.h                     \
diff --git a/src/lsmsvgattributes.h b/src/lsmsvgattributes.h
index 5059377..9ac6db4 100644
--- a/src/lsmsvgattributes.h
+++ b/src/lsmsvgattributes.h
@@ -128,6 +128,16 @@ typedef struct {
        LsmSvgMorphologyOperator value;
 } LsmSvgMorphologyOperatorAttribute;
 
+typedef struct {
+       LsmAttribute base;
+       LsmSvgEdgeMode value;
+} LsmSvgEdgeModeAttribute;
+
+typedef struct {
+       LsmAttribute base;
+       LsmSvgOneOrTwoInteger value;
+} LsmSvgOneOrTwoIntegerAttribute;
+
 G_END_DECLS
 
 #endif
diff --git a/src/lsmsvgdocument.c b/src/lsmsvgdocument.c
index c5e7b67..bf7a6d2 100644
--- a/src/lsmsvgdocument.c
+++ b/src/lsmsvgdocument.c
@@ -30,7 +30,9 @@
 #include <lsmsvgellipseelement.h>
 #include <lsmsvgfilterelement.h>
 #include <lsmsvgfilterblend.h>
+#include <lsmsvgfiltercolormatrix.h>
 #include <lsmsvgfiltercomposite.h>
+#include <lsmsvgfilterconvolvematrix.h>
 #include <lsmsvgfilterflood.h>
 #include <lsmsvgfiltergaussianblur.h>
 #include <lsmsvgfilterimage.h>
@@ -39,7 +41,6 @@
 #include <lsmsvgfiltermergenode.h>
 #include <lsmsvgfiltermorphology.h>
 #include <lsmsvgfilterspecularlighting.h>
-#include <lsmsvgfiltercolormatrix.h>
 #include <lsmsvgfiltertile.h>
 #include <lsmsvggelement.h>
 #include <lsmsvgimageelement.h>
@@ -171,6 +172,8 @@ _create_element (LsmDomDocument *document, const char *tag_name)
                node = lsm_svg_filter_specular_lighting_new ();
        else if (strcmp (tag_name, "feColorMatrix") == 0)
                node = lsm_svg_filter_color_matrix_new ();
+       else if (strcmp (tag_name, "feConvolveMatrix") == 0)
+               node = lsm_svg_filter_convolve_matrix_new ();
        else if (strcmp (tag_name, "feImage") == 0)
                node = lsm_svg_filter_image_new ();
        else if (strcmp (tag_name, "feMorphology") == 0)
diff --git a/src/lsmsvgenums.c b/src/lsmsvgenums.c
index 4920d70..c5d12c4 100644
--- a/src/lsmsvgenums.c
+++ b/src/lsmsvgenums.c
@@ -585,3 +585,25 @@ lsm_svg_morphology_operator_from_string (const char *string)
        return lsm_enum_value_from_string (string, lsm_svg_morphology_operator_strings,
                                           G_N_ELEMENTS (lsm_svg_morphology_operator_strings));
 }
+
+static const char *lsm_svg_edge_mode_strings[] = {
+       "duplicate",
+       "wrap",
+       "none"
+};
+
+const char *
+lsm_svg_edge_mode_to_string (LsmSvgEdgeMode edge_mode)
+{
+       if (edge_mode < 0 || edge_mode > LSM_SVG_EDGE_MODE_NONE)
+               return NULL;
+
+       return lsm_svg_edge_mode_strings[edge_mode];
+}
+
+LsmSvgEdgeMode
+lsm_svg_edge_mode_from_string (const char *string)
+{
+       return lsm_enum_value_from_string (string, lsm_svg_edge_mode_strings,
+                                          G_N_ELEMENTS (lsm_svg_edge_mode_strings));
+}
diff --git a/src/lsmsvgenums.h b/src/lsmsvgenums.h
index 19471b4..13c7bcd 100644
--- a/src/lsmsvgenums.h
+++ b/src/lsmsvgenums.h
@@ -372,6 +372,16 @@ typedef enum {
 const char *                   lsm_svg_morphology_operator_to_string   (LsmSvgMorphologyOperator 
morpholoy_operator);
 LsmSvgMorphologyOperator       lsm_svg_morphology_operator_from_string (const char *string);
 
+typedef enum {
+       LSM_SVG_EDGE_MODE_ERROR = -1,
+       LSM_SVG_EDGE_MODE_DUPLICATE,
+       LSM_SVG_EDGE_MODE_WRAP,
+       LSM_SVG_EDGE_MODE_NONE
+} LsmSvgEdgeMode;
+
+const char *           lsm_svg_edge_mode_to_string     (LsmSvgEdgeMode edge_mode);
+LsmSvgEdgeMode         lsm_svg_edge_mode_from_string   (const char *string);
+
 G_END_DECLS
 
 #endif
diff --git a/src/lsmsvgfilterconvolvematrix.c b/src/lsmsvgfilterconvolvematrix.c
new file mode 100644
index 0000000..e65b926
--- /dev/null
+++ b/src/lsmsvgfilterconvolvematrix.c
@@ -0,0 +1,125 @@
+/* Lasem
+ * 
+ * Copyright © 2015 Emmanuel Pacaud
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ *     Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#include <lsmsvgfilterconvolvematrix.h>
+#include <lsmsvgview.h>
+
+static GObjectClass *parent_class;
+
+/* GdomNode implementation */
+
+static const char *
+lsm_svg_filter_convolve_matrix_get_node_name (LsmDomNode *node)
+{
+       return "feConvolveMatrix";
+}
+
+/* LsmSvgElement implementation */
+
+static void
+lsm_svg_filter_convolve_matrix_apply  (LsmSvgFilterPrimitive *self, LsmSvgView *view,
+                                      const char *input, const char *output, const LsmBox *subregion)
+{
+       LsmSvgFilterConvolveMatrix *convolve_matrix = LSM_SVG_FILTER_CONVOLVE_MATRIX (self);
+
+       lsm_svg_view_apply_convolve_matrix (view, input, output, subregion,
+                                           convolve_matrix->order.value.a,
+                                           convolve_matrix->order.value.b,
+                                           convolve_matrix->kernel.value.n_values,
+                                           convolve_matrix->kernel.value.values,
+                                           convolve_matrix->edge_mode.value);
+}
+
+/* LsmSvgFilterConvolveMatrix implementation */
+
+LsmDomNode *
+lsm_svg_filter_convolve_matrix_new (void)
+{
+       return g_object_new (LSM_TYPE_SVG_FILTER_CONVOLVE_MATRIX, NULL);
+}
+
+static const LsmSvgOneOrTwoInteger order_default = {0, 0};
+static const LsmSvgVector kernel_default = { .n_values = 0, .values = NULL};
+static const LsmSvgEdgeMode edge_mode_default = LSM_SVG_EDGE_MODE_NONE;
+
+static void
+lsm_svg_filter_convolve_matrix_init (LsmSvgFilterConvolveMatrix *self)
+{
+       self->order.value = order_default;
+       self->kernel.value = kernel_default;
+       self->edge_mode.value = edge_mode_default;
+}
+
+static void
+lsm_svg_filter_convolve_matrix_finalize (GObject *object)
+{
+       parent_class->finalize (object);
+}
+
+/* LsmSvgFilterConvolveMatrix class */
+
+static const LsmAttributeInfos lsm_svg_filter_convolve_matrix_attribute_infos[] = {
+       {
+               .name = "order",
+               .attribute_offset = offsetof (LsmSvgFilterConvolveMatrix, order),
+               .trait_class = &lsm_svg_one_or_two_integer_trait_class,
+               .trait_default = &order_default
+       },
+       {
+               .name = "kernelMatrix",
+               .attribute_offset = offsetof (LsmSvgFilterConvolveMatrix, kernel),
+               .trait_class = &lsm_svg_vector_trait_class,
+               .trait_default = &kernel_default
+       },
+       {
+               .name = "edgeMode",
+               .attribute_offset = offsetof (LsmSvgFilterConvolveMatrix, edge_mode),
+               .trait_class = &lsm_svg_edge_mode_trait_class,
+               .trait_default = &edge_mode_default
+       }
+};
+
+static void
+lsm_svg_filter_convolve_matrix_class_init (LsmSvgFilterConvolveMatrixClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       LsmDomNodeClass *d_node_class = LSM_DOM_NODE_CLASS (klass);
+       LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_CLASS (klass);
+       LsmSvgFilterPrimitiveClass *f_primitive_class = LSM_SVG_FILTER_PRIMITIVE_CLASS (klass);
+
+       parent_class = g_type_class_peek_parent (klass);
+
+       object_class->finalize = lsm_svg_filter_convolve_matrix_finalize;
+
+       d_node_class->get_node_name = lsm_svg_filter_convolve_matrix_get_node_name;
+
+       s_element_class->attribute_manager = lsm_attribute_manager_duplicate 
(s_element_class->attribute_manager);
+
+       lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
+                                             G_N_ELEMENTS (lsm_svg_filter_convolve_matrix_attribute_infos),
+                                             lsm_svg_filter_convolve_matrix_attribute_infos);
+
+       f_primitive_class->apply = lsm_svg_filter_convolve_matrix_apply;
+}
+
+G_DEFINE_TYPE (LsmSvgFilterConvolveMatrix, lsm_svg_filter_convolve_matrix, LSM_TYPE_SVG_FILTER_PRIMITIVE)
diff --git a/src/lsmsvgfilterconvolvematrix.h b/src/lsmsvgfilterconvolvematrix.h
new file mode 100644
index 0000000..1f98d61
--- /dev/null
+++ b/src/lsmsvgfilterconvolvematrix.h
@@ -0,0 +1,59 @@
+/* Lasem
+ *
+ * Copyright © 2015 Emmanuel Pacaud
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ *     Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_SVG_FILTER_CONVOLVE_MATRIX_H
+#define LSM_SVG_FILTER_CONVOLVE_MATRIX_H
+
+#include <lsmsvgtypes.h>
+#include <lsmsvgfilterprimitive.h>
+
+G_BEGIN_DECLS
+
+#define LSM_TYPE_SVG_FILTER_CONVOLVE_MATRIX             (lsm_svg_filter_convolve_matrix_get_type ())
+#define LSM_SVG_FILTER_CONVOLVE_MATRIX(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
LSM_TYPE_SVG_FILTER_CONVOLVE_MATRIX, LsmSvgFilterConvolveMatrix))
+#define LSM_SVG_FILTER_CONVOLVE_MATRIX_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), 
LSM_TYPE_SVG_FILTER_CONVOLVE_MATRIX, LsmSvgFilterConvolveMatrixClass))
+#define LSM_IS_SVG_FILTER_CONVOLVE_MATRIX(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
LSM_TYPE_SVG_FILTER_CONVOLVE_MATRIX))
+#define LSM_IS_SVG_FILTER_CONVOLVE_MATRIX_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), 
LSM_TYPE_SVG_FILTER_CONVOLVE_MATRIX))
+#define LSM_SVG_FILTER_CONVOLVE_MATRIX_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), 
LSM_TYPE_SVG_FILTER_CONVOLVE_MATRIX, LsmSvgFilterConvolveMatrixClass))
+
+typedef struct _LsmSvgFilterConvolveMatrixClass LsmSvgFilterConvolveMatrixClass;
+
+struct _LsmSvgFilterConvolveMatrix {
+       LsmSvgFilterPrimitive base;
+
+       LsmSvgOneOrTwoIntegerAttribute order;
+       LsmSvgVectorAttribute kernel;
+       LsmSvgEdgeModeAttribute edge_mode;
+};
+
+struct _LsmSvgFilterConvolveMatrixClass {
+       LsmSvgFilterPrimitiveClass  element_class;
+};
+
+GType lsm_svg_filter_convolve_matrix_get_type (void);
+
+LsmDomNode *   lsm_svg_filter_convolve_matrix_new              (void);
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmsvgfiltersurface.c b/src/lsmsvgfiltersurface.c
index c3dc4fd..8e278c9 100644
--- a/src/lsmsvgfiltersurface.c
+++ b/src/lsmsvgfiltersurface.c
@@ -613,6 +613,129 @@ lsm_svg_filter_surface_color_matrix (LsmSvgFilterSurface *input, LsmSvgFilterSur
 }
 
 void
+lsm_svg_filter_surface_convolve_matrix (LsmSvgFilterSurface *input, LsmSvgFilterSurface *output,
+                                        unsigned order_x, unsigned order_y, unsigned n_values, const double 
*values,
+                                        LsmSvgEdgeMode edge_mode)
+{
+       cairo_t *cairo;
+       int ch;
+       gint x, y, x1, x2, y1, y2;
+       gint width, height;
+       gint rowstride;
+       guchar *in_pixels;
+       guchar *output_pixels;
+       double kval, sum;
+       guchar sval;
+       int sx, sy, kx, ky;
+       /* TODO target */
+       double targetx = 0.0, targety = 0.0;
+       /* TODO d */
+       double dx = 1.0, dy = 1.0;
+       /* TODO */
+       gboolean preserve_alpha = FALSE;
+       /* TODO */
+       double divisor = 1.0;
+       /* TODO */
+       double bias = 0.0;
+       int umch, i, j;
+       gint tempresult;
+
+       g_return_if_fail (input != NULL);
+       g_return_if_fail (output != NULL);
+       g_return_if_fail (values != NULL || n_values < 1);
+
+       width = cairo_image_surface_get_width (input->surface);
+       height = cairo_image_surface_get_height (input->surface);
+
+       if (width != cairo_image_surface_get_width (output->surface) ||
+           height != cairo_image_surface_get_height (output->surface))
+               return;
+
+       if (height < 1 || width < 1)
+               return;
+
+       if (order_y * order_x != n_values)
+               return;
+
+       x1 = CLAMP (input->subregion.x, 0, width);
+       x2 = CLAMP (input->subregion.x + input->subregion.width, 0, width);
+       y1 = CLAMP (input->subregion.y, 0, height);
+       y2 = CLAMP (input->subregion.y + input->subregion.height, 0, height);
+
+       cairo_surface_flush (input->surface);
+       cairo = cairo_create (output->surface);
+
+       in_pixels = cairo_image_surface_get_data (input->surface);
+       output_pixels = cairo_image_surface_get_data (output->surface);
+       rowstride = cairo_image_surface_get_stride (input->surface);
+
+       for (y = y1; y < y2; y++)
+               for (x = x1; x < x2; x++) {
+                       for (umch = 0; umch < 3 + !preserve_alpha; umch++) {
+                               ch = channelmap[umch];
+                               sum = 0;
+                               for (i = 0; i < order_y; i++)
+                                       for (j = 0; j < order_x; j++) {
+                                               int alpha;
+                                               sx = x - targetx + j * dx;
+                                               sy = y - targety + i * dy;
+                                               if (edge_mode == LSM_SVG_EDGE_MODE_DUPLICATE) {
+                                                       if (sx < x1)
+                                                               sx = x1;
+                                                       if (sx >= x2)
+                                                               sx = x2 - 1;
+                                                       if (sy < y1)
+                                                               sy = y1;
+                                                       if (sy >= y2)
+                                                               sy = y2 - 1;
+                                               } else if (edge_mode == LSM_SVG_EDGE_MODE_WRAP) {
+                                                       if (sx < x1 || (sx >= x2))
+                                                               sx = x1 + (sx - x1) % (x2 - x1);
+                                                       if (sy < y1 || (sy >= y2))
+                                                               sy = y1 + (sy - y1) % (y2 - y1);
+                                               } else if (edge_mode == LSM_SVG_EDGE_MODE_NONE)
+                                                       if (sx < x1 || (sx >= x2) ||
+                                                           sy < y1 || (sy >= y2))
+                                                               continue;
+
+                                               kx = order_x - j - 1;
+                                               ky = order_y - i - 1;
+                                               alpha = in_pixels[4 * sx + sy * rowstride + 3];
+                                               if (ch == 3)
+                                                       sval = alpha;
+                                               else if (alpha)
+                                                       sval = in_pixels[4 * sx + sy * rowstride + ch] * 255 
/ alpha;
+                                               else
+                                                       sval = 0;
+                                               kval = values[kx + ky * order_x];
+                                               sum += (double) sval *kval;
+                                       }
+                               tempresult = sum / divisor + bias;
+
+                               if (tempresult > 255)
+                                       tempresult = 255;
+                               if (tempresult < 0)
+                                       tempresult = 0;
+
+                               output_pixels[4 * x + y * rowstride + ch] = tempresult;
+                       }
+                       if (preserve_alpha)
+                               output_pixels[4 * x + y * rowstride + channelmap[3]] =
+                                       in_pixels[4 * x + y * rowstride + channelmap[3]];
+                       for (umch = 0; umch < 3; umch++) {
+                               ch = channelmap[umch];
+                               output_pixels[4 * x + y * rowstride + ch] =
+                                       output_pixels[4 * x + y * rowstride + ch] *
+                                       output_pixels[4 * x + y * rowstride + channelmap[3]] / 255;
+                       }
+               }
+
+       cairo_surface_mark_dirty (output->surface);
+
+       cairo_destroy (cairo);
+}
+
+void
 lsm_svg_filter_surface_image (LsmSvgFilterSurface *output, GdkPixbuf *pixbuf,
                              LsmSvgPreserveAspectRatio preserve_aspect_ratio)
 {
diff --git a/src/lsmsvgfiltersurface.h b/src/lsmsvgfiltersurface.h
index 20574d1..c820a51 100644
--- a/src/lsmsvgfiltersurface.h
+++ b/src/lsmsvgfiltersurface.h
@@ -64,6 +64,10 @@ void                         lsm_svg_filter_surface_merge            (LsmSvgFilterSurface 
*input, LsmSvgFilter
 void                   lsm_svg_filter_surface_tile             (LsmSvgFilterSurface *input, 
LsmSvgFilterSurface *output);
 void                   lsm_svg_filter_surface_color_matrix     (LsmSvgFilterSurface *input, 
LsmSvgFilterSurface *output,
                                                                 LsmSvgColorFilterType type, unsigned 
n_values, const double *values);
+void                   lsm_svg_filter_surface_convolve_matrix  (LsmSvgFilterSurface *input, 
LsmSvgFilterSurface *output,
+                                                                unsigned x_order, unsigned y_order,
+                                                                unsigned n_values, const double *values,
+                                                                LsmSvgEdgeMode edge_mode);
 void                   lsm_svg_filter_surface_image            (LsmSvgFilterSurface *output, GdkPixbuf 
*pixbuf,
                                                                 LsmSvgPreserveAspectRatio 
preserve_aspect_ratio);
 void                   lsm_svg_filter_surface_morphology       (LsmSvgFilterSurface *input_surface, 
LsmSvgFilterSurface *output_surface,
diff --git a/src/lsmsvgtraits.c b/src/lsmsvgtraits.c
index 61a7616..5120049 100644
--- a/src/lsmsvgtraits.c
+++ b/src/lsmsvgtraits.c
@@ -1272,6 +1272,47 @@ const LsmTraitClass lsm_svg_one_or_two_double_trait_class = {
 };
 
 static gboolean
+lsm_svg_one_or_two_integer_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+       LsmSvgOneOrTwoInteger *trait = (LsmSvgOneOrTwoInteger *) abstract_trait;
+       char *end_ptr;
+
+       trait->a = g_ascii_strtoll (string, &end_ptr, 10);
+       if (end_ptr == string) {
+               trait->a = 0;
+               trait->b = 0;
+               return FALSE;
+       }
+
+       string = end_ptr;
+
+       lsm_str_skip_spaces (&string);
+
+       if (string[0] == '\0') {
+               trait->b = trait->a;
+               return TRUE;
+       }
+
+       trait->b = g_ascii_strtoll (string, &end_ptr, 10);
+
+       return TRUE;
+}
+
+static char *
+lsm_svg_one_or_two_integer_trait_to_string (LsmTrait *abstract_trait)
+{
+       LsmSvgOneOrTwoInteger *trait = (LsmSvgOneOrTwoInteger *) abstract_trait;
+
+       return g_strdup_printf ("%d %d", trait->a, trait->b);
+}
+
+const LsmTraitClass lsm_svg_one_or_two_integer_trait_class = {
+       .size = sizeof (double),
+       .from_string = lsm_svg_one_or_two_integer_trait_from_string,
+       .to_string = lsm_svg_one_or_two_integer_trait_to_string
+};
+
+static gboolean
 lsm_svg_overflow_trait_from_string (LsmTrait *abstract_trait, char *string)
 {
        LsmSvgOverflow *trait = (LsmSvgOverflow *) abstract_trait;
@@ -1342,3 +1383,27 @@ const LsmTraitClass lsm_svg_morphology_operator_trait_class = {
        .from_string = lsm_svg_morphology_operator_trait_from_string,
        .to_string = lsm_svg_morphology_operator_trait_to_string
 };
+
+static gboolean
+lsm_svg_edge_mode_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+       LsmSvgEdgeMode *trait = (LsmSvgEdgeMode *) abstract_trait;
+
+       *trait = lsm_svg_edge_mode_from_string (string);
+
+       return *trait >= 0;
+}
+
+static char *
+lsm_svg_edge_mode_trait_to_string (LsmTrait *abstract_trait)
+{
+       LsmSvgEdgeMode *trait = (LsmSvgEdgeMode *) abstract_trait;
+
+       return g_strdup (lsm_svg_edge_mode_to_string (*trait));
+}
+
+const LsmTraitClass lsm_svg_edge_mode_trait_class = {
+       .size = sizeof (LsmSvgEdgeMode),
+       .from_string = lsm_svg_edge_mode_trait_from_string,
+       .to_string = lsm_svg_edge_mode_trait_to_string
+};
diff --git a/src/lsmsvgtraits.h b/src/lsmsvgtraits.h
index 5ef84d4..a802494 100644
--- a/src/lsmsvgtraits.h
+++ b/src/lsmsvgtraits.h
@@ -77,6 +77,11 @@ typedef struct {
        double b;
 } LsmSvgOneOrTwoDouble;
 
+typedef struct {
+       int a;
+       int b;
+} LsmSvgOneOrTwoInteger;
+
 extern const LsmTraitClass lsm_svg_angle_trait_class;
 extern const LsmTraitClass lsm_svg_blending_mode_trait_class;
 extern const LsmTraitClass lsm_svg_enable_background_trait_class;
@@ -85,10 +90,12 @@ extern const LsmTraitClass lsm_svg_color_filter_type_trait_class;
 extern const LsmTraitClass lsm_svg_comp_op_trait_class;
 extern const LsmTraitClass lsm_svg_dash_array_trait_class;
 extern const LsmTraitClass lsm_svg_display_trait_class;
+extern const LsmTraitClass lsm_svg_edge_mode_trait_class;
 extern const LsmTraitClass lsm_svg_fill_rule_trait_class;
 extern const LsmTraitClass lsm_svg_font_stretch_trait_class;
 extern const LsmTraitClass lsm_svg_font_style_trait_class;
 extern const LsmTraitClass lsm_svg_font_weight_trait_class;
+extern const LsmTraitClass lsm_svg_one_or_two_integer_trait_class;
 extern const LsmTraitClass lsm_svg_length_trait_class;
 extern const LsmTraitClass lsm_svg_length_list_trait_class;
 extern const LsmTraitClass lsm_svg_line_join_trait_class;
@@ -97,13 +104,13 @@ extern const LsmTraitClass lsm_svg_marker_units_trait_class;
 extern const LsmTraitClass lsm_svg_matrix_trait_class;
 extern const LsmTraitClass lsm_svg_morphology_operator_trait_class;
 extern const LsmTraitClass lsm_svg_one_or_two_double_trait_class;
-extern const LsmTraitClass lsm_svg_vector_trait_class;
 extern const LsmTraitClass lsm_svg_overflow_trait_class;
 extern const LsmTraitClass lsm_svg_paint_trait_class;
 extern const LsmTraitClass lsm_svg_pattern_units_trait_class;
 extern const LsmTraitClass lsm_svg_preserve_aspect_ratio_trait_class;
 extern const LsmTraitClass lsm_svg_spread_method_trait_class;
 extern const LsmTraitClass lsm_svg_text_anchor_trait_class;
+extern const LsmTraitClass lsm_svg_vector_trait_class;
 extern const LsmTraitClass lsm_svg_visibility_trait_class;
 extern const LsmTraitClass lsm_svg_writing_mode_trait_class;
 
diff --git a/src/lsmsvgtypes.h b/src/lsmsvgtypes.h
index 554e2e4..3675138 100644
--- a/src/lsmsvgtypes.h
+++ b/src/lsmsvgtypes.h
@@ -49,6 +49,7 @@ typedef struct _LsmSvgFilterPrimitive LsmSvgFilterPrimitive;
 typedef struct _LsmSvgFilterBlend LsmSvgFilterBlend;
 typedef struct _LsmSvgFilterColorMatrix LsmSvgFilterColorMatrix;
 typedef struct _LsmSvgFilterComposite LsmSvgFilterComposite;
+typedef struct _LsmSvgFilterConvolveMatrix LsmSvgFilterConvolveMatrix;
 typedef struct _LsmSvgFilterFlood LsmSvgFilterFlood;
 typedef struct _LsmSvgFilterGaussianBlur LsmSvgFilterGaussianBlur;
 typedef struct _LsmSvgFilterImage LsmSvgFilterImage;
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index 51e7386..ae6a9f1 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -2251,6 +2251,29 @@ lsm_svg_view_apply_morphology (LsmSvgView *view, const char *input, const char *
 }
 
 void
+lsm_svg_view_apply_convolve_matrix (LsmSvgView *view, const char *input, const char *output, const LsmBox 
*subregion,
+                                   unsigned x_order, unsigned y_order, unsigned n_values, double *values, 
LsmSvgEdgeMode edge_mode)
+{
+       LsmSvgFilterSurface *input_surface;
+       LsmSvgFilterSurface *output_surface;
+       LsmBox subregion_px;
+
+       g_return_if_fail (LSM_IS_SVG_VIEW (view));
+
+       input_surface = _get_filter_surface (view, input);
+
+       if (input_surface == NULL) {
+               lsm_debug_render ("[SvgView::apply_color_matrix] Input '%s' not found", input);
+               return;
+       }
+
+       lsm_cairo_box_user_to_device (view->dom_view.cairo, &subregion_px, subregion);
+       output_surface = _create_filter_surface (view, output, input_surface, &subregion_px);
+
+       lsm_svg_filter_surface_convolve_matrix (input_surface, output_surface, x_order, y_order, n_values, 
values, edge_mode);
+}
+
+void
 lsm_svg_view_apply_merge (LsmSvgView *view, const char *input, const char *output, const LsmBox *subregion)
 {
        LsmSvgFilterSurface *input_surface;
diff --git a/src/lsmsvgview.h b/src/lsmsvgview.h
index d1c4224..b586964 100644
--- a/src/lsmsvgview.h
+++ b/src/lsmsvgview.h
@@ -181,6 +181,9 @@ void                lsm_svg_view_apply_image                (LsmSvgView *view, const char 
*output, const Ls
                                                         GdkPixbuf *pixbuf, LsmSvgPreserveAspectRatio 
preserve_aspect_ratio);
 void           lsm_svg_view_apply_morphology           (LsmSvgView *view, const char *input, const char 
*output, const LsmBox *subregion,
                                                         LsmSvgMorphologyOperator op, double radius);
+void           lsm_svg_view_apply_convolve_matrix      (LsmSvgView *view, const char *input, const char 
*output, const LsmBox *subregion,
+                                                        unsigned a, unsigned b, unsigned n_values, double 
*values,
+                                                        LsmSvgEdgeMode edge_mode);
 
 G_END_DECLS
 



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