[lasem] svg_morphology: import algorithm from librsvg
- From: Emmanuel Pacaud <emmanuel src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [lasem] svg_morphology: import algorithm from librsvg
- Date: Sun, 2 Aug 2015 19:22:15 +0000 (UTC)
commit 7466f0b3b28001892441edf484b3fee5c6b9aca5
Author: Emmanuel Pacaud <emmanuel gnome org>
Date: Sun Aug 2 12:19:31 2015 +0200
svg_morphology: import algorithm from librsvg
docs/reference/lasem/Makefile.am | 3 +
src/Makefile.am | 4 +
src/lsmsvgdocument.c | 3 +
src/lsmsvgfiltermorphology.c | 116 ++++++++++++++++++++++++++++++++++++++
src/lsmsvgfiltermorphology.h | 58 +++++++++++++++++++
src/lsmsvgfiltersurface.c | 82 ++++++++++++++++++++++++++-
src/lsmsvgfiltersurface.h | 2 +
src/lsmsvgtraits.h | 1 +
src/lsmsvgtypes.h | 1 +
src/lsmsvgview.c | 28 +++++++++
src/lsmsvgview.h | 2 +
11 files changed, 299 insertions(+), 1 deletions(-)
---
diff --git a/docs/reference/lasem/Makefile.am b/docs/reference/lasem/Makefile.am
index 75b668c..a88e1c3 100644
--- a/docs/reference/lasem/Makefile.am
+++ b/docs/reference/lasem/Makefile.am
@@ -153,11 +153,14 @@ IGNORE_HFILES=\
lsmsvgfilterprimitive.h \
lsmsvgfilterblend.h \
lsmsvgfiltercomposite.h \
+ lsmsvgfiltercolormatrix.h \
lsmsvgfilterflood.h \
lsmsvgfiltergaussianblur.h \
+ lsmsvgfilterimage.h \
lsmsvgfilteroffset.h \
lsmsvgfiltermerge.h \
lsmsvgfiltermergenode.h \
+ lsmsvgfiltermorphology.h \
lsmsvgfilterspecularlighting.h \
lsmsvgfiltertile.h \
lsmsvgfiltersurface.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 4d78c57..98640b8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -142,6 +142,7 @@ LASEM_SVG_SRCS = \
lsmsvgfilteroffset.c \
lsmsvgfiltermerge.c \
lsmsvgfiltermergenode.c \
+ lsmsvgfiltermorphology.c \
lsmsvgfilterspecularlighting.c \
lsmsvgfiltertile.c \
lsmsvgfiltersurface.c
@@ -254,12 +255,15 @@ LASEM_SVG_HDRS = \
lsmsvgfilterelement.h \
lsmsvgfilterprimitive.h \
lsmsvgfilterblend.h \
+ lsmsvgfiltercolormatrix.h \
lsmsvgfiltercomposite.h \
lsmsvgfilterflood.h \
lsmsvgfiltergaussianblur.h \
+ lsmsvgfilterimage.h \
lsmsvgfilteroffset.h \
lsmsvgfiltermerge.h \
lsmsvgfiltermergenode.h \
+ lsmsvgfiltermorphology.h \
lsmsvgfilterspecularlighting.h \
lsmsvgfiltertile.h \
lsmsvgfiltersurface.h
diff --git a/src/lsmsvgdocument.c b/src/lsmsvgdocument.c
index 99ade04..c5e7b67 100644
--- a/src/lsmsvgdocument.c
+++ b/src/lsmsvgdocument.c
@@ -37,6 +37,7 @@
#include <lsmsvgfilteroffset.h>
#include <lsmsvgfiltermerge.h>
#include <lsmsvgfiltermergenode.h>
+#include <lsmsvgfiltermorphology.h>
#include <lsmsvgfilterspecularlighting.h>
#include <lsmsvgfiltercolormatrix.h>
#include <lsmsvgfiltertile.h>
@@ -172,6 +173,8 @@ _create_element (LsmDomDocument *document, const char *tag_name)
node = lsm_svg_filter_color_matrix_new ();
else if (strcmp (tag_name, "feImage") == 0)
node = lsm_svg_filter_image_new ();
+ else if (strcmp (tag_name, "feMorphology") == 0)
+ node = lsm_svg_filter_morphology_new ();
else if (strcmp (tag_name, "feTile") == 0)
node = lsm_svg_filter_tile_new ();
diff --git a/src/lsmsvgfiltermorphology.c b/src/lsmsvgfiltermorphology.c
new file mode 100644
index 0000000..52dfded
--- /dev/null
+++ b/src/lsmsvgfiltermorphology.c
@@ -0,0 +1,116 @@
+/* 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 <lsmsvgfiltermorphology.h>
+#include <lsmsvgview.h>
+
+static GObjectClass *parent_class;
+
+/* GdomNode implementation */
+
+static const char *
+lsm_svg_filter_morphology_get_node_name (LsmDomNode *node)
+{
+ return "feMorphology";
+}
+
+/* LsmSvgElement implementation */
+
+static void
+lsm_svg_filter_morphology_apply (LsmSvgFilterPrimitive *self, LsmSvgView *view,
+ const char *input, const char *output, const LsmBox *subregion)
+{
+ double radius;
+
+ LsmSvgFilterMorphology *morphology = LSM_SVG_FILTER_MORPHOLOGY (self);
+
+ radius = lsm_svg_view_normalize_length (view, &morphology->radius.length,
LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
+
+ lsm_svg_view_apply_morphology (view, input, output, subregion, morphology->op.value, radius);
+}
+
+/* LsmSvgFilterMorphology implementation */
+
+LsmDomNode *
+lsm_svg_filter_morphology_new (void)
+{
+ return g_object_new (LSM_TYPE_SVG_FILTER_MORPHOLOGY, NULL);
+}
+
+static const LsmSvgLength radius_default = { .value_unit = 0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
+static const LsmSvgMorphologyOperator operator_default = LSM_SVG_MORPHOLOGY_OPERATOR_ERODE;
+
+static void
+lsm_svg_filter_morphology_init (LsmSvgFilterMorphology *self)
+{
+ self->radius.length = radius_default;
+ self->op.value = operator_default;
+}
+
+static void
+lsm_svg_filter_morphology_finalize (GObject *object)
+{
+ parent_class->finalize (object);
+}
+
+/* LsmSvgFilterMorphology class */
+
+static const LsmAttributeInfos lsm_svg_filter_morphology_attribute_infos[] = {
+ {
+ .name = "radius",
+ .attribute_offset = offsetof (LsmSvgFilterMorphology, radius),
+ .trait_class = &lsm_svg_length_trait_class,
+ .trait_default = &radius_default
+ },
+ {
+ .name = "operator",
+ .attribute_offset = offsetof (LsmSvgFilterMorphology, op),
+ .trait_class = &lsm_svg_morphology_operator_trait_class,
+ .trait_default = &operator_default
+ }
+};
+
+static void
+lsm_svg_filter_morphology_class_init (LsmSvgFilterMorphologyClass *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_morphology_finalize;
+
+ d_node_class->get_node_name = lsm_svg_filter_morphology_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_morphology_attribute_infos),
+ lsm_svg_filter_morphology_attribute_infos);
+
+ f_primitive_class->apply = lsm_svg_filter_morphology_apply;
+}
+
+G_DEFINE_TYPE (LsmSvgFilterMorphology, lsm_svg_filter_morphology, LSM_TYPE_SVG_FILTER_PRIMITIVE)
diff --git a/src/lsmsvgfiltermorphology.h b/src/lsmsvgfiltermorphology.h
new file mode 100644
index 0000000..8bcb1af
--- /dev/null
+++ b/src/lsmsvgfiltermorphology.h
@@ -0,0 +1,58 @@
+/* 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_MORPHOLOGY_H
+#define LSM_SVG_FILTER_MORPHOLOGY_H
+
+#include <lsmsvgtypes.h>
+#include <lsmsvgfilterprimitive.h>
+
+G_BEGIN_DECLS
+
+#define LSM_TYPE_SVG_FILTER_MORPHOLOGY (lsm_svg_filter_morphology_get_type ())
+#define LSM_SVG_FILTER_MORPHOLOGY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
LSM_TYPE_SVG_FILTER_MORPHOLOGY, LsmSvgFilterMorphology))
+#define LSM_SVG_FILTER_MORPHOLOGY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),
LSM_TYPE_SVG_FILTER_MORPHOLOGY, LsmSvgFilterMorphologyClass))
+#define LSM_IS_SVG_FILTER_MORPHOLOGY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),
LSM_TYPE_SVG_FILTER_MORPHOLOGY))
+#define LSM_IS_SVG_FILTER_MORPHOLOGY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),
LSM_TYPE_SVG_FILTER_MORPHOLOGY))
+#define LSM_SVG_FILTER_MORPHOLOGY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),
LSM_TYPE_SVG_FILTER_MORPHOLOGY, LsmSvgFilterMorphologyClass))
+
+typedef struct _LsmSvgFilterMorphologyClass LsmSvgFilterMorphologyClass;
+
+struct _LsmSvgFilterMorphology {
+ LsmSvgFilterPrimitive base;
+
+ LsmSvgMorphologyOperatorAttribute op;
+ LsmSvgLengthAttribute radius;
+};
+
+struct _LsmSvgFilterMorphologyClass {
+ LsmSvgFilterPrimitiveClass element_class;
+};
+
+GType lsm_svg_filter_morphology_get_type (void);
+
+LsmDomNode * lsm_svg_filter_morphology_new (void);
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmsvgfiltersurface.c b/src/lsmsvgfiltersurface.c
index 5a8f171..c3dc4fd 100644
--- a/src/lsmsvgfiltersurface.c
+++ b/src/lsmsvgfiltersurface.c
@@ -32,6 +32,8 @@
#include <math.h>
#include <string.h>
+static const int channelmap[4] = {2, 1, 0, 3};
+
struct _LsmSvgFilterSurface {
char *name;
cairo_surface_t *surface;
@@ -479,7 +481,6 @@ lsm_svg_filter_surface_color_matrix (LsmSvgFilterSurface *input, LsmSvgFilterSur
gint sum;
guchar *in_pixels;
guchar *output_pixels;
- int channelmap[4] = {2, 1, 0, 3};
double setting;
g_return_if_fail (input != NULL);
@@ -646,3 +647,82 @@ lsm_svg_filter_surface_image (LsmSvgFilterSurface *output, GdkPixbuf *pixbuf,
cairo_destroy (cairo);
}
+
+void
+lsm_svg_filter_surface_morphology (LsmSvgFilterSurface *input, LsmSvgFilterSurface *output,
+ LsmSvgMorphologyOperator op, double rx, double ry)
+{
+ cairo_t *cairo;
+ int i, j;
+ int ch, extreme;
+ gint x, y, x1, x2, y1, y2;
+ gint width, height;
+ gint rowstride;
+ guchar *in_pixels;
+ guchar *output_pixels;
+ gint kx, ky;
+ guchar val;
+
+ g_return_if_fail (input != NULL);
+ g_return_if_fail (output != NULL);
+
+ 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;
+
+ kx = rx;
+ ky = ry;
+
+ if (kx < 1 && ky < 1)
+ return;
+
+ 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);
+
+ 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);
+
+ for (y = y1; y < y2; y++)
+ for (x = x1; x < x2; x++)
+ for (ch = 0; ch < 4; ch++) {
+ if (op == LSM_SVG_MORPHOLOGY_OPERATOR_ERODE)
+ extreme = 255;
+ else
+ extreme = 0;
+ for (i = -ky; i < ky + 1; i++)
+ for (j = -kx; j < kx + 1; j++) {
+ if (y + i >= height || y + i < 0 || x + j >= width || x + j <
0)
+ continue;
+
+ val = in_pixels[(y + i) * rowstride + (x + j) * 4 + ch];
+
+
+ if (op == LSM_SVG_MORPHOLOGY_OPERATOR_ERODE) {
+ if (extreme > val)
+ extreme = val;
+ } else {
+ if (extreme < val)
+ extreme = val;
+ }
+
+ }
+ output_pixels[y * rowstride + x * 4 + ch] = extreme;
+ }
+
+ cairo_surface_mark_dirty (output->surface);
+
+ cairo_destroy (cairo);
+}
+
diff --git a/src/lsmsvgfiltersurface.h b/src/lsmsvgfiltersurface.h
index 48c9bfd..20574d1 100644
--- a/src/lsmsvgfiltersurface.h
+++ b/src/lsmsvgfiltersurface.h
@@ -66,6 +66,8 @@ void lsm_svg_filter_surface_color_matrix (LsmSvgFilterSurface *input,
LsmSvg
LsmSvgColorFilterType type, unsigned
n_values, const double *values);
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,
+ LsmSvgMorphologyOperator op, double rx,
double ry);
G_END_DECLS
diff --git a/src/lsmsvgtraits.h b/src/lsmsvgtraits.h
index 64f16aa..5ef84d4 100644
--- a/src/lsmsvgtraits.h
+++ b/src/lsmsvgtraits.h
@@ -95,6 +95,7 @@ extern const LsmTraitClass lsm_svg_line_join_trait_class;
extern const LsmTraitClass lsm_svg_line_cap_trait_class;
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;
diff --git a/src/lsmsvgtypes.h b/src/lsmsvgtypes.h
index d3931da..554e2e4 100644
--- a/src/lsmsvgtypes.h
+++ b/src/lsmsvgtypes.h
@@ -54,6 +54,7 @@ typedef struct _LsmSvgFilterGaussianBlur LsmSvgFilterGaussianBlur;
typedef struct _LsmSvgFilterImage LsmSvgFilterImage;
typedef struct _LsmSvgFilterMerge LsmSvgFilterMerge;
typedef struct _LsmSvgFilterMergeNode LsmSvgFilterMergeNode;
+typedef struct _LsmSvgFilterMorphology LsmSvgFilterMorphology;
typedef struct _LsmSvgFilterOffset LsmSvgFilterOffset;
typedef struct _LsmSvgFilterSpecularLighting LsmSvgFilterSpecularLighting;
typedef struct _LsmSvgFilterTile LsmSvgFilterTile;
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index 61647db..51e7386 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -2222,6 +2222,34 @@ lsm_svg_view_apply_color_matrix (LsmSvgView *view, const char *input, const char
lsm_svg_filter_surface_color_matrix (input_surface, output_surface, type, n_values, values);
}
+void
+lsm_svg_view_apply_morphology (LsmSvgView *view, const char *input, const char *output, const LsmBox
*subregion,
+ LsmSvgMorphologyOperator op, double radius)
+{
+ LsmSvgFilterSurface *input_surface;
+ LsmSvgFilterSurface *output_surface;
+ LsmBox subregion_px;
+ double rx, ry;
+
+ 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_morphoogy] 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);
+
+ rx = radius;
+ ry = radius;
+ cairo_user_to_device_distance (view->dom_view.cairo, &rx, &ry);
+
+ lsm_svg_filter_surface_morphology (input_surface, output_surface, op, rx, ry);
+}
+
void
lsm_svg_view_apply_merge (LsmSvgView *view, const char *input, const char *output, const LsmBox *subregion)
{
diff --git a/src/lsmsvgview.h b/src/lsmsvgview.h
index 128fc62..d1c4224 100644
--- a/src/lsmsvgview.h
+++ b/src/lsmsvgview.h
@@ -179,6 +179,8 @@ void lsm_svg_view_apply_merge (LsmSvgView *view, const char
*input, const ch
void lsm_svg_view_apply_tile (LsmSvgView *view, const char *input, const char
*output, const LsmBox *subregion);
void lsm_svg_view_apply_image (LsmSvgView *view, const char *output, const LsmBox
*subregion,
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);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]