2006-12-10 05:33:38 +08:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
1997-11-25 06:05:25 +08:00
|
|
|
* 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
|
1998-04-13 13:44:11 +08:00
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
1997-11-25 06:05:25 +08:00
|
|
|
*/
|
2000-12-17 05:37:03 +08:00
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2000-04-28 01:27:28 +08:00
|
|
|
|
2000-12-17 05:37:03 +08:00
|
|
|
#include <gtk/gtk.h>
|
|
|
|
|
2004-09-03 08:06:21 +08:00
|
|
|
#include "libgimpbase/gimpbase.h"
|
2007-03-09 21:00:01 +08:00
|
|
|
#include "libgimpmath/gimpmath.h"
|
2002-10-20 18:14:17 +08:00
|
|
|
#include "libgimpwidgets/gimpwidgets.h"
|
|
|
|
|
2001-09-26 07:23:09 +08:00
|
|
|
#include "display-types.h"
|
2000-12-17 05:37:03 +08:00
|
|
|
|
2001-05-15 19:25:25 +08:00
|
|
|
#include "base/tile-manager.h"
|
|
|
|
#include "base/tile.h"
|
|
|
|
|
2002-11-21 23:46:19 +08:00
|
|
|
#include "core/gimp.h"
|
2005-07-31 02:19:54 +08:00
|
|
|
#include "core/gimpdrawable.h"
|
2001-05-09 10:32:03 +08:00
|
|
|
#include "core/gimpimage.h"
|
2003-03-19 22:44:08 +08:00
|
|
|
#include "core/gimpimage-colormap.h"
|
2004-07-14 00:36:29 +08:00
|
|
|
#include "core/gimpprojection.h"
|
2001-05-09 10:32:03 +08:00
|
|
|
|
2005-07-20 04:42:14 +08:00
|
|
|
#include "widgets/gimprender.h"
|
|
|
|
|
2003-11-10 07:24:40 +08:00
|
|
|
#include "gimpcanvas.h"
|
2001-09-26 07:23:09 +08:00
|
|
|
#include "gimpdisplay.h"
|
2001-11-01 05:20:09 +08:00
|
|
|
#include "gimpdisplayshell.h"
|
2002-03-15 06:42:50 +08:00
|
|
|
#include "gimpdisplayshell-filter.h"
|
2001-11-02 17:31:21 +08:00
|
|
|
#include "gimpdisplayshell-render.h"
|
2001-09-26 07:23:09 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
typedef struct _RenderInfo RenderInfo;
|
2001-01-30 11:17:26 +08:00
|
|
|
|
|
|
|
typedef void (* RenderFunc) (RenderInfo *info);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
struct _RenderInfo
|
|
|
|
{
|
2001-12-01 02:23:49 +08:00
|
|
|
GimpDisplayShell *shell;
|
|
|
|
TileManager *src_tiles;
|
2007-03-14 22:37:04 +08:00
|
|
|
const guint *alpha;
|
|
|
|
const guchar *src;
|
2001-12-01 02:23:49 +08:00
|
|
|
guchar *dest;
|
|
|
|
gint x, y;
|
|
|
|
gint w, h;
|
2004-02-04 10:00:04 +08:00
|
|
|
gdouble scalex;
|
|
|
|
gdouble scaley;
|
2005-07-31 06:29:02 +08:00
|
|
|
gint src_x;
|
|
|
|
gint src_y;
|
2001-12-01 02:23:49 +08:00
|
|
|
gint dest_bpp;
|
|
|
|
gint dest_bpl;
|
|
|
|
gint dest_width;
|
2007-08-14 23:17:30 +08:00
|
|
|
|
|
|
|
gint xstart;
|
|
|
|
gint xdelta;
|
2007-08-16 05:29:43 +08:00
|
|
|
gint yfraction;
|
1997-11-25 06:05:25 +08:00
|
|
|
};
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
static void gimp_display_shell_render_info_scale (RenderInfo *info,
|
|
|
|
GimpDisplayShell *shell,
|
|
|
|
TileManager *src_tiles,
|
|
|
|
gdouble scale_x,
|
|
|
|
gdouble scale_y);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
static void gimp_display_shell_render_setup_notify (GObject *config,
|
|
|
|
GParamSpec *param_spec,
|
|
|
|
Gimp *gimp);
|
2002-11-21 23:46:19 +08:00
|
|
|
|
|
|
|
|
2005-07-20 04:42:14 +08:00
|
|
|
static guchar *tile_buf = NULL;
|
2007-03-14 22:37:04 +08:00
|
|
|
|
2005-07-20 04:42:14 +08:00
|
|
|
static guint check_mod = 0;
|
|
|
|
static guint check_shift = 0;
|
2004-09-02 22:28:37 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
void
|
2005-07-20 04:42:14 +08:00
|
|
|
gimp_display_shell_render_init (Gimp *gimp)
|
2002-11-21 23:46:19 +08:00
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_GIMP (gimp));
|
2007-03-14 22:37:04 +08:00
|
|
|
g_return_if_fail (tile_buf == NULL);
|
2002-11-21 23:46:19 +08:00
|
|
|
|
2003-01-06 06:07:10 +08:00
|
|
|
g_signal_connect (gimp->config, "notify::transparency-size",
|
2007-08-16 05:29:43 +08:00
|
|
|
G_CALLBACK (gimp_display_shell_render_setup_notify),
|
2002-11-21 23:46:19 +08:00
|
|
|
gimp);
|
2003-01-06 06:07:10 +08:00
|
|
|
g_signal_connect (gimp->config, "notify::transparency-type",
|
2007-08-16 05:29:43 +08:00
|
|
|
G_CALLBACK (gimp_display_shell_render_setup_notify),
|
2002-11-21 23:46:19 +08:00
|
|
|
gimp);
|
|
|
|
|
2007-03-14 22:37:04 +08:00
|
|
|
/* allocate a buffer for arranging information from a row of tiles */
|
|
|
|
tile_buf = g_new (guchar, GIMP_RENDER_BUF_WIDTH * MAX_CHANNELS);
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
gimp_display_shell_render_setup_notify (G_OBJECT (gimp->config), NULL, gimp);
|
2002-11-21 23:46:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2005-07-20 04:42:14 +08:00
|
|
|
gimp_display_shell_render_exit (Gimp *gimp)
|
2002-11-21 23:46:19 +08:00
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_GIMP (gimp));
|
|
|
|
|
2003-01-06 06:07:10 +08:00
|
|
|
g_signal_handlers_disconnect_by_func (gimp->config,
|
2007-08-16 05:29:43 +08:00
|
|
|
gimp_display_shell_render_setup_notify,
|
2002-11-21 23:46:19 +08:00
|
|
|
gimp);
|
|
|
|
|
|
|
|
if (tile_buf)
|
|
|
|
{
|
|
|
|
g_free (tile_buf);
|
|
|
|
tile_buf = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-08-16 05:29:43 +08:00
|
|
|
gimp_display_shell_render_setup_notify (GObject *config,
|
|
|
|
GParamSpec *param_spec,
|
|
|
|
Gimp *gimp)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2002-11-21 23:46:19 +08:00
|
|
|
GimpCheckSize check_size;
|
2001-01-30 11:17:26 +08:00
|
|
|
|
2002-11-21 23:46:19 +08:00
|
|
|
g_object_get (config,
|
|
|
|
"transparency-size", &check_size,
|
|
|
|
NULL);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
switch (check_size)
|
|
|
|
{
|
2004-09-02 22:28:37 +08:00
|
|
|
case GIMP_CHECK_SIZE_SMALL_CHECKS:
|
2001-01-30 11:17:26 +08:00
|
|
|
check_mod = 0x3;
|
1997-11-25 06:05:25 +08:00
|
|
|
check_shift = 2;
|
|
|
|
break;
|
2007-08-16 05:29:43 +08:00
|
|
|
|
2004-09-02 22:28:37 +08:00
|
|
|
case GIMP_CHECK_SIZE_MEDIUM_CHECKS:
|
2001-01-30 11:17:26 +08:00
|
|
|
check_mod = 0x7;
|
1997-11-25 06:05:25 +08:00
|
|
|
check_shift = 3;
|
|
|
|
break;
|
2007-08-16 05:29:43 +08:00
|
|
|
|
2004-09-02 22:28:37 +08:00
|
|
|
case GIMP_CHECK_SIZE_LARGE_CHECKS:
|
2001-01-30 11:17:26 +08:00
|
|
|
check_mod = 0xf;
|
1997-11-25 06:05:25 +08:00
|
|
|
check_shift = 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-01-30 11:17:26 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Render Image functions */
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
static void render_image_rgb (RenderInfo *info);
|
|
|
|
static void render_image_rgb_a (RenderInfo *info);
|
|
|
|
static void render_image_gray (RenderInfo *info);
|
|
|
|
static void render_image_gray_a (RenderInfo *info);
|
|
|
|
static void render_image_indexed (RenderInfo *info);
|
|
|
|
static void render_image_indexed_a (RenderInfo *info);
|
2001-12-01 02:23:49 +08:00
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
static const guint * render_image_init_alpha (gint mult);
|
2007-03-14 22:37:04 +08:00
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
static const guchar * render_image_tile_fault (RenderInfo *info);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
|
1998-08-20 14:46:07 +08:00
|
|
|
static RenderFunc render_funcs[6] =
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-01-30 11:17:26 +08:00
|
|
|
render_image_rgb,
|
|
|
|
render_image_rgb_a,
|
|
|
|
render_image_gray,
|
|
|
|
render_image_gray_a,
|
|
|
|
render_image_indexed,
|
|
|
|
render_image_indexed_a,
|
1997-11-25 06:05:25 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2004-10-01 17:50:04 +08:00
|
|
|
static void gimp_display_shell_render_highlight (GimpDisplayShell *shell,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint w,
|
|
|
|
gint h,
|
|
|
|
GdkRectangle *highlight);
|
2005-07-31 06:29:02 +08:00
|
|
|
static void gimp_display_shell_render_mask (GimpDisplayShell *shell,
|
2005-07-31 02:19:54 +08:00
|
|
|
RenderInfo *info);
|
2004-10-01 17:50:04 +08:00
|
|
|
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/*****************************************************************/
|
|
|
|
/* This function is the core of the display--it offsets and */
|
|
|
|
/* scales the image according to the current parameters in the */
|
2006-03-29 01:55:52 +08:00
|
|
|
/* display object. It handles color, grayscale, 8, 15, 16, 24 */
|
1997-11-25 06:05:25 +08:00
|
|
|
/* & 32 bit output depths. */
|
|
|
|
/*****************************************************************/
|
|
|
|
|
|
|
|
void
|
2001-12-01 02:23:49 +08:00
|
|
|
gimp_display_shell_render (GimpDisplayShell *shell,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint w,
|
2004-10-01 17:50:04 +08:00
|
|
|
gint h,
|
|
|
|
GdkRectangle *highlight)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2005-07-31 06:29:02 +08:00
|
|
|
GimpProjection *projection;
|
|
|
|
RenderInfo info;
|
|
|
|
GimpImageType type;
|
2001-12-01 02:23:49 +08:00
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
g_return_if_fail (w > 0 && h > 0);
|
|
|
|
|
2006-03-29 01:55:52 +08:00
|
|
|
projection = shell->display->image->projection;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
/* Initialize RenderInfo with values that don't change during the
|
|
|
|
* call of this function.
|
2007-06-22 04:27:19 +08:00
|
|
|
*/
|
|
|
|
info.shell = shell;
|
2001-01-30 11:17:26 +08:00
|
|
|
|
2007-06-22 04:27:19 +08:00
|
|
|
info.x = x + shell->offset_x;
|
|
|
|
info.y = y + shell->offset_y;
|
|
|
|
info.w = w;
|
|
|
|
info.h = h;
|
|
|
|
|
|
|
|
info.dest_bpp = 3;
|
|
|
|
info.dest_bpl = info.dest_bpp * GIMP_RENDER_BUF_WIDTH;
|
|
|
|
info.dest_width = info.dest_bpp * info.w;
|
|
|
|
|
|
|
|
if (GIMP_IMAGE_TYPE_HAS_ALPHA (gimp_projection_get_image_type (projection)))
|
|
|
|
{
|
|
|
|
gdouble opacity = gimp_projection_get_opacity (projection);
|
|
|
|
|
|
|
|
info.alpha = render_image_init_alpha (opacity * 255.999);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Setup RenderInfo for rendering a GimpProjection level. */
|
|
|
|
{
|
|
|
|
TileManager *src_tiles;
|
|
|
|
gint level;
|
|
|
|
|
|
|
|
level = gimp_projection_get_level (projection,
|
|
|
|
shell->scale_x,
|
|
|
|
shell->scale_y);
|
|
|
|
|
|
|
|
src_tiles = gimp_projection_get_tiles_at_level (projection, level);
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
gimp_display_shell_render_info_scale (&info,
|
|
|
|
shell,
|
|
|
|
src_tiles,
|
|
|
|
shell->scale_x * (1 << level),
|
|
|
|
shell->scale_y * (1 << level));
|
2007-06-22 04:27:19 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1998-12-06 05:48:37 +08:00
|
|
|
/* Currently, only RGBA and GRAYA projection types are used - the rest
|
2001-01-30 11:17:26 +08:00
|
|
|
* are in case of future need. -- austin, 28th Nov 1998.
|
|
|
|
*/
|
2007-06-22 04:27:19 +08:00
|
|
|
type = gimp_projection_get_image_type (projection);
|
|
|
|
|
2005-04-28 01:01:56 +08:00
|
|
|
if (G_UNLIKELY (type != GIMP_RGBA_IMAGE && type != GIMP_GRAYA_IMAGE))
|
|
|
|
g_warning ("using untested projection type %d", type);
|
1998-12-06 05:48:37 +08:00
|
|
|
|
2005-04-28 01:01:56 +08:00
|
|
|
(* render_funcs[type]) (&info);
|
2001-12-01 02:23:49 +08:00
|
|
|
|
|
|
|
/* apply filters to the rendered projection */
|
2003-11-22 06:52:36 +08:00
|
|
|
if (shell->filter_stack)
|
|
|
|
gimp_color_display_stack_convert (shell->filter_stack,
|
|
|
|
shell->render_buf,
|
|
|
|
w, h,
|
|
|
|
3,
|
2005-07-20 04:42:14 +08:00
|
|
|
3 * GIMP_RENDER_BUF_WIDTH);
|
2001-12-01 02:23:49 +08:00
|
|
|
|
2004-10-01 17:50:04 +08:00
|
|
|
/* dim pixels outside the highlighted rectangle */
|
|
|
|
if (highlight)
|
2005-07-31 02:19:54 +08:00
|
|
|
{
|
|
|
|
gimp_display_shell_render_highlight (shell, x, y, w, h, highlight);
|
|
|
|
}
|
2005-07-31 18:40:54 +08:00
|
|
|
else if (shell->mask)
|
2005-07-31 02:19:54 +08:00
|
|
|
{
|
2007-06-22 04:27:19 +08:00
|
|
|
TileManager *src_tiles = gimp_drawable_get_tiles (shell->mask);
|
|
|
|
|
|
|
|
/* The mask does not (yet) have an image pyramid, use the base scale of
|
|
|
|
* the shell.
|
|
|
|
*/
|
2007-08-16 05:29:43 +08:00
|
|
|
gimp_display_shell_render_info_scale (&info,
|
|
|
|
shell,
|
|
|
|
src_tiles,
|
|
|
|
shell->scale_x,
|
|
|
|
shell->scale_y);
|
2005-07-31 06:29:02 +08:00
|
|
|
|
2005-07-31 18:40:54 +08:00
|
|
|
gimp_display_shell_render_mask (shell, &info);
|
2005-07-31 02:19:54 +08:00
|
|
|
}
|
2004-10-01 17:50:04 +08:00
|
|
|
|
2001-12-01 02:23:49 +08:00
|
|
|
/* put it to the screen */
|
2003-11-11 03:35:56 +08:00
|
|
|
gimp_canvas_draw_rgb (GIMP_CANVAS (shell->canvas), GIMP_CANVAS_STYLE_RENDER,
|
|
|
|
x + shell->disp_xoffset, y + shell->disp_yoffset,
|
|
|
|
w, h,
|
|
|
|
shell->render_buf,
|
2005-07-20 04:42:14 +08:00
|
|
|
3 * GIMP_RENDER_BUF_WIDTH,
|
2003-11-11 03:35:56 +08:00
|
|
|
shell->offset_x, shell->offset_y);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-01 17:50:04 +08:00
|
|
|
#define GIMP_DISPLAY_SHELL_DIM_PIXEL(buf,x) \
|
|
|
|
{ \
|
|
|
|
buf[3 * (x) + 0] >>= 1; \
|
|
|
|
buf[3 * (x) + 1] >>= 1; \
|
|
|
|
buf[3 * (x) + 2] >>= 1; \
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This function highlights the given area by dimming all pixels outside. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_display_shell_render_highlight (GimpDisplayShell *shell,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint w,
|
|
|
|
gint h,
|
|
|
|
GdkRectangle *highlight)
|
|
|
|
{
|
|
|
|
guchar *buf = shell->render_buf;
|
|
|
|
GdkRectangle rect;
|
|
|
|
|
|
|
|
rect.x = shell->offset_x + x;
|
|
|
|
rect.y = shell->offset_y + y;
|
|
|
|
rect.width = w;
|
|
|
|
rect.height = h;
|
|
|
|
|
|
|
|
if (gdk_rectangle_intersect (highlight, &rect, &rect))
|
|
|
|
{
|
|
|
|
rect.x -= shell->offset_x + x;
|
|
|
|
rect.y -= shell->offset_y + y;
|
|
|
|
|
|
|
|
for (y = 0; y < rect.y; y++)
|
|
|
|
{
|
|
|
|
for (x = 0; x < w; x++)
|
|
|
|
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
|
|
|
|
|
2005-07-20 04:42:14 +08:00
|
|
|
buf += 3 * GIMP_RENDER_BUF_WIDTH;
|
2004-10-01 17:50:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for ( ; y < rect.y + rect.height; y++)
|
|
|
|
{
|
|
|
|
for (x = 0; x < rect.x; x++)
|
|
|
|
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
|
|
|
|
|
|
|
|
for (x += rect.width; x < w; x++)
|
|
|
|
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
|
|
|
|
|
2005-07-20 04:42:14 +08:00
|
|
|
buf += 3 * GIMP_RENDER_BUF_WIDTH;
|
2004-10-01 17:50:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for ( ; y < h; y++)
|
|
|
|
{
|
|
|
|
for (x = 0; x < w; x++)
|
|
|
|
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
|
|
|
|
|
2005-07-20 04:42:14 +08:00
|
|
|
buf += 3 * GIMP_RENDER_BUF_WIDTH;
|
2004-10-01 17:50:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (y = 0; y < h; y++)
|
|
|
|
{
|
|
|
|
for (x = 0; x < w; x++)
|
|
|
|
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
|
|
|
|
|
2005-07-20 04:42:14 +08:00
|
|
|
buf += 3 * GIMP_RENDER_BUF_WIDTH;
|
2004-10-01 17:50:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-07-31 02:19:54 +08:00
|
|
|
static void
|
2005-07-31 06:29:02 +08:00
|
|
|
gimp_display_shell_render_mask (GimpDisplayShell *shell,
|
|
|
|
RenderInfo *info)
|
2005-07-31 02:19:54 +08:00
|
|
|
{
|
|
|
|
gint y, ye;
|
|
|
|
gint x, xe;
|
|
|
|
gboolean initial = TRUE;
|
|
|
|
|
|
|
|
y = info->y;
|
|
|
|
ye = info->y + info->h;
|
|
|
|
xe = info->x + info->w;
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
info->yfraction = 256 * fmod (y/info->scaley, 1.0);
|
2005-07-31 02:19:54 +08:00
|
|
|
info->src = render_image_tile_fault (info);
|
|
|
|
|
|
|
|
while (TRUE)
|
|
|
|
{
|
2007-08-16 05:29:43 +08:00
|
|
|
gint error = floor ((y + 1) / info->scaley) - floor (y / info->scaley);
|
2005-07-31 02:19:54 +08:00
|
|
|
|
|
|
|
if (!initial && (error == 0))
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
|
|
|
|
}
|
2005-07-31 02:19:54 +08:00
|
|
|
else
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
const guchar *src = info->src;
|
|
|
|
guchar *dest = info->dest;
|
2005-07-31 02:19:54 +08:00
|
|
|
|
2006-03-17 21:27:08 +08:00
|
|
|
switch (shell->mask_color)
|
|
|
|
{
|
|
|
|
case GIMP_RED_CHANNEL:
|
|
|
|
for (x = info->x; x < xe; x++, src++, dest += 3)
|
|
|
|
{
|
|
|
|
if (*src & 0x80)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
dest[1] = dest[1] >> 2;
|
|
|
|
dest[2] = dest[2] >> 2;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_GREEN_CHANNEL:
|
|
|
|
for (x = info->x; x < xe; x++, src++, dest += 3)
|
|
|
|
{
|
|
|
|
if (*src & 0x80)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
dest[0] = dest[0] >> 2;
|
|
|
|
dest[2] = dest[2] >> 2;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_BLUE_CHANNEL:
|
|
|
|
for (x = info->x; x < xe; x++, src++, dest += 3)
|
|
|
|
{
|
|
|
|
if (*src & 0x80)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
dest[0] = dest[0] >> 2;
|
|
|
|
dest[1] = dest[1] >> 2;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
2005-07-31 02:19:54 +08:00
|
|
|
}
|
2006-03-17 21:27:08 +08:00
|
|
|
}
|
2005-07-31 02:19:54 +08:00
|
|
|
|
|
|
|
if (++y == ye)
|
|
|
|
break;
|
|
|
|
|
|
|
|
info->dest += info->dest_bpl;
|
|
|
|
|
|
|
|
if (error)
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
info->src_y += error;
|
2007-08-16 05:29:43 +08:00
|
|
|
info->yfraction = 256 * fmod (y/info->scaley, 1.0);
|
2006-04-12 20:49:29 +08:00
|
|
|
info->src = render_image_tile_fault (info);
|
2005-07-31 02:19:54 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
initial = TRUE;
|
|
|
|
}
|
2005-07-31 02:19:54 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
initial = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-10-01 17:50:04 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/*************************/
|
|
|
|
/* 8 Bit functions */
|
|
|
|
/*************************/
|
|
|
|
|
|
|
|
static void
|
1998-08-20 14:46:07 +08:00
|
|
|
render_image_indexed (RenderInfo *info)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2005-04-28 00:44:28 +08:00
|
|
|
const guchar *cmap;
|
|
|
|
gint y, ye;
|
|
|
|
gint x, xe;
|
2005-04-28 01:01:56 +08:00
|
|
|
gboolean initial = TRUE;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2006-03-29 01:55:52 +08:00
|
|
|
cmap = gimp_image_get_colormap (info->shell->display->image);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-01-30 11:17:26 +08:00
|
|
|
y = info->y;
|
1997-11-25 06:05:25 +08:00
|
|
|
ye = info->y + info->h;
|
|
|
|
xe = info->x + info->w;
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
info->yfraction = 256 * fmod (y/info->scaley, 1.0);
|
1997-11-25 06:05:25 +08:00
|
|
|
info->src = render_image_tile_fault (info);
|
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
while (TRUE)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2007-08-16 05:29:43 +08:00
|
|
|
gint error = floor ((y + 1) / info->scaley) - floor (y / info->scaley);
|
2003-04-04 19:42:46 +08:00
|
|
|
|
|
|
|
if (!initial && (error == 0))
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
else
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
const guchar *src = info->src;
|
|
|
|
guchar *dest = info->dest;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
for (x = info->x; x < xe; x++)
|
|
|
|
{
|
2005-04-28 00:44:28 +08:00
|
|
|
guint val = src[INDEXED_PIX] * 3;
|
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
src += 1;
|
1998-03-14 06:56:39 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
dest[0] = cmap[val + 0];
|
|
|
|
dest[1] = cmap[val + 1];
|
|
|
|
dest[2] = cmap[val + 2];
|
|
|
|
dest += 3;
|
|
|
|
}
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
if (++y == ye)
|
|
|
|
break;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
info->dest += info->dest_bpl;
|
1998-12-06 05:48:37 +08:00
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
if (error)
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
info->src_y += error;
|
2007-08-16 05:29:43 +08:00
|
|
|
info->yfraction = 256 * fmod (y/info->scaley, 1.0);
|
2006-04-12 20:49:29 +08:00
|
|
|
info->src = render_image_tile_fault (info);
|
2005-04-28 07:27:10 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
initial = TRUE;
|
|
|
|
}
|
2005-04-28 07:27:10 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
initial = FALSE;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1998-08-20 14:46:07 +08:00
|
|
|
render_image_indexed_a (RenderInfo *info)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2005-04-28 00:44:28 +08:00
|
|
|
const guint *alpha = info->alpha;
|
2006-03-29 01:55:52 +08:00
|
|
|
const guchar *cmap = gimp_image_get_colormap (info->shell->display->image);
|
2005-04-28 00:44:28 +08:00
|
|
|
gint y, ye;
|
|
|
|
gint x, xe;
|
2005-04-28 01:01:56 +08:00
|
|
|
gboolean initial = TRUE;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-01-30 11:17:26 +08:00
|
|
|
y = info->y;
|
1997-11-25 06:05:25 +08:00
|
|
|
ye = info->y + info->h;
|
|
|
|
xe = info->x + info->w;
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
info->yfraction = 256 * fmod (y/info->scaley, 1.0);
|
1997-11-25 06:05:25 +08:00
|
|
|
info->src = render_image_tile_fault (info);
|
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
while (TRUE)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2007-08-16 05:29:43 +08:00
|
|
|
gint error = floor ((y + 1) / info->scaley) - floor (y / info->scaley);
|
2003-04-04 19:42:46 +08:00
|
|
|
|
|
|
|
if (!initial && (error == 0) && (y & check_mod))
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
else
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
2005-04-28 00:44:28 +08:00
|
|
|
const guchar *src = info->src;
|
|
|
|
guchar *dest = info->dest;
|
|
|
|
guint dark_light;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
dark_light = (y >> check_shift) + (info->x >> check_shift);
|
1998-08-20 14:46:07 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
for (x = info->x; x < xe; x++)
|
|
|
|
{
|
|
|
|
guint r, g, b, a = alpha[src[ALPHA_I_PIX]];
|
2005-04-28 00:44:28 +08:00
|
|
|
guint val = src[INDEXED_PIX] * 3;
|
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
src += 2;
|
|
|
|
|
|
|
|
if (dark_light & 0x1)
|
|
|
|
{
|
|
|
|
r = gimp_render_blend_dark_check[(a | cmap[val + 0])];
|
|
|
|
g = gimp_render_blend_dark_check[(a | cmap[val + 1])];
|
|
|
|
b = gimp_render_blend_dark_check[(a | cmap[val + 2])];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
r = gimp_render_blend_light_check[(a | cmap[val + 0])];
|
|
|
|
g = gimp_render_blend_light_check[(a | cmap[val + 1])];
|
|
|
|
b = gimp_render_blend_light_check[(a | cmap[val + 2])];
|
|
|
|
}
|
|
|
|
|
|
|
|
dest[0] = r;
|
|
|
|
dest[1] = g;
|
|
|
|
dest[2] = b;
|
|
|
|
dest += 3;
|
|
|
|
|
|
|
|
if (((x + 1) & check_mod) == 0)
|
|
|
|
dark_light += 1;
|
|
|
|
}
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
if (++y == ye)
|
|
|
|
break;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
info->dest += info->dest_bpl;
|
1998-12-06 05:48:37 +08:00
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
if (error)
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
info->src_y += error;
|
2007-08-16 05:29:43 +08:00
|
|
|
info->yfraction = 256 * fmod (y/info->scaley, 1.0);
|
2006-04-12 20:49:29 +08:00
|
|
|
info->src = render_image_tile_fault (info);
|
2005-04-28 07:27:10 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
initial = TRUE;
|
|
|
|
}
|
2005-04-28 07:27:10 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
initial = FALSE;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1998-08-20 14:46:07 +08:00
|
|
|
render_image_gray (RenderInfo *info)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2005-04-28 00:44:28 +08:00
|
|
|
gint y, ye;
|
|
|
|
gint x, xe;
|
2005-04-28 01:01:56 +08:00
|
|
|
gboolean initial = TRUE;
|
2001-01-30 11:17:26 +08:00
|
|
|
|
|
|
|
y = info->y;
|
1997-11-25 06:05:25 +08:00
|
|
|
ye = info->y + info->h;
|
|
|
|
xe = info->x + info->w;
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
info->yfraction = 256 * fmod (y/info->scaley, 1.0);
|
1997-11-25 06:05:25 +08:00
|
|
|
info->src = render_image_tile_fault (info);
|
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
while (TRUE)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2007-08-16 05:29:43 +08:00
|
|
|
gint error = floor ((y + 1) / info->scaley) - floor (y / info->scaley);
|
2003-04-04 19:42:46 +08:00
|
|
|
|
|
|
|
if (!initial && (error == 0))
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
else
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
const guchar *src = info->src;
|
|
|
|
guchar *dest = info->dest;
|
2003-11-11 03:35:56 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
for (x = info->x; x < xe; x++)
|
|
|
|
{
|
|
|
|
guint val = src[GRAY_PIX];
|
2005-04-28 00:44:28 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
src += 1;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
dest[0] = val;
|
|
|
|
dest[1] = val;
|
|
|
|
dest[2] = val;
|
|
|
|
dest += 3;
|
|
|
|
}
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
if (++y == ye)
|
|
|
|
break;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
info->dest += info->dest_bpl;
|
1998-12-06 05:48:37 +08:00
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
if (error)
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
info->src_y += error;
|
2007-08-16 05:29:43 +08:00
|
|
|
info->yfraction = 256 * fmod (y/info->scaley, 1.0);
|
2006-04-12 20:49:29 +08:00
|
|
|
info->src = render_image_tile_fault (info);
|
2005-04-28 07:27:10 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
initial = TRUE;
|
|
|
|
}
|
2005-04-28 07:27:10 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
initial = FALSE;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1998-08-20 14:46:07 +08:00
|
|
|
render_image_gray_a (RenderInfo *info)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2005-04-28 00:44:28 +08:00
|
|
|
const guint *alpha = info->alpha;
|
|
|
|
gint y, ye;
|
|
|
|
gint x, xe;
|
2005-04-28 01:01:56 +08:00
|
|
|
gboolean initial = TRUE;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-01-30 11:17:26 +08:00
|
|
|
y = info->y;
|
1997-11-25 06:05:25 +08:00
|
|
|
ye = info->y + info->h;
|
|
|
|
xe = info->x + info->w;
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
info->yfraction = 256 * fmod (y/info->scaley, 1.0);
|
1997-11-25 06:05:25 +08:00
|
|
|
info->src = render_image_tile_fault (info);
|
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
while (TRUE)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2007-08-16 05:29:43 +08:00
|
|
|
gint error = floor ((y + 1) / info->scaley) - floor (y / info->scaley);
|
2003-04-04 19:42:46 +08:00
|
|
|
|
|
|
|
if (!initial && (error == 0) && (y & check_mod))
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
else
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
const guchar *src = info->src;
|
|
|
|
guchar *dest = info->dest;
|
2005-04-28 00:44:28 +08:00
|
|
|
guint dark_light;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
dark_light = (y >> check_shift) + (info->x >> check_shift);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
for (x = info->x; x < xe; x++)
|
|
|
|
{
|
|
|
|
guint a = alpha[src[ALPHA_G_PIX]];
|
2005-04-28 00:44:28 +08:00
|
|
|
guint val;
|
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
if (dark_light & 0x1)
|
|
|
|
val = gimp_render_blend_dark_check[(a | src[GRAY_PIX])];
|
|
|
|
else
|
|
|
|
val = gimp_render_blend_light_check[(a | src[GRAY_PIX])];
|
2005-04-28 00:44:28 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
src += 2;
|
1998-08-20 14:46:07 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
dest[0] = val;
|
|
|
|
dest[1] = val;
|
|
|
|
dest[2] = val;
|
|
|
|
dest += 3;
|
1998-08-20 14:46:07 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
if (((x + 1) & check_mod) == 0)
|
|
|
|
dark_light += 1;
|
|
|
|
}
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
if (++y == ye)
|
|
|
|
break;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
info->dest += info->dest_bpl;
|
1998-12-06 05:48:37 +08:00
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
if (error)
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
info->src_y += error;
|
2007-08-16 05:29:43 +08:00
|
|
|
info->yfraction = 256 * fmod (y/info->scaley, 1.0);
|
2006-04-12 20:49:29 +08:00
|
|
|
info->src = render_image_tile_fault (info);
|
2005-04-28 07:27:10 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
initial = TRUE;
|
|
|
|
}
|
2005-04-28 07:27:10 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
initial = FALSE;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1998-08-20 14:46:07 +08:00
|
|
|
render_image_rgb (RenderInfo *info)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2005-04-28 00:44:28 +08:00
|
|
|
gint y, ye;
|
|
|
|
gint xe;
|
2005-04-28 01:01:56 +08:00
|
|
|
gboolean initial = TRUE;
|
2001-01-30 11:17:26 +08:00
|
|
|
|
|
|
|
y = info->y;
|
2000-10-26 07:14:11 +08:00
|
|
|
ye = info->y + info->h;
|
|
|
|
xe = info->x + info->w;
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
info->yfraction = 256 * fmod (y/info->scaley, 1.0);
|
1997-11-25 06:05:25 +08:00
|
|
|
info->src = render_image_tile_fault (info);
|
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
while (TRUE)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2007-08-16 05:29:43 +08:00
|
|
|
gint error = floor ((y + 1) / info->scaley) - floor (y / info->scaley);
|
2003-04-04 19:42:46 +08:00
|
|
|
|
|
|
|
if (!initial && (error == 0))
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
else
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
2003-02-21 20:48:13 +08:00
|
|
|
memcpy (info->dest, info->src, 3 * info->w);
|
2006-04-12 20:49:29 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
if (++y == ye)
|
|
|
|
break;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
info->dest += info->dest_bpl;
|
1998-12-06 05:48:37 +08:00
|
|
|
|
2005-04-28 18:48:38 +08:00
|
|
|
if (error)
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
info->src_y += error;
|
2007-08-16 05:29:43 +08:00
|
|
|
info->yfraction = 256 * fmod (y/info->scaley, 1.0);
|
2006-04-12 20:49:29 +08:00
|
|
|
info->src = render_image_tile_fault (info);
|
2005-04-28 07:27:10 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
initial = TRUE;
|
|
|
|
}
|
2005-04-28 07:27:10 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
initial = FALSE;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1998-08-20 14:46:07 +08:00
|
|
|
render_image_rgb_a (RenderInfo *info)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2005-04-28 00:44:28 +08:00
|
|
|
const guint *alpha = info->alpha;
|
|
|
|
gint y, ye;
|
|
|
|
gint x, xe;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-01-30 11:17:26 +08:00
|
|
|
y = info->y;
|
2000-10-26 07:14:11 +08:00
|
|
|
ye = info->y + info->h;
|
|
|
|
xe = info->x + info->w;
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
info->yfraction = 256 * fmod (y/info->scaley, 1.0);
|
1997-11-25 06:05:25 +08:00
|
|
|
info->src = render_image_tile_fault (info);
|
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
while (TRUE)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2007-08-16 05:29:43 +08:00
|
|
|
gint error = floor ((y + 1) / info->scaley) - floor (y / info->scaley);
|
2003-04-04 19:42:46 +08:00
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
const guchar *src = info->src;
|
|
|
|
guchar *dest = info->dest;
|
|
|
|
guint dark_light;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
dark_light = (y >> check_shift) + (info->x >> check_shift);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
for (x = info->x; x < xe; x++)
|
|
|
|
{
|
|
|
|
guint r, g, b, a = alpha[src[ALPHA_PIX]];
|
2005-04-28 00:44:28 +08:00
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
if (dark_light & 0x1)
|
|
|
|
{
|
|
|
|
r = gimp_render_blend_dark_check[(a | src[RED_PIX])];
|
|
|
|
g = gimp_render_blend_dark_check[(a | src[GREEN_PIX])];
|
|
|
|
b = gimp_render_blend_dark_check[(a | src[BLUE_PIX])];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
r = gimp_render_blend_light_check[(a | src[RED_PIX])];
|
|
|
|
g = gimp_render_blend_light_check[(a | src[GREEN_PIX])];
|
|
|
|
b = gimp_render_blend_light_check[(a | src[BLUE_PIX])];
|
|
|
|
}
|
2006-04-12 20:49:29 +08:00
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
src += 4;
|
2006-04-12 20:49:29 +08:00
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
dest[0] = r;
|
|
|
|
dest[1] = g;
|
|
|
|
dest[2] = b;
|
|
|
|
dest += 3;
|
2006-04-12 20:49:29 +08:00
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
if (((x + 1) & check_mod) == 0)
|
|
|
|
dark_light += 1;
|
2006-04-12 20:49:29 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
if (++y == ye)
|
|
|
|
break;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
info->dest += info->dest_bpl;
|
1998-12-06 05:48:37 +08:00
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
info->yfraction = 256 * fmod (y/info->scaley, 1.0);
|
|
|
|
info->src_y += error;
|
|
|
|
info->src = render_image_tile_fault (info);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-08-16 05:29:43 +08:00
|
|
|
gimp_display_shell_render_info_scale (RenderInfo *info,
|
|
|
|
GimpDisplayShell *shell,
|
|
|
|
TileManager *src_tiles,
|
|
|
|
gdouble scale_x,
|
|
|
|
gdouble scale_y)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2007-06-22 04:27:19 +08:00
|
|
|
info->src_tiles = src_tiles;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2007-06-22 04:27:19 +08:00
|
|
|
/* We must reset info->dest because this member is modified in render
|
|
|
|
* functions.
|
|
|
|
*/
|
|
|
|
info->dest = shell->render_buf;
|
2005-07-31 06:29:02 +08:00
|
|
|
|
2007-06-22 04:27:19 +08:00
|
|
|
info->scalex = scale_x;
|
|
|
|
info->scaley = scale_y;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-07-31 06:29:02 +08:00
|
|
|
info->src_x = (gdouble) info->x / info->scalex;
|
|
|
|
info->src_y = (gdouble) info->y / info->scaley;
|
2007-08-14 23:17:30 +08:00
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
info->xstart = (info->src_x +
|
|
|
|
((info->x / info->scalex) -
|
|
|
|
floor (info->x / info->scalex))) * 65536.0;
|
|
|
|
|
|
|
|
info->xdelta = (1 << 16) * (1.0 / info->scalex);
|
2005-07-31 06:29:02 +08:00
|
|
|
}
|
|
|
|
|
2007-03-14 22:37:04 +08:00
|
|
|
static const guint *
|
2001-01-30 11:17:26 +08:00
|
|
|
render_image_init_alpha (gint mult)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
static guint *alpha_mult = NULL;
|
2001-01-30 11:17:26 +08:00
|
|
|
static gint alpha_val = -1;
|
|
|
|
|
|
|
|
gint i;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
if (alpha_val != mult)
|
|
|
|
{
|
|
|
|
if (!alpha_mult)
|
2006-04-12 20:49:29 +08:00
|
|
|
alpha_mult = g_new (guint, 256);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
alpha_val = mult;
|
|
|
|
for (i = 0; i < 256; i++)
|
2006-04-12 20:49:29 +08:00
|
|
|
alpha_mult[i] = ((mult * i) / 255) << 8;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return alpha_mult;
|
|
|
|
}
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
static inline void
|
2007-08-22 22:31:22 +08:00
|
|
|
compute_sample (gint left_weight,
|
|
|
|
gint middle_weight,
|
|
|
|
gint right_weight,
|
|
|
|
gint top_weight,
|
|
|
|
gint center_weight,
|
|
|
|
gint bottom_weight,
|
|
|
|
gint sum,
|
|
|
|
const guchar *src0,
|
|
|
|
const guchar *src1,
|
|
|
|
const guchar *src2,
|
|
|
|
const guchar *src3,
|
|
|
|
const guchar *src4,
|
|
|
|
const guchar *src5,
|
|
|
|
const guchar *src6,
|
|
|
|
const guchar *src7,
|
|
|
|
const guchar *src8,
|
|
|
|
guchar *dest,
|
|
|
|
gint bpp)
|
2007-08-16 05:29:43 +08:00
|
|
|
{
|
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
/* adjusting the weights to avoid integer overflowing */
|
|
|
|
left_weight >>= 2;
|
|
|
|
right_weight >>= 2;
|
|
|
|
middle_weight >>= 2;
|
2007-08-22 23:25:16 +08:00
|
|
|
top_weight >>= 2;
|
|
|
|
bottom_weight >>= 2;
|
|
|
|
center_weight >>= 2;
|
|
|
|
sum >>= 4; /* need to adjust the sum of weights accordingly as
|
2007-08-22 22:31:22 +08:00
|
|
|
well */
|
|
|
|
switch (bpp)
|
2007-08-16 05:29:43 +08:00
|
|
|
{
|
|
|
|
gint i;
|
2007-08-22 22:31:22 +08:00
|
|
|
gint a;
|
2007-08-16 05:29:43 +08:00
|
|
|
case 4:
|
|
|
|
#define ALPHA 3
|
2007-08-22 22:31:22 +08:00
|
|
|
a = (middle_weight * (
|
|
|
|
src5[ALPHA] * top_weight +
|
|
|
|
src0[ALPHA] * center_weight +
|
|
|
|
src2[ALPHA] * bottom_weight) +
|
|
|
|
|
|
|
|
right_weight * (
|
|
|
|
src6[ALPHA] * top_weight +
|
|
|
|
src1[ALPHA] * center_weight +
|
|
|
|
src3[ALPHA] * bottom_weight) +
|
|
|
|
|
|
|
|
left_weight * (
|
|
|
|
src4[ALPHA] * top_weight +
|
|
|
|
src7[ALPHA] * center_weight +
|
|
|
|
src8[ALPHA] * bottom_weight));
|
|
|
|
dest[ALPHA] = a/sum; /*< if the data was premultiplied, this would
|
|
|
|
be the computation for every channel, and
|
|
|
|
the shifting would not be needed */
|
|
|
|
|
|
|
|
for (i=0; i<ALPHA; i++)
|
2007-08-16 05:29:43 +08:00
|
|
|
{
|
2007-08-22 22:31:22 +08:00
|
|
|
gint res = ((middle_weight * (
|
|
|
|
src5[ALPHA] * src5[i] * top_weight + /*< perhaps the alpha could be merged with */
|
|
|
|
src0[ALPHA] * src0[i] * center_weight + /* the vertical weights once per pixel instead */
|
|
|
|
src2[ALPHA] * src2[i] * bottom_weight) + /* of four times in total? */
|
|
|
|
|
|
|
|
right_weight * (
|
|
|
|
src6[ALPHA] * src6[i] * top_weight +
|
|
|
|
src1[ALPHA] * src1[i] * center_weight +
|
|
|
|
src3[ALPHA] * src3[i] * bottom_weight) +
|
|
|
|
|
|
|
|
left_weight * (
|
|
|
|
src4[ALPHA] * src4[i] * top_weight +
|
|
|
|
src7[ALPHA] * src7[i] * center_weight +
|
|
|
|
src8[ALPHA] * src8[i] * bottom_weight)
|
|
|
|
|
|
|
|
) / a);
|
|
|
|
if (res < 0)
|
|
|
|
dest[i] = 0;
|
|
|
|
else if (res>255)
|
|
|
|
dest[i] = 255;
|
|
|
|
else
|
|
|
|
dest[i] = res;
|
2007-08-16 05:29:43 +08:00
|
|
|
}
|
|
|
|
#undef ALPHA
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
#define ALPHA 1
|
2007-08-22 22:31:22 +08:00
|
|
|
a = (middle_weight * (
|
|
|
|
src5[ALPHA] * top_weight +
|
|
|
|
src0[ALPHA] * center_weight +
|
|
|
|
src2[ALPHA] * bottom_weight) +
|
|
|
|
|
|
|
|
right_weight * (
|
|
|
|
src6[ALPHA] * top_weight +
|
|
|
|
src1[ALPHA] * center_weight +
|
|
|
|
src3[ALPHA] * bottom_weight) +
|
|
|
|
|
|
|
|
left_weight * (
|
|
|
|
src4[ALPHA] * top_weight +
|
|
|
|
src7[ALPHA] * center_weight +
|
|
|
|
src8[ALPHA] * bottom_weight));
|
|
|
|
dest[ALPHA] = a/sum; /*< if the data was premultiplied, this would
|
|
|
|
be the computation for every channel, and
|
|
|
|
the shifting would not be needed */
|
|
|
|
|
|
|
|
for (i=0; i<ALPHA; i++)
|
2007-08-16 05:29:43 +08:00
|
|
|
{
|
2007-08-22 22:31:22 +08:00
|
|
|
gint res = ((middle_weight * (
|
|
|
|
src5[ALPHA] * src5[i] * top_weight +
|
|
|
|
src0[ALPHA] * src0[i] * center_weight +
|
|
|
|
src2[ALPHA] * src2[i] * bottom_weight) +
|
|
|
|
|
|
|
|
right_weight * (
|
|
|
|
src6[ALPHA] * src6[i] * top_weight +
|
|
|
|
src1[ALPHA] * src1[i] * center_weight +
|
|
|
|
src3[ALPHA] * src3[i] * bottom_weight) +
|
|
|
|
|
|
|
|
left_weight * (
|
|
|
|
src4[ALPHA] * src4[i] * top_weight +
|
|
|
|
src7[ALPHA] * src7[i] * center_weight +
|
|
|
|
src8[ALPHA] * src8[i] * bottom_weight)
|
|
|
|
|
|
|
|
) / a);
|
|
|
|
if (res < 0)
|
|
|
|
dest[i] = 0;
|
|
|
|
else if (res>255)
|
|
|
|
dest[i] = 255;
|
|
|
|
else
|
|
|
|
dest[i] = res;
|
2007-08-16 05:29:43 +08:00
|
|
|
}
|
|
|
|
#undef ALPHA
|
|
|
|
break;
|
2007-08-22 22:31:22 +08:00
|
|
|
default:
|
|
|
|
g_warning ("bpp=%i not implemented as bicubic filter", bpp);
|
2007-08-16 05:29:43 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* fast paths */
|
|
|
|
static const guchar * render_image_tile_fault_one_row (RenderInfo *info);
|
|
|
|
static const guchar * render_image_tile_fault_nearest (RenderInfo *info);
|
|
|
|
|
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
/* 456 <- this is the order of the numbered tiles/pixels
|
|
|
|
* 701
|
|
|
|
* 823
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2007-08-14 21:52:42 +08:00
|
|
|
/* function to render a horizontal line of view data */
|
2007-03-14 22:37:04 +08:00
|
|
|
static const guchar *
|
1997-11-25 06:05:25 +08:00
|
|
|
render_image_tile_fault (RenderInfo *info)
|
2007-08-16 05:29:43 +08:00
|
|
|
{
|
|
|
|
Tile *tile0;
|
|
|
|
Tile *tile1;
|
|
|
|
Tile *tile2;
|
|
|
|
Tile *tile3;
|
2007-08-22 22:31:22 +08:00
|
|
|
Tile *tile4;
|
|
|
|
Tile *tile5;
|
|
|
|
Tile *tile6;
|
|
|
|
Tile *tile7;
|
|
|
|
Tile *tile8;
|
2007-08-16 05:29:43 +08:00
|
|
|
|
|
|
|
const guchar *src0;
|
|
|
|
const guchar *src1;
|
|
|
|
const guchar *src2;
|
|
|
|
const guchar *src3;
|
2007-08-22 22:31:22 +08:00
|
|
|
const guchar *src4;
|
|
|
|
const guchar *src5;
|
|
|
|
const guchar *src6;
|
|
|
|
const guchar *src7;
|
|
|
|
const guchar *src8;
|
2007-08-16 05:29:43 +08:00
|
|
|
|
|
|
|
guchar *dest;
|
|
|
|
gint width;
|
2007-08-22 22:31:22 +08:00
|
|
|
gint tilex0; /* the current x-tile indice used for the middle
|
2007-08-16 05:29:43 +08:00
|
|
|
sample pair*/
|
|
|
|
gint tilex1; /* the current x-tile indice used for the right
|
|
|
|
sample pair */
|
2007-08-22 22:31:22 +08:00
|
|
|
gint tilexL; /* the current x-tile indice used for the left
|
|
|
|
sample pair */
|
2007-08-16 05:29:43 +08:00
|
|
|
gint xdelta; /* fixed point amount to increment source x
|
|
|
|
coordinas for each horizontal integer destination
|
|
|
|
pixel increment */
|
|
|
|
gint bpp;
|
|
|
|
glong x;
|
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
gint footprint_x;
|
|
|
|
gint footprint_y;
|
2007-08-16 05:29:43 +08:00
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
gint left_weight;
|
|
|
|
gint middle_weight;
|
|
|
|
gint right_weight;
|
|
|
|
|
|
|
|
gint top_weight;
|
|
|
|
gint center_weight;
|
|
|
|
gint bottom_weight;
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
/* dispatch to fast path functions on special conditions */
|
|
|
|
if ((info->scalex == 1.0 &&
|
2007-08-22 22:31:22 +08:00
|
|
|
info->scaley == 1.0) || /* use nearest neighbour for exact use of levels */
|
|
|
|
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
(info->shell->scale_x > 1.0 &&
|
2007-08-22 22:31:22 +08:00
|
|
|
info->shell->scale_y > 1.0) ||
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
/* use nearest neighbour interpolation when the desired scale
|
2007-08-22 22:31:22 +08:00
|
|
|
* is 1:1 with the available pyramid. By removing this optimization
|
|
|
|
* zoom levels > 100% will have antialiasing on the crossings in the
|
|
|
|
* borders of the pixelation cells.
|
2007-08-16 05:29:43 +08:00
|
|
|
*/
|
2007-08-22 22:31:22 +08:00
|
|
|
|
2007-08-22 23:25:16 +08:00
|
|
|
(info->scalex < 0.25 || info->scaley < 0.25))
|
2007-08-22 22:31:22 +08:00
|
|
|
/* use nearest neighbour scaling when being abused, to avoid integer overflows */
|
|
|
|
{
|
2007-08-16 05:29:43 +08:00
|
|
|
return render_image_tile_fault_nearest (info);
|
|
|
|
}
|
2007-08-22 22:31:22 +08:00
|
|
|
/* FIXME: it is crucial that this fast path is migrated to the
|
|
|
|
* proper box filter code as well before commiting to GIMP */
|
2007-08-16 05:29:43 +08:00
|
|
|
else if (((info->src_y) & ~(TILE_WIDTH -1)) ==
|
2007-08-22 22:31:22 +08:00
|
|
|
((info->src_y + 1) & ~(TILE_WIDTH -1)) &&
|
|
|
|
((info->src_y) & ~(TILE_WIDTH -1)) ==
|
|
|
|
((info->src_y - 1) & ~(TILE_WIDTH -1))
|
|
|
|
)
|
2007-08-16 05:29:43 +08:00
|
|
|
{
|
|
|
|
/* all the tiles needed are in a single row */
|
|
|
|
return render_image_tile_fault_one_row (info);
|
|
|
|
}
|
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
footprint_y = (1.0/info->scaley) * 256 / 2;
|
|
|
|
footprint_x = (1.0/info->scalex) * 256 / 2;
|
|
|
|
|
|
|
|
{
|
|
|
|
gint dy = info->yfraction;
|
|
|
|
if (dy > footprint_y)
|
|
|
|
top_weight = 0;
|
|
|
|
else
|
|
|
|
top_weight = footprint_y - dy;
|
|
|
|
|
|
|
|
if (0xff - dy > footprint_y)
|
|
|
|
bottom_weight = 0;
|
|
|
|
else
|
|
|
|
bottom_weight = footprint_y - (0xff - dy);
|
|
|
|
|
|
|
|
center_weight = (footprint_y*2) - top_weight - bottom_weight;
|
|
|
|
}
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
tile0 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
info->src_x, info->src_y, TRUE, FALSE);
|
|
|
|
tile2 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
info->src_x, info->src_y+1, TRUE, FALSE);
|
2007-08-22 22:31:22 +08:00
|
|
|
tile5 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
info->src_x, info->src_y-1, TRUE, FALSE);
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
tile1 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
info->src_x+1, info->src_y, TRUE, FALSE);
|
|
|
|
tile3 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
info->src_x+1, info->src_y+1, TRUE, FALSE);
|
2007-08-22 22:31:22 +08:00
|
|
|
tile6 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
info->src_x+1, info->src_y-1, TRUE, FALSE);
|
|
|
|
|
|
|
|
tile7 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
info->src_x-1, info->src_y, TRUE, FALSE);
|
|
|
|
tile8 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
info->src_x-1, info->src_y+1, TRUE, FALSE);
|
|
|
|
tile4 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
info->src_x-1, info->src_y-1, TRUE, FALSE);
|
2007-08-16 05:29:43 +08:00
|
|
|
|
|
|
|
g_return_val_if_fail (tile0 != NULL, tile_buf);
|
|
|
|
|
|
|
|
src0 = tile_data_pointer (tile0,
|
|
|
|
info->src_x % TILE_WIDTH,
|
|
|
|
info->src_y % TILE_HEIGHT);
|
|
|
|
if (tile1)
|
|
|
|
{
|
|
|
|
src1 = tile_data_pointer (tile1,
|
|
|
|
(info->src_x + 1)% TILE_WIDTH,
|
|
|
|
info->src_y % TILE_HEIGHT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src1 = src0; /* reusing existing pixel data */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tile2)
|
|
|
|
{
|
|
|
|
src2 = tile_data_pointer (tile2,
|
|
|
|
info->src_x % TILE_WIDTH,
|
|
|
|
(info->src_y + 1) % TILE_HEIGHT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src2 = src0; /* reusing existing pixel data */
|
|
|
|
}
|
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
if (tile5)
|
|
|
|
{
|
|
|
|
src5 = tile_data_pointer (tile5,
|
|
|
|
(info->src_x) % TILE_WIDTH,
|
|
|
|
(info->src_y - 1) % TILE_HEIGHT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src5 = src0; /* reusing existing pixel data */
|
|
|
|
}
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
if (tile3)
|
|
|
|
{
|
|
|
|
src3 = tile_data_pointer (tile3,
|
|
|
|
(info->src_x + 1) % TILE_WIDTH,
|
|
|
|
(info->src_y + 1) % TILE_HEIGHT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src3 = src1; /* reusing existing pixel data */
|
|
|
|
}
|
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
|
|
|
|
|
|
|
|
if (tile4)
|
|
|
|
{
|
|
|
|
src4 = tile_data_pointer (tile4,
|
|
|
|
(info->src_x - 1) % TILE_WIDTH,
|
|
|
|
(info->src_y - 1) % TILE_HEIGHT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src4 = src5; /* reusing existing pixel data */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tile6)
|
|
|
|
{
|
|
|
|
src6 = tile_data_pointer (tile6,
|
|
|
|
(info->src_x + 1) % TILE_WIDTH,
|
|
|
|
(info->src_y - 1) % TILE_HEIGHT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src6 = src0; /* reusing existing pixel data */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tile7)
|
|
|
|
{
|
|
|
|
src7 = tile_data_pointer (tile7,
|
|
|
|
(info->src_x - 1) % TILE_WIDTH,
|
|
|
|
(info->src_y) % TILE_HEIGHT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src7 = src0; /* reusing existing pixel data */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tile8)
|
|
|
|
{
|
|
|
|
src8 = tile_data_pointer (tile8,
|
|
|
|
(info->src_x - 1) % TILE_WIDTH,
|
|
|
|
(info->src_y + 1) % TILE_HEIGHT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src8 = src2; /* reusing existing pixel data */
|
|
|
|
}
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
bpp = tile_manager_bpp (info->src_tiles);
|
|
|
|
dest = tile_buf;
|
|
|
|
|
|
|
|
x = info->xstart;
|
|
|
|
|
|
|
|
width = info->w;
|
|
|
|
|
|
|
|
tilex0 = info->src_x / TILE_WIDTH;
|
|
|
|
tilex1 = (info->src_x + 1) / TILE_WIDTH;
|
2007-08-22 22:31:22 +08:00
|
|
|
tilexL = (info->src_x - 1) / TILE_WIDTH;
|
2007-08-16 05:29:43 +08:00
|
|
|
|
|
|
|
xdelta = info->xdelta;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
gint src_x = x >> 16;
|
|
|
|
gint skipped;
|
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
{
|
|
|
|
gint dx = (x >> 8) & 0xff;
|
|
|
|
gint foosum;
|
|
|
|
if (dx > footprint_x)
|
|
|
|
left_weight = 0;
|
|
|
|
else
|
|
|
|
left_weight = footprint_x - dx;
|
|
|
|
|
|
|
|
if (0xff - dx > footprint_x)
|
|
|
|
right_weight = 0;
|
|
|
|
else
|
|
|
|
right_weight = footprint_x - (0xff - dx);
|
|
|
|
|
|
|
|
middle_weight = (footprint_x*2) - left_weight - right_weight;
|
|
|
|
|
|
|
|
foosum = footprint_x*2 * footprint_y*2;
|
|
|
|
|
|
|
|
compute_sample (left_weight, middle_weight, right_weight,
|
|
|
|
top_weight, center_weight, bottom_weight, foosum,
|
|
|
|
src0, src1, src2, src3, src4, src5, src6, src7, src8,
|
2007-08-16 05:29:43 +08:00
|
|
|
dest,
|
|
|
|
bpp);
|
2007-08-22 22:31:22 +08:00
|
|
|
}
|
2007-08-16 05:29:43 +08:00
|
|
|
dest += bpp;
|
|
|
|
|
|
|
|
x += xdelta;
|
|
|
|
|
|
|
|
skipped = (x >> 16) - src_x;
|
|
|
|
|
|
|
|
if (skipped)
|
|
|
|
{
|
|
|
|
/* if we changed integer source pixel coordinates in the source
|
|
|
|
* buffer, make sure the src pointers (and their backing tiles) are
|
|
|
|
* correct
|
|
|
|
*/
|
2007-08-22 22:31:22 +08:00
|
|
|
|
|
|
|
if (src4 != src5)
|
|
|
|
{
|
|
|
|
src4 += skipped * bpp;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tilexL=-1; /* this forces a refetch of the left most source samples */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src7 != src0)
|
|
|
|
{
|
|
|
|
src7 += skipped * bpp;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tilexL=-1; /* this forces a refetch of the left most source samples */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src8 != src2)
|
|
|
|
{
|
|
|
|
src8 += skipped * bpp;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tilexL=-1; /* this forces a refetch of the left most source samples */
|
|
|
|
}
|
|
|
|
|
|
|
|
src5 += skipped * bpp;
|
2007-08-16 05:29:43 +08:00
|
|
|
src0 += skipped * bpp;
|
|
|
|
src2 += skipped * bpp;
|
2007-08-22 22:31:22 +08:00
|
|
|
|
|
|
|
src1 += skipped * bpp;
|
2007-08-16 05:29:43 +08:00
|
|
|
src3 += skipped * bpp;
|
2007-08-22 22:31:22 +08:00
|
|
|
src6 += skipped * bpp;
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
|
|
|
|
src_x += skipped;
|
|
|
|
|
|
|
|
if ((src_x / TILE_WIDTH) != tilex0)
|
|
|
|
{
|
|
|
|
tile_release (tile0, FALSE);
|
|
|
|
|
|
|
|
if (tile2)
|
|
|
|
tile_release (tile2, FALSE);
|
2007-08-22 22:31:22 +08:00
|
|
|
if (tile5)
|
|
|
|
tile_release (tile5, FALSE);
|
2007-08-16 05:29:43 +08:00
|
|
|
|
|
|
|
tilex0 += 1;
|
|
|
|
|
|
|
|
tile0 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
src_x, info->src_y, TRUE, FALSE);
|
|
|
|
tile2 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
src_x, info->src_y+1, TRUE, FALSE);
|
2007-08-22 22:31:22 +08:00
|
|
|
tile5 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
src_x, info->src_y-1, TRUE, FALSE);
|
2007-08-16 05:29:43 +08:00
|
|
|
if (!tile0)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
src0 = tile_data_pointer (tile0,
|
|
|
|
src_x % TILE_WIDTH,
|
|
|
|
info->src_y % TILE_HEIGHT);
|
2007-08-22 22:31:22 +08:00
|
|
|
if (!tile2)
|
|
|
|
{
|
|
|
|
src2 = src0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src2 = tile_data_pointer (tile2,
|
|
|
|
(src_x) % TILE_WIDTH,
|
|
|
|
(info->src_y + 1) % TILE_HEIGHT);
|
|
|
|
}
|
|
|
|
if (!tile5)
|
|
|
|
{
|
|
|
|
src5 = src0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src5 = tile_data_pointer (tile5,
|
|
|
|
src_x % TILE_WIDTH,
|
|
|
|
(info->src_y - 1)% TILE_HEIGHT);
|
|
|
|
}
|
2007-08-16 05:29:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (((src_x+1) / TILE_WIDTH) != tilex1)
|
|
|
|
{
|
|
|
|
if (tile1)
|
|
|
|
tile_release (tile1, FALSE);
|
|
|
|
if (tile3)
|
|
|
|
tile_release (tile3, FALSE);
|
2007-08-22 22:31:22 +08:00
|
|
|
if (tile6)
|
|
|
|
tile_release (tile6, FALSE);
|
2007-08-16 05:29:43 +08:00
|
|
|
|
|
|
|
tilex1 += 1;
|
|
|
|
|
|
|
|
tile1 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
src_x + 1, info->src_y,
|
|
|
|
TRUE, FALSE);
|
|
|
|
tile3 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
src_x + 1, info->src_y + 1,
|
|
|
|
TRUE, FALSE);
|
2007-08-22 22:31:22 +08:00
|
|
|
tile6 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
src_x + 1, info->src_y - 1,
|
|
|
|
TRUE, FALSE);
|
2007-08-16 05:29:43 +08:00
|
|
|
|
|
|
|
if (!tile1)
|
|
|
|
{
|
|
|
|
src1 = src0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src1 = tile_data_pointer (tile1,
|
|
|
|
(src_x + 1) % TILE_WIDTH,
|
|
|
|
info->src_y % TILE_HEIGHT);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!tile3)
|
|
|
|
{
|
|
|
|
src3 = src2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src3 = tile_data_pointer (tile3,
|
|
|
|
(src_x + 1) % TILE_WIDTH,
|
|
|
|
(info->src_y+1) % TILE_HEIGHT);
|
|
|
|
}
|
2007-08-22 22:31:22 +08:00
|
|
|
|
|
|
|
if (!tile6)
|
|
|
|
{
|
|
|
|
src6 = src5;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src6 = tile_data_pointer (tile6,
|
|
|
|
(src_x + 1) % TILE_WIDTH,
|
|
|
|
(info->src_y-1) % TILE_HEIGHT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (((src_x-1) / TILE_WIDTH) != tilexL)
|
|
|
|
{
|
|
|
|
if (tile4)
|
|
|
|
tile_release (tile4, FALSE);
|
|
|
|
if (tile7)
|
|
|
|
tile_release (tile7, FALSE);
|
|
|
|
if (tile8)
|
|
|
|
tile_release (tile8, FALSE);
|
|
|
|
|
|
|
|
tilexL += 1;
|
|
|
|
|
|
|
|
tile4 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
src_x - 1, info->src_y - 1,
|
|
|
|
TRUE, FALSE);
|
|
|
|
tile7 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
src_x - 1, info->src_y,
|
|
|
|
TRUE, FALSE);
|
|
|
|
tile8 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
src_x - 1, info->src_y + 1,
|
|
|
|
TRUE, FALSE);
|
|
|
|
|
|
|
|
if (!tile7)
|
|
|
|
{
|
|
|
|
src7 = src0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src7 = tile_data_pointer (tile7,
|
|
|
|
(src_x - 1) % TILE_WIDTH,
|
|
|
|
info->src_y % TILE_HEIGHT);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!tile8)
|
|
|
|
{
|
|
|
|
src8 = src2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src8 = tile_data_pointer (tile8,
|
|
|
|
(src_x - 1) % TILE_WIDTH,
|
|
|
|
(info->src_y+1) % TILE_HEIGHT);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!tile4)
|
|
|
|
{
|
|
|
|
src4 = src5;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src4 = tile_data_pointer (tile4,
|
|
|
|
(src_x - 1) % TILE_WIDTH,
|
|
|
|
(info->src_y-1) % TILE_HEIGHT);
|
|
|
|
}
|
2007-08-16 05:29:43 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (--width);
|
|
|
|
|
|
|
|
done:
|
|
|
|
if (tile0)
|
|
|
|
tile_release (tile0, FALSE);
|
|
|
|
if (tile1)
|
|
|
|
tile_release (tile1, FALSE);
|
2007-08-22 22:31:22 +08:00
|
|
|
if (tile2)
|
|
|
|
tile_release (tile2, FALSE);
|
2007-08-16 05:29:43 +08:00
|
|
|
if (tile3)
|
|
|
|
tile_release (tile3, FALSE);
|
2007-08-22 22:31:22 +08:00
|
|
|
if (tile4)
|
|
|
|
tile_release (tile4, FALSE);
|
|
|
|
if (tile5)
|
|
|
|
tile_release (tile5, FALSE);
|
|
|
|
if (tile6)
|
|
|
|
tile_release (tile6, FALSE);
|
|
|
|
if (tile7)
|
|
|
|
tile_release (tile7, FALSE);
|
|
|
|
if (tile8)
|
|
|
|
tile_release (tile8, FALSE);
|
2007-08-16 05:29:43 +08:00
|
|
|
|
|
|
|
return tile_buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* function to render a horizontal line of view data */
|
|
|
|
static const guchar *
|
|
|
|
render_image_tile_fault_nearest (RenderInfo *info)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2005-04-28 00:44:28 +08:00
|
|
|
Tile *tile;
|
2005-04-28 07:27:10 +08:00
|
|
|
const guchar *src;
|
2005-04-28 00:44:28 +08:00
|
|
|
guchar *dest;
|
|
|
|
gint width;
|
|
|
|
gint tilex;
|
2007-08-14 23:17:30 +08:00
|
|
|
gint xdelta;
|
2005-07-31 06:29:02 +08:00
|
|
|
gint bpp;
|
2007-08-14 21:52:42 +08:00
|
|
|
glong x;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-02-07 23:16:45 +08:00
|
|
|
tile = tile_manager_get_tile (info->src_tiles,
|
2006-04-12 20:49:29 +08:00
|
|
|
info->src_x, info->src_y, TRUE, FALSE);
|
2005-04-28 01:01:56 +08:00
|
|
|
|
2005-04-28 01:53:10 +08:00
|
|
|
g_return_val_if_fail (tile != NULL, tile_buf);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
src = tile_data_pointer (tile,
|
|
|
|
info->src_x % TILE_WIDTH,
|
|
|
|
info->src_y % TILE_HEIGHT);
|
2005-07-31 06:29:02 +08:00
|
|
|
|
|
|
|
bpp = tile_manager_bpp (info->src_tiles);
|
2001-01-30 11:17:26 +08:00
|
|
|
dest = tile_buf;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2007-08-14 23:17:30 +08:00
|
|
|
x = info->xstart;
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
width = info->w;
|
|
|
|
|
2003-03-22 00:28:06 +08:00
|
|
|
tilex = info->src_x / TILE_WIDTH;
|
|
|
|
|
2007-08-14 23:17:30 +08:00
|
|
|
xdelta = info->xdelta;
|
2007-08-14 21:52:42 +08:00
|
|
|
|
2005-04-28 07:27:10 +08:00
|
|
|
do
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2007-08-14 21:52:42 +08:00
|
|
|
const guchar *s = src;
|
|
|
|
gint src_x = x >> 16;
|
|
|
|
gint skipped;
|
2005-04-28 07:27:10 +08:00
|
|
|
|
|
|
|
switch (bpp)
|
|
|
|
{
|
|
|
|
case 4:
|
|
|
|
*dest++ = *s++;
|
|
|
|
case 3:
|
|
|
|
*dest++ = *s++;
|
|
|
|
case 2:
|
|
|
|
*dest++ = *s++;
|
|
|
|
case 1:
|
|
|
|
*dest++ = *s++;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2007-08-14 23:17:30 +08:00
|
|
|
x += xdelta;
|
2007-08-14 21:52:42 +08:00
|
|
|
skipped = (x >> 16) - src_x;
|
|
|
|
if (skipped)
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
2007-08-14 21:52:42 +08:00
|
|
|
src += skipped * bpp;
|
|
|
|
src_x += skipped;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2007-08-14 21:52:42 +08:00
|
|
|
if ((src_x / TILE_WIDTH) != tilex)
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
tile_release (tile, FALSE);
|
|
|
|
tilex += 1;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
tile = tile_manager_get_tile (info->src_tiles,
|
2007-08-14 21:52:42 +08:00
|
|
|
src_x, info->src_y, TRUE, FALSE);
|
2006-04-12 20:49:29 +08:00
|
|
|
if (!tile)
|
|
|
|
return tile_buf;
|
2000-10-26 07:14:11 +08:00
|
|
|
|
2006-04-12 20:49:29 +08:00
|
|
|
src = tile_data_pointer (tile,
|
2007-08-14 21:52:42 +08:00
|
|
|
src_x % TILE_WIDTH,
|
2005-04-28 18:48:38 +08:00
|
|
|
info->src_y % TILE_HEIGHT);
|
2006-04-12 20:49:29 +08:00
|
|
|
}
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
2005-04-28 07:27:10 +08:00
|
|
|
while (--width);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1998-07-10 10:43:12 +08:00
|
|
|
tile_release (tile, FALSE);
|
2001-01-30 11:17:26 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
return tile_buf;
|
|
|
|
}
|
2007-08-16 05:29:43 +08:00
|
|
|
|
|
|
|
static const guchar *
|
|
|
|
render_image_tile_fault_one_row (RenderInfo *info)
|
|
|
|
{
|
2007-08-22 22:31:22 +08:00
|
|
|
/* NOTE: there are some additional overhead that can be factored out
|
2007-08-22 23:25:16 +08:00
|
|
|
* in the tile administration in this fast path
|
2007-08-22 22:31:22 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
Tile *tile0;
|
|
|
|
Tile *tile1;
|
|
|
|
Tile *tile7;
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
const guchar *src0;
|
|
|
|
const guchar *src1;
|
|
|
|
const guchar *src2;
|
|
|
|
const guchar *src3;
|
2007-08-22 22:31:22 +08:00
|
|
|
const guchar *src4;
|
|
|
|
const guchar *src5;
|
|
|
|
const guchar *src6;
|
|
|
|
const guchar *src7;
|
|
|
|
const guchar *src8;
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
guchar *dest;
|
|
|
|
gint width;
|
2007-08-22 22:31:22 +08:00
|
|
|
gint tilex0; /* the current x-tile indice used for the middle
|
|
|
|
sample pair*/
|
|
|
|
gint tilex1; /* the current x-tile indice used for the right
|
|
|
|
sample pair */
|
|
|
|
gint tilexL; /* the current x-tile indice used for the left
|
|
|
|
sample pair */
|
|
|
|
gint xdelta; /* fixed point amount to increment source x
|
|
|
|
coordinas for each horizontal integer destination
|
|
|
|
pixel increment */
|
2007-08-16 05:29:43 +08:00
|
|
|
gint bpp;
|
|
|
|
glong x;
|
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
gint footprint_x;
|
|
|
|
gint footprint_y;
|
2007-08-16 05:29:43 +08:00
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
gint left_weight;
|
|
|
|
gint middle_weight;
|
|
|
|
gint right_weight;
|
2007-08-16 05:29:43 +08:00
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
gint top_weight;
|
|
|
|
gint center_weight;
|
|
|
|
gint bottom_weight;
|
|
|
|
|
|
|
|
footprint_y = (1.0/info->scaley) * 256 / 2;
|
|
|
|
footprint_x = (1.0/info->scalex) * 256 / 2;
|
|
|
|
|
|
|
|
{
|
|
|
|
gint dy = info->yfraction;
|
|
|
|
if (dy > footprint_y)
|
|
|
|
top_weight = 0;
|
|
|
|
else
|
|
|
|
top_weight = footprint_y - dy;
|
|
|
|
|
|
|
|
if (0xff - dy > footprint_y)
|
|
|
|
bottom_weight = 0;
|
|
|
|
else
|
|
|
|
bottom_weight = footprint_y - (0xff - dy);
|
|
|
|
|
|
|
|
center_weight = (footprint_y*2) - top_weight - bottom_weight;
|
|
|
|
}
|
2007-08-16 05:29:43 +08:00
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
tile0 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
info->src_x, info->src_y, TRUE, FALSE);
|
|
|
|
|
|
|
|
tile1 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
info->src_x+1, info->src_y, TRUE, FALSE);
|
|
|
|
|
|
|
|
tile7 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
info->src_x-1, info->src_y, TRUE, FALSE);
|
|
|
|
|
|
|
|
g_return_val_if_fail (tile0 != NULL, tile_buf);
|
|
|
|
|
|
|
|
src0 = tile_data_pointer (tile0,
|
2007-08-16 05:29:43 +08:00
|
|
|
info->src_x % TILE_WIDTH,
|
|
|
|
info->src_y % TILE_HEIGHT);
|
2007-08-22 22:31:22 +08:00
|
|
|
src2 = tile_data_pointer (tile0,
|
2007-08-16 05:29:43 +08:00
|
|
|
info->src_x % TILE_WIDTH,
|
|
|
|
(info->src_y + 1) % TILE_HEIGHT);
|
2007-08-22 22:31:22 +08:00
|
|
|
if (tile1)
|
2007-08-16 05:29:43 +08:00
|
|
|
{
|
2007-08-22 22:31:22 +08:00
|
|
|
src1 = tile_data_pointer (tile1,
|
2007-08-16 05:29:43 +08:00
|
|
|
(info->src_x + 1)% TILE_WIDTH,
|
|
|
|
info->src_y % TILE_HEIGHT);
|
2007-08-22 22:31:22 +08:00
|
|
|
src3 = tile_data_pointer (tile1,
|
2007-08-16 05:29:43 +08:00
|
|
|
(info->src_x + 1) % TILE_WIDTH,
|
|
|
|
(info->src_y + 1) % TILE_HEIGHT);
|
|
|
|
}
|
2007-08-22 22:31:22 +08:00
|
|
|
else
|
2007-08-16 05:29:43 +08:00
|
|
|
{
|
2007-08-22 22:31:22 +08:00
|
|
|
src1 = src0; /* reusing existing pixel data */
|
|
|
|
src3 = src1; /* reusing existing pixel data */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tile7)
|
|
|
|
{
|
|
|
|
src5 = tile_data_pointer (tile7,
|
|
|
|
(info->src_x) % TILE_WIDTH,
|
|
|
|
(info->src_y - 1) % TILE_HEIGHT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src5 = src0; /* reusing existing pixel data */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tile7)
|
|
|
|
{
|
|
|
|
src4 = tile_data_pointer (tile7,
|
|
|
|
(info->src_x - 1) % TILE_WIDTH,
|
|
|
|
(info->src_y - 1) % TILE_HEIGHT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src4 = src5; /* reusing existing pixel data */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tile1)
|
|
|
|
{
|
|
|
|
src6 = tile_data_pointer (tile1,
|
2007-08-16 05:29:43 +08:00
|
|
|
(info->src_x + 1) % TILE_WIDTH,
|
2007-08-22 22:31:22 +08:00
|
|
|
(info->src_y - 1) % TILE_HEIGHT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src6 = src0; /* reusing existing pixel data */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tile7)
|
|
|
|
{
|
|
|
|
src7 = tile_data_pointer (tile7,
|
|
|
|
(info->src_x - 1) % TILE_WIDTH,
|
|
|
|
(info->src_y) % TILE_HEIGHT);
|
|
|
|
src8 = tile_data_pointer (tile7,
|
|
|
|
(info->src_x - 1) % TILE_WIDTH,
|
2007-08-16 05:29:43 +08:00
|
|
|
(info->src_y + 1) % TILE_HEIGHT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-08-22 22:31:22 +08:00
|
|
|
src7 = src0; /* reusing existing pixel data */
|
|
|
|
src8 = src2; /* reusing existing pixel data */
|
2007-08-16 05:29:43 +08:00
|
|
|
}
|
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
bpp = tile_manager_bpp (info->src_tiles);
|
|
|
|
dest = tile_buf;
|
2007-08-16 05:29:43 +08:00
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
x = info->xstart;
|
2007-08-16 05:29:43 +08:00
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
width = info->w;
|
2007-08-16 05:29:43 +08:00
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
tilex0 = info->src_x / TILE_WIDTH;
|
|
|
|
tilex1 = (info->src_x + 1) / TILE_WIDTH;
|
|
|
|
tilexL = (info->src_x - 1) / TILE_WIDTH;
|
2007-08-16 05:29:43 +08:00
|
|
|
|
|
|
|
xdelta = info->xdelta;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
gint src_x = x >> 16;
|
|
|
|
gint skipped;
|
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
{
|
|
|
|
gint dx = (x >> 8) & 0xff;
|
|
|
|
gint foosum;
|
|
|
|
if (dx > footprint_x)
|
|
|
|
left_weight = 0;
|
|
|
|
else
|
|
|
|
left_weight = footprint_x - dx;
|
|
|
|
|
|
|
|
if (0xff - dx > footprint_x)
|
|
|
|
right_weight = 0;
|
|
|
|
else
|
|
|
|
right_weight = footprint_x - (0xff - dx);
|
|
|
|
|
|
|
|
middle_weight = (footprint_x*2) - left_weight - right_weight;
|
|
|
|
|
|
|
|
foosum = footprint_x*2 * footprint_y*2;
|
|
|
|
|
|
|
|
compute_sample (left_weight, middle_weight, right_weight,
|
|
|
|
top_weight, center_weight, bottom_weight, foosum,
|
|
|
|
src0, src1, src2, src3, src4, src5, src6, src7, src8,
|
2007-08-16 05:29:43 +08:00
|
|
|
dest,
|
|
|
|
bpp);
|
2007-08-22 22:31:22 +08:00
|
|
|
}
|
2007-08-16 05:29:43 +08:00
|
|
|
dest += bpp;
|
|
|
|
|
|
|
|
x += xdelta;
|
|
|
|
|
|
|
|
skipped = (x >> 16) - src_x;
|
|
|
|
|
|
|
|
if (skipped)
|
|
|
|
{
|
2007-08-22 22:31:22 +08:00
|
|
|
/* if we changed integer source pixel coordinates in the source
|
|
|
|
* buffer, make sure the src pointers (and their backing tiles) are
|
|
|
|
* correct
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (src4 != src5)
|
|
|
|
{
|
|
|
|
src4 += skipped * bpp;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tilexL=-1; /* this forces a refetch of the left most source samples */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src7 != src0)
|
|
|
|
{
|
|
|
|
src7 += skipped * bpp;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tilexL=-1; /* this forces a refetch of the left most source samples */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src8 != src2)
|
|
|
|
{
|
|
|
|
src8 += skipped * bpp;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tilexL=-1; /* this forces a refetch of the left most source samples */
|
|
|
|
}
|
|
|
|
|
|
|
|
src5 += skipped * bpp;
|
2007-08-16 05:29:43 +08:00
|
|
|
src0 += skipped * bpp;
|
|
|
|
src2 += skipped * bpp;
|
2007-08-22 22:31:22 +08:00
|
|
|
|
|
|
|
src1 += skipped * bpp;
|
2007-08-16 05:29:43 +08:00
|
|
|
src3 += skipped * bpp;
|
2007-08-22 22:31:22 +08:00
|
|
|
src6 += skipped * bpp;
|
|
|
|
|
2007-08-16 05:29:43 +08:00
|
|
|
|
|
|
|
src_x += skipped;
|
|
|
|
|
|
|
|
if ((src_x / TILE_WIDTH) != tilex0)
|
|
|
|
{
|
2007-08-22 22:31:22 +08:00
|
|
|
tile_release (tile0, FALSE);
|
2007-08-16 05:29:43 +08:00
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
tilex0 += 1;
|
2007-08-16 05:29:43 +08:00
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
tile0 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
src_x, info->src_y, TRUE, FALSE);
|
|
|
|
if (!tile0)
|
2007-08-16 05:29:43 +08:00
|
|
|
goto done;
|
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
src0 = tile_data_pointer (tile0,
|
2007-08-16 05:29:43 +08:00
|
|
|
src_x % TILE_WIDTH,
|
|
|
|
info->src_y % TILE_HEIGHT);
|
2007-08-22 22:31:22 +08:00
|
|
|
src2 = tile_data_pointer (tile0,
|
|
|
|
(src_x) % TILE_WIDTH,
|
|
|
|
(info->src_y + 1) % TILE_HEIGHT);
|
|
|
|
src5 = tile_data_pointer (tile0,
|
2007-08-16 05:29:43 +08:00
|
|
|
src_x % TILE_WIDTH,
|
2007-08-22 22:31:22 +08:00
|
|
|
(info->src_y - 1)% TILE_HEIGHT);
|
2007-08-16 05:29:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (((src_x+1) / TILE_WIDTH) != tilex1)
|
|
|
|
{
|
2007-08-22 22:31:22 +08:00
|
|
|
if (tile1)
|
|
|
|
tile_release (tile1, FALSE);
|
2007-08-16 05:29:43 +08:00
|
|
|
|
|
|
|
tilex1 += 1;
|
|
|
|
|
2007-08-22 22:31:22 +08:00
|
|
|
tile1 = tile_manager_get_tile (info->src_tiles,
|
2007-08-16 05:29:43 +08:00
|
|
|
src_x + 1, info->src_y,
|
|
|
|
TRUE, FALSE);
|
2007-08-22 22:31:22 +08:00
|
|
|
|
|
|
|
if (!tile1)
|
|
|
|
{
|
2007-08-16 05:29:43 +08:00
|
|
|
src1 = src0;
|
|
|
|
src3 = src2;
|
2007-08-22 22:31:22 +08:00
|
|
|
src6 = src5;
|
2007-08-16 05:29:43 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-08-22 22:31:22 +08:00
|
|
|
src1 = tile_data_pointer (tile1,
|
2007-08-16 05:29:43 +08:00
|
|
|
(src_x + 1) % TILE_WIDTH,
|
|
|
|
info->src_y % TILE_HEIGHT);
|
2007-08-22 22:31:22 +08:00
|
|
|
src3 = tile_data_pointer (tile1,
|
2007-08-16 05:29:43 +08:00
|
|
|
(src_x + 1) % TILE_WIDTH,
|
|
|
|
(info->src_y+1) % TILE_HEIGHT);
|
2007-08-22 22:31:22 +08:00
|
|
|
src6 = tile_data_pointer (tile1,
|
|
|
|
(src_x + 1) % TILE_WIDTH,
|
|
|
|
(info->src_y-1) % TILE_HEIGHT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (((src_x-1) / TILE_WIDTH) != tilexL)
|
|
|
|
{
|
|
|
|
if (tile7)
|
|
|
|
tile_release (tile7, FALSE);
|
|
|
|
|
|
|
|
tilexL += 1;
|
|
|
|
|
|
|
|
tile7 = tile_manager_get_tile (info->src_tiles,
|
|
|
|
src_x - 1, info->src_y,
|
|
|
|
TRUE, FALSE);
|
|
|
|
|
|
|
|
if (!tile7)
|
|
|
|
{
|
|
|
|
src7 = src0;
|
|
|
|
src8 = src2;
|
|
|
|
src4 = src5;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src7 = tile_data_pointer (tile7,
|
|
|
|
(src_x - 1) % TILE_WIDTH,
|
|
|
|
info->src_y % TILE_HEIGHT);
|
|
|
|
src8 = tile_data_pointer (tile7,
|
|
|
|
(src_x - 1) % TILE_WIDTH,
|
|
|
|
(info->src_y+1) % TILE_HEIGHT);
|
|
|
|
src4 = tile_data_pointer (tile7,
|
|
|
|
(src_x - 1) % TILE_WIDTH,
|
|
|
|
(info->src_y-1) % TILE_HEIGHT);
|
2007-08-16 05:29:43 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (--width);
|
|
|
|
|
|
|
|
done:
|
2007-08-22 22:31:22 +08:00
|
|
|
if (tile0)
|
|
|
|
tile_release (tile0, FALSE);
|
|
|
|
if (tile1)
|
|
|
|
tile_release (tile1, FALSE);
|
|
|
|
if (tile7)
|
|
|
|
tile_release (tile7, FALSE);
|
2007-08-16 05:29:43 +08:00
|
|
|
|
|
|
|
return tile_buf;
|
|
|
|
}
|