Example #1
0
/**
 * gimp_pixbuf_create_buffer:
 * @pixbuf: a #GdkPixbuf
 *
 * Returns a #GeglBuffer that's backed by the @pixbuf's pixels, without
 * copying them. This function refs the pixbuf, so it will be kept
 * around for as long as te buffer exists.
 *
 * Return value: a new #GeglBuffer as a wrapper around @pixbuf.
 *
 * Since: GIMP 2.10
 **/
GeglBuffer *
gimp_pixbuf_create_buffer (GdkPixbuf *pixbuf)
{
    gint width;
    gint height;
    gint rowstride;

    g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);

    width     = gdk_pixbuf_get_width (pixbuf);
    height    = gdk_pixbuf_get_height (pixbuf);
    rowstride = gdk_pixbuf_get_rowstride (pixbuf);

    return gegl_buffer_linear_new_from_data (gdk_pixbuf_get_pixels (pixbuf),
            gimp_pixbuf_get_format (pixbuf),
            GEGL_RECTANGLE (0, 0, width, height),
            rowstride,
            (GDestroyNotify) g_object_unref,
            g_object_ref (pixbuf));
}
TEST ()
{
  GeglBuffer   *buffer;
  GeglRectangle extent = {0,0, 10, 10};
  gfloat       *buf;
  gint          i;
  test_start();

  buf = g_malloc (sizeof (float) * 12 * 10);
  for (i=0;i<120;i++)
    buf[i]=i%12==5?0.5:0.0;

  buffer = gegl_buffer_linear_new_from_data (buf, babl_format ("Y float"),
                                             &extent,
                                             12 * 4,
                                             G_CALLBACK(g_free), /* destroy_notify */
                                             NULL   /* destroy_notify_data */);
  print_buffer (buffer);
  test_end ();
  gegl_buffer_destroy (buffer);
}
Example #3
0
GeglBuffer *
gimp_cairo_surface_create_buffer (cairo_surface_t *surface)
{
  const Babl *format;
  gint        width;
  gint        height;

  g_return_val_if_fail (surface != NULL, NULL);
  g_return_val_if_fail (cairo_surface_get_type (surface) ==
                        CAIRO_SURFACE_TYPE_IMAGE, NULL);

  format = gimp_cairo_surface_get_format  (surface);
  width  = cairo_image_surface_get_width  (surface);
  height = cairo_image_surface_get_height (surface);

  return
    gegl_buffer_linear_new_from_data (cairo_image_surface_get_data (surface),
                                      format,
                                      GEGL_RECTANGLE (0, 0, width, height),
                                      cairo_image_surface_get_stride (surface),
                                      (GDestroyNotify) cairo_surface_destroy,
                                      cairo_surface_reference (surface));
}
Example #4
0
void
gimp_display_shell_render (GimpDisplayShell *shell,
                           cairo_t          *cr,
                           gint              x,
                           gint              y,
                           gint              w,
                           gint              h)
{
  GimpImage       *image;
  GeglBuffer      *buffer;
#ifdef USE_NODE_BLIT
  GeglNode        *node;
#endif
  gdouble          scale_x       = 1.0;
  gdouble          scale_y       = 1.0;
  gdouble          buffer_scale  = 1.0;
  gint             viewport_offset_x;
  gint             viewport_offset_y;
  gint             viewport_width;
  gint             viewport_height;
  gint             scaled_x;
  gint             scaled_y;
  gint             scaled_width;
  gint             scaled_height;
  cairo_surface_t *xfer;
  gint             xfer_src_x;
  gint             xfer_src_y;
  gint             mask_src_x = 0;
  gint             mask_src_y = 0;
  gint             cairo_stride;
  guchar          *cairo_data;
  GeglBuffer      *cairo_buffer;

  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
  g_return_if_fail (cr != NULL);
  g_return_if_fail (w > 0 && h > 0);

  image  = gimp_display_get_image (shell->display);
  buffer = gimp_pickable_get_buffer (GIMP_PICKABLE (image));
#ifdef USE_NODE_BLIT
  node   = gimp_projectable_get_graph (GIMP_PROJECTABLE (image));
#endif

#ifdef GIMP_DISPLAY_RENDER_ENABLE_SCALING
  /* if we had this future API, things would look pretty on hires (retina) */
  scale_x = gdk_window_get_scale_factor (gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET (shell))));
#endif

  scale_x = MIN (scale_x, GIMP_DISPLAY_RENDER_MAX_SCALE);
  scale_y = scale_x;

  if (shell->scale_x > shell->scale_y)
    {
      scale_y *= (shell->scale_x / shell->scale_y);

      buffer_scale = shell->scale_y * scale_y;
    }
  else if (shell->scale_y > shell->scale_x)
    {
      scale_x *= (shell->scale_y / shell->scale_x);

      buffer_scale = shell->scale_x * scale_x;
    }
  else
    {
      buffer_scale = shell->scale_x * scale_x;
    }

  gimp_display_shell_scroll_get_scaled_viewport (shell,
                                                 &viewport_offset_x,
                                                 &viewport_offset_y,
                                                 &viewport_width,
                                                 &viewport_height);

  scaled_x      = floor ((x + viewport_offset_x) * scale_x);
  scaled_y      = floor ((y + viewport_offset_y) * scale_y);
  scaled_width  = ceil (w * scale_x);
  scaled_height = ceil (h * scale_y);

  if (shell->rotate_transform)
    {
      xfer = cairo_surface_create_similar_image (cairo_get_target (cr),
                                                 CAIRO_FORMAT_ARGB32,
                                                 scaled_width,
                                                 scaled_height);
      cairo_surface_mark_dirty (xfer);
      xfer_src_x = 0;
      xfer_src_y = 0;
    }
  else
    {
      xfer = gimp_display_xfer_get_surface (shell->xfer,
                                            scaled_width,
                                            scaled_height,
                                            &xfer_src_x,
                                            &xfer_src_y);
    }

  cairo_stride = cairo_image_surface_get_stride (xfer);
  cairo_data   = cairo_image_surface_get_data (xfer) +
                 xfer_src_y * cairo_stride + xfer_src_x * 4;

  cairo_buffer = gegl_buffer_linear_new_from_data (cairo_data,
                                                   babl_format ("cairo-ARGB32"),
                                                   GEGL_RECTANGLE (0, 0,
                                                                   scaled_width,
                                                                   scaled_height),
                                                   cairo_stride,
                                                   NULL, NULL);

  if (shell->profile_transform ||
      gimp_display_shell_has_filter (shell))
    {
      gboolean can_convert_to_u8;

      /*  if there is a profile transform or a display filter, we need
       *  to use temp buffers
       */

      can_convert_to_u8 = gimp_display_shell_profile_can_convert_to_u8 (shell);

      /*  create the filter buffer if we have filters
       */
      if ((gimp_display_shell_has_filter (shell) || ! can_convert_to_u8) &&
          ! shell->filter_buffer)
        {
          gint w = GIMP_DISPLAY_RENDER_BUF_WIDTH  * GIMP_DISPLAY_RENDER_MAX_SCALE;
          gint h = GIMP_DISPLAY_RENDER_BUF_HEIGHT * GIMP_DISPLAY_RENDER_MAX_SCALE;

          shell->filter_data =
            gegl_malloc (w * h * babl_format_get_bytes_per_pixel (shell->filter_format));

          shell->filter_stride =
            w * babl_format_get_bytes_per_pixel (shell->filter_format);

          shell->filter_buffer =
            gegl_buffer_linear_new_from_data (shell->filter_data,
                                              shell->filter_format,
                                              GEGL_RECTANGLE (0, 0, w, h),
                                              GEGL_AUTO_ROWSTRIDE,
                                              (GDestroyNotify) gegl_free,
                                              shell->filter_data);
        }

      if (shell->profile_transform)
        {
          /*  if there is a profile transform, load the projection
           *  pixels into the profile_buffer
           */
#ifndef USE_NODE_BLIT
          gegl_buffer_get (buffer,
                           GEGL_RECTANGLE (scaled_x, scaled_y,
                                           scaled_width, scaled_height),
                           buffer_scale,
                           gimp_projectable_get_format (GIMP_PROJECTABLE (image)),
                           shell->profile_data, shell->profile_stride,
                           GEGL_ABYSS_CLAMP);
#else
          gegl_node_blit (node,
                          buffer_scale,
                          GEGL_RECTANGLE (scaled_x, scaled_y,
                                          scaled_width, scaled_height),
                          gimp_projectable_get_format (GIMP_PROJECTABLE (image)),
                          shell->profile_data, shell->profile_stride,
                          GEGL_BLIT_CACHE);
#endif

          if (gimp_display_shell_has_filter (shell) || ! can_convert_to_u8)
            {
              /*  if there are filters, convert the pixels from the
               *  profile_buffer to the filter_buffer
               */
              gimp_display_shell_profile_convert_buffer (shell,
                                                         shell->profile_buffer,
                                                         GEGL_RECTANGLE (0, 0,
                                                                         scaled_width,
                                                                         scaled_height),
                                                         shell->filter_buffer,
                                                         GEGL_RECTANGLE (0, 0,
                                                                         scaled_width,
                                                                         scaled_height));
            }
          else
            {
              /*  otherwise, convert the profile_buffer directly into
               *  the cairo_buffer
               */
              gimp_display_shell_profile_convert_buffer (shell,
                                                         shell->profile_buffer,
                                                         GEGL_RECTANGLE (0, 0,
                                                                         scaled_width,
                                                                         scaled_height),
                                                         cairo_buffer,
                                                         GEGL_RECTANGLE (0, 0,
                                                                         scaled_width,
                                                                         scaled_height));
            }
        }
      else
        {
          /*  otherwise, load the projection pixels directly into the
           *  filter_buffer
           */
#ifndef USE_NODE_BLIT
          gegl_buffer_get (buffer,
                           GEGL_RECTANGLE (scaled_x, scaled_y,
                                           scaled_width, scaled_height),
                           buffer_scale,
                           shell->filter_format,
                           shell->filter_data, shell->filter_stride,
                           GEGL_ABYSS_CLAMP);
#else
          gegl_node_blit (node,
                          buffer_scale,
                          GEGL_RECTANGLE (scaled_x, scaled_y,
                                          scaled_width, scaled_height),
                          shell->filter_format,
                          shell->filter_data, shell->filter_stride,
                          GEGL_BLIT_CACHE);
#endif
        }

      if (gimp_display_shell_has_filter (shell))
        {
          /*  convert the filter_buffer in place
           */
          gimp_color_display_stack_convert_buffer (shell->filter_stack,
                                                   shell->filter_buffer,
                                                   GEGL_RECTANGLE (0, 0,
                                                                   scaled_width,
                                                                   scaled_height));
        }

      if (gimp_display_shell_has_filter (shell) || ! can_convert_to_u8)
        {
          /*  finally, copy the filter buffer to the cairo-ARGB32 buffer
           */
          gegl_buffer_get (shell->filter_buffer,
                           GEGL_RECTANGLE (0, 0,
                                           scaled_width,
                                           scaled_height),
                           1.0,
                           babl_format ("cairo-ARGB32"),
                           cairo_data, cairo_stride,
                           GEGL_ABYSS_CLAMP);
        }
    }
  else
    {
      /*  otherwise we can copy the projection pixels straight to the
       *  cairo-ARGB32 buffer
       */
#ifndef USE_NODE_BLIT
      gegl_buffer_get (buffer,
                       GEGL_RECTANGLE (scaled_x, scaled_y,
                                       scaled_width, scaled_height),
                       buffer_scale,
                       babl_format ("cairo-ARGB32"),
                       cairo_data, cairo_stride,
                       GEGL_ABYSS_CLAMP);
#else
      gegl_node_blit (node,
                      buffer_scale,
                      GEGL_RECTANGLE (scaled_x, scaled_y,
                                      scaled_width, scaled_height),
                      babl_format ("cairo-ARGB32"),
                      cairo_data, cairo_stride,
                      GEGL_BLIT_CACHE);
#endif
    }

  g_object_unref (cairo_buffer);

  if (shell->mask)
    {
      if (! shell->mask_surface)
        {
          shell->mask_surface =
            cairo_image_surface_create (CAIRO_FORMAT_A8,
                                        GIMP_DISPLAY_RENDER_BUF_WIDTH  *
                                        GIMP_DISPLAY_RENDER_MAX_SCALE,
                                        GIMP_DISPLAY_RENDER_BUF_HEIGHT *
                                        GIMP_DISPLAY_RENDER_MAX_SCALE);
        }

      cairo_surface_mark_dirty (shell->mask_surface);

      cairo_stride = cairo_image_surface_get_stride (shell->mask_surface);
      cairo_data   = cairo_image_surface_get_data (shell->mask_surface) +
                     mask_src_y * cairo_stride + mask_src_x * 4;

      gegl_buffer_get (shell->mask,
                       GEGL_RECTANGLE (scaled_x - shell->mask_offset_x,
                                       scaled_y - shell->mask_offset_y,
                                       scaled_width, scaled_height),
                       buffer_scale,
                       babl_format ("Y u8"),
                       cairo_data, cairo_stride,
                       GEGL_ABYSS_NONE);

      if (shell->mask_inverted)
        {
          gint mask_height = scaled_height;

          while (mask_height--)
            {
              gint    mask_width = scaled_width;
              guchar *d          = cairo_data;

              while (mask_width--)
                {
                  guchar inv = 255 - *d;

                  *d++ = inv;
                }

              cairo_data += cairo_stride;
            }
        }
    }

  /*  put it to the screen  */
  cairo_save (cr);

  cairo_rectangle (cr, x, y, w, h);

  cairo_scale (cr, 1.0 / scale_x, 1.0 / scale_y);

  cairo_set_source_surface (cr, xfer,
                            x * scale_x - xfer_src_x,
                            y * scale_y - xfer_src_y);

  if (shell->rotate_transform)
    {
      cairo_pattern_t *pattern;

      pattern = cairo_get_source (cr);
      cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);

      cairo_set_line_width (cr, 1.0);
      cairo_stroke_preserve (cr);

      cairo_surface_destroy (xfer);
    }

  cairo_clip (cr);
  cairo_paint (cr);

  if (shell->mask)
    {
      gimp_cairo_set_source_rgba (cr, &shell->mask_color);
      cairo_mask_surface (cr, shell->mask_surface,
                          (x - mask_src_x) * scale_x,
                          (y - mask_src_y) * scale_y);
    }

  cairo_restore (cr);
}
Example #5
0
static gboolean
test_operation (const char *operation_name)
{
  gboolean result = FALSE;

  const Babl *format = babl_format ("RGBA u8");
  const gint bpp = babl_format_get_bytes_per_pixel (format);
  const gint out_width = 5 + 10;
  const gint out_height = 5 + 10;

  guchar *output_with_abyss = gegl_malloc (out_width * out_height * bpp);
  guchar *output_no_abyss   = gegl_malloc (out_width * out_height * bpp);

  GeglColor *upper_color = gegl_color_new ("rgb(0.2, 0.8, 0.2)");
  GeglColor *lower_color = gegl_color_new ("rgb(0.0, 0.0, 0.0)");
  GeglColor *transparent = gegl_color_new ("rgba(0.0, 0.0, 0.0, 0.0)");

  {
    /* Using abyss */
    GeglNode *ptn = gegl_node_new();

    GeglNode *test_op, *upper_rect, *lower_rect;

    test_op = gegl_node_new_child (ptn,
                                   "operation", operation_name,
                                   NULL);

    upper_rect = gegl_node_new_child (ptn,
                                   "operation", "gegl:rectangle",
                                   "color", upper_color,
                                   "x", 5.0,
                                   "y", 5.0,
                                   "width", 10.0,
                                   "height", 10.0,
                                   NULL);

    lower_rect = gegl_node_new_child (ptn,
                                   "operation", "gegl:rectangle",
                                   "color", lower_color,
                                   "x", 0.0,
                                   "y", 0.0,
                                   "width", 10.0,
                                   "height", 10.0,
                                   NULL);

    gegl_node_connect_to (lower_rect, "output", test_op, "input");
    gegl_node_connect_to (upper_rect, "output", test_op, "aux");

    {
      int i;
      guchar *out = output_with_abyss;
      for (i = 0; i < out_height; i++)
        {
          gegl_node_blit (test_op,
                          1.0,
                          GEGL_RECTANGLE (0, i, out_width, 1),
                          format,
                          out,
                          GEGL_AUTO_ROWSTRIDE,
                          0);
          out += out_width * bpp;
        }
    }

    g_object_unref (ptn);
  }

  {
    /* Explicit transparency */
    GeglNode *ptn = gegl_node_new();

    GeglNode *test_op, *upper_rect, *lower_rect;
    GeglNode *upper_over, *lower_over;
    GeglNode *background;

    test_op = gegl_node_new_child (ptn,
                                   "operation", operation_name,
                                   NULL);

    background = gegl_node_new_child (ptn,
                                   "operation", "gegl:rectangle",
                                   "color", transparent,
                                   "x", 0.0,
                                   "y", 0.0,
                                   "width", 10.0 + 5.0,
                                   "height", 10.0 + 5.0,
                                   NULL);

    upper_rect = gegl_node_new_child (ptn,
                                   "operation", "gegl:rectangle",
                                   "color", upper_color,
                                   "x", 5.0,
                                   "y", 5.0,
                                   "width", 10.0,
                                   "height", 10.0,
                                   NULL);

    upper_over = gegl_node_new_child (ptn,
                                   "operation", "gegl:over",
                                   NULL);

    lower_rect = gegl_node_new_child (ptn,
                                   "operation", "gegl:rectangle",
                                   "color", lower_color,
                                   "x", 0.0,
                                   "y", 0.0,
                                   "width", 10.0,
                                   "height", 10.0,
                                   NULL);

    lower_over = gegl_node_new_child (ptn,
                                   "operation", "gegl:over",
                                   NULL);

    gegl_node_connect_to (lower_rect, "output", lower_over, "aux");
    gegl_node_connect_to (upper_rect, "output", upper_over, "aux");

    gegl_node_connect_to (background, "output", lower_over, "input");
    gegl_node_connect_to (background, "output", upper_over, "input");

    gegl_node_connect_to (lower_over, "output", test_op, "input");
    gegl_node_connect_to (upper_over, "output", test_op, "aux");

    {
      int i;
      guchar *out = output_no_abyss;
      for (i = 0; i < out_height; i++)
        {
          gegl_node_blit (test_op,
                          1.0,
                          GEGL_RECTANGLE (0, i, out_width, 1),
                          format,
                          out,
                          GEGL_AUTO_ROWSTRIDE,
                          0);
          out += out_width * bpp;
        }
    }

    g_object_unref (ptn);
  }

  if (0 == memcmp (output_with_abyss, output_no_abyss, out_width * out_height * bpp))
    {
      printf (".");
      fflush(stdout);
      result = TRUE;
    }
  else
    {
      printf ("\n %s ... FAIL\n", operation_name);
      result = FALSE;
    }

  if (!result)
    {
      GeglBuffer *linear;
      gchar *filename;

      filename = g_strconcat (operation_name, " - with abyss.png", NULL);
      linear = gegl_buffer_linear_new_from_data (output_with_abyss,
                                                format,
                                                GEGL_RECTANGLE (0, 0, out_width, out_height),
                                                GEGL_AUTO_ROWSTRIDE,
                                                NULL,
                                                NULL);
      dump_to_png (filename, linear);
      g_free (filename);
      g_object_unref (linear);

      filename = g_strconcat (operation_name, " - no abyss.png", NULL);
      linear = gegl_buffer_linear_new_from_data (output_no_abyss,
                                                 format,
                                                 GEGL_RECTANGLE (0, 0, out_width, out_height),
                                                 GEGL_AUTO_ROWSTRIDE,
                                                 NULL,
                                                 NULL);
      dump_to_png (filename, linear);
      g_free (filename);
      g_object_unref (linear);
    }

  gegl_free (output_with_abyss);
  gegl_free (output_no_abyss);

  return result;
}
Example #6
0
void
gimp_display_shell_render (GimpDisplayShell *shell,
                           cairo_t          *cr,
                           gint              x,
                           gint              y,
                           gint              w,
                           gint              h)
{
  GimpImage       *image;
  GimpProjection  *projection;
  GeglBuffer      *buffer;
  gdouble          scale_x      = 1.0;
  gdouble          scale_y      = 1.0;
  gdouble          buffer_scale = 1.0;
  gint             viewport_offset_x;
  gint             viewport_offset_y;
  gint             viewport_width;
  gint             viewport_height;
  gint             scaled_x;
  gint             scaled_y;
  gint             scaled_width;
  gint             scaled_height;
  cairo_surface_t *xfer;
  gint             xfer_src_x;
  gint             xfer_src_y;
  gint             mask_src_x = 0;
  gint             mask_src_y = 0;
  gint             stride;
  guchar          *data;

  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
  g_return_if_fail (cr != NULL);
  g_return_if_fail (w > 0 && h > 0);

  image      = gimp_display_get_image (shell->display);
  projection = gimp_image_get_projection (image);
  buffer     = gimp_pickable_get_buffer (GIMP_PICKABLE (projection));

#ifdef GIMP_DISPLAY_RENDER_ENABLE_SCALING
  /* if we had this future API, things would look pretty on hires (retina) */
  scale_x = gdk_window_get_scale_factor (gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET (shell))));
#endif

  scale_x = MIN (scale_x, GIMP_DISPLAY_RENDER_MAX_SCALE);
  scale_y = scale_x;

  if (shell->scale_x > shell->scale_y)
    {
      scale_y *= (shell->scale_x / shell->scale_y);

      buffer_scale = shell->scale_y * scale_y;
    }
  else if (shell->scale_y > shell->scale_x)
    {
      scale_x *= (shell->scale_y / shell->scale_x);

      buffer_scale = shell->scale_x * scale_x;
    }
  else
    {
      buffer_scale = shell->scale_x * scale_x;
    }

  gimp_display_shell_scroll_get_scaled_viewport (shell,
                                                 &viewport_offset_x,
                                                 &viewport_offset_y,
                                                 &viewport_width,
                                                 &viewport_height);

  scaled_x      = floor ((x + viewport_offset_x) * scale_x);
  scaled_y      = floor ((y + viewport_offset_y) * scale_y);
  scaled_width  = ceil (w * scale_x);
  scaled_height = ceil (h * scale_y);

  if (shell->rotate_transform)
    {
      xfer = cairo_surface_create_similar_image (cairo_get_target (cr),
                                                 CAIRO_FORMAT_ARGB32,
                                                 scaled_width,
                                                 scaled_height);
      cairo_surface_mark_dirty (xfer);
      xfer_src_x = 0;
      xfer_src_y = 0;
    }
  else
    {
      xfer = gimp_display_xfer_get_surface (shell->xfer,
                                            scaled_width,
                                            scaled_height,
                                            &xfer_src_x,
                                            &xfer_src_y);
    }

  stride = cairo_image_surface_get_stride (xfer);
  data = cairo_image_surface_get_data (xfer);
  data += xfer_src_y * stride + xfer_src_x * 4;

  /*  apply filters to the rendered projection  */
  if (shell->filter_stack)
    {
      const Babl *filter_format = babl_format ("R'G'B'A float");

      if (! shell->filter_buffer)
        {
          gint w = GIMP_DISPLAY_RENDER_BUF_WIDTH  * GIMP_DISPLAY_RENDER_MAX_SCALE;
          gint h = GIMP_DISPLAY_RENDER_BUF_HEIGHT * GIMP_DISPLAY_RENDER_MAX_SCALE;

          shell->filter_data =
            gegl_malloc (w * h * babl_format_get_bytes_per_pixel (filter_format));

          shell->filter_stride = w * babl_format_get_bytes_per_pixel (filter_format);

          shell->filter_buffer =
            gegl_buffer_linear_new_from_data (shell->filter_data,
                                              filter_format,
                                              GEGL_RECTANGLE (0, 0, w, h),
                                              GEGL_AUTO_ROWSTRIDE,
                                              (GDestroyNotify) gegl_free,
                                              shell->filter_data);
        }

      gegl_buffer_get (buffer,
                       GEGL_RECTANGLE (scaled_x, scaled_y,
                                       scaled_width, scaled_height),
                       buffer_scale,
                       filter_format, shell->filter_data,
                       shell->filter_stride, GEGL_ABYSS_CLAMP);


      gimp_color_display_stack_convert_buffer (shell->filter_stack,
                                               shell->filter_buffer,
                                               GEGL_RECTANGLE (0, 0,
                                                               scaled_width,
                                                               scaled_height));

      gegl_buffer_get (shell->filter_buffer,
                       GEGL_RECTANGLE (0, 0,
                                       scaled_width,
                                       scaled_height),
                       1.0,
                       babl_format ("cairo-ARGB32"),
                       data, stride,
                       GEGL_ABYSS_CLAMP);
    }
  else
    {
      gegl_buffer_get (buffer,
                       GEGL_RECTANGLE (scaled_x, scaled_y,
                                       scaled_width, scaled_height),
                       buffer_scale,
                       babl_format ("cairo-ARGB32"),
                       data, stride,
                       GEGL_ABYSS_CLAMP);
    }

  if (shell->mask)
    {
      gint mask_height;

      if (! shell->mask_surface)
        {
          shell->mask_surface =
            cairo_image_surface_create (CAIRO_FORMAT_A8,
                                        GIMP_DISPLAY_RENDER_BUF_WIDTH  *
                                        GIMP_DISPLAY_RENDER_MAX_SCALE,
                                        GIMP_DISPLAY_RENDER_BUF_HEIGHT *
                                        GIMP_DISPLAY_RENDER_MAX_SCALE);
        }

      cairo_surface_mark_dirty (shell->mask_surface);

      stride = cairo_image_surface_get_stride (shell->mask_surface);
      data = cairo_image_surface_get_data (shell->mask_surface);
      data += mask_src_y * stride + mask_src_x * 4;

      gegl_buffer_get (shell->mask,
                       GEGL_RECTANGLE (scaled_x, scaled_y,
                                       scaled_width, scaled_height),
                       buffer_scale,
                       babl_format ("Y u8"),
                       data, stride,
                       GEGL_ABYSS_CLAMP);

      /* invert the mask so what is *not* the foreground object is masked */
      mask_height = scaled_height;
      while (mask_height--)
        {
          gint    mask_width = scaled_width;
          guchar *d          = data;

          while (mask_width--)
            {
              guchar inv = 255 - *d;

              *d++ = inv;
            }

          data += stride;
        }
    }

  /*  put it to the screen  */
  cairo_save (cr);

  cairo_rectangle (cr, x, y, w, h);

  cairo_scale (cr, 1.0 / scale_x, 1.0 / scale_y);

  cairo_set_source_surface (cr, xfer,
                            x * scale_x - xfer_src_x,
                            y * scale_y - xfer_src_y);

  if (shell->rotate_transform)
    {
      cairo_pattern_t *pattern;

      pattern = cairo_get_source (cr);
      cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);

      cairo_set_line_width (cr, 1.0);
      cairo_stroke_preserve (cr);

      cairo_surface_destroy (xfer);
    }

  cairo_clip (cr);
  cairo_paint (cr);

  if (shell->mask)
    {
      gimp_cairo_set_source_rgba (cr, &shell->mask_color);
      cairo_mask_surface (cr, shell->mask_surface,
                          (x - mask_src_x) * scale_x,
                          (y - mask_src_y) * scale_y);
    }

  cairo_restore (cr);
}
Example #7
0
TEST ()
{
  GeglBuffer         *out;
  gint                i;
  GeglBuffer         *linear_a;
  GeglBuffer         *linear_b;
  GeglBuffer         *linear_c;
  GeglBuffer         *linear_d;
  gfloat             *linear_data;
  GeglBufferIterator *iter;
  GeglRectangle       out_extent = {-1, -1, 5, 5};

  test_start();

  linear_data = malloc (sizeof(float) * 3 * 3);

  for (i = 0; i < 3 * 3; ++i)
    linear_data[i] = 0.25;

  linear_a = gegl_buffer_linear_new_from_data (linear_data,
                                               babl_format ("Y float"),
                                               GEGL_RECTANGLE(-1, -1, 3, 3),
                                               GEGL_AUTO_ROWSTRIDE,
                                               NULL,
                                               NULL);

  linear_b = gegl_buffer_linear_new_from_data (linear_data,
                                               babl_format ("Y float"),
                                               GEGL_RECTANGLE(1, -1, 3, 3),
                                               GEGL_AUTO_ROWSTRIDE,
                                               NULL,
                                               NULL);

  linear_c = gegl_buffer_linear_new_from_data (linear_data,
                                               babl_format ("Y float"),
                                               GEGL_RECTANGLE(1, 1, 3, 3),
                                               GEGL_AUTO_ROWSTRIDE,
                                               NULL,
                                               NULL);

  linear_d = gegl_buffer_linear_new_from_data (linear_data,
                                               babl_format ("Y float"),
                                               GEGL_RECTANGLE(-1, 1, 3, 3),
                                               GEGL_AUTO_ROWSTRIDE,
                                               NULL,
                                               NULL);

  out = gegl_buffer_new (&out_extent, babl_format ("Y float"));

  iter = gegl_buffer_iterator_new (out, &out_extent, 0, NULL,
                                   GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE);

  gegl_buffer_iterator_add (iter, linear_a, &out_extent, 0, NULL,
                            GEGL_BUFFER_READ, GEGL_ABYSS_BLACK);

  gegl_buffer_iterator_add (iter, linear_b, &out_extent, 0, NULL,
                            GEGL_BUFFER_READ, GEGL_ABYSS_BLACK);

  gegl_buffer_iterator_add (iter, linear_c, &out_extent, 0, NULL,
                            GEGL_BUFFER_READ, GEGL_ABYSS_BLACK);

  gegl_buffer_iterator_add (iter, linear_d, &out_extent, 0, NULL,
                            GEGL_BUFFER_READ, GEGL_ABYSS_BLACK);

  while (gegl_buffer_iterator_next (iter))
    {
      gint ix, iy, pos;

      pos = 0;
      for (iy = iter->roi[0].y; iy < iter->roi[0].y + iter->roi[0].height; ++iy)
        for (ix = iter->roi[0].x; ix < iter->roi[0].x + iter->roi[0].width; ++ix)
          {
            gfloat **fdata = (gfloat **)iter->data;

            fdata[0][pos] = fdata[1][pos] + fdata[2][pos] + fdata[3][pos] + fdata[4][pos];
            if (fdata[0][pos] > 1.0f)
              fdata[0][pos] = 1.0f;

            ++pos;
          }
    }

  print_buffer (out);
  g_object_unref (out);
  g_object_unref (linear_a);
  g_object_unref (linear_b);
  g_object_unref (linear_c);
  g_object_unref (linear_d);
  free (linear_data);
  test_end ();
}