[lasem] svg_convolve_matrix: implement divisor, bias, target and preserve_alpha



commit f280e32dcde106709f42cf7d88dba724040f3e8f
Author: Emmanuel Pacaud <emmanuel gnome org>
Date:   Mon Aug 3 23:41:18 2015 +0200

    svg_convolve_matrix: implement divisor, bias, target and preserve_alpha

 src/lsmsvgattributes.h           |   10 ++++
 src/lsmsvgfilterconvolvematrix.c |   87 ++++++++++++++++++++++++++++++++++++-
 src/lsmsvgfilterconvolvematrix.h |    5 ++
 src/lsmsvgfiltersurface.c        |   21 ++++-----
 src/lsmsvgfiltersurface.h        |    3 +-
 src/lsmsvgview.c                 |    7 ++-
 src/lsmsvgview.h                 |    3 +-
 src/lsmtraits.c                  |   53 +++++++++++++++++++++++
 src/lsmtraits.h                  |    2 +
 9 files changed, 173 insertions(+), 18 deletions(-)
---
diff --git a/src/lsmsvgattributes.h b/src/lsmsvgattributes.h
index 9ac6db4..280c6e8 100644
--- a/src/lsmsvgattributes.h
+++ b/src/lsmsvgattributes.h
@@ -40,6 +40,16 @@ typedef struct {
 
 typedef struct {
        LsmAttribute base;
+       gboolean value;
+} LsmSvgBooleanAttribute;
+
+typedef struct {
+       LsmAttribute base;
+       int value;
+} LsmSvgIntegerAttribute;
+
+typedef struct {
+       LsmAttribute base;
        double value;
 } LsmSvgDoubleAttribute;
 
diff --git a/src/lsmsvgfilterconvolvematrix.c b/src/lsmsvgfilterconvolvematrix.c
index e65b926..46f0721 100644
--- a/src/lsmsvgfilterconvolvematrix.c
+++ b/src/lsmsvgfilterconvolvematrix.c
@@ -40,14 +40,56 @@ static void
 lsm_svg_filter_convolve_matrix_apply  (LsmSvgFilterPrimitive *self, LsmSvgView *view,
                                       const char *input, const char *output, const LsmBox *subregion)
 {
+       double divisor;
+       int order_x;
+       int order_y;
+       int target_x;
+       int target_y;
+
        LsmSvgFilterConvolveMatrix *convolve_matrix = LSM_SVG_FILTER_CONVOLVE_MATRIX (self);
 
+       order_x = convolve_matrix->order.value.a;
+       order_y = convolve_matrix->order.value.b;
+
+       if (lsm_attribute_is_defined (&convolve_matrix->target_x.base))
+               target_x = convolve_matrix->target_x.value;
+       else
+               target_x = order_x / 2;
+
+       if (lsm_attribute_is_defined (&convolve_matrix->target_y.base))
+               target_y = convolve_matrix->target_y.value;
+       else
+               target_y = order_y / 2;
+
+       target_x = CLAMP (target_x, 0, order_x);
+       target_y = CLAMP (target_y, 0, order_y);
+
+       if (lsm_attribute_is_defined (&convolve_matrix->divisor.base))
+               divisor = convolve_matrix->divisor.value;
+       else {
+               int i;
+
+               divisor = 0.0;
+
+               for (i = 0; i < convolve_matrix->kernel.value.n_values; i++)
+                       divisor += convolve_matrix->kernel.value.values[i];
+       }
+
+       if (divisor <= 0.0) {
+               lsm_warning_dom ("[SvgFilterConvolveMatrix::apply] Invalid divisor");
+               return;
+       }
+
        lsm_svg_view_apply_convolve_matrix (view, input, output, subregion,
-                                           convolve_matrix->order.value.a,
-                                           convolve_matrix->order.value.b,
+                                           order_x, order_y,
                                            convolve_matrix->kernel.value.n_values,
                                            convolve_matrix->kernel.value.values,
-                                           convolve_matrix->edge_mode.value);
+                                           divisor,
+                                           convolve_matrix->bias.value,
+                                           target_x,
+                                           target_y,
+                                           convolve_matrix->edge_mode.value,
+                                           convolve_matrix->preserve_alpha.value);
 }
 
 /* LsmSvgFilterConvolveMatrix implementation */
@@ -60,14 +102,23 @@ lsm_svg_filter_convolve_matrix_new (void)
 
 static const LsmSvgOneOrTwoInteger order_default = {0, 0};
 static const LsmSvgVector kernel_default = { .n_values = 0, .values = NULL};
+static const double divisor_default = 0.0;
+static const double bias_default = 0.0;
+static const int target_default = -1;
 static const LsmSvgEdgeMode edge_mode_default = LSM_SVG_EDGE_MODE_NONE;
+static const gboolean preserve_alpha_default = FALSE;
 
 static void
 lsm_svg_filter_convolve_matrix_init (LsmSvgFilterConvolveMatrix *self)
 {
        self->order.value = order_default;
        self->kernel.value = kernel_default;
+       self->divisor.value = divisor_default;
+       self->bias.value = bias_default;
+       self->target_x.value = target_default;
+       self->target_y.value = target_default;
        self->edge_mode.value = edge_mode_default;
+       self->preserve_alpha.value = preserve_alpha_default;
 }
 
 static void
@@ -92,10 +143,40 @@ static const LsmAttributeInfos lsm_svg_filter_convolve_matrix_attribute_infos[]
                .trait_default = &kernel_default
        },
        {
+               .name = "divisor",
+               .attribute_offset = offsetof (LsmSvgFilterConvolveMatrix, divisor),
+               .trait_class = &lsm_double_trait_class,
+               .trait_default = &divisor_default
+       },
+       {
+               .name = "bias",
+               .attribute_offset = offsetof (LsmSvgFilterConvolveMatrix, bias),
+               .trait_class = &lsm_double_trait_class,
+               .trait_default = &bias_default
+       },
+       {
+               .name = "targetX",
+               .attribute_offset = offsetof (LsmSvgFilterConvolveMatrix, target_x),
+               .trait_class = &lsm_integer_trait_class,
+               .trait_default = &target_default
+       },
+       {
+               .name = "targetY",
+               .attribute_offset = offsetof (LsmSvgFilterConvolveMatrix, target_y),
+               .trait_class = &lsm_integer_trait_class,
+               .trait_default = &target_default
+       },
+       {
                .name = "edgeMode",
                .attribute_offset = offsetof (LsmSvgFilterConvolveMatrix, edge_mode),
                .trait_class = &lsm_svg_edge_mode_trait_class,
                .trait_default = &edge_mode_default
+       },
+       {
+               .name = "preserveAlpha",
+               .attribute_offset = offsetof (LsmSvgFilterConvolveMatrix, preserve_alpha),
+               .trait_class = &lsm_boolean_trait_class,
+               .trait_default = &preserve_alpha_default
        }
 };
 
diff --git a/src/lsmsvgfilterconvolvematrix.h b/src/lsmsvgfilterconvolvematrix.h
index 1f98d61..be012a5 100644
--- a/src/lsmsvgfilterconvolvematrix.h
+++ b/src/lsmsvgfilterconvolvematrix.h
@@ -43,7 +43,12 @@ struct _LsmSvgFilterConvolveMatrix {
 
        LsmSvgOneOrTwoIntegerAttribute order;
        LsmSvgVectorAttribute kernel;
+       LsmSvgDoubleAttribute divisor;
+       LsmSvgDoubleAttribute bias;
+       LsmSvgIntegerAttribute target_x;
+       LsmSvgIntegerAttribute target_y;
        LsmSvgEdgeModeAttribute edge_mode;
+       LsmSvgBooleanAttribute preserve_alpha;
 };
 
 struct _LsmSvgFilterConvolveMatrixClass {
diff --git a/src/lsmsvgfiltersurface.c b/src/lsmsvgfiltersurface.c
index 57e1adc..9c77d59 100644
--- a/src/lsmsvgfiltersurface.c
+++ b/src/lsmsvgfiltersurface.c
@@ -615,7 +615,8 @@ 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)
+                                        double divisor, double bias, unsigned target_x, unsigned target_y,
+                                        LsmSvgEdgeMode edge_mode, gboolean preserve_alpha)
 {
        cairo_t *cairo;
        int ch;
@@ -627,16 +628,8 @@ lsm_svg_filter_surface_convolve_matrix (LsmSvgFilterSurface *input, LsmSvgFilter
        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;
 
@@ -644,6 +637,9 @@ lsm_svg_filter_surface_convolve_matrix (LsmSvgFilterSurface *input, LsmSvgFilter
        g_return_if_fail (output != NULL);
        g_return_if_fail (values != NULL || n_values < 1);
 
+       if (divisor <= 0.0)
+               return;
+
        width = cairo_image_surface_get_width (input->surface);
        height = cairo_image_surface_get_height (input->surface);
 
@@ -657,6 +653,9 @@ lsm_svg_filter_surface_convolve_matrix (LsmSvgFilterSurface *input, LsmSvgFilter
        if (order_y * order_x != n_values)
                return;
 
+       if (target_x > order_x || target_y > order_y)
+               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);
@@ -677,8 +676,8 @@ lsm_svg_filter_surface_convolve_matrix (LsmSvgFilterSurface *input, LsmSvgFilter
                                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;
+                                               sx = x - target_x + j * dx;
+                                               sy = y - target_y + i * dy;
                                                if (edge_mode == LSM_SVG_EDGE_MODE_DUPLICATE) {
                                                        if (sx < x1)
                                                                sx = x1;
diff --git a/src/lsmsvgfiltersurface.h b/src/lsmsvgfiltersurface.h
index 731e348..45ab6ed 100644
--- a/src/lsmsvgfiltersurface.h
+++ b/src/lsmsvgfiltersurface.h
@@ -67,7 +67,8 @@ void                  lsm_svg_filter_surface_color_matrix     (LsmSvgFilterSurface *input, 
LsmSvg
 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);
+                                                                double divisor, double bias, unsigned 
target_x, unsigned target_y,
+                                                                LsmSvgEdgeMode edge_mode, gboolean 
preserve_alpha);
 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/lsmsvgview.c b/src/lsmsvgview.c
index 348ff40..6b34f09 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -2252,7 +2252,9 @@ 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)
+                                   unsigned x_order, unsigned y_order, unsigned n_values, double *values,
+                                   double divisor, double bias, int target_x, int target_y,
+                                   LsmSvgEdgeMode edge_mode, gboolean preserve_alpha)
 {
        LsmSvgFilterSurface *input_surface;
        LsmSvgFilterSurface *output_surface;
@@ -2270,7 +2272,8 @@ lsm_svg_view_apply_convolve_matrix (LsmSvgView *view, const char *input, const c
        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);
+       lsm_svg_filter_surface_convolve_matrix (input_surface, output_surface, x_order, y_order, n_values, 
values,
+                                               divisor, bias, target_x, target_y, edge_mode, preserve_alpha);
 }
 
 void 
diff --git a/src/lsmsvgview.h b/src/lsmsvgview.h
index 487e5b0..bc6c780 100644
--- a/src/lsmsvgview.h
+++ b/src/lsmsvgview.h
@@ -183,7 +183,8 @@ void                lsm_svg_view_apply_morphology           (LsmSvgView *view, const char 
*input, con
                                                         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);
+                                                        double divisor, double bias, int target_x, int 
target_y,
+                                                        LsmSvgEdgeMode edge_mode, gboolean preserve_alpha);
 void           lsm_svg_view_apply_specular_lighting    (LsmSvgView *view, const char *output, const LsmBox 
*subregion,
                                                         double surface_scale, double specular_constant, 
double specular_exponent,
                                                         double dx, double dy);
diff --git a/src/lsmtraits.c b/src/lsmtraits.c
index ad46efb..96809dd 100644
--- a/src/lsmtraits.c
+++ b/src/lsmtraits.c
@@ -31,6 +31,59 @@ const LsmTraitClass lsm_null_trait_class = {
 };
 
 static gboolean
+lsm_boolean_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+       gboolean *trait = (gboolean *) abstract_trait;
+
+       if (g_strcmp0 ("true", string) == 0)
+               *trait = TRUE;
+       else if (g_strcmp0 ("false", string) == 0)
+               *trait = FALSE;
+       else return FALSE;
+
+       return TRUE;
+}
+
+static char *
+lsm_boolean_trait_to_string (LsmTrait *abstract_trait)
+{
+       gboolean *trait = (gboolean *) abstract_trait;
+
+       return g_strdup_printf ("%s", *trait ? "true" : "false");
+}
+
+const LsmTraitClass lsm_boolean_trait_class = {
+       .size = sizeof (gboolean),
+       .from_string = lsm_boolean_trait_from_string,
+       .to_string = lsm_boolean_trait_to_string
+};
+
+static gboolean
+lsm_integer_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+       int *trait = (int *) abstract_trait;
+       char *end_ptr;
+
+       *trait = g_ascii_strtoll (string, &end_ptr, 10);
+
+       return end_ptr != string;
+}
+
+static char *
+lsm_integer_trait_to_string (LsmTrait *abstract_trait)
+{
+       int *trait = (int *) abstract_trait;
+
+       return g_strdup_printf ("%d", *trait);
+}
+
+const LsmTraitClass lsm_integer_trait_class = {
+       .size = sizeof (int),
+       .from_string = lsm_integer_trait_from_string,
+       .to_string = lsm_integer_trait_to_string
+};
+
+static gboolean
 lsm_double_trait_from_string (LsmTrait *abstract_trait, char *string)
 {
        double *trait = (double *) abstract_trait;
diff --git a/src/lsmtraits.h b/src/lsmtraits.h
index 5716554..6d58d0d 100644
--- a/src/lsmtraits.h
+++ b/src/lsmtraits.h
@@ -39,6 +39,8 @@ typedef struct {
 } LsmTraitClass;
 
 extern const LsmTraitClass lsm_null_trait_class;
+extern const LsmTraitClass lsm_boolean_trait_class;
+extern const LsmTraitClass lsm_integer_trait_class;
 extern const LsmTraitClass lsm_double_trait_class;
 extern const LsmTraitClass lsm_box_trait_class;
 



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