Commit 6d2a6d5e authored by Michael Natterer's avatar Michael Natterer 😴 Committed by Michael Natterer

Abstract the legacy projection code away into a virtual function of

2008-11-08  Michael Natterer  <mitch@gimp.org>

	Abstract the legacy projection code away into a virtual function
	of GimpDrawable:

	* app/core/gimpdrawable.[ch]: add new virtual function
	GimpDrawable::project_region() which projects an area of a
	drawable onto a passed in PixelRegion.

	* app/core/Makefile.am
	* app/core/gimpchannel-project.[ch]
	* app/core/gimplayer-project.[ch]: new files which implement it.

	* app/core/gimpchannel.c
	* app/core/gimplayer.c: hook it in.

	* app/core/gimpprojection-construct.c: get rid all the projection
	code moved to above new files and project all drawables in one
	loop.

	* app/core/gimpprojectable.[ch]: remove the legacy methods
	get_colormap() and get_components(), they are not needed any
	longer.

	* app/core/gimpimage.c: changed accordingly.


svn path=/trunk/; revision=27571
parent f8666de7
2008-11-08 Michael Natterer <mitch@gimp.org>
Abstract the legacy projection code away into a virtual function
of GimpDrawable:
* app/core/gimpdrawable.[ch]: add new virtual function
GimpDrawable::project_region() which projects an area of a
drawable onto a passed in PixelRegion.
* app/core/Makefile.am
* app/core/gimpchannel-project.[ch]
* app/core/gimplayer-project.[ch]: new files which implement it.
* app/core/gimpchannel.c
* app/core/gimplayer.c: hook it in.
* app/core/gimpprojection-construct.c: get rid all the projection
code moved to above new files and project all drawables in one
loop.
* app/core/gimpprojectable.[ch]: remove the legacy methods
get_colormap() and get_components(), they are not needed any
longer.
* app/core/gimpimage.c: changed accordingly.
2008-11-07 Sven Neumann <sven@gimp.org>
* app/core/gimppalette-load.c (gimp_palette_load_aco): improved
......
......@@ -74,6 +74,8 @@ libappcore_a_sources = \
gimpchannel.h \
gimpchannel-combine.c \
gimpchannel-combine.h \
gimpchannel-project.c \
gimpchannel-project.h \
gimpchannel-select.c \
gimpchannel-select.h \
gimpchannelpropundo.c \
......@@ -252,6 +254,8 @@ libappcore_a_sources = \
gimplayer.h \
gimplayer-floating-sel.c \
gimplayer-floating-sel.h \
gimplayer-project.c \
gimplayer-project.h \
gimplayermask.c \
gimplayermask.h \
gimplayermaskpropundo.c \
......
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpchannel-project.h
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <gegl.h>
#include "libgimpcolor/gimpcolor.h"
#include "core-types.h"
#include "base/pixel-region.h"
#include "paint-funcs/paint-funcs.h"
#include "gimpchannel.h"
#include "gimpchannel-project.h"
void
gimp_channel_project_region (GimpDrawable *drawable,
gint x,
gint y,
gint width,
gint height,
PixelRegion *projPR,
gboolean combine)
{
GimpChannel *channel = GIMP_CHANNEL (drawable);
PixelRegion srcPR;
guchar col[3];
guchar opacity;
gimp_rgba_get_uchar (&channel->color,
&col[0], &col[1], &col[2], &opacity);
pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
x, y, width, height,
FALSE);
if (combine)
{
combine_regions (projPR, &srcPR, projPR, NULL, col,
opacity,
GIMP_NORMAL_MODE,
NULL,
(gimp_channel_get_show_masked (channel) ?
COMBINE_INTEN_A_CHANNEL_MASK :
COMBINE_INTEN_A_CHANNEL_SELECTION));
}
else
{
initial_region (projPR, &srcPR, NULL, col,
opacity,
GIMP_NORMAL_MODE,
NULL,
(gimp_channel_get_show_masked (channel) ?
INITIAL_CHANNEL_MASK :
INITIAL_CHANNEL_SELECTION));
}
}
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpchannel-project.h
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GIMP_CHANNEL_PROJECT_H__
#define __GIMP_CHANNEL_PROJECT_H__
void gimp_channel_project_region (GimpDrawable *drawable,
gint x,
gint y,
gint width,
gint height,
PixelRegion *projPR,
gboolean combine);
#endif /* __GIMP_CHANNEL_PROJECT_H__ */
......@@ -48,6 +48,7 @@
#include "gimpimage-undo.h"
#include "gimpimage-undo-push.h"
#include "gimpchannel.h"
#include "gimpchannel-project.h"
#include "gimpcontext.h"
#include "gimpdrawable-stroke.h"
#include "gimpmarshal.h"
......@@ -278,6 +279,7 @@ gimp_channel_class_init (GimpChannelClass *klass)
drawable_class->get_active_components = gimp_channel_get_active_components;
drawable_class->apply_region = gimp_channel_apply_region;
drawable_class->replace_region = gimp_channel_replace_region;
drawable_class->project_region = gimp_channel_project_region;
drawable_class->set_tiles = gimp_channel_set_tiles;
drawable_class->swap_pixels = gimp_channel_swap_pixels;
......
......@@ -1039,6 +1039,24 @@ gimp_drawable_replace_region (GimpDrawable *drawable,
x, y);
}
void
gimp_drawable_project_region (GimpDrawable *drawable,
gint x,
gint y,
gint width,
gint height,
PixelRegion *projPR,
gboolean combine)
{
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
g_return_if_fail (projPR != NULL);
GIMP_DRAWABLE_GET_CLASS (drawable)->project_region (drawable,
x, y, width, height,
projPR, combine);
}
TileManager *
gimp_drawable_get_tiles (GimpDrawable *drawable)
{
......
......@@ -89,6 +89,13 @@ struct _GimpDrawableClass
PixelRegion *maskPR,
gint x,
gint y);
void (* project_region) (GimpDrawable *drawable,
gint x,
gint y,
gint width,
gint height,
PixelRegion *projPR,
gboolean combine);
TileManager * (* get_tiles) (GimpDrawable *drawable);
void (* set_tiles) (GimpDrawable *drawable,
gboolean push_undo,
......@@ -158,6 +165,13 @@ void gimp_drawable_replace_region (GimpDrawable *drawable,
PixelRegion *maskPR,
gint x,
gint y);
void gimp_drawable_project_region (GimpDrawable *drawable,
gint x,
gint y,
gint width,
gint height,
PixelRegion *projPR,
gboolean combine);
TileManager * gimp_drawable_get_tiles (GimpDrawable *drawable);
void gimp_drawable_set_tiles (GimpDrawable *drawable,
......
......@@ -174,7 +174,6 @@ static void gimp_image_projectable_flush (GimpProjectable *projectable
gboolean invalidate_preview);
static GeglNode * gimp_image_get_graph (GimpProjectable *projectable);
static GimpImage * gimp_image_get_image (GimpProjectable *projectable);
static gboolean * gimp_image_get_components (GimpProjectable *projectable);
static void gimp_image_mask_update (GimpDrawable *drawable,
gint x,
......@@ -570,8 +569,6 @@ gimp_projectable_iface_init (GimpProjectableInterface *iface)
iface->invalidate_preview = (void (*) (GimpProjectable*)) gimp_viewable_invalidate_preview;
iface->get_layers = (GList * (*) (GimpProjectable*)) gimp_image_get_layer_iter;
iface->get_channels = (GList * (*) (GimpProjectable*)) gimp_image_get_channel_iter;
iface->get_components = gimp_image_get_components;
iface->get_colormap = (const guchar * (*) (GimpProjectable*)) gimp_image_get_colormap;
}
static void
......@@ -1196,14 +1193,6 @@ gimp_image_get_image (GimpProjectable *projectable)
return GIMP_IMAGE (projectable);
}
static gboolean *
gimp_image_get_components (GimpProjectable *projectable)
{
GimpImage *image = GIMP_IMAGE (projectable);
return image->visible;
}
static GeglNode *
gimp_image_get_graph (GimpProjectable *projectable)
{
......
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimplayer-project.h
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <gegl.h>
#include "core-types.h"
#include "base/pixel-region.h"
#include "paint-funcs/paint-funcs.h"
#include "gimpimage.h"
#include "gimpimage-colormap.h"
#include "gimplayer.h"
#include "gimplayer-project.h"
#include "gimplayermask.h"
void
gimp_layer_project_region (GimpDrawable *drawable,
gint x,
gint y,
gint width,
gint height,
PixelRegion *projPR,
gboolean combine)
{
GimpLayer *layer = GIMP_LAYER (drawable);
GimpLayerMask *mask = gimp_layer_get_mask (layer);
if (mask && gimp_layer_mask_get_show (mask))
{
/* If we're showing the layer mask instead of the layer... */
PixelRegion srcPR;
pixel_region_init (&srcPR,
gimp_drawable_get_tiles (GIMP_DRAWABLE (mask)),
x, y, width, height,
FALSE);
copy_gray_to_region (&srcPR, projPR);
}
else
{
/* Otherwise, normal */
GimpImage *image = gimp_item_get_image (GIMP_ITEM (layer));
PixelRegion srcPR;
PixelRegion maskPR;
PixelRegion *mask_pr = NULL;
const guchar *colormap = NULL;
InitialMode initial_mode;
CombinationMode combination_mode;
pixel_region_init (&srcPR,
gimp_drawable_get_tiles (drawable),
x, y, width, height,
FALSE);
if (mask && gimp_layer_mask_get_apply (mask))
{
pixel_region_init (&maskPR,
gimp_drawable_get_tiles (GIMP_DRAWABLE (mask)),
x, y, width, height,
FALSE);
mask_pr = &maskPR;
}
/* Based on the type of the layer, project the layer onto the
* projection image...
*/
switch (gimp_drawable_type (drawable))
{
case GIMP_RGB_IMAGE:
case GIMP_GRAY_IMAGE:
initial_mode = INITIAL_INTENSITY;
combination_mode = COMBINE_INTEN_A_INTEN;
break;
case GIMP_RGBA_IMAGE:
case GIMP_GRAYA_IMAGE:
initial_mode = INITIAL_INTENSITY_ALPHA;
combination_mode = COMBINE_INTEN_A_INTEN_A;
break;
case GIMP_INDEXED_IMAGE:
colormap = gimp_image_get_colormap (image),
initial_mode = INITIAL_INDEXED;
combination_mode = COMBINE_INTEN_A_INDEXED;
break;
case GIMP_INDEXEDA_IMAGE:
colormap = gimp_image_get_colormap (image),
initial_mode = INITIAL_INDEXED_ALPHA;
combination_mode = COMBINE_INTEN_A_INDEXED_A;
break;
default:
g_assert_not_reached ();
break;
}
if (combine)
{
combine_regions (projPR, &srcPR, projPR, mask_pr,
colormap,
gimp_layer_get_opacity (layer) * 255.999,
gimp_layer_get_mode (layer),
image->visible,
combination_mode);
}
else
{
initial_region (&srcPR, projPR, mask_pr,
colormap,
gimp_layer_get_opacity (layer) * 255.999,
gimp_layer_get_mode (layer),
image->visible,
initial_mode);
}
}
}
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimplayer-project.h
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GIMP_LAYER_PROJECT_H__
#define __GIMP_LAYER_PROJECT_H__
void gimp_layer_project_region (GimpDrawable *drawable,
gint x,
gint y,
gint width,
gint height,
PixelRegion *projPR,
gboolean combine);
#endif /* __GIMP_LAYER_PROJECT_H__ */
......@@ -46,6 +46,7 @@
#include "gimpimage.h"
#include "gimplayer-floating-sel.h"
#include "gimplayer.h"
#include "gimplayer-project.h"
#include "gimplayermask.h"
#include "gimpmarshal.h"
#include "gimppickable.h"
......@@ -275,6 +276,7 @@ gimp_layer_class_init (GimpLayerClass *klass)
drawable_class->estimate_memsize = gimp_layer_estimate_memsize;
drawable_class->invalidate_boundary = gimp_layer_invalidate_boundary;
drawable_class->get_active_components = gimp_layer_get_active_components;
drawable_class->project_region = gimp_layer_project_region;
drawable_class->set_tiles = gimp_layer_set_tiles;
klass->opacity_changed = NULL;
......
......@@ -242,33 +242,3 @@ gimp_projectable_get_channels (GimpProjectable *projectable)
return NULL;
}
gboolean *
gimp_projectable_get_components (GimpProjectable *projectable)
{
GimpProjectableInterface *iface;
g_return_val_if_fail (GIMP_IS_PROJECTABLE (projectable), NULL);
iface = GIMP_PROJECTABLE_GET_INTERFACE (projectable);
if (iface->get_components)
return iface->get_components (projectable);
return NULL;
}
const guchar *
gimp_projectable_get_colormap (GimpProjectable *projectable)
{
GimpProjectableInterface *iface;
g_return_val_if_fail (GIMP_IS_PROJECTABLE (projectable), NULL);
iface = GIMP_PROJECTABLE_GET_INTERFACE (projectable);
if (iface->get_colormap)
return iface->get_colormap (projectable);
return NULL;
}
......@@ -56,8 +56,6 @@ struct _GimpProjectableInterface
/* legacy API virtual functions */
GList * (* get_layers) (GimpProjectable *projectable);
GList * (* get_channels) (GimpProjectable *projectable);
gboolean * (* get_components) (GimpProjectable *projectable);
const guchar * (* get_colormap) (GimpProjectable *projectable);
};
......@@ -82,8 +80,6 @@ void gimp_projectable_invalidate_preview (GimpProjectable *projectable
/* legacy API */
GList * gimp_projectable_get_layers (GimpProjectable *projectable);
GList * gimp_projectable_get_channels (GimpProjectable *projectable);
gboolean * gimp_projectable_get_components (GimpProjectable *projectable);
const guchar * gimp_projectable_get_colormap (GimpProjectable *projectable);
#endif /* __GIMP_PROJECTABLE_H__ */
......@@ -20,8 +20,6 @@
#include <gegl.h>
#include "libgimpcolor/gimpcolor.h"
#include "core-types.h"
#include "base/pixel-region.h"
......@@ -31,7 +29,6 @@
#include "gimplayer.h"
#include "gimplayer-floating-sel.h"
#include "gimplayermask.h"
#include "gimppickable.h"
#include "gimpprojectable.h"
#include "gimpprojection.h"
......@@ -40,51 +37,22 @@
/* local function prototypes */
static void gimp_projection_construct_gegl (GimpProjection *proj,
gint x,
gint y,
gint w,
gint h);
static void gimp_projection_construct_layers (GimpProjection *proj,
gint x,
gint y,
gint w,
gint h);
static void gimp_projection_construct_channels (GimpProjection *proj,
gint x,
gint y,
gint w,
gint h);
static void gimp_projection_initialize (GimpProjection *proj,
gint x,
gint y,
gint w,
gint h);
static void project_intensity (GimpProjection *proj,
GimpLayer *layer,
PixelRegion *src,
PixelRegion *dest,
PixelRegion *mask);
static void project_intensity_alpha (GimpProjection *proj,
GimpLayer *layer,
PixelRegion *src,
PixelRegion *dest,
PixelRegion *mask);
static void project_indexed (GimpProjection *proj,
GimpLayer *layer,
PixelRegion *src,
PixelRegion *dest,
PixelRegion *mask);
static void project_indexed_alpha (GimpProjection *proj,
GimpLayer *layer,
PixelRegion *src,
PixelRegion *dest,
PixelRegion *mask);
static void project_channel (GimpProjection *proj,
GimpChannel *channel,
PixelRegion *src,
PixelRegion *src2);
static void gimp_projection_construct_gegl (GimpProjection *proj,
gint x,
gint y,
gint w,
gint h);
static void gimp_projection_construct_legacy (GimpProjection *proj,
gboolean with_layers,
gint x,
gint y,
gint w,
gint h);
static void gimp_projection_initialize (GimpProjection *proj,
gint x,
gint y,
gint w,
gint h);
/* public functions */
......@@ -137,7 +105,7 @@ gimp_projection_construct (GimpProjection *proj,
proj->construct_flag = TRUE;
gimp_projection_construct_channels (proj, x, y, w, h);
gimp_projection_construct_legacy (proj, FALSE, x, y, w, h);
return;
}
......@@ -162,8 +130,7 @@ gimp_projection_construct (GimpProjection *proj,
{
proj->construct_flag = FALSE;
gimp_projection_construct_layers (proj, x, y, w, h);
gimp_projection_construct_channels (proj, x, y, w, h);
gimp_projection_construct_legacy (proj, TRUE, x, y, w, h);
}
}
......@@ -196,170 +163,78 @@ gimp_projection_construct_gegl (GimpProjection *proj,
}
static void
gimp_projection_construct_layers (GimpProjection *proj,
gimp_projection_construct_legacy (GimpProjection *proj,
gboolean with_layers,
gint x,
gint y,
gint w,
gint h)
{
GimpLayer *layer;
GList *list;
GList *reverse_list = NULL;
gint x1, y1, x2, y2;
gint off_x;
gint off_y;
GList *list;
GList *reverse_list = NULL;
for (list = gimp_projectable_get_layers (proj->projectable);
for (list = gimp_projectable_get_channels (proj->projectable);
list;
list = g_list_next (list))
{
layer = list->data;
if (gimp_layer_is_floating_sel (layer))
if (gimp_item_get_visible (GIMP_ITEM (list->data)))
{
/* composite the floating selection if it exists
*/
floating_sel_composite (layer, x, y, w, h, FALSE);
}
else if (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);
reverse_list = g_list_prepend (reverse_list, list->data);
}
}
for (list = reverse_list; list; list = g_list_next (list))
if (with_layers)
{
GimpLayerMask *mask;
PixelRegion src1PR;
PixelRegion src2PR;
PixelRegion maskPR;
layer = list->data;
mask = gimp_layer_get_mask (layer);
gimp_item_get_offset (GIMP_ITEM (layer), &off_x, &off_y);
x1 = CLAMP (off_x, x, x + w);
y1 = CLAMP (off_y, y, y + h);
x2 = CLAMP (off_x + gimp_item_get_width (GIMP_ITEM (layer)), x, x + w);
y2 = CLAMP (off_y + gimp_item_get_height (GIMP_ITEM (layer)), y, y + h);
/* configure the pixel regions */
pixel_region_init (&src1PR,
gimp_pickable_get_tiles (GIMP_PICKABLE (proj)),
x1, y1, (x2 - x1), (y2 - y1),
TRUE);
/* If we're showing the layer mask instead of the layer... */
if (mask && gimp_layer_mask_get_show (mask))
{
pixel_region_init (&src2PR,
gimp_drawable_get_tiles (GIMP_DRAWABLE (mask)),
x1 - off_x, y1 - off_y,
x2 - x1, y2 - y1,
FALSE);
copy_gray_to_region (&src2PR, &src1PR);
}
/* Otherwise, normal */
else
for (list = gimp_projectable_get_layers (proj->projectable);
list;
list = g_list_next (list))
{
PixelRegion *mask_pr = NULL;
pixel_region_init (&src2PR,
gimp_drawable_get_tiles (GIMP_DRAWABLE (layer)),
x1 - off_x, y1 - off_y,
x2 - x1, y2 - y1,
FALSE);
GimpLayer *layer = list->data;
if (mask && gimp_layer_mask_get_apply (mask))
if (gimp_layer_is_floating_sel (layer))
{
pixel_region_init (&maskPR,
gimp_drawable_get_tiles (GIMP_DRAWABLE (mask)),
x1 - off_x, y1 - off_y,
x2 - x1, y2 - y1,
FALSE);
mask_pr = &maskPR;
/* composite the floating selection if it exists
*/
floating_sel_composite (layer, x, y, w, h, FALSE);
}
/* Based on the type of the layer, project the layer onto the
* projection image...
*/
switch (gimp_drawable_type (GIMP_DRAWABLE (layer)))
else if (gimp_item_get_visible (GIMP_ITEM (layer)))
{
case GIMP_RGB_IMAGE:
case GIMP_GRAY_IMAGE:
project_intensity (proj, layer, &src2PR, &src1PR, mask_pr);
break;
case GIMP_RGBA_IMAGE:
case GIMP_GRAYA_IMAGE:
project_intensity_alpha (proj, layer, &src2PR, &src1PR, mask_pr);
break;
case GIMP_INDEXED_IMAGE:
project_indexed (proj, layer, &src2PR, &src1PR, mask_pr);
break;