예제 #1
0
void
gimp_channel_combine_mask (GimpChannel    *mask,
                           GimpChannel    *add_on,
                           GimpChannelOps  op,
                           gint            off_x,
                           gint            off_y)
{
  PixelRegion srcPR, destPR;
  gint        x, y, w, h;

  g_return_if_fail (GIMP_IS_CHANNEL (mask));
  g_return_if_fail (GIMP_IS_CHANNEL (add_on));

  if (! gimp_rectangle_intersect (off_x, off_y,
                                  gimp_item_get_width  (GIMP_ITEM (add_on)),
                                  gimp_item_get_height (GIMP_ITEM (add_on)),
                                  0, 0,
                                  gimp_item_get_width  (GIMP_ITEM (mask)),
                                  gimp_item_get_height (GIMP_ITEM (mask)),
                                  &x, &y, &w, &h))
    return;

  pixel_region_init (&srcPR, gimp_drawable_get_tiles (GIMP_DRAWABLE (add_on)),
                     x - off_x, y - off_y, w, h, FALSE);
  pixel_region_init (&destPR, gimp_drawable_get_tiles (GIMP_DRAWABLE (mask)),
                     x, y, w, h, TRUE);

  switch (op)
    {
    case GIMP_CHANNEL_OP_ADD:
    case GIMP_CHANNEL_OP_REPLACE:
      pixel_regions_process_parallel ((PixelProcessorFunc)
                                      gimp_channel_combine_sub_region_add,
                                      NULL, 2, &srcPR, &destPR);
      break;

    case GIMP_CHANNEL_OP_SUBTRACT:
      pixel_regions_process_parallel ((PixelProcessorFunc)
                                      gimp_channel_combine_sub_region_sub,
                                      NULL, 2, &srcPR, &destPR);
      break;

    case GIMP_CHANNEL_OP_INTERSECT:
      pixel_regions_process_parallel ((PixelProcessorFunc)
                                      gimp_channel_combine_sub_region_intersect,
                                      NULL, 2, &srcPR, &destPR);
      break;

    default:
      g_warning ("%s: unknown operation type", G_STRFUNC);
      break;
    }

  mask->bounds_known = FALSE;

  gimp_drawable_update (GIMP_DRAWABLE (mask), x, y, w, h);
}
예제 #2
0
void
floating_sel_anchor (GimpLayer *layer)
{
  GimpImage    *image;
  GimpDrawable *drawable;
  GimpFilter   *filter = NULL;
  gint          off_x, off_y;
  gint          dr_off_x, dr_off_y;

  g_return_if_fail (GIMP_IS_LAYER (layer));
  g_return_if_fail (gimp_layer_is_floating_sel (layer));

  /* Don't let gimp_image_remove_layer free the layer while we still need it */
  g_object_ref (layer);

  image = gimp_item_get_image (GIMP_ITEM (layer));

  gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_FS_ANCHOR,
                               C_("undo-type", "Anchor Floating Selection"));

  drawable = gimp_layer_get_floating_sel_drawable (layer);

  gimp_item_get_offset (GIMP_ITEM (layer), &off_x, &off_y);
  gimp_item_get_offset (GIMP_ITEM (drawable), &dr_off_x, &dr_off_y);

  if (gimp_item_get_visible (GIMP_ITEM (layer)) &&
      gimp_rectangle_intersect (off_x, off_y,
                                gimp_item_get_width  (GIMP_ITEM (layer)),
                                gimp_item_get_height (GIMP_ITEM (layer)),
                                dr_off_x, dr_off_y,
                                gimp_item_get_width  (GIMP_ITEM (drawable)),
                                gimp_item_get_height (GIMP_ITEM (drawable)),
                                NULL, NULL, NULL, NULL))
    {
      filter = gimp_drawable_get_floating_sel_filter (drawable);
      g_object_ref (filter);
    }

  /*  first remove the filter, then merge it, or we will get warnings
   *  about already connected nodes
   */
  gimp_image_remove_layer (image, layer, TRUE, NULL);

  if (filter)
    {
      gimp_drawable_merge_filter (drawable, filter, NULL, NULL);
      g_object_unref (filter);
    }

  gimp_image_undo_group_end (image);

  /*  invalidate the boundaries  */
  gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (gimp_image_get_mask (image)));

  g_object_unref (layer);
}
예제 #3
0
void
gimp_channel_combine_rect (GimpChannel    *mask,
                           GimpChannelOps  op,
                           gint            x,
                           gint            y,
                           gint            w,
                           gint            h)
{
  GeglBuffer *buffer;

  g_return_if_fail (GIMP_IS_CHANNEL (mask));

  buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask));

  if (! gimp_gegl_mask_combine_rect (buffer, op, x, y, w, h))
    return;

  gimp_rectangle_intersect (x, y, w, h,
                            0, 0,
                            gimp_item_get_width  (GIMP_ITEM (mask)),
                            gimp_item_get_height (GIMP_ITEM (mask)),
                            &x, &y, &w, &h);

  /*  Determine new boundary  */
  if (mask->bounds_known && (op == GIMP_CHANNEL_OP_ADD) && ! mask->empty)
    {
      if (x < mask->x1)
        mask->x1 = x;
      if (y < mask->y1)
        mask->y1 = y;
      if ((x + w) > mask->x2)
        mask->x2 = (x + w);
      if ((y + h) > mask->y2)
        mask->y2 = (y + h);
    }
  else if (op == GIMP_CHANNEL_OP_REPLACE || mask->empty)
    {
      mask->empty = FALSE;
      mask->x1    = x;
      mask->y1    = y;
      mask->x2    = x + w;
      mask->y2    = y + h;
    }
  else
    {
      mask->bounds_known = FALSE;
    }

  mask->x1 = CLAMP (mask->x1, 0, gimp_item_get_width  (GIMP_ITEM (mask)));
  mask->y1 = CLAMP (mask->y1, 0, gimp_item_get_height (GIMP_ITEM (mask)));
  mask->x2 = CLAMP (mask->x2, 0, gimp_item_get_width  (GIMP_ITEM (mask)));
  mask->y2 = CLAMP (mask->y2, 0, gimp_item_get_height (GIMP_ITEM (mask)));

  gimp_drawable_update (GIMP_DRAWABLE (mask), x, y, w, h);
}
예제 #4
0
static void
gimp_image_map_tool_guide_moved (GimpGuide        *guide,
                                 const GParamSpec *pspec,
                                 GimpImageMapTool *im_tool)
{
  GimpImageMapOptions *options = GIMP_IMAGE_MAP_TOOL_GET_OPTIONS (im_tool);
  GimpItem            *item    = GIMP_ITEM (im_tool->drawable);
  gdouble              position;

  if (options->preview_alignment == GIMP_ALIGN_LEFT ||
      options->preview_alignment == GIMP_ALIGN_RIGHT)
    {
      position = ((gdouble) (gimp_guide_get_position (guide) -
                             gimp_item_get_offset_x (item)) /
                  (gdouble) gimp_item_get_width (item));
    }
  else
    {
      position = ((gdouble) (gimp_guide_get_position (guide) -
                             gimp_item_get_offset_y (item)) /
                  (gdouble) gimp_item_get_height (item));
    }

  g_object_set (options,
                "preview-position", CLAMP (position, 0.0, 1.0),
                NULL);
}
예제 #5
0
/*
 * Position the dropped item in the middle of the viewport.
 */
static void
gimp_display_shell_dnd_position_item (GimpDisplayShell *shell,
                                      GimpImage        *image,
                                      GimpItem         *item)
{
  gint item_width  = gimp_item_get_width  (item);
  gint item_height = gimp_item_get_height (item);
  gint off_x, off_y;

  if (item_width  >= gimp_image_get_width  (image) &&
      item_height >= gimp_image_get_height (image))
    {
      off_x = (gimp_image_get_width  (image) - item_width)  / 2;
      off_y = (gimp_image_get_height (image) - item_height) / 2;
    }
  else
    {
      gint x, y;
      gint width, height;

      gimp_display_shell_untransform_viewport (shell, &x, &y, &width, &height);

      off_x = x + (width  - item_width)  / 2;
      off_y = y + (height - item_height) / 2;
    }

  gimp_item_translate (item,
                       off_x - gimp_item_get_offset_x (item),
                       off_y - gimp_item_get_offset_y (item),
                       FALSE);
}
예제 #6
0
static void
gimp_cage_tool_image_map_update (GimpCageTool *ct)
{
    GimpTool         *tool  = GIMP_TOOL (ct);
    GimpDisplayShell *shell = gimp_display_get_shell (tool->display);
    GimpItem         *item  = GIMP_ITEM (tool->drawable);
    gint              x, y;
    gint              w, h;
    gint              off_x, off_y;
    GeglRectangle     visible;

    gimp_display_shell_untransform_viewport (shell, &x, &y, &w, &h);

    gimp_item_get_offset (item, &off_x, &off_y);

    gimp_rectangle_intersect (x, y, w, h,
                              off_x,
                              off_y,
                              gimp_item_get_width  (item),
                              gimp_item_get_height (item),
                              &visible.x,
                              &visible.y,
                              &visible.width,
                              &visible.height);

    visible.x -= off_x;
    visible.y -= off_y;

    gimp_image_map_apply (ct->image_map, &visible);
}
void
gimp_drawable_foreground_extract (GimpDrawable              *drawable,
                                  GimpForegroundExtractMode  mode,
                                  GimpDrawable              *mask,
                                  GimpProgress              *progress)
{
  SioxState    *state;
  const gdouble sensitivity[3] = { SIOX_DEFAULT_SENSITIVITY_L,
                                   SIOX_DEFAULT_SENSITIVITY_A,
                                   SIOX_DEFAULT_SENSITIVITY_B };

  g_return_if_fail (GIMP_IS_DRAWABLE (mask));
  g_return_if_fail (mode == GIMP_FOREGROUND_EXTRACT_SIOX);

  state =
    gimp_drawable_foreground_extract_siox_init (drawable,
                                                0, 0,
                                                gimp_item_get_width  (GIMP_ITEM (mask)),
                                                gimp_item_get_height (GIMP_ITEM (mask)));

  if (state)
    {
      gimp_drawable_foreground_extract_siox (mask, state,
                                             SIOX_REFINEMENT_RECALCULATE,
                                             SIOX_DEFAULT_SMOOTHNESS,
                                             sensitivity,
                                             FALSE,
                                             progress);

      gimp_drawable_foreground_extract_siox_done (state);
    }
}
예제 #8
0
static void
gimp_image_rotate_item_offset (GimpImage        *image,
                               GimpRotationType  rotate_type,
                               GimpItem         *item,
                               gint              off_x,
                               gint              off_y)
{
  gint x = 0;
  gint y = 0;

  switch (rotate_type)
    {
    case GIMP_ROTATE_90:
      x = gimp_image_get_height (image) - off_y - gimp_item_get_width (item);
      y = off_x;
      break;

    case GIMP_ROTATE_270:
      x = off_y;
      y = gimp_image_get_width (image) - off_x - gimp_item_get_height (item);
      break;

    case GIMP_ROTATE_180:
      return;
    }

  gimp_item_get_offset (item, &off_x, &off_y);

  x -= off_x;
  y -= off_y;

  if (x || y)
    gimp_item_translate (item, x, y, FALSE);
}
예제 #9
0
static void
gimp_tiling_update_strokes (GimpSymmetry *sym,
                            GimpDrawable *drawable,
                            GimpCoords   *origin)
{
  GimpTiling *tiling  = GIMP_TILING (sym);
  GList      *strokes = NULL;
  GimpCoords *coords;
  gint        width;
  gint        height;
  gint        startx = origin->x;
  gint        starty = origin->y;
  gint        x;
  gint        y;
  gint        x_count;
  gint        y_count;

  g_list_free_full (sym->strokes, g_free);
  sym->strokes = NULL;

  width  = gimp_item_get_width (GIMP_ITEM (drawable));
  height = gimp_item_get_height (GIMP_ITEM (drawable));

  if (origin->x > 0 && tiling->max_x == 0)
    startx = origin->x - tiling->interval_x * (gint) (origin->x / tiling->interval_x + 1);
  if (origin->y > 0 && tiling->max_y == 0)
    {
      starty = origin->y - tiling->interval_y * (gint) (origin->y / tiling->interval_y + 1);
      if (tiling->shift > 0.0)
        startx -= tiling->shift * (gint) (origin->y / tiling->interval_y + 1);
    }
  for (y_count = 0, y = starty; y < height + tiling->interval_y;
       y_count++, y += tiling->interval_y)
    {
      if (tiling->max_y && y_count >= (gint) tiling->max_y)
        break;
      for (x_count = 0, x = startx; x < width + tiling->interval_x;
           x_count++, x += tiling->interval_x)
        {
          if (tiling->max_x && x_count >= (gint) tiling->max_x)
            break;
          coords = g_memdup (origin, sizeof (GimpCoords));
          coords->x = x;
          coords->y = y;
          strokes = g_list_prepend (strokes, coords);
          if (tiling->interval_x < 1.0)
            break;
        }
      if (tiling->max_x || startx + tiling->shift <= 0.0)
        startx = startx + tiling->shift;
      else
        startx = startx - tiling->interval_x + tiling->shift;
      if (tiling->interval_y < 1.0)
        break;
    }

  sym->strokes = strokes;

  g_signal_emit_by_name (sym, "strokes-updated", sym->image);
}
예제 #10
0
static void
gimp_text_layer_render_layout (GimpTextLayer  *layer,
                               GimpTextLayout *layout)
{
  GimpDrawable    *drawable = GIMP_DRAWABLE (layer);
  GimpItem        *item     = GIMP_ITEM (layer);
  GeglBuffer      *buffer;
  cairo_t         *cr;
  cairo_surface_t *surface;
  gint             width;
  gint             height;

  g_return_if_fail (gimp_drawable_has_alpha (drawable));

  width  = gimp_item_get_width  (item);
  height = gimp_item_get_height (item);

  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);

  cr = cairo_create (surface);
  gimp_text_layout_render (layout, cr, layer->text->base_dir, FALSE);
  cairo_destroy (cr);

  cairo_surface_flush (surface);

  buffer = gimp_cairo_surface_create_buffer (surface);

  gegl_buffer_copy (buffer, NULL,
                    gimp_drawable_get_buffer (drawable), NULL);

  g_object_unref (buffer);
  cairo_surface_destroy (surface);

  gimp_drawable_update (drawable, 0, 0, width, height);
}
예제 #11
0
static void
gimp_channel_combine_clear_complement (GimpChannel         *mask,
                                       const GeglRectangle *rect)
{
  gint width  = gimp_item_get_width  (GIMP_ITEM (mask));
  gint height = gimp_item_get_height (GIMP_ITEM (mask));

  gimp_channel_combine_clear (
    mask,
    GEGL_RECTANGLE (0,
                    0,
                    width,
                    rect->y));

  gimp_channel_combine_clear (
    mask,
    GEGL_RECTANGLE (0,
                    rect->y + rect->height,
                    width,
                    height - (rect->y + rect->height)));

  gimp_channel_combine_clear (
    mask,
    GEGL_RECTANGLE (0,
                    rect->y,
                    rect->x,
                    rect->height));

  gimp_channel_combine_clear (
    mask,
    GEGL_RECTANGLE (rect->x + rect->width,
                    rect->y,
                    width - (rect->x + rect->width),
                    rect->height));
}
예제 #12
0
static TempBuf *
gimp_ink_get_paint_area (GimpPaintCore    *paint_core,
                         GimpDrawable     *drawable,
                         GimpPaintOptions *paint_options,
                         const GimpCoords *coords)
{
  GimpInk *ink = GIMP_INK (paint_core);
  gint     x, y;
  gint     width, height;
  gint     dwidth, dheight;
  gint     x1, y1, x2, y2;
  gint     bytes;

  bytes = gimp_drawable_bytes_with_alpha (drawable);

  gimp_blob_bounds (ink->cur_blob, &x, &y, &width, &height);

  dwidth  = gimp_item_get_width  (GIMP_ITEM (drawable));
  dheight = gimp_item_get_height (GIMP_ITEM (drawable));

  x1 = CLAMP (x / SUBSAMPLE - 1,            0, dwidth);
  y1 = CLAMP (y / SUBSAMPLE - 1,            0, dheight);
  x2 = CLAMP ((x + width)  / SUBSAMPLE + 2, 0, dwidth);
  y2 = CLAMP ((y + height) / SUBSAMPLE + 2, 0, dheight);

  /*  configure the canvas buffer  */
  if ((x2 - x1) && (y2 - y1))
    paint_core->canvas_buf = temp_buf_resize (paint_core->canvas_buf, bytes,
                                              x1, y1,
                                              (x2 - x1), (y2 - y1));
  else
    return NULL;

  return paint_core->canvas_buf;
}
예제 #13
0
static void
gimp_drawable_edit_fill_direct (GimpDrawable    *drawable,
                                GimpFillOptions *options,
                                const gchar     *undo_desc)
{
  GeglBuffer    *buffer;
  GimpContext   *context;
  GimpLayerMode  mode;
  gint           width;
  gint           height;

  buffer  = gimp_drawable_get_buffer (drawable);
  context = GIMP_CONTEXT (options);
  mode    = gimp_context_get_paint_mode (context);
  width   = gimp_item_get_width  (GIMP_ITEM (drawable));
  height  = gimp_item_get_height (GIMP_ITEM (drawable));

  gimp_drawable_push_undo (drawable, undo_desc,
                           NULL, 0, 0, width, height);

  if (! gimp_layer_mode_is_subtractive (mode))
    gimp_fill_options_fill_buffer (options, drawable, buffer, 0, 0);
  else
    gimp_gegl_clear (buffer, NULL);
}
예제 #14
0
void
gimp_channel_combine_buffer (GimpChannel    *mask,
                             GeglBuffer     *add_on_buffer,
                             GimpChannelOps  op,
                             gint            off_x,
                             gint            off_y)
{
  GeglBuffer *buffer;
  gint        x, y, w, h;

  g_return_if_fail (GIMP_IS_CHANNEL (mask));
  g_return_if_fail (GEGL_IS_BUFFER (add_on_buffer));

  buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask));

  if (! gimp_gegl_mask_combine_buffer (buffer, add_on_buffer,
                                       op, off_x, off_y))
    return;

  gimp_rectangle_intersect (off_x, off_y,
                            gegl_buffer_get_width  (add_on_buffer),
                            gegl_buffer_get_height (add_on_buffer),
                            0, 0,
                            gimp_item_get_width  (GIMP_ITEM (mask)),
                            gimp_item_get_height (GIMP_ITEM (mask)),
                            &x, &y, &w, &h);

  mask->bounds_known = FALSE;

  gimp_drawable_update (GIMP_DRAWABLE (mask), x, y, w, h);
}
static BoundSeg *
gimp_region_select_tool_calculate (GimpRegionSelectTool *region_sel,
                                   GimpDisplay          *display,
                                   gint                 *n_segs)
{
  GimpDisplayShell *shell = gimp_display_get_shell (display);
  BoundSeg         *segs;
  PixelRegion       maskPR;

  gimp_display_shell_set_override_cursor (shell, GDK_WATCH);

  if (region_sel->region_mask)
    g_object_unref (region_sel->region_mask);

  region_sel->region_mask =
    GIMP_REGION_SELECT_TOOL_GET_CLASS (region_sel)->get_mask (region_sel,
                                                              display);

  if (! region_sel->region_mask)
    {
      gimp_display_shell_unset_override_cursor (shell);

      *n_segs = 0;
      return NULL;
    }

  /*  calculate and allocate a new segment array which represents the
   *  boundary of the contiguous region
   */
  pixel_region_init (&maskPR,
                     gimp_drawable_get_tiles (GIMP_DRAWABLE (region_sel->region_mask)),
                     0, 0,
                     gimp_item_get_width  (GIMP_ITEM (region_sel->region_mask)),
                     gimp_item_get_height (GIMP_ITEM (region_sel->region_mask)),
                     FALSE);

  segs = boundary_find (&maskPR, BOUNDARY_WITHIN_BOUNDS,
                        0, 0,
                        gimp_item_get_width  (GIMP_ITEM (region_sel->region_mask)),
                        gimp_item_get_height (GIMP_ITEM (region_sel->region_mask)),
                        BOUNDARY_HALF_WAY,
                        n_segs);

  gimp_display_shell_unset_override_cursor (shell);

  return segs;
}
예제 #16
0
void
gimp_image_resize_to_layers (GimpImage    *image,
                             GimpContext  *context,
                             GimpProgress *progress)
{
  GList    *list;
  GimpItem *item;
  gint      x, y;
  gint      width, height;

  g_return_if_fail (GIMP_IS_IMAGE (image));
  g_return_if_fail (GIMP_IS_CONTEXT (context));
  g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));

  list = gimp_image_get_layer_iter (image);

  if (! list)
    return;

  /* figure out starting values */
  item = list->data;

  x      = gimp_item_get_offset_x (item);
  y      = gimp_item_get_offset_y (item);
  width  = gimp_item_get_width  (item);
  height = gimp_item_get_height (item);

  /*  Respect all layers  */
  for (list = g_list_next (list); list; list = g_list_next (list))
    {
      item = list->data;

      gimp_rectangle_union (x, y,
                            width, height,
                            gimp_item_get_offset_x (item),
                            gimp_item_get_offset_y (item),
                            gimp_item_get_width  (item),
                            gimp_item_get_height (item),
                            &x, &y,
                            &width, &height);
    }

  gimp_image_resize (image, context,
                     width, height, -x, -y,
                     progress);
}
예제 #17
0
gboolean
gimp_item_get_popup_size (GimpViewable *viewable,
                          gint          width,
                          gint          height,
                          gboolean      dot_for_dot,
                          gint         *popup_width,
                          gint         *popup_height)
{
  GimpItem  *item  = GIMP_ITEM (viewable);
  GimpImage *image = gimp_item_get_image (item);

  if (image && ! image->gimp->config->layer_previews)
    return FALSE;

  if (gimp_item_get_width  (item) > width ||
      gimp_item_get_height (item) > height)
    {
      gboolean scaling_up;
      gdouble  xres = 1.0;
      gdouble  yres = 1.0;

      if (image)
        gimp_image_get_resolution (image, &xres, &yres);

      gimp_viewable_calc_preview_size (gimp_item_get_width  (item),
                                       gimp_item_get_height (item),
                                       width  * 2,
                                       height * 2,
                                       dot_for_dot,
                                       xres,
                                       yres,
                                       popup_width,
                                       popup_height,
                                       &scaling_up);

      if (scaling_up)
        {
          *popup_width  = gimp_item_get_width  (item);
          *popup_height = gimp_item_get_height (item);
        }

      return TRUE;
    }

  return FALSE;
}
예제 #18
0
void
gimp_channel_select_round_rect (GimpChannel         *channel,
                                gint                 x,
                                gint                 y,
                                gint                 w,
                                gint                 h,
                                gdouble              corner_radius_x,
                                gdouble              corner_radius_y,
                                GimpChannelOps       op,
                                gboolean             antialias,
                                gboolean             feather,
                                gdouble              feather_radius_x,
                                gdouble              feather_radius_y,
                                gboolean             push_undo)
{
  g_return_if_fail (GIMP_IS_CHANNEL (channel));
  g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel)));

  if (push_undo)
    gimp_channel_push_undo (channel, C_("undo-type", "Rounded Rectangle Select"));

  /*  if applicable, replace the current selection  */
  if (op == GIMP_CHANNEL_OP_REPLACE)
    gimp_channel_clear (channel, NULL, FALSE);

  /*  if feathering for rect, make a new mask with the
   *  rectangle and feather that with the old mask
   */
  if (feather || op == GIMP_CHANNEL_OP_INTERSECT)
    {
      GimpItem   *item = GIMP_ITEM (channel);
      GeglBuffer *add_on;

      add_on = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
                                                gimp_item_get_width  (item),
                                                gimp_item_get_height (item)),
                                babl_format ("Y float"));

      gimp_gegl_mask_combine_ellipse_rect (add_on, GIMP_CHANNEL_OP_ADD,
                                           x, y, w, h,
                                           corner_radius_x, corner_radius_y,
                                           antialias);

      if (feather)
        gimp_gegl_apply_feather (add_on, NULL, NULL, add_on, NULL,
                                 feather_radius_x,
                                 feather_radius_y);

      gimp_channel_combine_buffer (channel, add_on, op, 0, 0);
      g_object_unref (add_on);
    }
  else
    {
      gimp_channel_combine_ellipse_rect (channel, op, x, y, w, h,
                                         corner_radius_x, corner_radius_y,
                                         antialias);
    }
}
예제 #19
0
/**
 * gimp_projection_initialize:
 * @proj: A #GimpProjection.
 * @x:
 * @y:
 * @w:
 * @h:
 *
 * This function determines whether a visible layer with combine mode
 * Normal provides complete coverage over the specified area.  If not,
 * the projection is initialized to transparent black.
 */
static void
gimp_projection_initialize (GimpProjection *proj,
                            gint            x,
                            gint            y,
                            gint            w,
                            gint            h)
{
    GList    *list;
    gint      proj_off_x;
    gint      proj_off_y;
    gboolean  coverage = FALSE;

    gimp_projectable_get_offset (proj->projectable, &proj_off_x, &proj_off_y);

    for (list = gimp_projectable_get_layers (proj->projectable);
            list;
            list = g_list_next (list))
    {
        GimpLayer    *layer    = list->data;
        GimpDrawable *drawable = GIMP_DRAWABLE (layer);
        GimpItem     *item     = GIMP_ITEM (layer);
        gint          off_x, off_y;

        gimp_item_get_offset (item, &off_x, &off_y);

        /*  subtract the projectable's offsets because the list of
         *  update areas is in tile-pyramid coordinates, but our
         *  external API is always in terms of image coordinates.
         */
        off_x -= proj_off_x;
        off_y -= proj_off_y;

        if (gimp_item_get_visible (item)                          &&
                ! gimp_drawable_has_alpha (drawable)                  &&
                ! gimp_layer_get_mask (layer)                         &&
                gimp_layer_get_mode (layer) == GIMP_NORMAL_MODE       &&
                gimp_layer_get_opacity (layer) == GIMP_OPACITY_OPAQUE &&
                off_x <= x                                            &&
                off_y <= y                                            &&
                (off_x + gimp_item_get_width  (item)) >= (x + w)      &&
                (off_y + gimp_item_get_height (item)) >= (y + h))
        {
            coverage = TRUE;
            break;
        }
    }

    if (! coverage)
    {
        PixelRegion region;

        pixel_region_init (&region,
                           gimp_pickable_get_tiles (GIMP_PICKABLE (proj)),
                           x, y, w, h, TRUE);
        clear_region (&region);
    }
}
예제 #20
0
GimpTempBuf *
gimp_drawable_get_sub_preview (GimpDrawable *drawable,
                               gint          src_x,
                               gint          src_y,
                               gint          src_width,
                               gint          src_height,
                               gint          dest_width,
                               gint          dest_height)
{
  GimpItem    *item;
  GimpImage   *image;
  GeglBuffer  *buffer;
  GimpTempBuf *preview;
  gdouble      scale;
  gint         scaled_x;
  gint         scaled_y;

  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
  g_return_val_if_fail (src_x >= 0, NULL);
  g_return_val_if_fail (src_y >= 0, NULL);
  g_return_val_if_fail (src_width  > 0, NULL);
  g_return_val_if_fail (src_height > 0, NULL);
  g_return_val_if_fail (dest_width  > 0, NULL);
  g_return_val_if_fail (dest_height > 0, NULL);

  item = GIMP_ITEM (drawable);

  g_return_val_if_fail ((src_x + src_width)  <= gimp_item_get_width  (item), NULL);
  g_return_val_if_fail ((src_y + src_height) <= gimp_item_get_height (item), NULL);

  image = gimp_item_get_image (item);

  if (! image->gimp->config->layer_previews)
    return NULL;

  buffer = gimp_drawable_get_buffer (drawable);

  preview = gimp_temp_buf_new (dest_width, dest_height,
                               gimp_drawable_get_preview_format (drawable));

  scale = MIN ((gdouble) dest_width  / (gdouble) src_width,
               (gdouble) dest_height / (gdouble) src_height);

  scaled_x = RINT ((gdouble) src_x * scale);
  scaled_y = RINT ((gdouble) src_y * scale);

  gegl_buffer_get (buffer,
                   GEGL_RECTANGLE (scaled_x, scaled_y, dest_width, dest_height),
                   scale,
                   gimp_temp_buf_get_format (preview),
                   gimp_temp_buf_get_data (preview),
                   GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP);

  return preview;
}
예제 #21
0
static GeglBuffer *
gimp_ink_get_paint_buffer (GimpPaintCore    *paint_core,
                           GimpDrawable     *drawable,
                           GimpPaintOptions *paint_options,
                           const GimpCoords *coords,
                           gint             *paint_buffer_x,
                           gint             *paint_buffer_y)
{
  GimpInk *ink = GIMP_INK (paint_core);
  gint     x, y;
  gint     width, height;
  gint     dwidth, dheight;
  gint     x1, y1, x2, y2;

  gimp_blob_bounds (ink->cur_blob, &x, &y, &width, &height);

  dwidth  = gimp_item_get_width  (GIMP_ITEM (drawable));
  dheight = gimp_item_get_height (GIMP_ITEM (drawable));

  x1 = CLAMP (x / SUBSAMPLE - 1,            0, dwidth);
  y1 = CLAMP (y / SUBSAMPLE - 1,            0, dheight);
  x2 = CLAMP ((x + width)  / SUBSAMPLE + 2, 0, dwidth);
  y2 = CLAMP ((y + height) / SUBSAMPLE + 2, 0, dheight);

  /*  configure the canvas buffer  */
  if ((x2 - x1) && (y2 - y1))
    {
      GimpTempBuf *temp_buf;
      const Babl  *format;

      if (gimp_drawable_get_linear (drawable))
        format = babl_format ("RGBA float");
      else
        format = babl_format ("R'G'B'A float");

      temp_buf = gimp_temp_buf_new ((x2 - x1), (y2 - y1),
                                    format);

      *paint_buffer_x = x1;
      *paint_buffer_y = y1;

      if (paint_core->paint_buffer)
        g_object_unref (paint_core->paint_buffer);

      paint_core->paint_buffer = gimp_temp_buf_create_buffer (temp_buf);

      gimp_temp_buf_unref (temp_buf);

      return paint_core->paint_buffer;
    }

  return NULL;
}
예제 #22
0
gboolean
floating_sel_to_layer (GimpLayer  *layer,
                       GError    **error)
{
  GimpItem  *item;
  GimpImage *image;

  g_return_val_if_fail (GIMP_IS_LAYER (layer), FALSE);
  g_return_val_if_fail (gimp_layer_is_floating_sel (layer), FALSE);
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

  item  = GIMP_ITEM (layer);
  image = gimp_item_get_image (item);

  /*  Check if the floating layer belongs to a channel  */
  if (GIMP_IS_CHANNEL (gimp_layer_get_floating_sel_drawable (layer)))
    {
      g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
			   _("Cannot create a new layer from the floating "
			     "selection because it belongs to a layer mask "
			     "or channel."));
      return FALSE;
    }

  gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_FS_TO_LAYER,
                               C_("undo-type", "Floating Selection to Layer"));

  gimp_image_undo_push_fs_to_layer (image, NULL, layer);

  gimp_drawable_detach_floating_sel (gimp_layer_get_floating_sel_drawable (layer));
  gimp_layer_set_floating_sel_drawable (layer, NULL);

  gimp_item_set_visible (item, TRUE, TRUE);
  gimp_layer_set_lock_alpha (layer, FALSE, TRUE);

  gimp_image_undo_group_end (image);

  /* When the floating selection is converted to/from a normal layer
   * it does something resembling a name change, so emit the
   * "name-changed" signal
   */
  gimp_object_name_changed (GIMP_OBJECT (layer));

  gimp_drawable_update (GIMP_DRAWABLE (layer),
                        0, 0,
                        gimp_item_get_width  (item),
                        gimp_item_get_height (item));

  return TRUE;
}
예제 #23
0
static void
offset_half_y_callback (GtkWidget    *widget,
                        OffsetDialog *dialog)
{
  GimpImage *image = dialog->image;

  if (image)
    {
      GimpItem *item = GIMP_ITEM (gimp_image_get_active_drawable (image));

      gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (dialog->off_se),
                                  1, gimp_item_get_height (item) / 2);
   }
}
예제 #24
0
void
gimp_channel_select_buffer (GimpChannel    *channel,
                            const gchar    *undo_desc,
                            GeglBuffer     *add_on,
                            gint            offset_x,
                            gint            offset_y,
                            GimpChannelOps  op,
                            gboolean        feather,
                            gdouble         feather_radius_x,
                            gdouble         feather_radius_y)
{
  g_return_if_fail (GIMP_IS_CHANNEL (channel));
  g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel)));
  g_return_if_fail (undo_desc != NULL);
  g_return_if_fail (GEGL_IS_BUFFER (add_on));

  gimp_channel_push_undo (channel, undo_desc);

  /*  if applicable, replace the current selection  */
  if (op == GIMP_CHANNEL_OP_REPLACE)
    gimp_channel_clear (channel, NULL, FALSE);

  if (feather || op == GIMP_CHANNEL_OP_INTERSECT)
    {
      GimpItem   *item = GIMP_ITEM (channel);
      GeglBuffer *add_on2;

      add_on2 = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
                                                 gimp_item_get_width  (item),
                                                 gimp_item_get_height (item)),
                                 babl_format ("Y float"));

      gimp_gegl_mask_combine_buffer (add_on2, add_on,
                                     GIMP_CHANNEL_OP_ADD,
                                     offset_x, offset_y);

      if (feather)
        gimp_gegl_apply_feather (add_on2, NULL, NULL, add_on2, NULL,
                                 feather_radius_x,
                                 feather_radius_y);

      gimp_channel_combine_buffer (channel, add_on2, op, 0, 0);
      g_object_unref (add_on2);
    }
  else
    {
      gimp_channel_combine_buffer (channel, add_on, op, offset_x, offset_y);
    }
}
void
gimp_drawable_foreground_extract_siox (GimpDrawable       *mask,
                                       SioxState          *state,
                                       SioxRefinementType  refinement,
                                       gint                smoothness,
                                       const gdouble       sensitivity[3],
                                       gboolean            multiblob,
                                       GimpProgress       *progress)
{
  GeglBuffer *buffer;
  gint        x1, y1;
  gint        x2, y2;

  g_return_if_fail (GIMP_IS_DRAWABLE (mask));
  g_return_if_fail (babl_format_get_bytes_per_pixel (gimp_drawable_get_format (mask)) == 1);

  g_return_if_fail (state != NULL);

  g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));

  if (progress)
    gimp_progress_start (progress, _("Foreground Extraction"), FALSE);

  if (GIMP_IS_CHANNEL (mask))
    {
      gimp_channel_bounds (GIMP_CHANNEL (mask), &x1, &y1, &x2, &y2);
    }
  else
    {
      x1 = 0;
      y1 = 0;
      x2 = gimp_item_get_width  (GIMP_ITEM (mask));
      y2 = gimp_item_get_height (GIMP_ITEM (mask));
    }

  buffer = gimp_drawable_get_buffer (mask);

  siox_foreground_extract (state, refinement,
                           gimp_gegl_buffer_get_tiles (buffer),
                           x1, y1, x2, y2,
                           smoothness, sensitivity, multiblob,
                           (SioxProgressFunc) gimp_progress_set_value,
                           progress);

  if (progress)
    gimp_progress_end (progress);

  gimp_drawable_update (mask, x1, y1, x2, y2);
}
예제 #26
0
void
gimp_item_get_preview_size (GimpViewable *viewable,
                            gint          size,
                            gboolean      is_popup,
                            gboolean      dot_for_dot,
                            gint         *width,
                            gint         *height)
{
  GimpItem  *item  = GIMP_ITEM (viewable);
  GimpImage *image = gimp_item_get_image (item);

  if (image && ! image->gimp->config->layer_previews && ! is_popup)
    {
      *width  = size;
      *height = size;
      return;
    }

  if (image && ! is_popup)
    {
      gdouble xres;
      gdouble yres;

      gimp_image_get_resolution (image, &xres, &yres);

      gimp_viewable_calc_preview_size (gimp_image_get_width  (image),
                                       gimp_image_get_height (image),
                                       size,
                                       size,
                                       dot_for_dot,
                                       xres,
                                       yres,
                                       width,
                                       height,
                                       NULL);
    }
  else
    {
      gimp_viewable_calc_preview_size (gimp_item_get_width  (item),
                                       gimp_item_get_height (item),
                                       size,
                                       size,
                                       dot_for_dot, 1.0, 1.0,
                                       width,
                                       height,
                                       NULL);
    }
}
예제 #27
0
static void
gimp_floating_sel_undo_pop (GimpUndo            *undo,
                            GimpUndoMode         undo_mode,
                            GimpUndoAccumulator *accum)
{
  GimpFloatingSelUndo *floating_sel_undo = GIMP_FLOATING_SEL_UNDO (undo);
  GimpLayer           *floating_layer    = GIMP_LAYER (GIMP_ITEM_UNDO (undo)->item);

  GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum);

  switch (undo->undo_type)
    {
    case GIMP_UNDO_FS_TO_LAYER:
      if (undo_mode == GIMP_UNDO_MODE_UNDO)
        {
          /*  Update the preview for the floating sel  */
          gimp_viewable_invalidate_preview (GIMP_VIEWABLE (floating_layer));

          gimp_layer_set_floating_sel_drawable (floating_layer,
                                                floating_sel_undo->drawable);
          gimp_image_set_active_layer (undo->image, floating_layer);

          gimp_drawable_attach_floating_sel (gimp_layer_get_floating_sel_drawable (floating_layer),
                                             floating_layer);
        }
      else
        {
          gimp_drawable_detach_floating_sel (gimp_layer_get_floating_sel_drawable (floating_layer));
          gimp_layer_set_floating_sel_drawable (floating_layer, NULL);
        }

      /* When the floating selection is converted to/from a normal
       * layer it does something resembling a name change, so emit the
       * "name-changed" signal
       */
      gimp_object_name_changed (GIMP_OBJECT (floating_layer));

      gimp_drawable_update (GIMP_DRAWABLE (floating_layer),
                            0, 0,
                            gimp_item_get_width  (GIMP_ITEM (floating_layer)),
                            gimp_item_get_height (GIMP_ITEM (floating_layer)));
      break;

    default:
      g_assert_not_reached ();
    }
}
예제 #28
0
void
gimp_channel_select_scan_convert (GimpChannel     *channel,
                                  const gchar     *undo_desc,
                                  GimpScanConvert *scan_convert,
                                  gint             offset_x,
                                  gint             offset_y,
                                  GimpChannelOps   op,
                                  gboolean         antialias,
                                  gboolean         feather,
                                  gdouble          feather_radius_x,
                                  gdouble          feather_radius_y,
                                  gboolean         push_undo)
{
  GimpItem   *item;
  GeglBuffer *add_on;

  g_return_if_fail (GIMP_IS_CHANNEL (channel));
  g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel)));
  g_return_if_fail (undo_desc != NULL);
  g_return_if_fail (scan_convert != NULL);

  if (push_undo)
    gimp_channel_push_undo (channel, undo_desc);

  /*  if applicable, replace the current selection  */
  if (op == GIMP_CHANNEL_OP_REPLACE)
    gimp_channel_clear (channel, NULL, FALSE);

  item = GIMP_ITEM (channel);

  add_on = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
                                            gimp_item_get_width  (item),
                                            gimp_item_get_height (item)),
                            babl_format ("Y float"));

  gimp_scan_convert_render (scan_convert, add_on,
                            offset_x, offset_y, antialias);

  if (feather)
    gimp_gegl_apply_feather (add_on, NULL, NULL, add_on, NULL,
                             feather_radius_x,
                             feather_radius_y);

  gimp_channel_combine_buffer (channel, add_on, op, 0, 0);
  g_object_unref (add_on);
}
예제 #29
0
static void
gimp_image_map_tool_add_guide (GimpImageMapTool *im_tool)
{
  GimpImageMapOptions *options = GIMP_IMAGE_MAP_TOOL_GET_OPTIONS (im_tool);
  GimpItem            *item;
  GimpImage           *image;
  GimpOrientationType  orientation;
  gint                 position;

  if (im_tool->percent_guide)
    return;

  item = GIMP_ITEM (im_tool->drawable);
  image = gimp_item_get_image (item);

  if (options->preview_alignment == GIMP_ALIGN_LEFT ||
      options->preview_alignment == GIMP_ALIGN_RIGHT)
    {
      orientation = GIMP_ORIENTATION_VERTICAL;

      position = (gimp_item_get_offset_x (item) +
                  gimp_item_get_width (item) *
                  options->preview_position);
    }
  else
    {
      orientation = GIMP_ORIENTATION_HORIZONTAL;

      position = (gimp_item_get_offset_y (item) +
                  gimp_item_get_height (item) *
                  options->preview_position);
    }

  im_tool->percent_guide = gimp_guide_custom_new (orientation,
                                                  image->gimp->next_guide_ID++,
                                                  GIMP_GUIDE_STYLE_SPLIT_VIEW);

  gimp_image_add_guide (image, im_tool->percent_guide, position);

  g_signal_connect (im_tool->percent_guide, "removed",
                    G_CALLBACK (gimp_image_map_tool_guide_removed),
                    im_tool);
  g_signal_connect (im_tool->percent_guide, "notify::position",
                    G_CALLBACK (gimp_image_map_tool_guide_moved),
                    im_tool);
}
예제 #30
0
/*
 * Position the dropped item in the middle of the viewport.
 */
static void
gimp_display_shell_dnd_position_item (GimpDisplayShell *shell,
                                      GimpItem         *item)
{
  gint x, y;
  gint width, height;
  gint off_x, off_y;

  gimp_display_shell_untransform_viewport (shell, &x, &y, &width, &height);

  gimp_item_get_offset (item, &off_x, &off_y);

  off_x = x + (width  - gimp_item_get_width  (item)) / 2 - off_x;
  off_y = y + (height - gimp_item_get_height (item)) / 2 - off_y;

  gimp_item_translate (item, off_x, off_y, FALSE);
}