[gnome-photos/gnome-3-22] Use our own composer for the SVG (and PDF) blend operation multiply



commit e53964be0381f0ccf315bfe35327ee69bbb54e8e
Author: Debarshi Ray <debarshir gnome org>
Date:   Wed Jun 21 17:19:56 2017 +0200

    Use our own composer for the SVG (and PDF) blend operation multiply
    
    The svg:multiply operation got removed in GEGL 0.3.16 due to conflicts
    with gegl:multiply. Even though gegl:multiply is intended to produce
    the same result as svg:multiply, that is not the case right now. They
    only match when the auxiliary and input buffers don't have any
    transparency.
    
    Let's implement and carry our own until this is resolved.
    
    Based on:
    https://www.cairographics.org/operators/
    https://www.w3.org/TR/2004/WD-SVG12-20041027/rendering.html#comp-op-prop

 src/Makefile.am                     |    2 +
 src/photos-operation-insta-hefe.c   |    2 +-
 src/photos-operation-svg-multiply.c |  229 +++++++++++++++++++++++++++++++++++
 src/photos-operation-svg-multiply.h |   45 +++++++
 src/photos-utils.c                  |    4 +-
 5 files changed, 280 insertions(+), 2 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 55fe257..f0c485a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -144,6 +144,8 @@ gnome_photos_SOURCES = \
        photos-operation-png-guess-sizes.h \
        photos-operation-saturation.c \
        photos-operation-saturation.h \
+       photos-operation-svg-multiply.c \
+       photos-operation-svg-multiply.h \
        photos-organize-collection-dialog.c \
        photos-organize-collection-dialog.h \
        photos-organize-collection-model.c \
diff --git a/src/photos-operation-insta-hefe.c b/src/photos-operation-insta-hefe.c
index b424a1c..458151f 100644
--- a/src/photos-operation-insta-hefe.c
+++ b/src/photos-operation-insta-hefe.c
@@ -69,7 +69,7 @@ photos_operation_insta_hefe_attach (GeglOperation *operation)
   self->output = gegl_node_get_output_proxy (operation->node, "output");
 
   curve = gegl_node_new_child (operation->node, "operation", "photos:insta-hefe-curve", NULL);
-  multiply = gegl_node_new_child (operation->node, "operation", "svg:multiply", "srgb", TRUE, NULL);
+  multiply = gegl_node_new_child (operation->node, "operation", "photos:svg-multiply", "srgb", TRUE, NULL);
   self->vignette = gegl_node_new_child (operation->node, "operation", "photos:insta-hefe-vignette", NULL);
 
   gegl_node_connect_to (self->vignette, "output", multiply, "aux");
diff --git a/src/photos-operation-svg-multiply.c b/src/photos-operation-svg-multiply.c
new file mode 100644
index 0000000..bece6f1
--- /dev/null
+++ b/src/photos-operation-svg-multiply.c
@@ -0,0 +1,229 @@
+/*
+ * Photos - access, organize and share your photos on GNOME
+ * Copyright © 2017 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+
+#include "config.h"
+
+#include <babl/babl.h>
+#include <gegl.h>
+#include <gegl-plugin.h>
+
+#include "photos-operation-svg-multiply.h"
+
+
+struct _PhotosOperationSvgMultiply
+{
+  GeglOperationPointComposer parent_instance;
+  gboolean srgb;
+};
+
+struct _PhotosOperationSvgMultiplyClass
+{
+  GeglOperationPointComposerClass parent_class;
+};
+
+enum
+{
+  PROP_0,
+  PROP_SRGB
+};
+
+
+G_DEFINE_TYPE (PhotosOperationSvgMultiply, photos_operation_svg_multiply, 
GEGL_TYPE_OPERATION_POINT_COMPOSER);
+
+
+static void
+photos_operation_svg_multiply_prepare (GeglOperation *operation)
+{
+  PhotosOperationSvgMultiply *self = PHOTOS_OPERATION_SVG_MULTIPLY (operation);
+  const Babl *format;
+
+  if (self->srgb)
+    format = babl_format ("R'aG'aB'aA float");
+  else
+    format = babl_format ("RaGaBaA float");
+
+  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input", format);
+  gegl_operation_set_format (operation, "output", format);
+}
+
+
+static gboolean
+photos_operation_svg_multiply_operation_process (GeglOperation *operation,
+                                                 GeglOperationContext *context,
+                                                 const gchar *output_pad,
+                                                 const GeglRectangle *roi,
+                                                 gint level)
+{
+  GObject *aux;
+  GObject *input;
+  const GeglRectangle *aux_bbox = NULL;
+  const GeglRectangle *in_bbox = NULL;
+  gboolean ret_val = TRUE;
+
+  aux = gegl_operation_context_get_object (context, "aux");
+  if (aux != NULL)
+    aux_bbox = gegl_buffer_get_abyss (GEGL_BUFFER (aux));
+
+  input = gegl_operation_context_get_object (context, "input");
+  if (input != NULL)
+    in_bbox = gegl_buffer_get_abyss (GEGL_BUFFER (input));
+
+  if (aux == NULL || (input != NULL && !gegl_rectangle_intersect (NULL, aux_bbox, roi)))
+    {
+      gegl_operation_context_set_object (context, "output", input);
+      goto out;
+    }
+
+  if (input == NULL || (aux != NULL && !gegl_rectangle_intersect (NULL, in_bbox, roi)))
+    {
+      gegl_operation_context_set_object (context, "output", aux);
+      goto out;
+    }
+
+  ret_val = GEGL_OPERATION_CLASS (photos_operation_svg_multiply_parent_class)->process (operation,
+                                                                                        context,
+                                                                                        output_pad,
+                                                                                        roi,
+                                                                                        level);
+
+ out:
+  return ret_val;
+}
+
+
+static gboolean
+photos_operation_svg_multiply_point_composer_process (GeglOperation *operation,
+                                                      void *in_buf,
+                                                      void *aux_buf,
+                                                      void *out_buf,
+                                                      glong n_pixels,
+                                                      const GeglRectangle *roi,
+                                                      gint level)
+{
+  gfloat *aux = aux_buf;
+  gfloat *in = in_buf;
+  gfloat *out = out_buf;
+  glong i;
+
+  g_return_val_if_fail (aux != NULL, FALSE);
+  g_return_val_if_fail (in != NULL, FALSE);
+
+  for (i = 0; i < n_pixels; i++)
+    {
+      const gfloat aA = aux[3];
+      const gfloat aB = in[3];
+      const gfloat aR = aA + aB * (1 - aA);
+      gint j;
+
+      out[3] = aR;
+
+      for (j = 0; j < 3; j++)
+        {
+          const gfloat xA = aux[j];
+          const gfloat xB = in[j];
+          gfloat xR;
+
+          xR = (1 - aB) * xA + (1 - aA) * xB + xA * xB;
+          out[j] = CLAMP (xR, 0.0f, aR);
+        }
+
+      aux += 4;
+      in += 4;
+      out += 4;
+    }
+
+  return TRUE;
+}
+
+
+static void
+photos_operation_svg_multiply_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+  PhotosOperationSvgMultiply *self = PHOTOS_OPERATION_SVG_MULTIPLY (object);
+
+  switch (prop_id)
+    {
+    case PROP_SRGB:
+      g_value_set_boolean (value, self->srgb);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+static void
+photos_operation_svg_multiply_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec 
*pspec)
+{
+  PhotosOperationSvgMultiply *self = PHOTOS_OPERATION_SVG_MULTIPLY (object);
+
+  switch (prop_id)
+    {
+    case PROP_SRGB:
+      self->srgb = g_value_get_boolean (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+static void
+photos_operation_svg_multiply_init (PhotosOperationSvgMultiply *self)
+{
+}
+
+
+static void
+photos_operation_svg_multiply_class_init (PhotosOperationSvgMultiplyClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (class);
+  GeglOperationPointComposerClass *point_composer_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (class);
+
+  operation_class->opencl_support = FALSE;
+
+  object_class->get_property = photos_operation_svg_multiply_get_property;
+  object_class->set_property = photos_operation_svg_multiply_set_property;
+  operation_class->prepare = photos_operation_svg_multiply_prepare;
+  operation_class->process = photos_operation_svg_multiply_operation_process;
+  point_composer_class->process = photos_operation_svg_multiply_point_composer_process;
+
+  g_object_class_install_property (object_class,
+                                   PROP_SRGB,
+                                   g_param_spec_boolean ("srgb",
+                                                         "sRGB",
+                                                         "Use sRGB gamma instead of linear",
+                                                         FALSE,
+                                                         G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+
+  gegl_operation_class_set_keys (operation_class,
+                                 "name", "photos:svg-multiply",
+                                 "title", "SVG Multiply",
+                                 "description", "SVG blend operation multiply",
+                                 "categories", "compositors:svgfilter",
+                                 NULL);
+}
diff --git a/src/photos-operation-svg-multiply.h b/src/photos-operation-svg-multiply.h
new file mode 100644
index 0000000..4605aeb
--- /dev/null
+++ b/src/photos-operation-svg-multiply.h
@@ -0,0 +1,45 @@
+/*
+ * Photos - access, organize and share your photos on GNOME
+ * Copyright © 2017 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef PHOTOS_OPERATION_SVG_MULTIPLY_H
+#define PHOTOS_OPERATION_SVG_MULTIPLY_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define PHOTOS_TYPE_OPERATION_SVG_MULTIPLY (photos_operation_svg_multiply_get_type ())
+
+#define PHOTOS_OPERATION_SVG_MULTIPLY(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+   PHOTOS_TYPE_OPERATION_SVG_MULTIPLY, PhotosOperationSvgMultiply))
+
+#define PHOTOS_IS_OPERATION_SVG_MULTIPLY(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+   PHOTOS_TYPE_OPERATION_SVG_MULTIPLY))
+
+typedef struct _PhotosOperationSvgMultiply      PhotosOperationSvgMultiply;
+typedef struct _PhotosOperationSvgMultiplyClass PhotosOperationSvgMultiplyClass;
+
+GType            photos_operation_svg_multiply_get_type       (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* PHOTOS_OPERATION_SVG_MULTIPLY_H */
diff --git a/src/photos-utils.c b/src/photos-utils.c
index e5d554e..8085956 100644
--- a/src/photos-utils.c
+++ b/src/photos-utils.c
@@ -1,6 +1,6 @@
 /*
  * Photos - access, organize and share your photos on GNOME
- * Copyright © 2012 – 2016 Red Hat, Inc.
+ * Copyright © 2012 – 2017 Red Hat, Inc.
  * Copyright © 2009 Yorba Foundation
  *
  * This program is free software; you can redistribute it and/or
@@ -50,6 +50,7 @@
 #include "photos-operation-jpg-guess-sizes.h"
 #include "photos-operation-png-guess-sizes.h"
 #include "photos-operation-saturation.h"
+#include "photos-operation-svg-multiply.h"
 #include "photos-query.h"
 #include "photos-share-point.h"
 #include "photos-share-point-email.h"
@@ -850,6 +851,7 @@ photos_utils_ensure_builtins (void)
       g_type_ensure (PHOTOS_TYPE_OPERATION_JPG_GUESS_SIZES);
       g_type_ensure (PHOTOS_TYPE_OPERATION_PNG_GUESS_SIZES);
       g_type_ensure (PHOTOS_TYPE_OPERATION_SATURATION);
+      g_type_ensure (PHOTOS_TYPE_OPERATION_SVG_MULTIPLY);
 
       g_type_ensure (PHOTOS_TYPE_SHARE_POINT_EMAIL);
       g_type_ensure (PHOTOS_TYPE_SHARE_POINT_GOOGLE);


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