예제 #1
0
파일: gimp-edit.c 프로젝트: LebedevRI/gimp
void
gimp_edit_fill (GimpImage       *image,
                GimpDrawable    *drawable,
                GimpFillOptions *options,
                const gchar     *undo_desc)
{
  GeglBuffer  *buffer;
  gint         x, y, width, height;

  g_return_if_fail (GIMP_IS_IMAGE (image));
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
  g_return_if_fail (GIMP_IS_FILL_OPTIONS (options));

  if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
    return;  /*  nothing to do, but the fill succeeded  */

  buffer = gimp_fill_options_create_buffer (options, drawable,
                                            GEGL_RECTANGLE (0, 0,
                                                            width, height));

  if (! undo_desc)
    undo_desc = gimp_fill_options_get_undo_desc (options);

  gimp_drawable_apply_buffer (drawable, buffer,
                              GEGL_RECTANGLE (0, 0, width, height),
                              TRUE, undo_desc,
                              gimp_context_get_opacity (GIMP_CONTEXT (options)),
                              gimp_context_get_paint_mode (GIMP_CONTEXT (options)),
                              NULL, x, y);

  g_object_unref (buffer);

  gimp_drawable_update (drawable, x, y, width, height);
}
예제 #2
0
void
gimp_drawable_bucket_fill (GimpDrawable         *drawable,
                           GimpFillOptions      *options,
                           gboolean              fill_transparent,
                           GimpSelectCriterion   fill_criterion,
                           gdouble               threshold,
                           gboolean              sample_merged,
                           gboolean              diagonal_neighbors,
                           gdouble               seed_x,
                           gdouble               seed_y)
{
  GimpImage  *image;
  GeglBuffer *buffer;
  gdouble     mask_x;
  gdouble     mask_y;
  gint        width, height;

  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
  g_return_if_fail (GIMP_IS_FILL_OPTIONS (options));

  image = gimp_item_get_image (GIMP_ITEM (drawable));
  gimp_set_busy (image->gimp);
  buffer = gimp_drawable_get_bucket_fill_buffer (drawable, options,
                                                 fill_transparent, fill_criterion,
                                                 threshold, sample_merged,
                                                 diagonal_neighbors,
                                                 seed_x, seed_y, NULL,
                                                 &mask_x, &mask_y, &width, &height);

  if (buffer)
    {
      /*  Apply it to the image  */
      gimp_drawable_apply_buffer (drawable, buffer,
                                  GEGL_RECTANGLE (0, 0, width, height),
                                  TRUE, C_("undo-type", "Bucket Fill"),
                                  gimp_context_get_opacity (GIMP_CONTEXT (options)),
                                  gimp_context_get_paint_mode (GIMP_CONTEXT (options)),
                                  GIMP_LAYER_COLOR_SPACE_AUTO,
                                  GIMP_LAYER_COLOR_SPACE_AUTO,
                                  gimp_layer_mode_get_paint_composite_mode (
                                                                            gimp_context_get_paint_mode (GIMP_CONTEXT (options))),
                                  NULL, (gint) mask_x, mask_y);
      g_object_unref (buffer);

      gimp_drawable_update (drawable, mask_x, mask_y, width, height);
    }
  gimp_unset_busy (image->gimp);
}
예제 #3
0
파일: gimp-edit.c 프로젝트: ellelstone/gimp
gboolean
gimp_edit_fade (GimpImage   *image,
                GimpContext *context)
{
  GimpDrawableUndo *undo;

  g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), FALSE);

  undo = GIMP_DRAWABLE_UNDO (gimp_image_undo_get_fadeable (image));

  if (undo && undo->applied_buffer)
    {
      GimpDrawable *drawable;
      GeglBuffer   *buffer;

      drawable = GIMP_DRAWABLE (GIMP_ITEM_UNDO (undo)->item);

      g_object_ref (undo);
      buffer = g_object_ref (undo->applied_buffer);

      gimp_image_undo (image);

      gimp_drawable_apply_buffer (drawable, buffer,
                                  GEGL_RECTANGLE (0, 0,
                                                  gegl_buffer_get_width (undo->buffer),
                                                  gegl_buffer_get_height (undo->buffer)),
                                  TRUE,
                                  gimp_object_get_name (undo),
                                  gimp_context_get_opacity (context),
                                  gimp_context_get_paint_mode (context),
                                  GIMP_LAYER_COLOR_SPACE_AUTO,
                                  GIMP_LAYER_COLOR_SPACE_AUTO,
                                  GIMP_LAYER_COMPOSITE_AUTO,
                                  NULL, undo->x, undo->y);

      g_object_unref (buffer);
      g_object_unref (undo);

      return TRUE;
    }

  return FALSE;
}
예제 #4
0
void
gimp_drawable_blend (GimpDrawable         *drawable,
                     GimpContext          *context,
                     GimpBlendMode         blend_mode,
                     GimpLayerModeEffects  paint_mode,
                     GimpGradientType      gradient_type,
                     gdouble               opacity,
                     gdouble               offset,
                     GimpRepeatMode        repeat,
                     gboolean              reverse,
                     gboolean              supersample,
                     gint                  max_depth,
                     gdouble               threshold,
                     gboolean              dither,
                     gdouble               startx,
                     gdouble               starty,
                     gdouble               endx,
                     gdouble               endy,
                     GimpProgress         *progress)
{
  GimpImage   *image;
  GeglBuffer  *buffer;
  gint         x, y, width, height;

  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
  g_return_if_fail (GIMP_IS_CONTEXT (context));
  g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));

  image = gimp_item_get_image (GIMP_ITEM (drawable));

  if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
    return;

  gimp_set_busy (image->gimp);

  /*  Always create an alpha temp buf (for generality) */
  buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height),
                            gimp_drawable_get_format_with_alpha (drawable));

  gradient_fill_region (image, drawable, context,
                        buffer, GEGL_RECTANGLE (0, 0, width, height),
                        blend_mode, gradient_type, offset, repeat, reverse,
                        supersample, max_depth, threshold, dither,
                        (startx - x), (starty - y),
                        (endx - x), (endy - y),
                        progress);

  gimp_drawable_apply_buffer (drawable, buffer,
                              GEGL_RECTANGLE (0, 0, width, height),
                              TRUE, C_("undo-type", "Blend"),
                              opacity, paint_mode,
                              NULL, x, y);

  /*  update the image  */
  gimp_drawable_update (drawable, x, y, width, height);

  /*  free the temporary buffer  */
  g_object_unref (buffer);

  gimp_unset_busy (image->gimp);
}
예제 #5
0
static void
gimp_drawable_bucket_fill_internal (GimpDrawable        *drawable,
                                    GimpFillType         fill_type,
                                    gint                 paint_mode,
                                    gdouble              opacity,
                                    gboolean             fill_transparent,
                                    GimpSelectCriterion  fill_criterion,
                                    gdouble              threshold,
                                    gboolean             sample_merged,
                                    gboolean             diagonal_neighbors,
                                    gdouble              x,
                                    gdouble              y,
                                    const GimpRGB       *color,
                                    GimpPattern         *pattern)
{
  GimpImage    *image;
  GimpPickable *pickable;
  GeglBuffer   *buffer;
  GeglBuffer   *mask_buffer;
  gint          x1, y1, x2, y2;
  gint          mask_offset_x = 0;
  gint          mask_offset_y = 0;
  gboolean      selection;

  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
  g_return_if_fail (fill_type != GIMP_FILL_PATTERN ||
                    GIMP_IS_PATTERN (pattern));
  g_return_if_fail (fill_type == GIMP_FILL_PATTERN ||
                    color != NULL);

  image = gimp_item_get_image (GIMP_ITEM (drawable));

  selection = gimp_item_mask_bounds (GIMP_ITEM (drawable), &x1, &y1, &x2, &y2);

  if ((x1 == x2) || (y1 == y2))
    return;

  gimp_set_busy (image->gimp);

  if (sample_merged)
    pickable = GIMP_PICKABLE (image);
  else
    pickable = GIMP_PICKABLE (drawable);

  /*  Do a seed bucket fill...To do this, calculate a new
   *  contiguous region. If there is a selection, calculate the
   *  intersection of this region with the existing selection.
   */
  mask_buffer = gimp_pickable_contiguous_region_by_seed (pickable,
                                                         TRUE,
                                                         threshold,
                                                         fill_transparent,
                                                         fill_criterion,
                                                         diagonal_neighbors,
                                                         (gint) x,
                                                         (gint) y);

  if (selection)
    {
      GimpDrawable *sel;
      gint          off_x = 0;
      gint          off_y = 0;

      if (! sample_merged)
        gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);

      sel = GIMP_DRAWABLE (gimp_image_get_mask (image));

      gimp_gegl_mask_combine_buffer (mask_buffer,
                                     gimp_drawable_get_buffer (sel),
                                     GIMP_CHANNEL_OP_INTERSECT,
                                     -off_x, -off_y);
    }

  gimp_gegl_mask_bounds (mask_buffer, &x1, &y1, &x2, &y2);

  /*  make sure we handle the mask correctly if it was sample-merged  */
  if (sample_merged)
    {
      GimpItem *item = GIMP_ITEM (drawable);
      gint      off_x, off_y;

      /*  Limit the channel bounds to the drawable's extents  */
      gimp_item_get_offset (item, &off_x, &off_y);

      x1 = CLAMP (x1, off_x, (off_x + gimp_item_get_width (item)));
      y1 = CLAMP (y1, off_y, (off_y + gimp_item_get_height (item)));
      x2 = CLAMP (x2, off_x, (off_x + gimp_item_get_width (item)));
      y2 = CLAMP (y2, off_y, (off_y + gimp_item_get_height (item)));

      mask_offset_x = x1;
      mask_offset_y = y1;

     /*  translate mask bounds to drawable coords  */
      x1 -= off_x;
      y1 -= off_y;
      x2 -= off_x;
      y2 -= off_y;
    }
  else
    {
      mask_offset_x = x1;
      mask_offset_y = y1;
    }

  buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, x2 - x1, y2 - y1),
                            gimp_drawable_get_format_with_alpha (drawable));

  switch (fill_type)
    {
    case GIMP_FILL_FOREGROUND:
    case GIMP_FILL_BACKGROUND:
    case GIMP_FILL_WHITE:
    case GIMP_FILL_TRANSPARENT:
      {
        GeglColor *gegl_color = gimp_gegl_color_new (color);

        gegl_buffer_set_color (buffer, NULL, gegl_color);
        g_object_unref (gegl_color);
      }
      break;

    case GIMP_FILL_PATTERN:
      {
        GeglBuffer *pattern_buffer = gimp_pattern_create_buffer (pattern);

        gegl_buffer_set_pattern (buffer, NULL, pattern_buffer, -x1, -y1);
        g_object_unref (pattern_buffer);
      }
      break;
    }

  gimp_gegl_apply_opacity (buffer, NULL, NULL, buffer,
                           mask_buffer,
                           -mask_offset_x,
                           -mask_offset_y,
                           1.0);
  g_object_unref (mask_buffer);

  /*  Apply it to the image  */
  gimp_drawable_apply_buffer (drawable, buffer,
                              GEGL_RECTANGLE (0, 0, x2 - x1, y2 - y1),
                              TRUE, C_("undo-type", "Bucket Fill"),
                              opacity, paint_mode,
                              NULL, x1, y1);

  g_object_unref (buffer);

  gimp_drawable_update (drawable, x1, y1, x2 - x1, y2 - y1);

  gimp_unset_busy (image->gimp);
}
예제 #6
0
void
gimp_edit_fill (GimpImage       *image,
                GimpDrawable    *drawable,
                GimpFillOptions *options,
                const gchar     *undo_desc)
{
  GeglBuffer  *dest_buffer;
  GimpPattern *pattern = NULL;
  GimpRGB      color;
  const Babl  *format;
  gint         x, y, width, height;

  g_return_if_fail (GIMP_IS_IMAGE (image));
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
  g_return_if_fail (GIMP_IS_FILL_OPTIONS (options));

  if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
    return;  /*  nothing to do, but the fill succeeded  */

  switch (gimp_fill_options_get_style (options))
    {
    case GIMP_FILL_STYLE_SOLID:
      gimp_context_get_foreground (GIMP_CONTEXT (options), &color);
      break;

    case GIMP_FILL_STYLE_PATTERN:
      pattern = gimp_context_get_pattern (GIMP_CONTEXT (options));
      break;
    }

  if (pattern &&
      babl_format_has_alpha (gimp_temp_buf_get_format (pattern->mask)) &&
      ! gimp_drawable_has_alpha (drawable))
    {
      format = gimp_drawable_get_format_with_alpha (drawable);
    }
  else
    {
      format = gimp_drawable_get_format (drawable);
    }

  dest_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height),
                                 format);

  if (pattern)
    {
      GeglBuffer *src_buffer = gimp_pattern_create_buffer (pattern);

      gegl_buffer_set_pattern (dest_buffer, NULL, src_buffer, 0, 0);
      g_object_unref (src_buffer);
    }
  else
    {
      GeglColor *gegl_color = gimp_gegl_color_new (&color);

      gegl_buffer_set_color (dest_buffer, NULL, gegl_color);
      g_object_unref (gegl_color);
    }

  if (! undo_desc)
    undo_desc = gimp_fill_options_get_undo_desc (options);

  gimp_drawable_apply_buffer (drawable, dest_buffer,
                              GEGL_RECTANGLE (0, 0, width, height),
                              TRUE, undo_desc,
                              gimp_context_get_opacity (GIMP_CONTEXT (options)),
                              gimp_context_get_paint_mode (GIMP_CONTEXT (options)),
                              NULL, x, y);

  g_object_unref (dest_buffer);

  gimp_drawable_update (drawable, x, y, width, height);
}
예제 #7
0
void
gimp_drawable_bucket_fill (GimpDrawable         *drawable,
                           GimpFillOptions      *options,
                           gboolean              fill_transparent,
                           GimpSelectCriterion   fill_criterion,
                           gdouble               threshold,
                           gboolean              sample_merged,
                           gboolean              diagonal_neighbors,
                           gdouble               seed_x,
                           gdouble               seed_y)
{
    GimpImage    *image;
    GimpPickable *pickable;
    GeglBuffer   *buffer;
    GeglBuffer   *mask_buffer;
    gboolean      antialias;
    gint          x, y, width, height;
    gint          mask_offset_x = 0;
    gint          mask_offset_y = 0;
    gint          sel_x, sel_y, sel_width, sel_height;

    g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
    g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
    g_return_if_fail (GIMP_IS_FILL_OPTIONS (options));

    image = gimp_item_get_image (GIMP_ITEM (drawable));

    if (! gimp_item_mask_intersect (GIMP_ITEM (drawable),
                                    &sel_x, &sel_y, &sel_width, &sel_height))
        return;

    gimp_set_busy (image->gimp);

    if (sample_merged)
        pickable = GIMP_PICKABLE (image);
    else
        pickable = GIMP_PICKABLE (drawable);

    antialias = gimp_fill_options_get_antialias (options);

    /*  Do a seed bucket fill...To do this, calculate a new
     *  contiguous region.
     */
    mask_buffer = gimp_pickable_contiguous_region_by_seed (pickable,
                  antialias,
                  threshold,
                  fill_transparent,
                  fill_criterion,
                  diagonal_neighbors,
                  (gint) seed_x,
                  (gint) seed_y);

    gimp_gegl_mask_bounds (mask_buffer, &x, &y, &width, &height);
    width  -= x;
    height -= y;

    /*  If there is a selection, inersect the region bounds
     *  with the selection bounds, to avoid processing areas
     *  that are going to be masked out anyway.  The actual
     *  intersection of the fill region with the mask data
     *  happens when combining the fill buffer, in
     *  gimp_drawable_apply_buffer().
     */
    if (! gimp_channel_is_empty (gimp_image_get_mask (image)))
    {
        gint off_x = 0;
        gint off_y = 0;

        if (sample_merged)
            gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);

        if (! gimp_rectangle_intersect (x, y, width, height,

                                        sel_x + off_x, sel_y + off_y,
                                        sel_width,     sel_height,

                                        &x, &y, &width, &height))
        {
            /*  The fill region and the selection are disjoint; bail.  */

            g_object_unref (mask_buffer);

            gimp_unset_busy (image->gimp);

            return;
        }
    }

    /*  make sure we handle the mask correctly if it was sample-merged  */
    if (sample_merged)
    {
        GimpItem *item = GIMP_ITEM (drawable);
        gint      off_x, off_y;

        /*  Limit the channel bounds to the drawable's extents  */
        gimp_item_get_offset (item, &off_x, &off_y);

        gimp_rectangle_intersect (x, y, width, height,

                                  off_x, off_y,
                                  gimp_item_get_width (item),
                                  gimp_item_get_height (item),

                                  &x, &y, &width, &height);

        mask_offset_x = x;
        mask_offset_y = y;

        /*  translate mask bounds to drawable coords  */
        x -= off_x;
        y -= off_y;
    }
    else
    {
        mask_offset_x = x;
        mask_offset_y = y;
    }

    buffer = gimp_fill_options_create_buffer (options, drawable,
             GEGL_RECTANGLE (0, 0,
                             width, height));

    gimp_gegl_apply_opacity (buffer, NULL, NULL, buffer,
                             mask_buffer,
                             -mask_offset_x,
                             -mask_offset_y,
                             1.0);
    g_object_unref (mask_buffer);

    /*  Apply it to the image  */
    gimp_drawable_apply_buffer (drawable, buffer,
                                GEGL_RECTANGLE (0, 0, width, height),
                                TRUE, C_("undo-type", "Bucket Fill"),
                                gimp_context_get_opacity (GIMP_CONTEXT (options)),
                                gimp_context_get_paint_mode (GIMP_CONTEXT (options)),
                                NULL, x, y);

    g_object_unref (buffer);

    gimp_drawable_update (drawable, x, y, width, height);

    gimp_unset_busy (image->gimp);
}
예제 #8
0
gboolean
gimp_edit_fill_full (GimpImage            *image,
                     GimpDrawable         *drawable,
                     const GimpRGB        *color,
                     GimpPattern          *pattern,
                     gdouble               opacity,
                     GimpLayerModeEffects  paint_mode,
                     const gchar          *undo_desc)
{
  GeglBuffer *dest_buffer;
  const Babl *format;
  gint        x, y, width, height;

  g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
  g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE);
  g_return_val_if_fail (color != NULL || pattern != NULL, FALSE);

  if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
    return TRUE;  /*  nothing to do, but the fill succeeded  */

  if (pattern &&
      babl_format_has_alpha (gimp_temp_buf_get_format (pattern->mask)) &&
      ! gimp_drawable_has_alpha (drawable))
    {
      format = gimp_drawable_get_format_with_alpha (drawable);
    }
  else
    {
      format = gimp_drawable_get_format (drawable);
    }

  dest_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height),
                                 format);

  if (pattern)
    {
      GeglBuffer *src_buffer = gimp_pattern_create_buffer (pattern);

      gegl_buffer_set_pattern (dest_buffer, NULL, src_buffer, 0, 0);
      g_object_unref (src_buffer);
    }
  else
    {
      GeglColor *gegl_color = gimp_gegl_color_new (color);

      gegl_buffer_set_color (dest_buffer, NULL, gegl_color);
      g_object_unref (gegl_color);
    }

  gimp_drawable_apply_buffer (drawable, dest_buffer,
                              GEGL_RECTANGLE (0, 0, width, height),
                              TRUE, undo_desc,
                              opacity, paint_mode,
                              NULL, x, y);

  g_object_unref (dest_buffer);

  gimp_drawable_update (drawable, x, y, width, height);

  return TRUE;
}