app: port GimpDrawableUndo, GimpDrawable::push_undo() and ::swap_tiles()

which gets rid of the manual implementation of sparse undo buffers,
but GEGL will take care of proper COW here soo enough.
This commit is contained in:
Michael Natterer 2012-03-22 14:13:17 +01:00
parent 2ff19d7087
commit a0c1007b66
12 changed files with 115 additions and 174 deletions

View File

@ -164,8 +164,7 @@ static void gimp_channel_set_buffer (GimpDrawable *drawable,
gint offset_y);
static GeglNode * gimp_channel_get_node (GimpItem *item);
static void gimp_channel_swap_pixels (GimpDrawable *drawable,
TileManager *tiles,
gboolean sparse,
GeglBuffer *buffer,
gint x,
gint y,
gint width,
@ -934,8 +933,7 @@ gimp_channel_get_node (GimpItem *item)
static void
gimp_channel_swap_pixels (GimpDrawable *drawable,
TileManager *tiles,
gboolean sparse,
GeglBuffer *buffer,
gint x,
gint y,
gint width,
@ -943,7 +941,7 @@ gimp_channel_swap_pixels (GimpDrawable *drawable,
{
gimp_drawable_invalidate_boundary (drawable);
GIMP_DRAWABLE_CLASS (parent_class)->swap_pixels (drawable, tiles, sparse,
GIMP_DRAWABLE_CLASS (parent_class)->swap_pixels (drawable, buffer,
x, y, width, height);
GIMP_CHANNEL (drawable)->bounds_known = FALSE;

View File

@ -101,9 +101,9 @@ gimp_drawable_real_apply_region (GimpDrawable *drawable,
GimpDrawableUndo *undo;
gimp_drawable_push_undo (drawable, undo_desc,
NULL,
x1, y1,
x2 - x1, y2 - y1,
NULL, FALSE);
x2 - x1, y2 - y1);
undo = GIMP_DRAWABLE_UNDO (gimp_image_undo_get_fadeable (image));
@ -258,9 +258,9 @@ gimp_drawable_real_replace_region (GimpDrawable *drawable,
/* If the calling procedure specified an undo step... */
if (push_undo)
gimp_drawable_push_undo (drawable, undo_desc,
NULL,
x1, y1,
x2 - x1, y2 - y1,
NULL, FALSE);
x2 - x1, y2 - y1);
/* configure the pixel regions */
pixel_region_init (&src1PR, gimp_drawable_get_tiles (drawable),

View File

@ -152,15 +152,13 @@ static GeglNode * gimp_drawable_get_node (GimpItem *item);
static void gimp_drawable_real_push_undo (GimpDrawable *drawable,
const gchar *undo_desc,
TileManager *tiles,
gboolean sparse,
GeglBuffer *buffer,
gint x,
gint y,
gint width,
gint height);
static void gimp_drawable_real_swap_pixels (GimpDrawable *drawable,
TileManager *tiles,
gboolean sparse,
GeglBuffer *buffer,
gint x,
gint y,
gint width,
@ -864,95 +862,57 @@ gimp_drawable_get_node (GimpItem *item)
static void
gimp_drawable_real_push_undo (GimpDrawable *drawable,
const gchar *undo_desc,
TileManager *tiles,
gboolean sparse,
GeglBuffer *buffer,
gint x,
gint y,
gint width,
gint height)
{
gboolean new_tiles = FALSE;
if (! tiles)
if (! buffer)
{
GeglBuffer *dest_buffer;
tiles = tile_manager_new (width, height, gimp_drawable_bytes (drawable));
dest_buffer = gimp_tile_manager_create_buffer (tiles,
gimp_drawable_get_format (drawable));
buffer = gimp_gegl_buffer_new (GIMP_GEGL_RECT (0, 0, width, height),
gimp_drawable_get_format (drawable));
gegl_buffer_copy (gimp_drawable_get_buffer (drawable),
GIMP_GEGL_RECT (x,y,width,height),
dest_buffer, GIMP_GEGL_RECT (0,0,0,0));
g_object_unref (dest_buffer);
new_tiles = TRUE;
GIMP_GEGL_RECT (x, y, width, height),
buffer,
GIMP_GEGL_RECT (0, 0, 0, 0));
}
else
{
g_object_ref (buffer);
}
gimp_image_undo_push_drawable (gimp_item_get_image (GIMP_ITEM (drawable)),
undo_desc, drawable,
tiles, sparse,
buffer,
x, y, width, height);
if (new_tiles)
tile_manager_unref (tiles);
g_object_unref (buffer);
}
static void
gimp_drawable_real_swap_pixels (GimpDrawable *drawable,
TileManager *tiles,
gboolean sparse,
GeglBuffer *buffer,
gint x,
gint y,
gint width,
gint height)
{
if (sparse)
{
gint i, j;
GeglBuffer *tmp;
for (i = y; i < (y + height); i += (TILE_HEIGHT - (i % TILE_HEIGHT)))
{
for (j = x; j < (x + width); j += (TILE_WIDTH - (j % TILE_WIDTH)))
{
Tile *src_tile;
Tile *dest_tile;
tmp = gimp_gegl_buffer_dup (buffer);
src_tile = tile_manager_get_tile (tiles, j, i, FALSE, FALSE);
gegl_buffer_copy (gimp_drawable_get_buffer (drawable),
GIMP_GEGL_RECT (x, y, width, height),
buffer,
GIMP_GEGL_RECT (0, 0, 0, 0));
gegl_buffer_copy (tmp,
GIMP_GEGL_RECT (0, 0, width, height),
gimp_drawable_get_buffer (drawable),
GIMP_GEGL_RECT (x, y, 0, 0));
if (tile_is_valid (src_tile))
{
/* swap tiles, not pixels! */
src_tile = tile_manager_get_tile (tiles,
j, i, TRUE, FALSE /*TRUE*/);
dest_tile = tile_manager_get_tile (gimp_drawable_get_tiles (drawable),
j, i, TRUE, FALSE /* TRUE */);
tile_manager_map_tile (tiles,
j, i, dest_tile);
tile_manager_map_tile (gimp_drawable_get_tiles (drawable),
j, i, src_tile);
tile_release (dest_tile, FALSE);
tile_release (src_tile, FALSE);
}
}
}
}
else
{
PixelRegion PR1, PR2;
pixel_region_init (&PR1, tiles,
0, 0, width, height, TRUE);
pixel_region_init (&PR2, gimp_drawable_get_tiles (drawable),
x, y, width, height, TRUE);
swap_region (&PR1, &PR2);
}
g_object_unref (tmp);
gimp_drawable_update (drawable, x, y, width, height);
}
@ -1568,49 +1528,39 @@ gimp_drawable_get_mode_node (GimpDrawable *drawable)
void
gimp_drawable_swap_pixels (GimpDrawable *drawable,
TileManager *tiles,
gboolean sparse,
GeglBuffer *buffer,
gint x,
gint y,
gint width,
gint height)
{
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
g_return_if_fail (tiles != NULL);
g_return_if_fail (GEGL_IS_BUFFER (buffer));
GIMP_DRAWABLE_GET_CLASS (drawable)->swap_pixels (drawable, tiles, sparse,
GIMP_DRAWABLE_GET_CLASS (drawable)->swap_pixels (drawable, buffer,
x, y, width, height);
}
void
gimp_drawable_push_undo (GimpDrawable *drawable,
const gchar *undo_desc,
GeglBuffer *buffer,
gint x,
gint y,
gint width,
gint height,
TileManager *tiles,
gboolean sparse)
gint height)
{
GimpItem *item;
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
g_return_if_fail (sparse == FALSE || tiles != NULL);
g_return_if_fail (buffer == NULL || GEGL_IS_BUFFER (buffer));
item = GIMP_ITEM (drawable);
g_return_if_fail (gimp_item_is_attached (item));
g_return_if_fail (sparse == FALSE ||
tile_manager_width (tiles) == gimp_item_get_width (item));
g_return_if_fail (sparse == FALSE ||
tile_manager_height (tiles) == gimp_item_get_height (item));
#if 0
g_printerr ("gimp_drawable_push_undo (%s, %d, %d, %d, %d)\n",
sparse ? "TRUE" : "FALSE", x, y, width, height);
#endif
if (! gimp_rectangle_intersect (x, y,
if (! buffer &&
! gimp_rectangle_intersect (x, y,
width, height,
0, 0,
gimp_item_get_width (item),
@ -1622,7 +1572,7 @@ gimp_drawable_push_undo (GimpDrawable *drawable,
}
GIMP_DRAWABLE_GET_CLASS (drawable)->push_undo (drawable, undo_desc,
tiles, sparse,
buffer,
x, y, width, height);
}

View File

@ -97,15 +97,13 @@ struct _GimpDrawableClass
gint offset_y);
void (* push_undo) (GimpDrawable *drawable,
const gchar *undo_desc,
TileManager *tiles,
gboolean sparse,
GeglBuffer *buffer,
gint x,
gint y,
gint width,
gint height);
void (* swap_pixels) (GimpDrawable *drawable,
TileManager *tiles,
gboolean sparse,
GeglBuffer *buffer,
gint x,
gint y,
gint width,
@ -195,8 +193,7 @@ GeglNode * gimp_drawable_get_source_node (GimpDrawable *drawable);
GeglNode * gimp_drawable_get_mode_node (GimpDrawable *drawable);
void gimp_drawable_swap_pixels (GimpDrawable *drawable,
TileManager *tiles,
gboolean sparse,
GeglBuffer *buffer,
gint x,
gint y,
gint width,
@ -204,12 +201,11 @@ void gimp_drawable_swap_pixels (GimpDrawable *drawable,
void gimp_drawable_push_undo (GimpDrawable *drawable,
const gchar *undo_desc,
GeglBuffer *buffer,
gint x,
gint y,
gint width,
gint height,
TileManager *tiles,
gboolean sparse);
gint height);
void gimp_drawable_fill (GimpDrawable *drawable,
const GimpRGB *color,

View File

@ -25,6 +25,7 @@
#include "base/tile-manager.h"
#include "gimp-utils.h"
#include "gimpimage.h"
#include "gimpdrawable.h"
#include "gimpdrawableundo.h"
@ -33,8 +34,7 @@
enum
{
PROP_0,
PROP_TILES,
PROP_SPARSE,
PROP_BUFFER,
PROP_X,
PROP_Y,
PROP_WIDTH,
@ -83,17 +83,11 @@ gimp_drawable_undo_class_init (GimpDrawableUndoClass *klass)
undo_class->pop = gimp_drawable_undo_pop;
undo_class->free = gimp_drawable_undo_free;
g_object_class_install_property (object_class, PROP_TILES,
g_param_spec_boxed ("tiles", NULL, NULL,
GIMP_TYPE_TILE_MANAGER,
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class, PROP_SPARSE,
g_param_spec_boolean ("sparse", NULL, NULL,
FALSE,
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class, PROP_BUFFER,
g_param_spec_object ("buffer", NULL, NULL,
GEGL_TYPE_BUFFER,
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class, PROP_X,
g_param_spec_int ("x", NULL, NULL,
@ -134,7 +128,7 @@ gimp_drawable_undo_constructed (GObject *object)
G_OBJECT_CLASS (parent_class)->constructed (object);
g_assert (GIMP_IS_DRAWABLE (GIMP_ITEM_UNDO (object)->item));
g_assert (drawable_undo->tiles != NULL);
g_assert (drawable_undo->buffer != NULL);
}
static void
@ -147,11 +141,8 @@ gimp_drawable_undo_set_property (GObject *object,
switch (property_id)
{
case PROP_TILES:
drawable_undo->tiles = g_value_dup_boxed (value);
break;
case PROP_SPARSE:
drawable_undo->sparse = g_value_get_boolean (value);
case PROP_BUFFER:
drawable_undo->buffer = g_value_dup_object (value);
break;
case PROP_X:
drawable_undo->x = g_value_get_int (value);
@ -182,11 +173,8 @@ gimp_drawable_undo_get_property (GObject *object,
switch (property_id)
{
case PROP_TILES:
g_value_set_boxed (value, drawable_undo->tiles);
break;
case PROP_SPARSE:
g_value_set_boolean (value, drawable_undo->sparse);
case PROP_BUFFER:
g_value_set_object (value, drawable_undo->buffer);
break;
case PROP_X:
g_value_set_int (value, drawable_undo->x);
@ -214,8 +202,7 @@ gimp_drawable_undo_get_memsize (GimpObject *object,
GimpDrawableUndo *drawable_undo = GIMP_DRAWABLE_UNDO (object);
gint64 memsize = 0;
memsize += tile_manager_get_memsize (drawable_undo->tiles,
drawable_undo->sparse);
memsize += gimp_gegl_buffer_get_memsize (drawable_undo->buffer);
return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
gui_size);
@ -231,8 +218,7 @@ gimp_drawable_undo_pop (GimpUndo *undo,
GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum);
gimp_drawable_swap_pixels (GIMP_DRAWABLE (GIMP_ITEM_UNDO (undo)->item),
drawable_undo->tiles,
drawable_undo->sparse,
drawable_undo->buffer,
drawable_undo->x,
drawable_undo->y,
drawable_undo->width,
@ -245,10 +231,10 @@ gimp_drawable_undo_free (GimpUndo *undo,
{
GimpDrawableUndo *drawable_undo = GIMP_DRAWABLE_UNDO (undo);
if (drawable_undo->tiles)
if (drawable_undo->buffer)
{
tile_manager_unref (drawable_undo->tiles);
drawable_undo->tiles = NULL;
g_object_unref (drawable_undo->buffer);
drawable_undo->buffer = NULL;
}
if (drawable_undo->src2_tiles)

View File

@ -36,8 +36,7 @@ struct _GimpDrawableUndo
{
GimpItemUndo parent_instance;
TileManager *tiles;
gboolean sparse;
GeglBuffer *buffer;
gint x;
gint y;
gint width;

View File

@ -23,8 +23,6 @@
#include "core-types.h"
#include "base/tile-manager.h"
#include "gimp.h"
#include "gimpchannelpropundo.h"
#include "gimpchannelundo.h"
@ -211,8 +209,7 @@ GimpUndo *
gimp_image_undo_push_drawable (GimpImage *image,
const gchar *undo_desc,
GimpDrawable *drawable,
TileManager *tiles,
gboolean sparse,
GeglBuffer *buffer,
gint x,
gint y,
gint width,
@ -222,28 +219,17 @@ gimp_image_undo_push_drawable (GimpImage *image,
g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
g_return_val_if_fail (tiles != NULL, NULL);
g_return_val_if_fail (sparse == TRUE ||
tile_manager_width (tiles) == width, NULL);
g_return_val_if_fail (sparse == TRUE ||
tile_manager_height (tiles) == height, NULL);
g_return_val_if_fail (GEGL_IS_BUFFER (buffer), NULL);
item = GIMP_ITEM (drawable);
g_return_val_if_fail (gimp_item_is_attached (item), NULL);
g_return_val_if_fail (sparse == FALSE ||
tile_manager_width (tiles) == gimp_item_get_width (item),
NULL);
g_return_val_if_fail (sparse == FALSE ||
tile_manager_height (tiles) == gimp_item_get_height (item),
NULL);
return gimp_image_undo_push (image, GIMP_TYPE_DRAWABLE_UNDO,
GIMP_UNDO_DRAWABLE, undo_desc,
GIMP_DIRTY_ITEM | GIMP_DIRTY_DRAWABLE,
"item", item,
"tiles", tiles,
"sparse", sparse,
"buffer", buffer,
"x", x,
"y", y,
"width", width,

View File

@ -59,8 +59,7 @@ GimpUndo * gimp_image_undo_push_sample_point (GimpImage *image,
GimpUndo * gimp_image_undo_push_drawable (GimpImage *image,
const gchar *undo_desc,
GimpDrawable *drawable,
TileManager *tiles,
gboolean sparse,
GeglBuffer *buffer,
gint x,
gint y,
gint width,

View File

@ -579,15 +579,16 @@ gimp_image_map_commit (GimpImageMap *image_map)
/* Register an undo step */
if (image_map->undo_tiles)
{
gint x = image_map->undo_offset_x;
gint y = image_map->undo_offset_y;
gint width = tile_manager_width (image_map->undo_tiles);
gint height = tile_manager_height (image_map->undo_tiles);
GeglBuffer *buffer = gimp_image_map_get_buffer (GIMP_PICKABLE (image_map));
gint x = image_map->undo_offset_x;
gint y = image_map->undo_offset_y;
gint width = gegl_buffer_get_width (buffer);
gint height = gegl_buffer_get_height (buffer);
gimp_drawable_push_undo (image_map->drawable,
image_map->undo_desc,
x, y, width, height,
image_map->undo_tiles, FALSE);
buffer,
x, y, width, height);
tile_manager_unref (image_map->undo_tiles);
image_map->undo_tiles = NULL;

View File

@ -1369,10 +1369,10 @@ gimp_layer_create_mask (const GimpLayer *layer,
gimp_drawable_push_undo (drawable,
C_("undo-type", "Transfer Alpha to Mask"),
NULL,
0, 0,
gimp_item_get_width (item),
gimp_item_get_height (item),
NULL, FALSE);
gimp_item_get_height (item));
set_alpha = gegl_node_new_child (NULL,
"operation", "gimp:set-alpha",
@ -1565,10 +1565,10 @@ gimp_layer_apply_mask (GimpLayer *layer,
if (push_undo)
gimp_drawable_push_undo (GIMP_DRAWABLE (layer), NULL,
NULL,
0, 0,
gimp_item_get_width (item),
gimp_item_get_height (item),
NULL, FALSE);
gimp_item_get_height (item));
/* Combine the current layer's alpha channel and the mask */
mask_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask));

View File

@ -33,6 +33,8 @@
#include "paint-funcs/paint-funcs.h"
#include "gegl/gimp-gegl-utils.h"
#include "core/gimp.h"
#include "core/gimp-utils.h"
#include "core/gimpdrawable.h"
@ -456,16 +458,42 @@ gimp_paint_core_finish (GimpPaintCore *core,
if (push_undo)
{
GeglBuffer *src;
GeglBuffer *buffer;
gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_PAINT,
core->undo_desc);
GIMP_PAINT_CORE_GET_CLASS (core)->push_undo (core, image, NULL);
/* set undo blocks */
gimp_paint_core_validate_undo_tiles (core, drawable,
core->x1,
core->y1,
core->x2 - core->x1,
core->y2 - core->y1);
src = gimp_tile_manager_create_buffer (core->undo_tiles,
gimp_drawable_get_format (drawable));
buffer = gimp_gegl_buffer_new (GIMP_GEGL_RECT (0, 0,
core->x2 - core->x1,
core->y2 - core->y1),
gimp_drawable_get_format (drawable));
gegl_buffer_copy (src,
GIMP_GEGL_RECT (core->x1, core->y1,
core->x2 - core->x1,
core->y2 - core->y1),
buffer,
GIMP_GEGL_RECT (0, 0, 0, 0));
gimp_drawable_push_undo (drawable, NULL,
buffer,
core->x1, core->y1,
core->x2 - core->x1, core->y2 - core->y1,
core->undo_tiles,
TRUE);
core->x2 - core->x1, core->y2 - core->y1);
g_object_unref (src);
g_object_unref (buffer);
gimp_image_undo_group_end (image);
}

View File

@ -91,8 +91,7 @@ static void gimp_text_layer_set_buffer (GimpDrawable *drawable,
gint offset_y);
static void gimp_text_layer_push_undo (GimpDrawable *drawable,
const gchar *undo_desc,
TileManager *tiles,
gboolean sparse,
GeglBuffer *buffer,
gint x,
gint y,
gint width,
@ -334,8 +333,7 @@ gimp_text_layer_set_buffer (GimpDrawable *drawable,
static void
gimp_text_layer_push_undo (GimpDrawable *drawable,
const gchar *undo_desc,
TileManager *tiles,
gboolean sparse,
GeglBuffer *buffer,
gint x,
gint y,
gint width,
@ -348,7 +346,7 @@ gimp_text_layer_push_undo (GimpDrawable *drawable,
gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_DRAWABLE, undo_desc);
GIMP_DRAWABLE_CLASS (parent_class)->push_undo (drawable, undo_desc,
tiles, sparse,
buffer,
x, y, width, height);
if (! layer->modified)