2000-05-31 14:15:06 +08:00
|
|
|
/* LIBGIMP - The GIMP Library
|
|
|
|
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
|
|
|
*
|
|
|
|
* gimppixelrgn.c
|
1998-01-25 18:26:47 +08:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
1999-11-18 05:13:50 +08:00
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
1998-01-25 18:26:47 +08:00
|
|
|
* License as published by the Free Software Foundation; either
|
2000-05-31 14:15:06 +08:00
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library 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
|
1998-01-25 18:26:47 +08:00
|
|
|
* Library General Public License for more details.
|
|
|
|
*
|
1999-11-18 05:13:50 +08:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
1998-04-13 13:44:11 +08:00
|
|
|
* License along with this library; if not, write to the
|
|
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 02111-1307, USA.
|
2000-05-31 14:15:06 +08:00
|
|
|
*/
|
1998-01-25 18:26:47 +08:00
|
|
|
|
2002-05-14 07:30:23 +08:00
|
|
|
#include "config.h"
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Experimental: comment-out the following #define if a memcpy() call is
|
|
|
|
slower than compiler-optimized memory copies for transfers of approx.
|
|
|
|
64-256 bytes.
|
|
|
|
|
|
|
|
FYI this #define is a win on Linux486/libc5. Unbenchmarked on other
|
2000-05-31 14:15:06 +08:00
|
|
|
architectures. --adam
|
|
|
|
*/
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
#define MEMCPY_IS_NICE
|
|
|
|
|
|
|
|
#ifdef MEMCPY_IS_NICE
|
|
|
|
#include <string.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdarg.h>
|
2002-05-03 19:31:08 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
#include "gimp.h"
|
|
|
|
|
|
|
|
|
Changed the semantics of GIMP_EXTENSION and (to some extent) of
2003-06-19 Michael Natterer <mitch@gimp.org>
Changed the semantics of GIMP_EXTENSION and (to some extent)
of GIMP_PLUGIN:
The old meaning of EXTENSION was "I live in the toolbox" and
PLUGIN meant "I take RUN-MODE,IMAGE,DRAWABLE args (but only if I
am invoked interactively)". This is completely useless, since
living in the toolbox means having "<Toolbox>" in the menu_path
and taking RUN-MODE,IMAGE,DRAWABLE means just that, regardless of
what type of procedure we are.
The new meaning of GIMP_PLUGIN is just "I am an ordinary procedure,
I am invoked, do my job and finish", while GIMP_EXTENSION means
"I will install temporary procedures and I will keep running to
keep them available".
(A GIMP_EXTENSION *must* call gimp_extension_ack() now to tell the
core that it's ready to run, or the core will block waiting for
the message !!!).
* configure.in: bumped version number to 1.3.16.
* libgimpbase/gimpprotocol.h: increased protocol version number so
old extensions will refuse to load.
* app/gui/plug-in-commands.c (plug_in_run_cmd_callback): don't
blindly pass RUN-MODE,IMAGE,DRAWABLE to GIMP_PLUGIN procedures but
look at their parameters and pass them either RUN-MODE, or
RUN-MODE,IMAGE, or RUN-MODE,IMAGE,DRAWABLE.
* app/pdb/procedural_db.c: cleaned up, better error reporting,
replaced an impossible error message by g_return_if_fail()
* app/plug-in/plug-in-message.c (plug_in_handle_proc_install):
better error messages.
* app/plug-in/plug-in-params.c: allocate parameter arrays using
g_new0() so we don't have to worry about uninitialized stuff
later.
* app/plug-in/plug-in-run.c (plug_in_run): wait for
gimp_extension_ack() installation confirmation for ALL extensions,
not just for automatically started ones.
* app/plug-in/plug-ins.c: cleanup.
* libgimp/gimp.[ch]: cleaned up and API-documented massively. Made
all magic values given in the GPConfig message static and added
accessor functions for them. Added gimp_tile_width()/height().
Added new function gimp_extension_enable() which turns on
asynchronous processing of temp_proc run requests without having
to enter an endless gimp_extension_process() loop. Moved all
private functions to the end of the file. Added tons of
g_return_if_fail() all over the place. Call gimp_run_procedure2()
from gimp_run_procedure() instead of duplicating the
code. Indentation, spacing, stuff...
* libgimp/gimptile.[ch]: removed gimp_tile_width()/height().
* libgimp/gimpdrawable.c
* libgimp/gimppixelrgn.c
* libgimp/gimptile.c: use the gimp_tile_width()/height() accessor
functions.
* libgimp/gimp.def: added gimp_extension_enable.
* libgimp/gimpmenu.c: removed evil code which connected to
_readchannel manually and use gimp_extension_enable() for watching
temp_procs.
* plug-ins/helpbrowser/helpbrowser.c: removed the same evil code
here and call gimp_extension_enable(). Call gimp_extension_ack()
to let the core know that the temp_proc is installed.
* plug-ins/script-fu/script-fu.c: made all procedures except the
permanently running "extension_script_fu" ordinary GIMP_PLUGIN
procedures.
* plug-ins/common/curve_bend.c
* plug-ins/common/plugindetails.c
* plug-ins/common/screenshot.c
* plug-ins/common/uniteditor.c
* plug-ins/common/winclipboard.c
* plug-ins/dbbrowser/dbbrowser.c
* plug-ins/gfli/gfli.c
* plug-ins/twain/twain.c
* plug-ins/webbrowser/webbrowser.c
* plug-ins/winsnap/winsnap.c: made them all ordinary GIMP_PLUGIN
procedures and renamed them from "extension_*" to "plug_in_*".
Random cleanups.
* app/widgets/gimphelp.c
* plug-ins/maze/maze_face.c: call "plug_in_web_browser" now.
2003-06-20 01:12:00 +08:00
|
|
|
#define TILE_WIDTH gimp_tile_width()
|
|
|
|
#define TILE_HEIGHT gimp_tile_height()
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
|
2000-05-31 14:15:06 +08:00
|
|
|
typedef struct _GimpPixelRgnHolder GimpPixelRgnHolder;
|
|
|
|
typedef struct _GimpPixelRgnIterator GimpPixelRgnIterator;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-05-31 14:15:06 +08:00
|
|
|
struct _GimpPixelRgnHolder
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-05-31 14:15:06 +08:00
|
|
|
GimpPixelRgn *pr;
|
|
|
|
guchar *original_data;
|
|
|
|
gint startx;
|
|
|
|
gint starty;
|
|
|
|
gint count;
|
1997-11-25 06:05:25 +08:00
|
|
|
};
|
|
|
|
|
2000-05-31 14:15:06 +08:00
|
|
|
struct _GimpPixelRgnIterator
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
GSList *pixel_regions;
|
2000-05-31 14:15:06 +08:00
|
|
|
gint region_width;
|
|
|
|
gint region_height;
|
|
|
|
gint portion_width;
|
|
|
|
gint portion_height;
|
|
|
|
gint process_count;
|
1997-11-25 06:05:25 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2000-05-31 14:15:06 +08:00
|
|
|
static gint gimp_get_portion_width (GimpPixelRgnIterator *pri);
|
|
|
|
static gint gimp_get_portion_height (GimpPixelRgnIterator *pri);
|
|
|
|
static gpointer gimp_pixel_rgns_configure (GimpPixelRgnIterator *pri);
|
|
|
|
static void gimp_pixel_rgn_configure (GimpPixelRgnHolder *prh,
|
2004-09-12 04:04:29 +08:00
|
|
|
GimpPixelRgnIterator *pri);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gimp_pixel_rgn_init:
|
|
|
|
* @pr: a pointer to a #GimpPixelRgn variable.
|
|
|
|
* @drawable: the #GimpDrawable the new region will be attached to.
|
2004-09-12 08:00:38 +08:00
|
|
|
* @x: the x coordinate of the top-left pixel of the region in the
|
|
|
|
* @drawable.
|
|
|
|
* @y: the y coordinate of the top-left pixel of the region in the
|
|
|
|
* @drawable.
|
2004-09-12 04:04:29 +08:00
|
|
|
* @width: the width of the region.
|
|
|
|
* @height: the height of the region.
|
2004-09-12 08:00:38 +08:00
|
|
|
* @dirty: a #gboolean indicating whether the @drawable should be marked
|
|
|
|
* as "dirty".
|
2004-09-12 04:04:29 +08:00
|
|
|
* @shadow: a #gboolean indicating whether the region is attached to the
|
|
|
|
* shadow tiles or the real @drawable tiles.
|
|
|
|
*
|
|
|
|
* Initialize the pixel region pointed by @pr with the specified parameters.
|
2004-10-18 03:17:09 +08:00
|
|
|
*
|
2004-12-21 05:39:48 +08:00
|
|
|
* The @dirty and @shadow flags can be used as follows:
|
2004-10-18 03:17:09 +08:00
|
|
|
*
|
2004-12-21 05:39:48 +08:00
|
|
|
* - @dirty = FALSE, @shadow = FALSE: the region will be used to read
|
|
|
|
* the actual drawable datas. This
|
|
|
|
* is useful for save plug-ins or for
|
|
|
|
* filters.
|
2004-10-18 03:17:09 +08:00
|
|
|
*
|
2004-12-21 05:39:48 +08:00
|
|
|
* - @dirty = FALSE, @shadow = TRUE: the region will be used to read the
|
|
|
|
* shadow tiles. This is used in
|
|
|
|
* some filter plug-ins which operate
|
|
|
|
* in two passes such as gaussian
|
|
|
|
* blur. The first pass reads the
|
|
|
|
* actual drawable data and writes to
|
|
|
|
* the shadow tiles, and the second
|
|
|
|
* one reads from and writes to the
|
|
|
|
* shadow tiles.
|
|
|
|
*
|
|
|
|
* - @dirty = TRUE, @shadow = TRUE: the region will be used to write to
|
|
|
|
* the shadow tiles. It is common
|
|
|
|
* practice to write to the shadow
|
|
|
|
* tiles and then use
|
|
|
|
* #gimp_drawable_merge_shadow () to
|
|
|
|
* merge the changes from the shadow
|
|
|
|
* tiles using the current selection
|
|
|
|
* as a mask.
|
|
|
|
*
|
|
|
|
* - @dirty = TRUE, @shadow = FALSE: the region will be used to directly
|
|
|
|
* change the drawable content. Don't
|
|
|
|
* do this, since this could prevent
|
|
|
|
* the Undo-System from working as
|
|
|
|
* expected.
|
2004-09-12 04:04:29 +08:00
|
|
|
**/
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
2000-05-31 14:15:06 +08:00
|
|
|
gimp_pixel_rgn_init (GimpPixelRgn *pr,
|
2004-09-12 04:04:29 +08:00
|
|
|
GimpDrawable *drawable,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint width,
|
|
|
|
gint height,
|
|
|
|
gboolean dirty,
|
|
|
|
gboolean shadow)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2002-05-03 19:31:08 +08:00
|
|
|
g_return_if_fail (pr != NULL);
|
|
|
|
g_return_if_fail (drawable != NULL);
|
|
|
|
g_return_if_fail (x >= 0 && x + width <= drawable->width);
|
|
|
|
g_return_if_fail (y >= 0 && y + height <= drawable->height);
|
|
|
|
|
2000-05-31 14:15:06 +08:00
|
|
|
pr->data = NULL;
|
|
|
|
pr->drawable = drawable;
|
|
|
|
pr->bpp = drawable->bpp;
|
1997-11-25 06:05:25 +08:00
|
|
|
pr->rowstride = pr->bpp * TILE_WIDTH;
|
2000-05-31 14:15:06 +08:00
|
|
|
pr->x = x;
|
|
|
|
pr->y = y;
|
|
|
|
pr->w = width;
|
|
|
|
pr->h = height;
|
|
|
|
pr->dirty = dirty;
|
|
|
|
pr->shadow = shadow;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2004-09-12 04:04:29 +08:00
|
|
|
/**
|
|
|
|
* gimp_pixel_rgn_resize:
|
|
|
|
* @pr: a pointer to a previously initialized #GimpPixelRgn.
|
2004-09-12 08:00:38 +08:00
|
|
|
* @x: the x coordinate of the new position of the region's
|
|
|
|
* top-left corner.
|
|
|
|
* @y: the y coordinate of the new position of the region's
|
|
|
|
* top-left corner.
|
2004-09-12 04:04:29 +08:00
|
|
|
* @width: the new width of the region.
|
|
|
|
* @height: the new height of the region.
|
|
|
|
*
|
|
|
|
* Change the position and size of a previously initialized pixel region.
|
|
|
|
**/
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
2000-05-31 14:15:06 +08:00
|
|
|
gimp_pixel_rgn_resize (GimpPixelRgn *pr,
|
2004-09-12 04:04:29 +08:00
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint width,
|
|
|
|
gint height)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2002-05-03 19:31:08 +08:00
|
|
|
g_return_if_fail (pr != NULL && pr->drawable != NULL);
|
|
|
|
g_return_if_fail (x >= 0 && x + width <= pr->drawable->width);
|
|
|
|
g_return_if_fail (y >= 0 && y + height <= pr->drawable->height);
|
|
|
|
|
2005-09-04 01:16:58 +08:00
|
|
|
/* If the data is non-null, data is contiguous--need to advance */
|
1997-11-25 06:05:25 +08:00
|
|
|
if (pr->data != NULL)
|
|
|
|
pr->data += ((y - pr->y) * pr->rowstride +
|
2004-09-12 04:04:29 +08:00
|
|
|
(x - pr->x) * pr->bpp);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-09-04 01:16:58 +08:00
|
|
|
/* update sizes for both contiguous and tiled regions */
|
1997-11-25 06:05:25 +08:00
|
|
|
pr->x = x;
|
|
|
|
pr->y = y;
|
|
|
|
pr->w = width;
|
|
|
|
pr->h = height;
|
|
|
|
}
|
|
|
|
|
2004-09-12 04:04:29 +08:00
|
|
|
/**
|
|
|
|
* gimp_pixel_rgn_get_pixel:
|
|
|
|
* @pr: a pointer to a previously initialized #GimpPixelRgn.
|
|
|
|
* @buf: a pointer to an array of #guchar
|
2004-09-12 07:43:38 +08:00
|
|
|
* @x: the x coordinate of the wanted pixel (relative to the drawable)
|
|
|
|
* @y: the y coordinate of the wanted pixel (relative to the drawable)
|
2004-09-12 04:04:29 +08:00
|
|
|
*
|
|
|
|
* Fill the buffer pointed by @buf with the value of the pixel at (@x, @y)
|
|
|
|
* in the region @pr. @buf should be large enough to hold the pixel value
|
|
|
|
* (1 #guchar for an indexed or grayscale drawable, 2 #guchar for
|
2004-09-12 20:23:50 +08:00
|
|
|
* indexed with alpha or grayscale with alpha drawable, 3 #guchar for
|
2004-09-12 04:04:29 +08:00
|
|
|
* rgb drawable and 4 #guchar for rgb with alpha drawable.
|
|
|
|
**/
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
2000-05-31 14:15:06 +08:00
|
|
|
gimp_pixel_rgn_get_pixel (GimpPixelRgn *pr,
|
2004-09-12 04:04:29 +08:00
|
|
|
guchar *buf,
|
|
|
|
gint x,
|
|
|
|
gint y)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-05-31 14:15:06 +08:00
|
|
|
GimpTile *tile;
|
|
|
|
guchar *tile_data;
|
|
|
|
gint b;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2002-05-03 19:31:08 +08:00
|
|
|
g_return_if_fail (pr != NULL && pr->drawable != NULL);
|
|
|
|
g_return_if_fail (x >= 0 && x < pr->drawable->width);
|
|
|
|
g_return_if_fail (y >= 0 && y < pr->drawable->height);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
tile = gimp_drawable_get_tile2 (pr->drawable, pr->shadow, x, y);
|
|
|
|
gimp_tile_ref (tile);
|
|
|
|
|
|
|
|
tile_data = tile->data + tile->bpp * (tile->ewidth * (y % TILE_HEIGHT) + (x % TILE_WIDTH));
|
|
|
|
|
|
|
|
for (b = 0; b < tile->bpp; b++)
|
|
|
|
*buf++ = *tile_data++;
|
|
|
|
|
1998-01-09 17:26:28 +08:00
|
|
|
gimp_tile_unref (tile, FALSE);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2004-09-12 04:04:29 +08:00
|
|
|
/**
|
|
|
|
* gimp_pixel_rgn_get_row:
|
|
|
|
* @pr: a pointer to a previously initialized #GimpPixelRgn.
|
2004-09-12 07:05:56 +08:00
|
|
|
* @buf: a pointer to an array of #guchar
|
2004-09-12 07:43:38 +08:00
|
|
|
* @x: the x coordinate of the first pixel (relative to the drawable).
|
|
|
|
* @y: the y coordinate of the first pixel (relative to the drawable).
|
2004-09-12 07:05:56 +08:00
|
|
|
* @width: the number of pixels to get.
|
2004-09-12 04:04:29 +08:00
|
|
|
*
|
2004-09-12 07:05:56 +08:00
|
|
|
* Get several pixels of a region in a row. This function fills the buffer
|
|
|
|
* @buf with the values of the pixels from (@x, @y) to (@x+@width-1, @y).
|
|
|
|
* @buf should be large enough to hold all these values.
|
2004-09-12 04:04:29 +08:00
|
|
|
**/
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
2000-05-31 14:15:06 +08:00
|
|
|
gimp_pixel_rgn_get_row (GimpPixelRgn *pr,
|
2004-09-12 04:04:29 +08:00
|
|
|
guchar *buf,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint width)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-05-31 14:15:06 +08:00
|
|
|
GimpTile *tile;
|
|
|
|
guchar *tile_data;
|
2004-02-17 05:32:51 +08:00
|
|
|
gint bpp, inc, min;
|
|
|
|
gint end;
|
|
|
|
gint boundary;
|
1997-11-25 06:05:25 +08:00
|
|
|
#ifndef MEMCPY_IS_NICE
|
2004-02-17 05:32:51 +08:00
|
|
|
gint b;
|
1997-11-25 06:05:25 +08:00
|
|
|
#endif
|
|
|
|
|
2002-05-03 19:31:08 +08:00
|
|
|
g_return_if_fail (pr != NULL && pr->drawable != NULL);
|
|
|
|
g_return_if_fail (buf != NULL);
|
|
|
|
g_return_if_fail (x >= 0 && x + width <= pr->drawable->width);
|
|
|
|
g_return_if_fail (y >= 0 && y < pr->drawable->height);
|
|
|
|
g_return_if_fail (width >= 0);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
end = x + width;
|
|
|
|
|
|
|
|
while (x < end)
|
|
|
|
{
|
|
|
|
tile = gimp_drawable_get_tile2 (pr->drawable, pr->shadow, x, y);
|
|
|
|
gimp_tile_ref (tile);
|
|
|
|
|
1998-01-26 05:32:01 +08:00
|
|
|
tile_data = tile->data + (int)tile->bpp * (int)(tile->ewidth * (int)(y % TILE_HEIGHT) + (x % TILE_WIDTH));
|
1997-11-25 06:05:25 +08:00
|
|
|
boundary = x + (tile->ewidth - (x % TILE_WIDTH));
|
|
|
|
bpp = tile->bpp;
|
|
|
|
|
|
|
|
#ifdef MEMCPY_IS_NICE
|
|
|
|
memcpy ((void *)buf,
|
2004-09-12 04:04:29 +08:00
|
|
|
(const void *)tile_data,
|
|
|
|
inc = (bpp *
|
|
|
|
( (min = MIN (end, boundary)) -x) ) );
|
2003-01-15 11:55:20 +08:00
|
|
|
x = min;
|
1997-11-25 06:05:25 +08:00
|
|
|
buf += inc;
|
|
|
|
#else
|
|
|
|
for ( ; x < end && x < boundary; x++)
|
2004-09-12 04:04:29 +08:00
|
|
|
{
|
|
|
|
for (b = 0; b < tile->bpp; b++)
|
|
|
|
*buf++ = tile_data[b];
|
|
|
|
tile_data += bpp;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
#endif /* MEMCPY_IS_NICE */
|
|
|
|
|
|
|
|
gimp_tile_unref (tile, FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-12 04:04:29 +08:00
|
|
|
/**
|
|
|
|
* gimp_pixel_rgn_get_col:
|
2004-09-12 07:05:56 +08:00
|
|
|
* @pr: a pointer to a previously initialized #GimpPixelRgn.
|
|
|
|
* @buf: a pointer to an array of #guchar
|
2004-09-12 07:43:38 +08:00
|
|
|
* @x: the x coordinate of the first pixel (relative to the drawable).
|
|
|
|
* @y: the y coordinate of the first pixel (relative to the drawable).
|
2004-09-12 07:05:56 +08:00
|
|
|
* @height: the number of pixels to get.
|
|
|
|
*
|
|
|
|
* Get several pixels of a region's column. This function fills the buffer
|
|
|
|
* @buf with the values of the pixels from (@x, @y) to (@x, @y+@height-1).
|
|
|
|
* @buf should be large enough to hold all these values.
|
2004-09-12 04:04:29 +08:00
|
|
|
*
|
|
|
|
**/
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
2000-05-31 14:15:06 +08:00
|
|
|
gimp_pixel_rgn_get_col (GimpPixelRgn *pr,
|
2004-09-12 04:04:29 +08:00
|
|
|
guchar *buf,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint height)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-05-31 14:15:06 +08:00
|
|
|
GimpTile *tile;
|
|
|
|
guchar *tile_data;
|
2004-02-17 05:32:51 +08:00
|
|
|
gint inc;
|
|
|
|
gint end;
|
|
|
|
gint boundary;
|
|
|
|
gint b;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2002-05-03 19:31:08 +08:00
|
|
|
g_return_if_fail (pr != NULL && pr->drawable != NULL);
|
|
|
|
g_return_if_fail (buf != NULL);
|
|
|
|
g_return_if_fail (x >= 0 && x < pr->drawable->width);
|
|
|
|
g_return_if_fail (y >= 0 && y + height <= pr->drawable->height);
|
|
|
|
g_return_if_fail (height >= 0);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
end = y + height;
|
|
|
|
|
|
|
|
while (y < end)
|
|
|
|
{
|
|
|
|
tile = gimp_drawable_get_tile2 (pr->drawable, pr->shadow, x, y);
|
|
|
|
gimp_tile_ref (tile);
|
|
|
|
|
|
|
|
tile_data = tile->data + tile->bpp * (tile->ewidth * (y % TILE_HEIGHT) + (x % TILE_WIDTH));
|
|
|
|
boundary = y + (tile->eheight - (y % TILE_HEIGHT));
|
|
|
|
inc = tile->bpp * tile->ewidth;
|
|
|
|
|
|
|
|
for ( ; y < end && y < boundary; y++)
|
2004-09-12 04:04:29 +08:00
|
|
|
{
|
|
|
|
for (b = 0; b < tile->bpp; b++)
|
|
|
|
*buf++ = tile_data[b];
|
|
|
|
tile_data += inc;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
gimp_tile_unref (tile, FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-12 04:04:29 +08:00
|
|
|
/**
|
|
|
|
* gimp_pixel_rgn_get_rect:
|
2004-09-12 07:05:56 +08:00
|
|
|
* @pr: a pointer to a previously initialized #GimpPixelRgn.
|
|
|
|
* @buf: a pointer to an array of #guchar
|
2004-09-12 07:43:38 +08:00
|
|
|
* @x: the x coordinate of the first pixel (relative to the drawable).
|
|
|
|
* @y: the y coordinate of the first pixel (relative to the drawable).
|
2004-09-12 07:05:56 +08:00
|
|
|
* @width: the width of the rectangle.
|
|
|
|
* @height: the height of the rectangle.
|
2004-09-12 04:04:29 +08:00
|
|
|
*
|
2004-09-12 07:05:56 +08:00
|
|
|
* Get all the pixel values from the rectangle defined by @x, @y, @width and
|
|
|
|
* @height. This function fills the buffer @buf with the values of the pixels
|
|
|
|
* from (@x, @y) to (@x+@width-1, @y+@height-1).
|
|
|
|
* @buf should be large enough to hold all these values (@width*@height*bpp).
|
2004-09-12 04:04:29 +08:00
|
|
|
**/
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
2000-05-31 14:15:06 +08:00
|
|
|
gimp_pixel_rgn_get_rect (GimpPixelRgn *pr,
|
2004-09-12 04:04:29 +08:00
|
|
|
guchar *buf,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint width,
|
|
|
|
gint height)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-05-31 14:15:06 +08:00
|
|
|
GimpTile *tile;
|
|
|
|
guchar *src;
|
|
|
|
guchar *dest;
|
|
|
|
gulong bufstride;
|
2004-02-17 05:32:51 +08:00
|
|
|
gint xstart, ystart;
|
|
|
|
gint xend, yend;
|
|
|
|
gint xboundary;
|
|
|
|
gint yboundary;
|
|
|
|
gint xstep, ystep;
|
|
|
|
gint ty, bpp;
|
1997-11-25 06:05:25 +08:00
|
|
|
#ifndef MEMCPY_IS_NICE
|
2004-02-17 05:32:51 +08:00
|
|
|
gint b, tx;
|
1997-11-25 06:05:25 +08:00
|
|
|
#endif
|
|
|
|
|
2002-05-03 19:31:08 +08:00
|
|
|
g_return_if_fail (pr != NULL && pr->drawable != NULL);
|
|
|
|
g_return_if_fail (buf != NULL);
|
|
|
|
g_return_if_fail (x >= 0 && x + width <= pr->drawable->width);
|
|
|
|
g_return_if_fail (y >= 0 && y + height <= pr->drawable->height);
|
|
|
|
g_return_if_fail (width >= 0);
|
|
|
|
g_return_if_fail (height >= 0);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
bpp = pr->bpp;
|
|
|
|
bufstride = bpp * width;
|
|
|
|
|
|
|
|
xstart = x;
|
|
|
|
ystart = y;
|
|
|
|
xend = x + width;
|
|
|
|
yend = y + height;
|
|
|
|
ystep = 0;
|
|
|
|
|
|
|
|
while (y < yend)
|
|
|
|
{
|
|
|
|
x = xstart;
|
|
|
|
while (x < xend)
|
2004-09-12 04:04:29 +08:00
|
|
|
{
|
|
|
|
tile = gimp_drawable_get_tile2 (pr->drawable, pr->shadow, x, y);
|
|
|
|
gimp_tile_ref (tile);
|
|
|
|
|
|
|
|
xstep = tile->ewidth - (x % TILE_WIDTH);
|
|
|
|
ystep = tile->eheight - (y % TILE_HEIGHT);
|
|
|
|
xboundary = x + xstep;
|
|
|
|
yboundary = y + ystep;
|
|
|
|
xboundary = MIN (xboundary, xend);
|
|
|
|
yboundary = MIN (yboundary, yend);
|
|
|
|
|
|
|
|
for (ty = y; ty < yboundary; ty++)
|
|
|
|
{
|
|
|
|
src = tile->data + tile->bpp * (tile->ewidth * (ty % TILE_HEIGHT) + (x % TILE_WIDTH));
|
|
|
|
dest = buf + bufstride * (ty - ystart) + bpp * (x - xstart);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
#ifdef MEMCPY_IS_NICE
|
2004-09-12 04:04:29 +08:00
|
|
|
memcpy ((void *)dest, (const void *)src, (xboundary-x)*bpp);
|
2003-12-05 23:55:15 +08:00
|
|
|
#else
|
2004-09-12 04:04:29 +08:00
|
|
|
for (tx = x; tx < xboundary; tx++)
|
|
|
|
{
|
|
|
|
for (b = 0; b < bpp; b++)
|
|
|
|
*dest++ = *src++;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
#endif /* MEMCPY_IS_NICE */
|
2004-09-12 04:04:29 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-09-12 04:04:29 +08:00
|
|
|
gimp_tile_unref (tile, FALSE);
|
|
|
|
x += xstep;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
y += ystep;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-12 04:04:29 +08:00
|
|
|
/**
|
|
|
|
* gimp_pixel_rgn_set_pixel:
|
2004-09-12 07:05:56 +08:00
|
|
|
* @pr: a pointer to a previously initialized #GimpPixelRgn.
|
|
|
|
* @buf: a pointer to an array of #guchar.
|
2004-09-12 07:43:38 +08:00
|
|
|
* @x: the x coordinate of the pixel (relative to the drawable).
|
|
|
|
* @y: the y coordinate of the pixel (relative to the drawable).
|
2004-09-12 04:04:29 +08:00
|
|
|
*
|
2004-09-12 07:05:56 +08:00
|
|
|
* Set the pixel at (@x, @y) to the values from @buf.
|
2004-09-12 04:04:29 +08:00
|
|
|
**/
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
2000-05-31 14:15:06 +08:00
|
|
|
gimp_pixel_rgn_set_pixel (GimpPixelRgn *pr,
|
2004-09-12 04:04:29 +08:00
|
|
|
const guchar *buf,
|
|
|
|
gint x,
|
|
|
|
gint y)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-05-31 14:15:06 +08:00
|
|
|
GimpTile *tile;
|
|
|
|
guchar *tile_data;
|
2003-07-02 02:11:18 +08:00
|
|
|
gint b;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2002-05-03 19:31:08 +08:00
|
|
|
g_return_if_fail (pr != NULL && pr->drawable != NULL);
|
|
|
|
g_return_if_fail (buf != NULL);
|
|
|
|
g_return_if_fail (x >= 0 && x < pr->drawable->width);
|
|
|
|
g_return_if_fail (y >= 0 && y < pr->drawable->height);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
tile = gimp_drawable_get_tile2 (pr->drawable, pr->shadow, x, y);
|
|
|
|
gimp_tile_ref (tile);
|
|
|
|
|
2003-07-02 02:11:18 +08:00
|
|
|
tile_data = tile->data + tile->bpp * (tile->ewidth *
|
|
|
|
(y % TILE_HEIGHT) + (x % TILE_WIDTH));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
for (b = 0; b < tile->bpp; b++)
|
|
|
|
*tile_data++ = *buf++;
|
|
|
|
|
|
|
|
gimp_tile_unref (tile, TRUE);
|
|
|
|
}
|
|
|
|
|
2004-09-12 04:04:29 +08:00
|
|
|
/**
|
|
|
|
* gimp_pixel_rgn_set_row:
|
2004-09-12 07:05:56 +08:00
|
|
|
* @pr: a pointer to a previously initialized #GimpPixelRgn.
|
|
|
|
* @buf: a pointer to an array of #guchar
|
2004-09-12 07:43:38 +08:00
|
|
|
* @x: the x coordinate of the first pixel (relative to the drawable).
|
|
|
|
* @y: the y coordinate of the first pixel (relative to the drawable).
|
2004-09-12 07:05:56 +08:00
|
|
|
* @width: the number of pixels to set.
|
2004-09-12 04:04:29 +08:00
|
|
|
*
|
2004-09-12 07:05:56 +08:00
|
|
|
* Set several pixels of a region in a row. This function draws the pixels
|
|
|
|
* from (@x, @y) to (@x+@width-1, @y) using the values of the buffer @buf.
|
|
|
|
* @buf should be large enough to hold all these values.
|
2004-09-12 04:04:29 +08:00
|
|
|
**/
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
2000-05-31 14:15:06 +08:00
|
|
|
gimp_pixel_rgn_set_row (GimpPixelRgn *pr,
|
2004-09-12 04:04:29 +08:00
|
|
|
const guchar *buf,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint width)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-05-31 14:15:06 +08:00
|
|
|
GimpTile *tile;
|
|
|
|
guchar *tile_data;
|
2003-07-02 02:11:18 +08:00
|
|
|
gint inc, min;
|
|
|
|
gint end;
|
|
|
|
gint boundary;
|
1997-11-25 06:05:25 +08:00
|
|
|
#ifndef MEMCPY_IS_NICE
|
2003-07-02 02:11:18 +08:00
|
|
|
gint b;
|
1997-11-25 06:05:25 +08:00
|
|
|
#endif
|
|
|
|
|
2002-05-03 19:31:08 +08:00
|
|
|
g_return_if_fail (pr != NULL && pr->drawable != NULL);
|
|
|
|
g_return_if_fail (buf != NULL);
|
|
|
|
g_return_if_fail (x >= 0 && x + width <= pr->drawable->width);
|
|
|
|
g_return_if_fail (y >= 0 && y < pr->drawable->height);
|
|
|
|
g_return_if_fail (width >= 0);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
end = x + width;
|
|
|
|
|
|
|
|
while (x < end)
|
|
|
|
{
|
|
|
|
tile = gimp_drawable_get_tile2 (pr->drawable, pr->shadow, x, y);
|
|
|
|
gimp_tile_ref (tile);
|
|
|
|
|
|
|
|
tile_data = tile->data + tile->bpp * (tile->ewidth * (y % TILE_HEIGHT) + (x % TILE_WIDTH));
|
|
|
|
boundary = x + (tile->ewidth - (x % TILE_WIDTH));
|
|
|
|
|
|
|
|
#ifdef MEMCPY_IS_NICE
|
|
|
|
memcpy ((void *)tile_data,
|
2004-09-12 04:04:29 +08:00
|
|
|
(const void *)buf,
|
|
|
|
inc = (tile->bpp *
|
|
|
|
( (min = MIN (end, boundary)) -x) ) );
|
1997-11-25 06:05:25 +08:00
|
|
|
x = min;
|
|
|
|
buf += inc;
|
|
|
|
#else
|
|
|
|
for ( ; x < end && x < boundary; x++)
|
2004-09-12 04:04:29 +08:00
|
|
|
{
|
|
|
|
for (b = 0; b < tile->bpp; b++)
|
|
|
|
*tile_data++ = *buf++;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
#endif /* MEMCPY_IS_NICE */
|
|
|
|
|
|
|
|
gimp_tile_unref (tile, TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-12 04:04:29 +08:00
|
|
|
/**
|
|
|
|
* gimp_pixel_rgn_set_col:
|
2004-09-12 07:05:56 +08:00
|
|
|
* @pr: a pointer to a previously initialized #GimpPixelRgn.
|
|
|
|
* @buf: a pointer to an array of #guchar
|
2004-09-12 07:43:38 +08:00
|
|
|
* @x: the x coordinate of the first pixel (relative to the drawable).
|
|
|
|
* @y: the y coordinate of the first pixel (relative to the drawable).
|
2004-09-12 07:05:56 +08:00
|
|
|
* @height: the number of pixels to set.
|
2004-09-12 04:04:29 +08:00
|
|
|
*
|
2004-09-12 07:05:56 +08:00
|
|
|
* Set several pixels of a region's column. This function draws the pixels
|
|
|
|
* from (@x, @y) to (@x, @y+@height-1) using the values from the buffer @buf.
|
|
|
|
* @buf should be large enough to hold all these values.
|
2004-09-12 04:04:29 +08:00
|
|
|
**/
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
2000-05-31 14:15:06 +08:00
|
|
|
gimp_pixel_rgn_set_col (GimpPixelRgn *pr,
|
2004-09-12 04:04:29 +08:00
|
|
|
const guchar *buf,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint height)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-05-31 14:15:06 +08:00
|
|
|
GimpTile *tile;
|
|
|
|
guchar *tile_data;
|
2003-07-02 02:11:18 +08:00
|
|
|
gint inc;
|
|
|
|
gint end;
|
|
|
|
gint boundary;
|
|
|
|
gint b;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2002-05-03 19:31:08 +08:00
|
|
|
g_return_if_fail (pr != NULL && pr->drawable != NULL);
|
|
|
|
g_return_if_fail (buf != NULL);
|
|
|
|
g_return_if_fail (x >= 0 && x < pr->drawable->width);
|
|
|
|
g_return_if_fail (y >= 0 && y + height <= pr->drawable->height);
|
|
|
|
g_return_if_fail (height >= 0);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
end = y + height;
|
|
|
|
|
|
|
|
while (y < end)
|
|
|
|
{
|
|
|
|
tile = gimp_drawable_get_tile2 (pr->drawable, pr->shadow, x, y);
|
|
|
|
gimp_tile_ref (tile);
|
|
|
|
|
|
|
|
tile_data = tile->data + tile->bpp * (tile->ewidth * (y % TILE_HEIGHT) + (x % TILE_WIDTH));
|
|
|
|
boundary = y + (tile->eheight - (y % TILE_HEIGHT));
|
|
|
|
inc = tile->bpp * tile->ewidth;
|
|
|
|
|
|
|
|
for ( ; y < end && y < boundary; y++)
|
2004-09-12 04:04:29 +08:00
|
|
|
{
|
|
|
|
for (b = 0; b < tile->bpp; b++)
|
|
|
|
tile_data[b] = *buf++;
|
|
|
|
tile_data += inc;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
gimp_tile_unref (tile, TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-12 04:04:29 +08:00
|
|
|
/**
|
|
|
|
* gimp_pixel_rgn_set_rect:
|
2004-09-12 07:05:56 +08:00
|
|
|
* @pr: a pointer to a previously initialized #GimpPixelRgn.
|
|
|
|
* @buf: a pointer to an array of #guchar
|
2004-09-12 07:43:38 +08:00
|
|
|
* @x: the x coordinate of the first pixel (relative to the drawable).
|
|
|
|
* @y: the y coordinate of the first pixel (relative to the drawable).
|
2004-09-12 07:05:56 +08:00
|
|
|
* @width: the width of the rectangle.
|
|
|
|
* @height: the height of the rectangle.
|
2004-09-12 04:04:29 +08:00
|
|
|
*
|
2004-09-12 07:05:56 +08:00
|
|
|
* Set all the pixel of the rectangle defined by @x, @y, @width and
|
|
|
|
* @height. This function draws the rectangle from (@x, @y) to
|
|
|
|
* (@x+@width-1, @y+@height-1), using the pixel values from the buffer @buf.
|
|
|
|
* @buf should be large enough to hold all these values (@width*@height*bpp).
|
2004-09-12 04:04:29 +08:00
|
|
|
**/
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
2000-05-31 14:15:06 +08:00
|
|
|
gimp_pixel_rgn_set_rect (GimpPixelRgn *pr,
|
2004-09-12 04:04:29 +08:00
|
|
|
const guchar *buf,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint width,
|
|
|
|
gint height)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2003-07-02 05:34:53 +08:00
|
|
|
GimpTile *tile;
|
|
|
|
const guchar *src;
|
|
|
|
guchar *dest;
|
|
|
|
gulong bufstride;
|
|
|
|
gint xstart, ystart;
|
|
|
|
gint xend, yend;
|
|
|
|
gint xboundary;
|
|
|
|
gint yboundary;
|
|
|
|
gint xstep, ystep;
|
|
|
|
gint ty, bpp;
|
1997-11-25 06:05:25 +08:00
|
|
|
#ifndef MEMCPY_IS_NICE
|
2003-07-02 05:34:53 +08:00
|
|
|
gint b, tx;
|
1997-11-25 06:05:25 +08:00
|
|
|
#endif
|
|
|
|
|
2002-05-03 19:31:08 +08:00
|
|
|
g_return_if_fail (pr != NULL && pr->drawable != NULL);
|
|
|
|
g_return_if_fail (buf != NULL);
|
|
|
|
g_return_if_fail (x >= 0 && x + width <= pr->drawable->width);
|
|
|
|
g_return_if_fail (y >= 0 && y + height <= pr->drawable->height);
|
|
|
|
g_return_if_fail (width >= 0);
|
|
|
|
g_return_if_fail (height >= 0);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
bpp = pr->bpp;
|
|
|
|
bufstride = bpp * width;
|
|
|
|
|
|
|
|
xstart = x;
|
|
|
|
ystart = y;
|
|
|
|
xend = x + width;
|
|
|
|
yend = y + height;
|
|
|
|
ystep = 0;
|
|
|
|
|
|
|
|
while (y < yend)
|
|
|
|
{
|
|
|
|
x = xstart;
|
|
|
|
while (x < xend)
|
2004-09-12 04:04:29 +08:00
|
|
|
{
|
|
|
|
tile = gimp_drawable_get_tile2 (pr->drawable, pr->shadow, x, y);
|
|
|
|
gimp_tile_ref (tile);
|
|
|
|
|
|
|
|
xstep = tile->ewidth - (x % TILE_WIDTH);
|
|
|
|
ystep = tile->eheight - (y % TILE_HEIGHT);
|
|
|
|
xboundary = x + xstep;
|
|
|
|
yboundary = y + ystep;
|
|
|
|
xboundary = MIN (xboundary, xend);
|
|
|
|
yboundary = MIN (yboundary, yend);
|
|
|
|
|
|
|
|
for (ty = y; ty < yboundary; ty++)
|
|
|
|
{
|
|
|
|
src = buf + bufstride * (ty - ystart) + bpp * (x - xstart);
|
|
|
|
dest = tile->data + tile->bpp * (tile->ewidth *
|
2003-07-02 02:11:18 +08:00
|
|
|
(ty % TILE_HEIGHT) + (x % TILE_WIDTH));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
#ifdef MEMCPY_IS_NICE
|
2004-09-12 04:04:29 +08:00
|
|
|
memcpy ((void *)dest, (const void *)src, (xboundary-x)*bpp);
|
1997-11-25 06:05:25 +08:00
|
|
|
#else
|
2004-09-12 04:04:29 +08:00
|
|
|
for (tx = x; tx < xboundary; tx++)
|
|
|
|
{
|
|
|
|
for (b = 0; b < bpp; b++)
|
|
|
|
*dest++ = *src++;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
#endif /* MEMCPY_IS_NICE */
|
2004-09-12 04:04:29 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-09-12 04:04:29 +08:00
|
|
|
gimp_tile_unref (tile, TRUE);
|
|
|
|
x += xstep;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
y += ystep;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-12 04:04:29 +08:00
|
|
|
/**
|
|
|
|
* gimp_pixel_rgns_register2:
|
2004-09-12 07:05:56 +08:00
|
|
|
* @nrgns: the number of regions to register.
|
|
|
|
* @prs: an array of @nrgns pointers to initialized #GimpPixelRgn.
|
2004-09-12 04:04:29 +08:00
|
|
|
*
|
2004-09-12 08:00:38 +08:00
|
|
|
* It takes a number of initialized regions of the same size and provides a
|
|
|
|
* pixel region iterator the iterator can be used to iterate over the
|
|
|
|
* registered pixel regions. While iterating the registered pixel regions will
|
|
|
|
* cover subsets of the original pixel regions, chosen for optimized access to
|
|
|
|
* the image data.
|
2004-09-12 20:23:50 +08:00
|
|
|
*
|
2004-09-12 07:43:38 +08:00
|
|
|
* Note that the given regions themselves are changed by this function, so
|
|
|
|
* they are resized to the first subsets.
|
2004-09-12 20:23:50 +08:00
|
|
|
*
|
2004-09-12 08:00:38 +08:00
|
|
|
* This function has to be used together with gimp_pixel_rgns_process in a loop.
|
|
|
|
*
|
2004-09-12 07:05:56 +08:00
|
|
|
* Returns: a #gpointer to a regions iterator.
|
2004-09-12 04:04:29 +08:00
|
|
|
**/
|
1997-11-25 06:05:25 +08:00
|
|
|
gpointer
|
2000-05-31 14:15:06 +08:00
|
|
|
gimp_pixel_rgns_register2 (gint nrgns,
|
2004-09-12 04:04:29 +08:00
|
|
|
GimpPixelRgn **prs)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-05-31 14:15:06 +08:00
|
|
|
GimpPixelRgnIterator *pri;
|
2003-07-02 02:11:18 +08:00
|
|
|
gboolean found;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-02-17 05:32:51 +08:00
|
|
|
g_return_val_if_fail (nrgns > 0, NULL);
|
|
|
|
g_return_val_if_fail (prs != NULL, NULL);
|
|
|
|
|
2005-09-04 01:16:58 +08:00
|
|
|
pri = g_new0 (GimpPixelRgnIterator, 1);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
found = FALSE;
|
|
|
|
while (nrgns --)
|
|
|
|
{
|
2005-09-04 01:16:58 +08:00
|
|
|
GimpPixelRgnHolder *prh;
|
|
|
|
GimpPixelRgn *pr;
|
|
|
|
|
1999-05-19 06:41:21 +08:00
|
|
|
pr = prs[nrgns];
|
2005-09-04 01:16:58 +08:00
|
|
|
|
|
|
|
prh = g_new0 (GimpPixelRgnHolder, 1);
|
1997-11-25 06:05:25 +08:00
|
|
|
prh->pr = pr;
|
|
|
|
|
|
|
|
if (pr != NULL)
|
2004-09-12 04:04:29 +08:00
|
|
|
{
|
|
|
|
/* If there is a defined value for data, make sure tiles is NULL */
|
|
|
|
if (pr->data)
|
|
|
|
pr->drawable = NULL;
|
2005-09-04 01:16:58 +08:00
|
|
|
|
2004-09-12 04:04:29 +08:00
|
|
|
prh->original_data = pr->data;
|
|
|
|
prh->startx = pr->x;
|
|
|
|
prh->starty = pr->y;
|
|
|
|
prh->pr->process_count = 0;
|
|
|
|
|
|
|
|
if (!found)
|
|
|
|
{
|
|
|
|
found = TRUE;
|
|
|
|
pri->region_width = pr->w;
|
|
|
|
pri->region_height = pr->h;
|
|
|
|
}
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Add the pixel Rgn holder to the list */
|
|
|
|
pri->pixel_regions = g_slist_prepend (pri->pixel_regions, prh);
|
|
|
|
}
|
|
|
|
|
1999-05-19 06:41:21 +08:00
|
|
|
return gimp_pixel_rgns_configure (pri);
|
|
|
|
}
|
|
|
|
|
2004-09-12 04:04:29 +08:00
|
|
|
/**
|
|
|
|
* gimp_pixel_rgns_register:
|
2004-09-12 20:23:50 +08:00
|
|
|
* @nrgns: the number of regions to register.
|
|
|
|
* @Varargs: @nrgns pointers to #GimpPixelRgn.
|
2004-09-12 04:04:29 +08:00
|
|
|
*
|
2004-09-12 07:05:56 +08:00
|
|
|
* This is the varargs version of #gimp_pixel_rgns_register2.
|
2004-09-12 04:04:29 +08:00
|
|
|
*
|
2004-09-12 07:05:56 +08:00
|
|
|
* Returns: a #gpointer to a regions iterator.
|
2004-09-12 04:04:29 +08:00
|
|
|
**/
|
1999-05-19 06:41:21 +08:00
|
|
|
gpointer
|
2000-05-31 14:15:06 +08:00
|
|
|
gimp_pixel_rgns_register (gint nrgns,
|
2004-09-12 04:04:29 +08:00
|
|
|
...)
|
1999-05-19 06:41:21 +08:00
|
|
|
{
|
2000-05-31 14:15:06 +08:00
|
|
|
GimpPixelRgn **prs;
|
2003-07-02 02:11:18 +08:00
|
|
|
gpointer pri;
|
|
|
|
gint n;
|
|
|
|
va_list ap;
|
1999-05-19 06:41:21 +08:00
|
|
|
|
2004-02-17 05:32:51 +08:00
|
|
|
g_return_val_if_fail (nrgns > 0, NULL);
|
|
|
|
|
2000-05-31 14:15:06 +08:00
|
|
|
prs = g_new (GimpPixelRgn *, nrgns);
|
1999-05-19 06:41:21 +08:00
|
|
|
|
|
|
|
va_start (ap, nrgns);
|
|
|
|
|
|
|
|
for (n = nrgns; n--; )
|
2000-05-31 14:15:06 +08:00
|
|
|
prs[n] = va_arg (ap, GimpPixelRgn *);
|
1999-05-19 06:41:21 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
va_end (ap);
|
|
|
|
|
1999-05-19 06:41:21 +08:00
|
|
|
pri = gimp_pixel_rgns_register2 (nrgns, prs);
|
2000-05-31 14:15:06 +08:00
|
|
|
|
1999-05-19 06:41:21 +08:00
|
|
|
g_free (prs);
|
|
|
|
|
|
|
|
return pri;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2004-09-12 04:04:29 +08:00
|
|
|
/**
|
|
|
|
* gimp_pixel_rgns_process:
|
2004-09-12 20:23:50 +08:00
|
|
|
* @pri_ptr: a regions iterator returned by #gimp_pixel_rgns_register,
|
|
|
|
* #gimp_pixel_rgns_register2 or #gimp_pixel_rgns_process.
|
2004-09-12 04:04:29 +08:00
|
|
|
*
|
2004-09-12 07:05:56 +08:00
|
|
|
* This function update the regions registered previously with one of the
|
|
|
|
* #gimp_pixel_rgns_register* functions to their next tile.
|
2004-09-12 04:04:29 +08:00
|
|
|
*
|
2004-09-12 07:05:56 +08:00
|
|
|
* Returns: a #gpointer to a new regions iterator or #NULL if there isn't
|
|
|
|
* any tiles left.
|
2004-09-12 04:04:29 +08:00
|
|
|
**/
|
1997-11-25 06:05:25 +08:00
|
|
|
gpointer
|
|
|
|
gimp_pixel_rgns_process (gpointer pri_ptr)
|
|
|
|
{
|
2000-05-31 14:15:06 +08:00
|
|
|
GimpPixelRgnIterator *pri;
|
2003-07-02 02:11:18 +08:00
|
|
|
GSList *list;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-02-17 05:32:51 +08:00
|
|
|
g_return_val_if_fail (pri_ptr != NULL, NULL);
|
|
|
|
|
2000-05-31 14:15:06 +08:00
|
|
|
pri = (GimpPixelRgnIterator*) pri_ptr;
|
1997-11-25 06:05:25 +08:00
|
|
|
pri->process_count++;
|
|
|
|
|
|
|
|
/* Unref all referenced tiles and increment the offsets */
|
|
|
|
|
2004-02-17 05:32:51 +08:00
|
|
|
for (list = pri->pixel_regions; list; list = list->next)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2004-02-17 05:32:51 +08:00
|
|
|
GimpPixelRgnHolder *prh = list->data;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
if ((prh->pr != NULL) && (prh->pr->process_count != pri->process_count))
|
2004-09-12 04:04:29 +08:00
|
|
|
{
|
|
|
|
/* This eliminates the possibility of incrementing the
|
|
|
|
* same region twice
|
|
|
|
*/
|
|
|
|
prh->pr->process_count++;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-09-12 04:04:29 +08:00
|
|
|
/* Unref the last referenced tile if the underlying region
|
2003-07-02 02:11:18 +08:00
|
|
|
* is a tile manager
|
|
|
|
*/
|
2004-09-12 04:04:29 +08:00
|
|
|
if (prh->pr->drawable)
|
|
|
|
{
|
|
|
|
GimpTile *tile = gimp_drawable_get_tile2 (prh->pr->drawable,
|
2003-07-02 02:11:18 +08:00
|
|
|
prh->pr->shadow,
|
|
|
|
prh->pr->x,
|
|
|
|
prh->pr->y);
|
2004-09-12 04:04:29 +08:00
|
|
|
gimp_tile_unref (tile, prh->pr->dirty);
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-09-12 04:04:29 +08:00
|
|
|
prh->pr->x += pri->portion_width;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2004-09-12 04:04:29 +08:00
|
|
|
if ((prh->pr->x - prh->startx) >= pri->region_width)
|
|
|
|
{
|
2005-09-04 01:16:58 +08:00
|
|
|
prh->pr->x = prh->startx;
|
2004-09-12 04:04:29 +08:00
|
|
|
prh->pr->y += pri->portion_height;
|
|
|
|
}
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return gimp_pixel_rgns_configure (pri);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-05-31 14:15:06 +08:00
|
|
|
static gint
|
|
|
|
gimp_get_portion_width (GimpPixelRgnIterator *pri)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2004-02-17 05:32:51 +08:00
|
|
|
GSList *list;
|
|
|
|
gint min_width = G_MAXINT;
|
|
|
|
gint width;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-07-02 02:11:18 +08:00
|
|
|
/* Find the minimum width to the next vertical tile (in the case of
|
|
|
|
* a tile manager) or to the end of the pixel region (in the case of
|
|
|
|
* no tile manager)
|
1997-11-25 06:05:25 +08:00
|
|
|
*/
|
|
|
|
|
2004-02-17 05:32:51 +08:00
|
|
|
for (list = pri->pixel_regions; list; list = list->next)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2004-02-17 05:32:51 +08:00
|
|
|
GimpPixelRgnHolder *prh = list->data;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
if (prh->pr)
|
|
|
|
{
|
|
|
|
/* Check if we're past the point of no return */
|
|
|
|
if ((prh->pr->x - prh->startx) >= pri->region_width)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (prh->pr->drawable)
|
|
|
|
{
|
|
|
|
width = TILE_WIDTH - (prh->pr->x % TILE_WIDTH);
|
2002-05-03 19:31:08 +08:00
|
|
|
width = CLAMP (width,
|
|
|
|
0,
|
|
|
|
(pri->region_width - (prh->pr->x - prh->startx)));
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
else
|
2005-09-04 01:16:58 +08:00
|
|
|
{
|
|
|
|
width = (pri->region_width - (prh->pr->x - prh->startx));
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
if (width < min_width)
|
|
|
|
min_width = width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return min_width;
|
|
|
|
}
|
|
|
|
|
2004-02-17 05:32:51 +08:00
|
|
|
static gint
|
2000-05-31 14:15:06 +08:00
|
|
|
gimp_get_portion_height (GimpPixelRgnIterator *pri)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2004-02-17 05:32:51 +08:00
|
|
|
GSList *list;
|
|
|
|
gint min_height = G_MAXINT;
|
|
|
|
gint height;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-07-02 02:11:18 +08:00
|
|
|
/* Find the minimum height to the next vertical tile (in the case of
|
|
|
|
* a tile manager) or to the end of the pixel region (in the case of
|
|
|
|
* no tile manager)
|
1997-11-25 06:05:25 +08:00
|
|
|
*/
|
|
|
|
|
2004-02-17 05:32:51 +08:00
|
|
|
for (list = pri->pixel_regions; list; list = list->next)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2004-02-17 05:32:51 +08:00
|
|
|
GimpPixelRgnHolder *prh = list->data;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
if (prh->pr)
|
|
|
|
{
|
|
|
|
/* Check if we're past the point of no return */
|
|
|
|
if ((prh->pr->y - prh->starty) >= pri->region_height)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (prh->pr->drawable)
|
|
|
|
{
|
|
|
|
height = TILE_HEIGHT - (prh->pr->y % TILE_HEIGHT);
|
2002-05-03 19:31:08 +08:00
|
|
|
height = CLAMP (height,
|
|
|
|
0,
|
|
|
|
(pri->region_height - (prh->pr->y - prh->starty)));
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
else
|
2005-09-04 01:16:58 +08:00
|
|
|
{
|
|
|
|
height = (pri->region_height - (prh->pr->y - prh->starty));
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
if (height < min_height)
|
|
|
|
min_height = height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return min_height;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gpointer
|
2000-05-31 14:15:06 +08:00
|
|
|
gimp_pixel_rgns_configure (GimpPixelRgnIterator *pri)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2004-02-17 05:32:51 +08:00
|
|
|
GSList *list;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Determine the portion width and height */
|
2005-09-04 01:16:58 +08:00
|
|
|
pri->portion_width = gimp_get_portion_width (pri);
|
1997-11-25 06:05:25 +08:00
|
|
|
pri->portion_height = gimp_get_portion_height (pri);
|
|
|
|
|
2005-09-04 01:16:58 +08:00
|
|
|
if (pri->portion_width == 0 ||
|
|
|
|
pri->portion_height == 0)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
/* free the pixel regions list */
|
2004-02-17 05:32:51 +08:00
|
|
|
for (list = pri->pixel_regions; list; list = list->next)
|
|
|
|
g_free (list->data);
|
|
|
|
|
|
|
|
g_slist_free (pri->pixel_regions);
|
|
|
|
g_free (pri);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pri->process_count++;
|
|
|
|
|
2004-02-17 05:32:51 +08:00
|
|
|
for (list = pri->pixel_regions; list; list = list->next)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2004-02-17 05:32:51 +08:00
|
|
|
GimpPixelRgnHolder *prh = list->data;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
if ((prh->pr != NULL) && (prh->pr->process_count != pri->process_count))
|
|
|
|
{
|
|
|
|
prh->pr->process_count++;
|
|
|
|
gimp_pixel_rgn_configure (prh, pri);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return pri;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2000-05-31 14:15:06 +08:00
|
|
|
gimp_pixel_rgn_configure (GimpPixelRgnHolder *prh,
|
2004-09-12 04:04:29 +08:00
|
|
|
GimpPixelRgnIterator *pri)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
/* Configure the rowstride and data pointer for the pixel region
|
|
|
|
* based on the current offsets into the region and whether the
|
|
|
|
* region is represented by a tile manager or not
|
|
|
|
*/
|
|
|
|
if (prh->pr->drawable)
|
|
|
|
{
|
2000-05-31 14:15:06 +08:00
|
|
|
GimpTile *tile;
|
|
|
|
gint offx;
|
|
|
|
gint offy;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-07-02 02:11:18 +08:00
|
|
|
tile = gimp_drawable_get_tile2 (prh->pr->drawable,
|
|
|
|
prh->pr->shadow,
|
|
|
|
prh->pr->x,
|
|
|
|
prh->pr->y);
|
1997-11-25 06:05:25 +08:00
|
|
|
gimp_tile_ref (tile);
|
|
|
|
|
|
|
|
offx = prh->pr->x % TILE_WIDTH;
|
|
|
|
offy = prh->pr->y % TILE_HEIGHT;
|
|
|
|
|
|
|
|
prh->pr->rowstride = tile->ewidth * prh->pr->bpp;
|
2003-07-02 02:11:18 +08:00
|
|
|
prh->pr->data = (tile->data +
|
|
|
|
offy * prh->pr->rowstride + offx * prh->pr->bpp);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
prh->pr->data = (prh->original_data +
|
2005-09-04 01:16:58 +08:00
|
|
|
prh->pr->y * prh->pr->rowstride +
|
|
|
|
prh->pr->x * prh->pr->bpp);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
prh->pr->w = pri->portion_width;
|
|
|
|
prh->pr->h = pri->portion_height;
|
|
|
|
}
|