mirror of
https://gitlab.gnome.org/GNOME/gimp
synced 2024-10-22 04:22:29 +00:00
1ed9180112
2001-12-02 Daniel Egger <degger@fhm.edu> * app/gimprc.c: Convert ugly comments into named structure fields. Much cleaner and less errorprone though may cause troubles on older compilers and then needs to be reverted. Please report! * app/base/base-types.h: Add FIXME reminder. * app/base/gimplut.c: Use CLAMP macro instead of if-cascade. * app/base/temp-buf.c: Remove duplicated calculations and simplify checks. * app/base/tile-manager.c: - (tile_manager_get_tile_num): Return success and take an additional pointer for the tilenumber. - Simplify logic in the rest of the file as a result. - Remove rotten debugging cruft. * app/core/gimpbrushgenerated.c: Fix two stylistic nits. * app/app_procs.c: Include <stdlib.h> for exit () prototype. * app/core/gimpdrawable-blend.c: Include <stdlib.h> for abs () prototype. * app/display/gimpdisplay.c: Include <string.h> for memcpy () prototype. * app/core/gimpimage-convert.c: (HIST_RGB): First parameter is not const. Fixes a gcc warning for a wrong return value. * libgimpwidgets/gimpunitmenu.c * app/core/gimpunit.c: Add suggested (by gcc 3.1 cvs) parentheses to group correct logic tests together. * app/paint-funcs/paint-funcs-generic.h: Fix my HAS_ALPHA macro to avoid gcc 3.1 cvs warning. * app/gimprc.h * pathP.h * base-config.h * app/base/boundary.h * app/base/gimplut.[ch] * app/base/pixel-region.h * app/base/pixel-surround.[ch] * app/base/temp-buf.[ch] * app/base/tile-manager-private.h * app/base/tile-manager.c * app/base/tile-private.h * app/base/tile.[ch] * app/core/gimp.h * app/core/gimpbrushgenerated.h * app/core/gimpbrushpipe.h * app/core/gimpchannel.[ch] * app/core/gimpcontainer.h * app/core/gimpcoreconfig.h * app/core/gimpdata.h * app/core/gimpdatafactory.[ch] * app/core/gimpdrawable-blend.c * app/core/gimpdrawable.[ch] * app/core/gimpimage.h * app/core/gimpimagefile.h * app/core/gimplayer.h * app/core/gimplayermask.h * app/core/gimpmoduleinfo.h * app/core/gimppalette.h * app/core/gimpundo.h * app/display/gimpdisplay.h * app/display/gimpdisplayshell-selection.h * app/display/gimpdisplayshell.h * app/gui/brush-select.h * app/gui/gradient-editor.h * app/gui/gradient-select.h * app/gui/info-dialog.h * app/gui/resize-dialog.h * app/tools/gimpbezierselecttool.h * app/tools/gimpcolorbalancetool.h * app/tools/gimpcolorpickertool.h * app/tools/gimpcurvestool.h * app/tools/gimpdodgeburntool.c * app/tools/gimpfreeselecttool.h * app/tools/gimpfuzzyselecttool.h * app/tools/gimphuesaturationtool.h * app/tools/gimpinktool-blob.h * app/tools/gimpinktool.h * app/tools/gimpiscissorstool.h * app/tools/gimpmagnifytool.h * app/tools/gimpmeasuretool.h * app/tools/gimppainttool.h * app/tools/gimppathtool.h * app/tools/gimprectselecttool.h * app/tools/gimpthresholdtool.h * app/tools/gimptool.h * app/tools/gimptransformtool.h * app/tools/path_toolP.h * app/widgets/gimpbrushfactoryview.h * app/widgets/gimpconstrainedhwrapbox.h * app/widgets/gimpcontainermenu.h * app/widgets/gimpcontainerview.h * app/widgets/gimpdialogfactory.h * app/widgets/gimpimagedock.h * app/widgets/gimplistitem.h * app/widgets/gimpmenuitem.h * app/widgets/gimpnavigationpreview.h * app/widgets/gimppreview.h: Unsignify lots of variables and parameters and use bitfields in structs where possible. First part of a huge cleanup all over the code...
769 lines
16 KiB
C
769 lines
16 KiB
C
/* The GIMP -- an 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 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 <string.h>
|
|
|
|
#include <glib.h>
|
|
|
|
#include "base-types.h"
|
|
|
|
#include "tile.h"
|
|
#include "tile-private.h"
|
|
#include "tile-cache.h"
|
|
#include "tile-manager.h"
|
|
#include "tile-manager-private.h"
|
|
#include "tile-swap.h"
|
|
|
|
|
|
static inline gboolean
|
|
tile_manager_get_tile_num (TileManager *tm,
|
|
gint xpixel,
|
|
gint ypixel,
|
|
guint *tile_num);
|
|
|
|
|
|
TileManager *
|
|
tile_manager_new (guint toplevel_width,
|
|
guint toplevel_height,
|
|
guint bpp)
|
|
{
|
|
TileManager *tm;
|
|
gint width;
|
|
gint height;
|
|
|
|
tm = g_new (TileManager, 1);
|
|
|
|
tm->user_data = NULL;
|
|
tm->validate_proc = NULL;
|
|
|
|
width = toplevel_width;
|
|
height = toplevel_height;
|
|
|
|
tm->x = 0;
|
|
tm->y = 0;
|
|
tm->width = width;
|
|
tm->height = height;
|
|
tm->bpp = bpp;
|
|
tm->ntile_rows = (height + TILE_HEIGHT - 1) / TILE_HEIGHT;
|
|
tm->ntile_cols = (width + TILE_WIDTH - 1) / TILE_WIDTH;
|
|
tm->tiles = NULL;
|
|
|
|
return tm;
|
|
}
|
|
|
|
void
|
|
tile_manager_destroy (TileManager *tm)
|
|
{
|
|
guint ntiles;
|
|
guint i;
|
|
|
|
g_return_if_fail (tm != NULL);
|
|
|
|
if (tm->tiles)
|
|
{
|
|
ntiles = tm->ntile_rows * tm->ntile_cols;
|
|
|
|
for (i = 0; i < ntiles; i++)
|
|
{
|
|
TILE_MUTEX_LOCK (tm->tiles[i]);
|
|
tile_detach (tm->tiles[i], tm, i);
|
|
}
|
|
|
|
g_free (tm->tiles);
|
|
}
|
|
|
|
g_free (tm);
|
|
}
|
|
|
|
|
|
void
|
|
tile_manager_set_validate_proc (TileManager *tm,
|
|
TileValidateProc proc)
|
|
{
|
|
g_return_if_fail (tm != NULL);
|
|
|
|
tm->validate_proc = proc;
|
|
}
|
|
|
|
|
|
Tile *
|
|
tile_manager_get_tile (TileManager *tm,
|
|
gint xpixel,
|
|
gint ypixel,
|
|
gboolean wantread,
|
|
gboolean wantwrite)
|
|
{
|
|
guint tile_num;
|
|
|
|
g_return_val_if_fail (tm != NULL, NULL);
|
|
|
|
if (!tile_manager_get_tile_num (tm, xpixel, ypixel, &tile_num))
|
|
return NULL;
|
|
|
|
return tile_manager_get (tm, tile_num, wantread, wantwrite);
|
|
}
|
|
|
|
Tile *
|
|
tile_manager_get (TileManager *tm,
|
|
guint tile_num,
|
|
gboolean wantread,
|
|
gboolean wantwrite)
|
|
{
|
|
Tile **tiles;
|
|
Tile **tile_ptr;
|
|
guint ntiles;
|
|
guint nrows, ncols;
|
|
gint right_tile;
|
|
gint bottom_tile;
|
|
guint i, j, k;
|
|
|
|
g_return_val_if_fail (tm != NULL, NULL);
|
|
|
|
ntiles = tm->ntile_rows * tm->ntile_cols;
|
|
|
|
if (tile_num >= ntiles)
|
|
return NULL;
|
|
|
|
if (!tm->tiles)
|
|
{
|
|
tm->tiles = g_new (Tile *, ntiles);
|
|
tiles = tm->tiles;
|
|
|
|
nrows = tm->ntile_rows;
|
|
ncols = tm->ntile_cols;
|
|
|
|
right_tile = tm->width - ((ncols - 1) * TILE_WIDTH);
|
|
bottom_tile = tm->height - ((nrows - 1) * TILE_HEIGHT);
|
|
|
|
for (i = 0, k = 0; i < nrows; i++)
|
|
{
|
|
for (j = 0; j < ncols; j++, k++)
|
|
{
|
|
tiles[k] = g_new (Tile, 1);
|
|
tile_init (tiles[k], tm->bpp);
|
|
tile_attach (tiles[k], tm, k);
|
|
|
|
if (j == (ncols - 1))
|
|
tiles[k]->ewidth = right_tile;
|
|
|
|
if (i == (nrows - 1))
|
|
tiles[k]->eheight = bottom_tile;
|
|
}
|
|
}
|
|
}
|
|
|
|
tile_ptr = &tm->tiles[tile_num];
|
|
|
|
if (wantwrite && !wantread)
|
|
{
|
|
g_warning("WRITE-ONLY TILE... UNTESTED!");
|
|
}
|
|
|
|
if (wantread)
|
|
{
|
|
TILE_MUTEX_LOCK (*tile_ptr);
|
|
if (wantwrite)
|
|
{
|
|
if ((*tile_ptr)->share_count > 1)
|
|
{
|
|
/* Copy-on-write required */
|
|
Tile *newtile = g_new (Tile, 1);
|
|
|
|
tile_init (newtile, (*tile_ptr)->bpp);
|
|
newtile->ewidth = (*tile_ptr)->ewidth;
|
|
newtile->eheight = (*tile_ptr)->eheight;
|
|
newtile->valid = (*tile_ptr)->valid;
|
|
newtile->data = g_new (guchar, tile_size (newtile));
|
|
|
|
if (!newtile->valid)
|
|
g_warning ("Oh boy, r/w tile is invalid... we suck. Please report.");
|
|
|
|
if ((*tile_ptr)->rowhint)
|
|
{
|
|
tile_sanitize_rowhints (newtile);
|
|
i = newtile->eheight;
|
|
while (i--)
|
|
{
|
|
newtile->rowhint[i] = (*tile_ptr)->rowhint[i];
|
|
}
|
|
}
|
|
|
|
if ((*tile_ptr)->data != NULL)
|
|
{
|
|
memcpy (newtile->data, (*tile_ptr)->data, tile_size (newtile));
|
|
}
|
|
else
|
|
{
|
|
tile_lock (*tile_ptr);
|
|
memcpy (newtile->data, (*tile_ptr)->data, tile_size (newtile));
|
|
tile_release (*tile_ptr, FALSE);
|
|
}
|
|
|
|
tile_detach (*tile_ptr, tm, tile_num);
|
|
TILE_MUTEX_LOCK (newtile);
|
|
tile_attach (newtile, tm, tile_num);
|
|
*tile_ptr = newtile;
|
|
}
|
|
|
|
(*tile_ptr)->write_count++;
|
|
(*tile_ptr)->dirty = TRUE;
|
|
}
|
|
TILE_MUTEX_UNLOCK (*tile_ptr);
|
|
tile_lock (*tile_ptr);
|
|
}
|
|
|
|
return *tile_ptr;
|
|
}
|
|
|
|
void
|
|
tile_manager_get_async (TileManager *tm,
|
|
gint xpixel,
|
|
gint ypixel)
|
|
{
|
|
Tile *tile_ptr;
|
|
guint tile_num;
|
|
|
|
g_return_if_fail (tm != NULL);
|
|
|
|
if (!tile_manager_get_tile_num (tm, xpixel, ypixel, &tile_num))
|
|
return;
|
|
|
|
tile_ptr = tm->tiles[tile_num];
|
|
tile_swap_in_async (tile_ptr);
|
|
}
|
|
|
|
void
|
|
tile_manager_validate (TileManager *tm,
|
|
Tile *tile)
|
|
{
|
|
g_return_if_fail (tm != NULL);
|
|
g_return_if_fail (tile != NULL);
|
|
|
|
tile->valid = TRUE;
|
|
|
|
if (tm->validate_proc)
|
|
(* tm->validate_proc) (tm, tile);
|
|
}
|
|
|
|
void
|
|
tile_manager_invalidate_tiles (TileManager *tm,
|
|
Tile *toplevel_tile)
|
|
{
|
|
gdouble x, y;
|
|
gint row, col;
|
|
gint num;
|
|
|
|
g_return_if_fail (tm != NULL);
|
|
g_return_if_fail (toplevel_tile != NULL);
|
|
|
|
col = toplevel_tile->tlink->tile_num % tm->ntile_cols;
|
|
row = toplevel_tile->tlink->tile_num / tm->ntile_cols;
|
|
|
|
x = (col * TILE_WIDTH + toplevel_tile->ewidth / 2.0) / (gdouble) tm->width;
|
|
y = (row * TILE_HEIGHT + toplevel_tile->eheight / 2.0) / (gdouble) tm->height;
|
|
|
|
if (tm->tiles)
|
|
{
|
|
col = x * tm->width / TILE_WIDTH;
|
|
row = y * tm->height / TILE_HEIGHT;
|
|
num = row * tm->ntile_cols + col;
|
|
tile_invalidate (&tm->tiles[num], tm, num);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
tile_invalidate_tile (Tile **tile_ptr,
|
|
TileManager *tm,
|
|
gint xpixel,
|
|
gint ypixel)
|
|
{
|
|
guint tile_num;
|
|
|
|
g_return_if_fail (tile_ptr != NULL);
|
|
g_return_if_fail (tm != NULL);
|
|
|
|
if (!tile_manager_get_tile_num (tm, xpixel, ypixel, &tile_num))
|
|
return;
|
|
|
|
tile_invalidate (tile_ptr, tm, tile_num);
|
|
}
|
|
|
|
|
|
void
|
|
tile_invalidate (Tile **tile_ptr,
|
|
TileManager *tm,
|
|
guint tile_num)
|
|
{
|
|
Tile *tile = *tile_ptr;
|
|
|
|
g_return_if_fail (tile_ptr != NULL);
|
|
g_return_if_fail (tm != NULL);
|
|
|
|
TILE_MUTEX_LOCK (tile);
|
|
|
|
if (!tile->valid)
|
|
goto leave;
|
|
|
|
if (tile->share_count > 1)
|
|
{
|
|
/* This tile is shared. Replace it with a new, invalid tile. */
|
|
Tile *newtile = g_new (Tile, 1);
|
|
|
|
tile_init (newtile, tile->bpp);
|
|
newtile->ewidth = tile->ewidth;
|
|
newtile->eheight = tile->eheight;
|
|
tile_detach (tile, tm, tile_num);
|
|
TILE_MUTEX_LOCK (newtile);
|
|
tile_attach (newtile, tm, tile_num);
|
|
tile = *tile_ptr = newtile;
|
|
}
|
|
|
|
if (tile->listhead)
|
|
tile_cache_flush (tile);
|
|
|
|
tile->valid = FALSE;
|
|
if (tile->data)
|
|
{
|
|
g_free (tile->data);
|
|
tile->data = NULL;
|
|
}
|
|
if (tile->swap_offset != -1)
|
|
{
|
|
/* If the tile is on disk, then delete its
|
|
* presence there.
|
|
*/
|
|
tile_swap_delete (tile);
|
|
}
|
|
|
|
leave:
|
|
TILE_MUTEX_UNLOCK (tile);
|
|
}
|
|
|
|
|
|
void
|
|
tile_manager_map_tile (TileManager *tm,
|
|
gint xpixel,
|
|
gint ypixel,
|
|
Tile *srctile)
|
|
{
|
|
guint tile_num;
|
|
|
|
g_return_if_fail (srctile != NULL);
|
|
|
|
if (!tile_manager_get_tile_num (tm, xpixel, ypixel, &tile_num))
|
|
return;
|
|
|
|
tile_manager_map (tm, tile_num, srctile);
|
|
}
|
|
|
|
void
|
|
tile_manager_map (TileManager *tm,
|
|
gint tile_num,
|
|
Tile *srctile)
|
|
{
|
|
Tile **tiles;
|
|
Tile **tile_ptr;
|
|
gint ntiles;
|
|
gint nrows, ncols;
|
|
gint right_tile;
|
|
gint bottom_tile;
|
|
gint i, j, k;
|
|
|
|
g_return_if_fail (tm != NULL);
|
|
g_return_if_fail (srctile != NULL);
|
|
|
|
ntiles = tm->ntile_rows * tm->ntile_cols;
|
|
|
|
if ((tile_num < 0) || (tile_num >= ntiles))
|
|
{
|
|
g_warning ("tile_manager_map: tile out of range.");
|
|
return;
|
|
}
|
|
|
|
if (!tm->tiles)
|
|
{
|
|
g_warning ("tile_manager_map: empty tile level - init'ing.");
|
|
|
|
tm->tiles = g_new (Tile *, ntiles);
|
|
tiles = tm->tiles;
|
|
|
|
nrows = tm->ntile_rows;
|
|
ncols = tm->ntile_cols;
|
|
|
|
right_tile = tm->width - ((ncols - 1) * TILE_WIDTH);
|
|
bottom_tile = tm->height - ((nrows - 1) * TILE_HEIGHT);
|
|
|
|
for (i = 0, k = 0; i < nrows; i++)
|
|
{
|
|
for (j = 0; j < ncols; j++, k++)
|
|
{
|
|
tiles[k] = g_new (Tile, 1);
|
|
tile_init (tiles[k], tm->bpp);
|
|
tile_attach (tiles[k], tm, k);
|
|
|
|
if (j == (ncols - 1))
|
|
tiles[k]->ewidth = right_tile;
|
|
|
|
if (i == (nrows - 1))
|
|
tiles[k]->eheight = bottom_tile;
|
|
}
|
|
}
|
|
}
|
|
|
|
tile_ptr = &tm->tiles[tile_num];
|
|
|
|
if (!srctile->valid)
|
|
g_warning("tile_manager_map: srctile not validated yet! please report.");
|
|
|
|
TILE_MUTEX_LOCK (*tile_ptr);
|
|
if ((*tile_ptr)->ewidth != srctile->ewidth ||
|
|
(*tile_ptr)->eheight != srctile->eheight ||
|
|
(*tile_ptr)->bpp != srctile->bpp)
|
|
{
|
|
g_warning ("tile_manager_map: nonconformant map (%p -> %p)",
|
|
srctile, *tile_ptr);
|
|
}
|
|
tile_detach (*tile_ptr, tm, tile_num);
|
|
|
|
TILE_MUTEX_LOCK (srctile);
|
|
tile_attach (srctile, tm, tile_num);
|
|
*tile_ptr = srctile;
|
|
TILE_MUTEX_UNLOCK (srctile);
|
|
}
|
|
|
|
static inline gboolean
|
|
tile_manager_get_tile_num (TileManager *tm,
|
|
gint xpixel,
|
|
gint ypixel,
|
|
guint *tile_num)
|
|
{
|
|
guint tile_row;
|
|
guint tile_col;
|
|
|
|
g_return_val_if_fail (tm != NULL, FALSE);
|
|
|
|
if ((xpixel < 0) || (ypixel < 0) ||
|
|
(xpixel >= tm->width) || (ypixel >= tm->height))
|
|
return FALSE;
|
|
|
|
tile_row = ypixel / TILE_HEIGHT;
|
|
tile_col = xpixel / TILE_WIDTH;
|
|
*tile_num = tile_row * tm->ntile_cols + tile_col;
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
tile_manager_set_user_data (TileManager *tm,
|
|
gpointer user_data)
|
|
{
|
|
g_return_if_fail (tm != NULL);
|
|
|
|
tm->user_data = user_data;
|
|
}
|
|
|
|
gpointer
|
|
tile_manager_get_user_data (const TileManager *tm)
|
|
{
|
|
g_return_val_if_fail (tm != NULL, NULL);
|
|
|
|
return tm->user_data;
|
|
}
|
|
|
|
gint
|
|
tile_manager_width (const TileManager *tm)
|
|
{
|
|
g_return_val_if_fail (tm != NULL, 0);
|
|
|
|
return tm->width;
|
|
}
|
|
|
|
gint
|
|
tile_manager_height (const TileManager *tm)
|
|
{
|
|
g_return_val_if_fail (tm != NULL, 0);
|
|
|
|
return tm->height;
|
|
}
|
|
|
|
gint
|
|
tile_manager_bpp (const TileManager *tm)
|
|
{
|
|
g_return_val_if_fail (tm != NULL, 0);
|
|
|
|
return tm->bpp;
|
|
}
|
|
|
|
void
|
|
tile_manager_get_offsets (const TileManager *tm,
|
|
gint *x,
|
|
gint *y)
|
|
{
|
|
g_return_if_fail (x!= NULL && y != NULL);
|
|
|
|
*x = tm->x;
|
|
*y = tm->y;
|
|
}
|
|
|
|
void
|
|
tile_manager_set_offsets (TileManager *tm,
|
|
gint x,
|
|
gint y)
|
|
{
|
|
g_return_if_fail (tm != NULL);
|
|
|
|
tm->x = x;
|
|
tm->y = y;
|
|
}
|
|
|
|
void
|
|
tile_manager_get_tile_coordinates (TileManager *tm,
|
|
Tile *tile,
|
|
gint *x,
|
|
gint *y)
|
|
{
|
|
TileLink *tl;
|
|
|
|
g_return_if_fail (tm != NULL);
|
|
g_return_if_fail (x != NULL && y != NULL);
|
|
|
|
for (tl = tile->tlink; tl; tl = tl->next)
|
|
{
|
|
if (tl->tm == tm) break;
|
|
}
|
|
|
|
if (tl == NULL)
|
|
{
|
|
g_warning ("tile_manager_get_tile_coordinates: tile not attached to manager");
|
|
return;
|
|
}
|
|
|
|
*x = TILE_WIDTH * (tl->tile_num % tm->ntile_cols);
|
|
*y = TILE_HEIGHT * (tl->tile_num / tm->ntile_cols);
|
|
}
|
|
|
|
|
|
void
|
|
tile_manager_map_over_tile (TileManager *tm,
|
|
Tile *tile,
|
|
Tile *srctile)
|
|
{
|
|
TileLink *tl;
|
|
|
|
g_return_if_fail (tm != NULL);
|
|
g_return_if_fail (tile != NULL);
|
|
g_return_if_fail (srctile != NULL);
|
|
|
|
for (tl = tile->tlink; tl; tl = tl->next)
|
|
{
|
|
if (tl->tm == tm) break;
|
|
}
|
|
|
|
if (tl == NULL)
|
|
{
|
|
g_warning ("tile_manager_map_over_tile: tile not attached to manager");
|
|
return;
|
|
}
|
|
|
|
tile_manager_map (tm, tl->tile_num, srctile);
|
|
}
|
|
|
|
PixelDataHandle *
|
|
request_pixel_data (TileManager *tm,
|
|
gint x1,
|
|
gint y1,
|
|
gint x2,
|
|
gint y2,
|
|
gboolean wantread,
|
|
gboolean wantwrite)
|
|
{
|
|
PixelDataHandlePrivate *pdh;
|
|
guint tile_num_1, tile_num_2;
|
|
guint w, h;
|
|
|
|
pdh = g_new (PixelDataHandlePrivate, 1);
|
|
pdh->tm = tm;
|
|
pdh->readable = wantread;
|
|
pdh->writeable = wantwrite;
|
|
pdh->x1 = x1;
|
|
pdh->y1 = y1;
|
|
pdh->x2 = x2;
|
|
pdh->y2 = y2;
|
|
pdh->public.width = w = (x2-x1)+1;
|
|
pdh->public.height = h = (y2-y1)+1;
|
|
|
|
tile_manager_get_tile_num (tm, x1, y1, &tile_num_1);
|
|
tile_manager_get_tile_num (tm, x2, y2, &tile_num_2);
|
|
|
|
/* FIXME: What if both nums are -1 aka inavlid? */
|
|
if (tile_num_1 == tile_num_2)
|
|
{
|
|
pdh->tile = tile_manager_get (tm, tile_num_1, wantread, wantwrite);
|
|
pdh->public.data = tile_data_pointer (pdh->tile, x1 % TILE_WIDTH, y1 % TILE_HEIGHT);
|
|
pdh->public.stride = tile_bpp (pdh->tile) * tile_ewidth (pdh->tile);
|
|
pdh->local_buffer = FALSE;
|
|
}
|
|
else
|
|
{
|
|
pdh->public.data = g_new (guchar, w * h * tm->bpp);
|
|
pdh->public.stride = tm->bpp * w;
|
|
pdh->local_buffer = TRUE;
|
|
pdh->tile = NULL;
|
|
|
|
if (wantread)
|
|
read_pixel_data (tm, x1, y1, x2, y2,
|
|
pdh->public.data, pdh->public.stride);
|
|
}
|
|
return (PixelDataHandle *) pdh;
|
|
}
|
|
|
|
void
|
|
release_pixel_data (PixelDataHandle *xpdh)
|
|
{
|
|
PixelDataHandlePrivate *pdh = (PixelDataHandlePrivate *)(xpdh);
|
|
|
|
if (pdh->local_buffer)
|
|
{
|
|
if (pdh->writeable)
|
|
write_pixel_data (pdh->tm, pdh->x1, pdh->y1, pdh->x2, pdh->y2,
|
|
pdh->public.data, pdh->public.stride);
|
|
g_free (pdh->public.data);
|
|
}
|
|
else
|
|
{
|
|
tile_release (pdh->tile, pdh->writeable);
|
|
}
|
|
g_free (pdh);
|
|
}
|
|
|
|
void
|
|
read_pixel_data (TileManager *tm,
|
|
gint x1,
|
|
gint y1,
|
|
gint x2,
|
|
gint y2,
|
|
guchar *buffer,
|
|
guint stride)
|
|
{
|
|
guint x, y;
|
|
guint rows, cols;
|
|
guint srcstride;
|
|
Tile *t;
|
|
guchar *s, *d;
|
|
|
|
for (y = y1; y <= y2; y += TILE_HEIGHT - (y % TILE_HEIGHT))
|
|
for (x = x1; x <= x2; x += TILE_WIDTH - (x % TILE_WIDTH))
|
|
{
|
|
t = tile_manager_get_tile (tm, x, y, TRUE, FALSE);
|
|
s = tile_data_pointer (t, x % TILE_WIDTH, y % TILE_HEIGHT);
|
|
d = buffer + stride * (y - y1) + tm->bpp * (x - x1);
|
|
rows = tile_eheight (t) - y % TILE_HEIGHT;
|
|
if (rows > (y2 - y + 1))
|
|
rows = y2 - y + 1;
|
|
|
|
cols = tile_ewidth (t) - x % TILE_WIDTH;
|
|
if (cols > (x2 - x + 1))
|
|
cols = x2 - x + 1;
|
|
|
|
srcstride = tile_ewidth (t) * tile_bpp (t);
|
|
|
|
while (rows --)
|
|
{
|
|
memcpy (d, s, cols * tm->bpp);
|
|
s += srcstride;
|
|
d += stride;
|
|
}
|
|
|
|
tile_release (t, FALSE);
|
|
}
|
|
}
|
|
|
|
void
|
|
write_pixel_data (TileManager *tm,
|
|
gint x1,
|
|
gint y1,
|
|
gint x2,
|
|
gint y2,
|
|
guchar *buffer,
|
|
guint stride)
|
|
{
|
|
guint x, y;
|
|
guint rows, cols;
|
|
guint dststride;
|
|
Tile *t;
|
|
guchar *s, *d;
|
|
|
|
for (y = y1; y <= y2; y += TILE_HEIGHT - (y % TILE_HEIGHT))
|
|
for (x = x1; x <= x2; x += TILE_WIDTH - (x % TILE_WIDTH))
|
|
{
|
|
t = tile_manager_get_tile (tm, x, y, TRUE, TRUE);
|
|
s = buffer + stride * (y - y1) + tm->bpp * (x - x1);
|
|
d = tile_data_pointer (t, x % TILE_WIDTH, y % TILE_HEIGHT);
|
|
rows = tile_eheight (t) - y % TILE_HEIGHT;
|
|
if (rows > (y2 - y + 1))
|
|
rows = y2 - y + 1;
|
|
|
|
cols = tile_ewidth (t) - x % TILE_WIDTH;
|
|
if (cols > (x2 - x + 1))
|
|
cols = x2 - x + 1;
|
|
|
|
dststride = tile_ewidth (t) * tile_bpp (t);
|
|
|
|
while (rows --)
|
|
{
|
|
memcpy (d, s, cols * tm->bpp);
|
|
s += stride;
|
|
d += dststride;
|
|
}
|
|
|
|
tile_release (t, TRUE);
|
|
}
|
|
}
|
|
|
|
void
|
|
read_pixel_data_1 (TileManager *tm,
|
|
gint x,
|
|
gint y,
|
|
guchar *buffer)
|
|
{
|
|
Tile *t;
|
|
guchar *s;
|
|
|
|
t = tile_manager_get_tile (tm, x, y, TRUE, FALSE);
|
|
s = tile_data_pointer (t, x % TILE_WIDTH, y % TILE_HEIGHT);
|
|
memcpy (buffer, s, tm->bpp);
|
|
tile_release (t, FALSE);
|
|
}
|
|
|
|
void
|
|
write_pixel_data_1 (TileManager *tm,
|
|
gint x,
|
|
gint y,
|
|
guchar *buffer)
|
|
{
|
|
Tile *t;
|
|
guchar *d;
|
|
|
|
t = tile_manager_get_tile (tm, x, y, TRUE, TRUE);
|
|
d = tile_data_pointer (t, x % TILE_WIDTH, y % TILE_HEIGHT);
|
|
memcpy (d, buffer, tm->bpp);
|
|
tile_release (t, TRUE);
|
|
}
|