Exemplo n.º 1
0
static void
gimp_projection_projectable_changed (GimpProjectable *projectable,
                                     GimpProjection  *proj)
{
  gint off_x, off_y;
  gint width, height;

  if (proj->idle_render.idle_id)
    {
      g_source_remove (proj->idle_render.idle_id);
      proj->idle_render.idle_id = 0;
    }

  gimp_area_list_free (proj->update_areas);
  proj->update_areas = NULL;

  if (proj->pyramid)
    {
      tile_pyramid_destroy (proj->pyramid);
      proj->pyramid = NULL;
    }

  if (proj->buffer)
    {
      g_object_unref (proj->buffer);
      proj->buffer = NULL;
    }

  gimp_projectable_get_offset (proj->projectable, &off_x, &off_y);
  gimp_projectable_get_size (projectable, &width, &height);

  gimp_projection_add_update_area (proj, off_x, off_y, width, height);
}
Exemplo n.º 2
0
static void
gimp_projection_paint_area (GimpProjection *proj,
                            gboolean        now,
                            gint            x,
                            gint            y,
                            gint            w,
                            gint            h)
{
  gint off_x, off_y;
  gint width, height;
  gint x1, y1, x2, y2;

  gimp_projectable_get_offset (proj->projectable, &off_x, &off_y);
  gimp_projectable_get_size   (proj->projectable, &width, &height);

  /*  Bounds check  */
  x1 = CLAMP (x,     0, width);
  y1 = CLAMP (y,     0, height);
  x2 = CLAMP (x + w, 0, width);
  y2 = CLAMP (y + h, 0, height);

  gimp_projection_invalidate (proj, x1, y1, x2 - x1, y2 - y1);

  /*  add 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.
   */
  g_signal_emit (proj, projection_signals[UPDATE], 0,
                 now,
                 x1 + off_x,
                 y1 + off_y,
                 x2 - x1,
                 y2 - y1);
}
Exemplo n.º 3
0
static void
gimp_projection_add_update_area (GimpProjection *proj,
                                 gint            x,
                                 gint            y,
                                 gint            w,
                                 gint            h)
{
  GimpArea *area;
  gint      off_x, off_y;
  gint      width, height;

  gimp_projectable_get_offset (proj->projectable, &off_x, &off_y);
  gimp_projectable_get_size   (proj->projectable, &width, &height);

  /*  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.
   */
  x -= off_x;
  y -= off_y;

  area = gimp_area_new (CLAMP (x,     0, width),
                        CLAMP (y,     0, height),
                        CLAMP (x + w, 0, width),
                        CLAMP (y + h, 0, height));

  proj->update_areas = gimp_area_list_process (proj->update_areas, area);
}
Exemplo n.º 4
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);
    }
}
Exemplo n.º 5
0
void
gimp_projection_construct (GimpProjection *proj,
                           gint            x,
                           gint            y,
                           gint            w,
                           gint            h)
{
    g_return_if_fail (GIMP_IS_PROJECTION (proj));

#if 0
    GList *layers = gimp_projectable_get_layers (proj->projectable);

    if (layers && ! layers->next) /* a single layer */
    {
        GimpLayer    *layer    = layers->data;
        GimpDrawable *drawable = GIMP_DRAWABLE (layer);
        GimpItem     *item     = GIMP_ITEM (layer);
        gint          width, height;
        gint          off_x, off_y;

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

        gimp_item_get_offset (item, &off_x, &off_y);

        if (gimp_drawable_has_alpha (drawable)                    &&
                gimp_item_get_visible (item)                          &&
                gimp_item_get_width  (item) == width                  &&
                gimp_item_get_height (item) == height                 &&
                ! gimp_drawable_is_indexed (layer)                    &&
                gimp_layer_get_opacity (layer) == GIMP_OPACITY_OPAQUE &&
                off_x == 0                                            &&
                off_y == 0                                            &&
                proj_offset_x == 0                                    &&
                proj_offset_y == 0)
        {
            PixelRegion srcPR, destPR;

            g_printerr ("cow-projection!");

            pixel_region_init (&srcPR,
                               gimp_drawable_get_tiles (layer),
                               x, y, w,h, FALSE);
            pixel_region_init (&destPR,
                               gimp_pickable_get_tiles (GIMP_PICKABLE (proj)),
                               x, y, w,h, TRUE);

            copy_region (&srcPR, &destPR);

            proj->construct_flag = TRUE;

            gimp_projection_construct_legacy (proj, FALSE, x, y, w, h);

            return;
        }
    }
#endif

    /*  First, determine if the projection image needs to be
     *  initialized--this is the case when there are no visible
     *  layers that cover the entire canvas--either because layers
     *  are offset or only a floating selection is visible
     */
    gimp_projection_initialize (proj, x, y, w, h);

    /*  call functions which process the list of layers and
     *  the list of channels
     */
    if (proj->use_gegl)
    {
        gimp_projection_construct_gegl (proj, x, y, w, h);
    }
    else
    {
        proj->construct_flag = FALSE;

        gimp_projection_construct_legacy (proj, TRUE, x, y, w, h);
    }
}
Exemplo n.º 6
0
static void
gimp_projection_construct_legacy (GimpProjection *proj,
                                  gboolean        with_layers,
                                  gint            x,
                                  gint            y,
                                  gint            w,
                                  gint            h)
{
    GList *list;
    GList *reverse_list = NULL;
    gint   proj_off_x;
    gint   proj_off_y;

    for (list = gimp_projectable_get_channels (proj->projectable);
            list;
            list = g_list_next (list))
    {
        if (gimp_item_get_visible (GIMP_ITEM (list->data)))
        {
            reverse_list = g_list_prepend (reverse_list, list->data);
        }
    }

    if (with_layers)
    {
        for (list = gimp_projectable_get_layers (proj->projectable);
                list;
                list = g_list_next (list))
        {
            GimpLayer *layer = list->data;

            if (! gimp_layer_is_floating_sel (layer) &&
                    gimp_item_get_visible (GIMP_ITEM (layer)))
            {
                /*  only add layers that are visible and not floating selections
                 *  to the list
                 */
                reverse_list = g_list_prepend (reverse_list, layer);
            }
        }
    }

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

    for (list = reverse_list; list; list = g_list_next (list))
    {
        GimpItem    *item = list->data;
        PixelRegion  projPR;
        gint         x1, y1;
        gint         x2, y2;
        gint         off_x;
        gint         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;

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

        pixel_region_init (&projPR,
                           gimp_pickable_get_tiles (GIMP_PICKABLE (proj)),
                           x1, y1, x2 - x1, y2 - y1,
                           TRUE);

        gimp_drawable_project_region (GIMP_DRAWABLE (item),
                                      x1 - off_x, y1 - off_y,
                                      x2 - x1,    y2 - y1,
                                      &projPR,
                                      proj->construct_flag);

        proj->construct_flag = TRUE;  /*  something was projected  */
    }

    g_list_free (reverse_list);
}