Gimp/app/core/gimpprojection-construct.c

325 lines
10 KiB
C
Raw Normal View History

/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gegl.h>
#include "core-types.h"
new directory app/base/ 2001-05-15 Michael Natterer <mitch@gimp.org> * configure.in: new directory app/base/ * app/Makefile.am * app/boundary.[ch] * app/brush_scale.[ch] * app/gimpchecks.h * app/gimplut.[ch] * app/pixel_processor.[ch] * app/pixel_region.[ch] * app/pixel_surround.[ch] * app/temp_buf.[ch] * app/tile.[ch] * app/tile_cache.[ch] * app/tile_manager.[ch] * app/tile_manager_pvt.h * app/tile_pvt.h * app/tile_swap.[ch]: moved to base/ * app/base/Makefile.am * app/base/base-types.h * app/base/*: new directory for the sub-object pixel maniplation and storage stuff. Does not include Gtk+ or anything outside base/. Did some cleanup in all files. * app/appenums.h * app/apptypes.h * app/core/gimpimage.h: removed types which are now in base/base-types.h. * app/base/base-config.[ch] * app/gimprc.[ch]: put the config variables for base/ to their own file so base/ doesn not have to include gimprc.h (does not yet work, i.e. the variables are un-configurable right now) * app/main.c: set a log handler for "Gimp-Base". * app/paint-funcs/Makefile.am * app/paint-funcs/paint-funcs.[ch]: removed the color hash which maps RGB to color indices because it's a totally standalone system which has nothing to do with the paint-funcs and introduced a GimpImage dependency. paint-funcs/ should be considered on the same sub-object (glib-only) level as base/, only in a different directory. * app/core/Makefile.am * app/core/gimpimage-colorhash.[ch]: put the color hash here. * app/gimage.c: don't invalidate the color hash here... * app/core/gimpimage.c: ... but in the colormap_changed() default inplementation. Initialize the hash in class_init(). * tools/pdbgen/Makefile.am: scan app/base/base-types.h for enums. * tools/pdbgen/enums.pl: regenerated. * app/[lots] * app/core/[of] * app/gui/[files] * app/pdb/[all] * app/tools/[over] * app/widgets/[the] * tools/pdbgen/pdb/[place]: changed #includes accordingly. And use base_config->value instead of the stuff from gimprc.h.
2001-05-15 04:25:25 -07:00
#include "base/pixel-region.h"
#include "base/tile-manager.h"
#include "paint-funcs/paint-funcs.h"
#include "gimplayer.h"
#include "gimppickable.h"
#include "gimpprojectable.h"
2004-07-13 09:36:29 -07:00
#include "gimpprojection.h"
#include "gimpprojection-construct.h"
app/core/Makefile.am app/core/core-types.h added an "application object" 2001-07-04 Michael Natterer <mitch@gimp.org> * app/core/Makefile.am * app/core/core-types.h * app/core/gimp.[ch]: added an "application object" called Gimp. Currently, it contains the image list, the clipboard, the data factories, the procedural hashtable and the tool info list. It's the toplevel object of the core object system. Finally, creating a Gimp object will return a standalone gimp core engine instance with no other global states/variables involved. * app/app_procs.[ch]: allocate a "Gimp" instance called "the_gimp" :) Removed stuff which is now done by the "Gimp" object. Merged gimp_init() into app_init() because gimp_init() is taken now. * app/context_manager.[ch]: removed stuff done by "Gimp". * app/batch.[ch] * app/gimage.[ch] * app/xcf/xcf-load.[ch] * app/xcf/xcf.[ch] * app/core/gimpedit.[ch] * app/tools/tool_manager.[ch]: pass around an additional "Gimp" argument. * app/pdb/procedural_db.[ch]: pass a "Gimp" pointer as first parameter to all internal procedures and to all procedural_db_* functions. * app/core/gimpcontext.[ch] * app/core/gimpimage.[ch]: added a "Gimp" pointer to the structs. * app/devices.c * app/errors.c * app/file-open.c * app/file-save.c * app/gimphelp.c * app/gimpunit.c * app/image_new.c * app/main.c * app/nav_window.c * app/plug_in.c * app/base/base.c * app/core/gimpdatafactory.c * app/core/gimpimage-duplicate.c * app/core/gimpimage-mask.c * app/core/gimptoolinfo.[ch] * app/gui/brush-select.c * app/gui/convert-dialog.c * app/gui/dialogs-constructors.c * app/gui/edit-commands.c * app/gui/file-open-dialog.c * app/gui/file-save-dialog.c * app/gui/gradient-editor.c * app/gui/gradient-select.c * app/gui/gui.c * app/gui/image-commands.c * app/gui/info-window.c * app/gui/menus.c * app/gui/palette-editor.c * app/gui/palette-import-dialog.c * app/gui/palette-select.c * app/gui/paths-dialog.c * app/gui/pattern-select.c * app/gui/preferences-dialog.c * app/gui/test-commands.c * app/gui/toolbox.c * app/gui/tools-commands.c * app/tools/gimpbezierselecttool.c * app/tools/gimpbucketfilltool.c * app/tools/gimppainttool.h * app/tools/gimptexttool.c * app/tools/gimptransformtool.h * app/widgets/gimpbufferview.c * app/widgets/gimpcontainerview-utils.c * app/widgets/gimpcursor.c * app/widgets/gimpdnd.c * app/widgets/gimpimagedock.c: changed accordingly. Cleaned up lots of includes. Many files still access the global "the_gimp" variable exported by app_procs.h. * tools/pdbgen/app.pl * tools/pdbgen/pdb/brush_select.pdb * tools/pdbgen/pdb/brushes.pdb * tools/pdbgen/pdb/convert.pdb * tools/pdbgen/pdb/edit.pdb * tools/pdbgen/pdb/fileops.pdb * tools/pdbgen/pdb/gradient_select.pdb * tools/pdbgen/pdb/gradients.pdb * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/palette.pdb * tools/pdbgen/pdb/pattern_select.pdb * tools/pdbgen/pdb/patterns.pdb * tools/pdbgen/pdb/procedural_db.pdb: changed accordingly. Don't use "the_gimp" here because all procedures get passed a "Gimp" pointer now. * app/pdb/*: regenerated.
2001-07-04 12:31:35 -07:00
new directory app/base/ 2001-05-15 Michael Natterer <mitch@gimp.org> * configure.in: new directory app/base/ * app/Makefile.am * app/boundary.[ch] * app/brush_scale.[ch] * app/gimpchecks.h * app/gimplut.[ch] * app/pixel_processor.[ch] * app/pixel_region.[ch] * app/pixel_surround.[ch] * app/temp_buf.[ch] * app/tile.[ch] * app/tile_cache.[ch] * app/tile_manager.[ch] * app/tile_manager_pvt.h * app/tile_pvt.h * app/tile_swap.[ch]: moved to base/ * app/base/Makefile.am * app/base/base-types.h * app/base/*: new directory for the sub-object pixel maniplation and storage stuff. Does not include Gtk+ or anything outside base/. Did some cleanup in all files. * app/appenums.h * app/apptypes.h * app/core/gimpimage.h: removed types which are now in base/base-types.h. * app/base/base-config.[ch] * app/gimprc.[ch]: put the config variables for base/ to their own file so base/ doesn not have to include gimprc.h (does not yet work, i.e. the variables are un-configurable right now) * app/main.c: set a log handler for "Gimp-Base". * app/paint-funcs/Makefile.am * app/paint-funcs/paint-funcs.[ch]: removed the color hash which maps RGB to color indices because it's a totally standalone system which has nothing to do with the paint-funcs and introduced a GimpImage dependency. paint-funcs/ should be considered on the same sub-object (glib-only) level as base/, only in a different directory. * app/core/Makefile.am * app/core/gimpimage-colorhash.[ch]: put the color hash here. * app/gimage.c: don't invalidate the color hash here... * app/core/gimpimage.c: ... but in the colormap_changed() default inplementation. Initialize the hash in class_init(). * tools/pdbgen/Makefile.am: scan app/base/base-types.h for enums. * tools/pdbgen/enums.pl: regenerated. * app/[lots] * app/core/[of] * app/gui/[files] * app/pdb/[all] * app/tools/[over] * app/widgets/[the] * tools/pdbgen/pdb/[place]: changed #includes accordingly. And use base_config->value instead of the stuff from gimprc.h.
2001-05-15 04:25:25 -07:00
/* local function prototypes */
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 */
void
2004-07-13 09:36:29 -07:00
gimp_projection_construct (GimpProjection *proj,
gint x,
gint y,
gint w,
gint h)
{
2004-07-13 09:36:29 -07:00
g_return_if_fail (GIMP_IS_PROJECTION (proj));
2004-07-13 09:36:29 -07:00
#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;
}
2004-07-13 09:36:29 -07:00
}
#endif
2004-07-13 09:36:29 -07:00
/* 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
*/
2004-07-13 09:36:29 -07:00
gimp_projection_initialize (proj, x, y, w, h);
2004-07-13 09:36:29 -07:00
/* 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);
}
}
/* private functions */
static void
gimp_projection_construct_gegl (GimpProjection *proj,
gint x,
gint y,
gint w,
gint h)
{
GeglNode *sink;
GeglRectangle rect;
sink = gimp_projection_get_sink_node (proj);
rect.x = x;
rect.y = y;
rect.width = w;
rect.height = h;
if (! proj->processor)
proj->processor = gegl_node_new_processor (sink, &rect);
else
gegl_processor_set_rectangle (proj->processor, &rect);
while (gegl_processor_work (proj->processor, NULL));
/* FIXME: Reuse it when it can handle dirty rects when painting
* properly
*/
g_object_unref (proj->processor);
proj->processor = NULL;
}
static void
gimp_projection_construct_legacy (GimpProjection *proj,
gboolean with_layers,
2004-07-13 09:36:29 -07:00
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;
Bye bye floating_sel_rigor() and floating_sel_relax(): 2008-11-09 Michael Natterer <mitch@gimp.org> Bye bye floating_sel_rigor() and floating_sel_relax(): * app/core/gimpdrawable.[ch] (gimp_drawable_init_src_region): implement compositing the floating selection on the fly. Add return parameter "TileManager **temp_tiles" which returns the temp buffer used for compositing; the caller has to unref the tiles. * app/core/gimpchannel-project.c * app/core/gimplayer-project.c: unref the temp_tiles. * app/core/gimplayer.[ch]: remove members fs.backing_store and fs.initial. * app/core/gimplayer-floating-sel.[ch]: remove functions rigor(), relax(), store() and restore(), they are not needed any longer. Some minor cleanup, more to come. * app/core/gimpprojection-construct.c: don't composite the floating selection before projecting because that happens on the fly now. * app/core/core-enums.[ch] * app/core/gimpfloatingselundo.c * app/core/gimpimage-undo-push.[ch]: remove the rigor and relax undos. * app/core/gimpdrawable.c * app/core/gimpimage-convert.c * app/core/gimpimage-duplicate.c * app/core/gimpimage.c * app/core/gimplayer.c * app/xcf/xcf-save.c: remove all calls to rigor and relax and all implementations of virtual functions that were just there to rigor/releax around chaining up. * tools/pdbgen/pdb/floating_sel.pdb: remove all code from the rigor and relax wrappers and deprecate the API. * app/pdb/floating-sel-cmds.c * libgimp/gimpfloatingsel_pdb.[ch]: regenerated. * plug-ins/file-xjt/xjt.c: don't call rigor and relax. svn path=/trunk/; revision=27579
2008-11-09 08:49:37 -08:00
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);
}
/**
* 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
2004-07-13 09:36:29 -07:00
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);
removed gimp_drawable_offsets(). 2003-05-08 Michael Natterer <mitch@gimp.org> * app/core/gimpdrawable.[ch]: removed gimp_drawable_offsets(). * app/core/gimpitem.[ch]: added gimp_item_offsets(). * app/core/gimpdrawable-blend.c * app/core/gimpdrawable-bucket-fill.c * app/core/gimpdrawable-histogram.c * app/core/gimpedit.c * app/core/gimpimage-convert.c * app/core/gimpimage-crop.c * app/core/gimpimage-mask-select.c * app/core/gimpimage-mask.c * app/core/gimpimage-merge.c * app/core/gimpimage-pick-color.c * app/core/gimpimage-preview.c * app/core/gimpimage-projection.c * app/core/gimpimage-undo-push.c * app/core/gimpimage.c * app/core/gimplayer-floating-sel.c * app/core/gimplayer.c * app/display/gimpdisplay.c * app/display/gimpdisplayshell-transform.c * app/display/gimpdisplayshell.c * app/gui/channels-commands.c * app/gui/layers-commands.c * app/paint/gimppaintcore.c * app/tools/gimpbezierselecttool.c * app/tools/gimpblendtool.c * app/tools/gimpbucketfilltool.c * app/tools/gimpbycolorselecttool.c * app/tools/gimpclonetool.c * app/tools/gimpcolorpickertool.c * app/tools/gimpcroptool.c * app/tools/gimpcurvestool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpfliptool.c * app/tools/gimpfuzzyselecttool.c * app/tools/gimpinktool.c * app/tools/gimplevelstool.c * app/tools/gimppainttool.c * app/tools/gimprectselecttool.c * app/tools/gimptransformtool.c * app/widgets/gimpselectioneditor.c * app/widgets/gimptoolbox.c * tools/pdbgen/pdb/color.pdb * tools/pdbgen/pdb/drawable.pdb: changed accordingly. * app/pdb/color_cmds.c * app/pdb/drawable_cmds.c: regenerated.
2003-05-08 07:06:03 -07:00
/* 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;
2004-07-13 09:36:29 -07:00
pixel_region_init (&region,
gimp_pickable_get_tiles (GIMP_PICKABLE (proj)),
x, y, w, h, TRUE);
clear_region (&region);
}
}