mirror of https://github.com/GNOME/gimp.git
Speed up our display rendering code paths by keeping data with
2007-12-13 Sven Neumann <sven@gimp.org> Speed up our display rendering code paths by keeping data with pre-multiplied alpha where possible. The projection tile-manager at 100 % zoom is not affected. So we can still always get the non-pre-multiplied pixel data. * app/core/gimpprojection.[ch]: removed gimp_projection_get_opacity(), the projection is always opaque. * app/base/tile-pyramid.[ch]: use pre-multiplied alpha for the upper levels of the pyramid. This speeds up validation of the upper levels significantly. * app/base/temp-buf.[ch]: added temp_buf_demultiply(). * app/core/gimpimage-preview.c: demultiply the preview temp-buf obtained from the projection's tile tyramid. * app/display/gimpdisplayshell-draw.c * app/display/gimpdisplayshell-render.c: added code to deal with pre-multiplied data. In fact all data returned by render_image_tile_fault() is now pre-multiplied so that render_image_rgb_a() and render_image_gray_a() don't need to use the large lookup tables from gimprender.[ch] any longer. svn path=/trunk/; revision=24352
This commit is contained in:
parent
daf03994b0
commit
aaa16d3b87
26
ChangeLog
26
ChangeLog
|
@ -1,3 +1,29 @@
|
|||
2007-12-13 Sven Neumann <sven@gimp.org>
|
||||
|
||||
Speed up our display rendering code paths by keeping data with
|
||||
pre-multiplied alpha where possible. The projection tile-manager
|
||||
at 100 % zoom is not affected. So we can still always get the
|
||||
non-pre-multiplied pixel data.
|
||||
|
||||
* app/core/gimpprojection.[ch]: removed
|
||||
gimp_projection_get_opacity(), the projection is always opaque.
|
||||
|
||||
* app/base/tile-pyramid.[ch]: use pre-multiplied alpha for the
|
||||
upper levels of the pyramid. This speeds up validation of the
|
||||
upper levels significantly.
|
||||
|
||||
* app/base/temp-buf.[ch]: added temp_buf_demultiply().
|
||||
|
||||
* app/core/gimpimage-preview.c: demultiply the preview temp-buf
|
||||
obtained from the projection's tile tyramid.
|
||||
|
||||
* app/display/gimpdisplayshell-draw.c
|
||||
* app/display/gimpdisplayshell-render.c: added code to deal with
|
||||
pre-multiplied data. In fact all data returned by
|
||||
render_image_tile_fault() is now pre-multiplied so that
|
||||
render_image_rgb_a() and render_image_gray_a() don't need to use
|
||||
the large lookup tables from gimprender.[ch] any longer.
|
||||
|
||||
2007-12-13 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* app/widgets/gimprender.[ch]: export the light and dark check
|
||||
|
|
|
@ -54,11 +54,11 @@ temp_buf_new (gint width,
|
|||
|
||||
temp = g_slice_new (TempBuf);
|
||||
|
||||
temp->width = width;
|
||||
temp->height = height;
|
||||
temp->bytes = bytes;
|
||||
temp->x = x;
|
||||
temp->y = y;
|
||||
temp->bytes = bytes;
|
||||
temp->width = width;
|
||||
temp->height = height;
|
||||
temp->x = x;
|
||||
temp->y = y;
|
||||
|
||||
temp->data = g_new (guchar, width * height * bytes);
|
||||
|
||||
|
@ -240,13 +240,13 @@ temp_buf_scale (TempBuf *src,
|
|||
gint new_width,
|
||||
gint new_height)
|
||||
{
|
||||
TempBuf *dest;
|
||||
guchar *src_data;
|
||||
guchar *dest_data;
|
||||
gdouble x_ratio;
|
||||
gdouble y_ratio;
|
||||
gint loop1;
|
||||
gint loop2;
|
||||
TempBuf *dest;
|
||||
const guchar *src_data;
|
||||
guchar *dest_data;
|
||||
gdouble x_ratio;
|
||||
gdouble y_ratio;
|
||||
gint loop1;
|
||||
gint loop2;
|
||||
|
||||
g_return_val_if_fail (src != NULL, NULL);
|
||||
g_return_val_if_fail (new_width > 0 && new_height > 0, NULL);
|
||||
|
@ -266,9 +266,9 @@ temp_buf_scale (TempBuf *src,
|
|||
{
|
||||
for (loop2 = 0 ; loop2 < new_width ; loop2++)
|
||||
{
|
||||
guchar *src_pixel;
|
||||
guchar *dest_pixel;
|
||||
gint i;
|
||||
const guchar *src_pixel;
|
||||
guchar *dest_pixel;
|
||||
gint i;
|
||||
|
||||
src_pixel = src_data +
|
||||
(gint) (loop2 * x_ratio) * src->bytes +
|
||||
|
@ -344,38 +344,93 @@ temp_buf_copy_area (TempBuf *src,
|
|||
return new;
|
||||
}
|
||||
|
||||
/**
|
||||
* temp_buf_demultiply:
|
||||
* @buf:
|
||||
*
|
||||
* Converts a TempBuf with pre-multiplied alpha to a 'normal' TempBuf.
|
||||
*/
|
||||
void
|
||||
temp_buf_free (TempBuf *temp_buf)
|
||||
temp_buf_demultiply (TempBuf *buf)
|
||||
{
|
||||
g_return_if_fail (temp_buf != NULL);
|
||||
guchar *data;
|
||||
gint pixels;
|
||||
gint x, y;
|
||||
|
||||
if (temp_buf->data)
|
||||
g_free (temp_buf->data);
|
||||
g_return_if_fail (buf != NULL);
|
||||
|
||||
g_slice_free (TempBuf, temp_buf);
|
||||
switch (buf->bytes)
|
||||
{
|
||||
case 1:
|
||||
break;
|
||||
|
||||
case 2:
|
||||
data = temp_buf_data (buf);
|
||||
pixels = buf->width * buf->height;
|
||||
while (pixels--)
|
||||
{
|
||||
if (data[1])
|
||||
data[0] = (data[0] << 8) / data[1];
|
||||
|
||||
data += 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
break;
|
||||
|
||||
case 4:
|
||||
data = temp_buf_data (buf);
|
||||
pixels = buf->width * buf->height;
|
||||
while (pixels--)
|
||||
{
|
||||
if (data[3])
|
||||
{
|
||||
data[0] = (data[0] << 8) / data[3];
|
||||
data[1] = (data[1] << 8) / data[3];
|
||||
data[2] = (data[2] << 8) / data[3];
|
||||
}
|
||||
|
||||
data += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
g_return_if_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
temp_buf_free (TempBuf *buf)
|
||||
{
|
||||
g_return_if_fail (buf != NULL);
|
||||
|
||||
if (buf->data)
|
||||
g_free (buf->data);
|
||||
|
||||
g_slice_free (TempBuf, buf);
|
||||
}
|
||||
|
||||
guchar *
|
||||
temp_buf_data (TempBuf *temp_buf)
|
||||
temp_buf_data (TempBuf *buf)
|
||||
{
|
||||
return temp_buf->data;
|
||||
return buf->data;
|
||||
}
|
||||
|
||||
guchar *
|
||||
temp_buf_data_clear (TempBuf *temp_buf)
|
||||
temp_buf_data_clear (TempBuf *buf)
|
||||
{
|
||||
memset (temp_buf->data, 0,
|
||||
temp_buf->height * temp_buf->width * temp_buf->bytes);
|
||||
memset (buf->data, 0, buf->height * buf->width * buf->bytes);
|
||||
|
||||
return temp_buf->data;
|
||||
return buf->data;
|
||||
}
|
||||
|
||||
gsize
|
||||
temp_buf_get_memsize (TempBuf *temp_buf)
|
||||
temp_buf_get_memsize (TempBuf *buf)
|
||||
{
|
||||
if (temp_buf)
|
||||
return (sizeof (TempBuf) +
|
||||
(gsize) temp_buf->bytes * temp_buf->width * temp_buf->height);
|
||||
if (buf)
|
||||
return (sizeof (TempBuf) + buf->bytes * buf->width * buf->height);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -22,12 +22,12 @@
|
|||
|
||||
struct _TempBuf
|
||||
{
|
||||
gint bytes; /* the necessary info */
|
||||
gint width;
|
||||
gint height;
|
||||
gint x, y; /* origin of data source */
|
||||
guchar *data; /* The data buffer. Do never access this field
|
||||
directly, use temp_buf_data() instead !! */
|
||||
gint bytes; /* number of bytes per pixel (1,2,3 or 4) */
|
||||
gint width;
|
||||
gint height;
|
||||
gint x, y; /* origin of data source */
|
||||
guchar *data; /* The data buffer. Do never access this field
|
||||
directly, use temp_buf_data() instead !! */
|
||||
};
|
||||
|
||||
|
||||
|
@ -62,6 +62,9 @@ TempBuf * temp_buf_copy_area (TempBuf *src,
|
|||
gint height,
|
||||
gint dest_x,
|
||||
gint dest_y);
|
||||
|
||||
void temp_buf_demultiply (TempBuf *buf);
|
||||
|
||||
void temp_buf_free (TempBuf *buf);
|
||||
guchar * temp_buf_data (TempBuf *buf);
|
||||
guchar * temp_buf_data_clear (TempBuf *buf);
|
||||
|
|
|
@ -41,15 +41,23 @@ struct _TilePyramid
|
|||
};
|
||||
|
||||
|
||||
static gint tile_pyramid_alloc_levels (TilePyramid *pyramid,
|
||||
gint top_level);
|
||||
static void tile_pyramid_validate_tile (TileManager *tm,
|
||||
Tile *tile,
|
||||
TileManager *tm_below);
|
||||
static void tile_pyramid_write_quarter (Tile *dest,
|
||||
Tile *src,
|
||||
gint i,
|
||||
gint j);
|
||||
static gint tile_pyramid_alloc_levels (TilePyramid *pyramid,
|
||||
gint top_level);
|
||||
static void tile_pyramid_validate_tile (TileManager *tm,
|
||||
Tile *tile,
|
||||
TileManager *tm_below);
|
||||
static void tile_pyramid_validate_upper_tile (TileManager *tm,
|
||||
Tile *tile,
|
||||
TileManager *tm_below);
|
||||
|
||||
static void tile_pyramid_write_quarter (Tile *dest,
|
||||
Tile *src,
|
||||
gint i,
|
||||
gint j);
|
||||
static void tile_pyramid_write_upper_quarter (Tile *dest,
|
||||
Tile *src,
|
||||
gint i,
|
||||
gint j);
|
||||
|
||||
/**
|
||||
* tile_pyramid_new:
|
||||
|
@ -178,8 +186,10 @@ tile_pyramid_get_level (gint width,
|
|||
|
||||
/**
|
||||
* tile_pyramid_get_tiles:
|
||||
* @pyramid: a #TilePyramid
|
||||
* @level: level, typically obtained using tile_pyramid_get_level()
|
||||
* @pyramid: a #TilePyramid
|
||||
* @level: level, typically obtained using tile_pyramid_get_level()
|
||||
* @is_premult: location to store whether the pixel data has the alpha
|
||||
* channel pre-multiplied or not
|
||||
*
|
||||
* Gives access to the #TileManager at @level of the @pyramid.
|
||||
*
|
||||
|
@ -187,7 +197,8 @@ tile_pyramid_get_level (gint width,
|
|||
**/
|
||||
TileManager *
|
||||
tile_pyramid_get_tiles (TilePyramid *pyramid,
|
||||
gint level)
|
||||
gint level,
|
||||
gboolean *is_premult)
|
||||
{
|
||||
g_return_val_if_fail (pyramid != NULL, NULL);
|
||||
|
||||
|
@ -195,6 +206,9 @@ tile_pyramid_get_tiles (TilePyramid *pyramid,
|
|||
|
||||
g_return_val_if_fail (pyramid->tiles[level] != NULL, NULL);
|
||||
|
||||
if (is_premult)
|
||||
*is_premult = (level > 0);
|
||||
|
||||
return pyramid->tiles[level];
|
||||
}
|
||||
|
||||
|
@ -338,8 +352,9 @@ tile_pyramid_alloc_levels (TilePyramid *pyramid,
|
|||
|
||||
for (level = pyramid->top_level + 1; level <= top_level; level++)
|
||||
{
|
||||
gint width = pyramid->width >> level;
|
||||
gint height = pyramid->height >> level;
|
||||
TileValidateProc proc;
|
||||
gint width = pyramid->width >> level;
|
||||
gint height = pyramid->height >> level;
|
||||
|
||||
if (width == 0 || height == 0)
|
||||
return pyramid->top_level;
|
||||
|
@ -354,14 +369,23 @@ tile_pyramid_alloc_levels (TilePyramid *pyramid,
|
|||
pyramid->tiles[level] = tile_manager_new (width, height, pyramid->bytes);
|
||||
|
||||
/* Use the level below to validate tiles. */
|
||||
if (level == 1)
|
||||
proc = (TileValidateProc) tile_pyramid_validate_tile;
|
||||
else
|
||||
proc = (TileValidateProc) tile_pyramid_validate_upper_tile;
|
||||
|
||||
tile_manager_set_validate_proc (pyramid->tiles[level],
|
||||
(TileValidateProc) tile_pyramid_validate_tile,
|
||||
proc,
|
||||
pyramid->tiles[level - 1]);
|
||||
}
|
||||
|
||||
return pyramid->top_level;
|
||||
}
|
||||
|
||||
/* This method is used to validate a pyramid tile from the base level.
|
||||
* It needs to pre-multiply the alpha channel because upper levels are
|
||||
* pre-multiplied.
|
||||
*/
|
||||
static void
|
||||
tile_pyramid_validate_tile (TileManager *tm,
|
||||
Tile *tile,
|
||||
|
@ -388,6 +412,39 @@ tile_pyramid_validate_tile (TileManager *tm,
|
|||
}
|
||||
}
|
||||
|
||||
/* This method is used to validate tiles in the upper pyramid levels.
|
||||
* Here all data has the alpha channel pre-multiplied.
|
||||
*/
|
||||
static void
|
||||
tile_pyramid_validate_upper_tile (TileManager *tm,
|
||||
Tile *tile,
|
||||
TileManager *tm_below)
|
||||
{
|
||||
gint tile_col;
|
||||
gint tile_row;
|
||||
gint i, j;
|
||||
|
||||
tile_manager_get_tile_col_row (tm, tile, &tile_col, &tile_row);
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
Tile *source = tile_manager_get_at (tm_below,
|
||||
tile_col * 2 + i,
|
||||
tile_row * 2 + j,
|
||||
TRUE, FALSE);
|
||||
if (source)
|
||||
{
|
||||
tile_pyramid_write_upper_quarter (tile, source, i, j);
|
||||
tile_release (source, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Average the src tile to one quarter of the destination tile.
|
||||
* The source tile doesn't have pre-multiplied alpha, but the
|
||||
* destination tile does.
|
||||
*/
|
||||
static void
|
||||
tile_pyramid_write_quarter (Tile *dest,
|
||||
Tile *src,
|
||||
|
@ -451,7 +508,7 @@ tile_pyramid_write_quarter (Tile *dest,
|
|||
dst[0] = ((src0[0] * src0[1] +
|
||||
src1[0] * src1[1] +
|
||||
src2[0] * src2[1] +
|
||||
src3[0] * src3[1]) / a);
|
||||
src3[0] * src3[1]) >> 10);
|
||||
dst[1] = (a + 2) >> 2;
|
||||
break;
|
||||
}
|
||||
|
@ -503,15 +560,15 @@ tile_pyramid_write_quarter (Tile *dest,
|
|||
dst[0] = ((src0[0] * src0[3] +
|
||||
src1[0] * src1[3] +
|
||||
src2[0] * src2[3] +
|
||||
src3[0] * src3[3]) / a);
|
||||
src3[0] * src3[3]) >> 10);
|
||||
dst[1] = ((src0[1] * src0[3] +
|
||||
src1[1] * src1[3] +
|
||||
src2[1] * src2[3] +
|
||||
src3[1] * src3[3]) / a);
|
||||
src3[1] * src3[3]) >> 10);
|
||||
dst[2] = ((src0[2] * src0[3] +
|
||||
src1[2] * src1[3] +
|
||||
src2[2] * src2[3] +
|
||||
src3[2] * src3[3]) / a);
|
||||
src3[2] * src3[3]) >> 10);
|
||||
dst[3] = (a + 2) >> 2;
|
||||
break;
|
||||
}
|
||||
|
@ -530,3 +587,103 @@ tile_pyramid_write_quarter (Tile *dest,
|
|||
src_data += src_ewidth * bpp * 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Average the src tile to one quarter of the destination tile.
|
||||
* The source and destination tiles have pre-multiplied alpha.
|
||||
*/
|
||||
static void
|
||||
tile_pyramid_write_upper_quarter (Tile *dest,
|
||||
Tile *src,
|
||||
gint i,
|
||||
gint j)
|
||||
{
|
||||
const guchar *src_data = tile_data_pointer (src, 0, 0);
|
||||
guchar *dest_data = tile_data_pointer (dest, 0, 0);
|
||||
const gint src_ewidth = tile_ewidth (src);
|
||||
const gint src_eheight = tile_eheight (src);
|
||||
const gint dest_ewidth = tile_ewidth (dest);
|
||||
const gint bpp = tile_bpp (dest);
|
||||
gint y;
|
||||
|
||||
/* Adjust dest pointer to the right quadrant. */
|
||||
dest_data += i * bpp * (TILE_WIDTH / 2) +
|
||||
j * bpp * dest_ewidth * (TILE_HEIGHT / 2);
|
||||
|
||||
for (y = 0; y < src_eheight / 2; y++)
|
||||
{
|
||||
const guchar *src0 = src_data;
|
||||
const guchar *src1 = src_data + bpp;
|
||||
const guchar *src2 = src0 + bpp * src_ewidth;
|
||||
const guchar *src3 = src1 + bpp * src_ewidth;
|
||||
guchar *dst = dest_data;
|
||||
gint x;
|
||||
|
||||
switch (bpp)
|
||||
{
|
||||
case 1:
|
||||
for (x = 0; x < src_ewidth / 2; x++)
|
||||
{
|
||||
dst[0] = (src0[0] + src1[0] + src2[0] + src3[0]) >> 2;
|
||||
|
||||
dst += 1;
|
||||
|
||||
src0 += 2;
|
||||
src1 += 2;
|
||||
src2 += 2;
|
||||
src3 += 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
for (x = 0; x < src_ewidth / 2; x++)
|
||||
{
|
||||
dst[0] = (src0[0] + src1[0] + src2[0] + src3[0]) >> 2;
|
||||
dst[1] = (src0[1] + src1[1] + src2[1] + src3[1]) >> 2;
|
||||
|
||||
dst += 2;
|
||||
|
||||
src0 += 4;
|
||||
src1 += 4;
|
||||
src2 += 4;
|
||||
src3 += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
for (x = 0; x < src_ewidth / 2; x++)
|
||||
{
|
||||
dst[0] = (src0[0] + src1[0] + src2[0] + src3[0]) >> 2;
|
||||
dst[1] = (src0[1] + src1[1] + src2[1] + src3[1]) >> 2;
|
||||
dst[2] = (src0[2] + src1[2] + src2[2] + src3[2]) >> 2;
|
||||
|
||||
dst += 3;
|
||||
|
||||
src0 += 6;
|
||||
src1 += 6;
|
||||
src2 += 6;
|
||||
src3 += 6;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
for (x = 0; x < src_ewidth / 2; x++)
|
||||
{
|
||||
dst[0] = (src0[0] + src1[0] + src2[0] + src3[0]) >> 2;
|
||||
dst[1] = (src0[1] + src1[1] + src2[1] + src3[1]) >> 2;
|
||||
dst[2] = (src0[2] + src1[2] + src2[2] + src3[2]) >> 2;
|
||||
dst[3] = (src0[3] + src1[3] + src2[3] + src3[3]) >> 2;
|
||||
|
||||
dst += 4;
|
||||
|
||||
src0 += 8;
|
||||
src1 += 8;
|
||||
src2 += 8;
|
||||
src3 += 8;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
dest_data += dest_ewidth * bpp;
|
||||
src_data += src_ewidth * bpp * 2;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,8 @@ gint tile_pyramid_get_level (gint width,
|
|||
gdouble scale);
|
||||
|
||||
TileManager * tile_pyramid_get_tiles (TilePyramid *pyramid,
|
||||
gint level);
|
||||
gint level,
|
||||
gboolean *is_premult);
|
||||
|
||||
void tile_pyramid_invalidate_area (TilePyramid *pyramid,
|
||||
gint x,
|
||||
|
|
|
@ -109,7 +109,7 @@ gimp_image_get_preview (GimpViewable *viewable,
|
|||
temp_buf_free (image->preview);
|
||||
|
||||
image->preview = gimp_image_get_new_preview (viewable, context,
|
||||
width, height);
|
||||
width, height);
|
||||
|
||||
return image->preview;
|
||||
}
|
||||
|
@ -122,16 +122,28 @@ gimp_image_get_new_preview (GimpViewable *viewable,
|
|||
gint height)
|
||||
{
|
||||
GimpImage *image = GIMP_IMAGE (viewable);
|
||||
TempBuf *buf;
|
||||
TileManager *tiles;
|
||||
gdouble scale_x;
|
||||
gdouble scale_y;
|
||||
gint level;
|
||||
gboolean is_premult;
|
||||
|
||||
scale_x = (gdouble) width / (gdouble) image->width;
|
||||
scale_y = (gdouble) height / (gdouble) image->height;
|
||||
|
||||
level = gimp_projection_get_level (image->projection, scale_x, scale_y);
|
||||
tiles = gimp_projection_get_tiles_at_level (image->projection, level);
|
||||
|
||||
return tile_manager_get_preview (tiles, width, height);
|
||||
tiles = gimp_projection_get_tiles_at_level (image->projection, level,
|
||||
&is_premult);
|
||||
|
||||
buf = tile_manager_get_preview (tiles, width, height);
|
||||
|
||||
/* FIXME: We could avoid this if the view renderer and all other
|
||||
* preview code would know how to deal with pre-multiply alpha.
|
||||
*/
|
||||
if (is_premult)
|
||||
temp_buf_demultiply (buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
|
|
@ -306,13 +306,14 @@ gimp_projection_new (GimpImage *image)
|
|||
TileManager *
|
||||
gimp_projection_get_tiles (GimpProjection *proj)
|
||||
{
|
||||
return gimp_projection_get_tiles_at_level (proj, 0);
|
||||
return gimp_projection_get_tiles_at_level (proj, 0, NULL);
|
||||
|
||||
}
|
||||
|
||||
TileManager *
|
||||
gimp_projection_get_tiles_at_level (GimpProjection *proj,
|
||||
gint level)
|
||||
gint level,
|
||||
gboolean *is_premult)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_PROJECTION (proj), NULL);
|
||||
|
||||
|
@ -327,7 +328,7 @@ gimp_projection_get_tiles_at_level (GimpProjection *proj,
|
|||
proj);
|
||||
}
|
||||
|
||||
return tile_pyramid_get_tiles (proj->pyramid, level);
|
||||
return tile_pyramid_get_tiles (proj->pyramid, level, is_premult);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -384,14 +385,6 @@ gimp_projection_get_bytes (const GimpProjection *proj)
|
|||
return GIMP_IMAGE_TYPE_BYTES (gimp_projection_get_image_type (proj));
|
||||
}
|
||||
|
||||
gdouble
|
||||
gimp_projection_get_opacity (const GimpProjection *proj)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_PROJECTION (proj), GIMP_OPACITY_OPAQUE);
|
||||
|
||||
return GIMP_OPACITY_OPAQUE;
|
||||
}
|
||||
|
||||
void
|
||||
gimp_projection_flush (GimpProjection *proj)
|
||||
{
|
||||
|
|
|
@ -85,7 +85,8 @@ TileManager * gimp_projection_get_tiles (GimpProjection *proj);
|
|||
|
||||
TileManager * gimp_projection_get_tiles_at_level
|
||||
(GimpProjection *proj,
|
||||
gint level);
|
||||
gint level,
|
||||
gboolean *is_premult);
|
||||
gint gimp_projection_get_level (GimpProjection *proj,
|
||||
gdouble scale_x,
|
||||
gdouble scale_y);
|
||||
|
@ -93,7 +94,6 @@ gint gimp_projection_get_level (GimpProjection *proj,
|
|||
GimpImage * gimp_projection_get_image (const GimpProjection *proj);
|
||||
GimpImageType gimp_projection_get_image_type (const GimpProjection *proj);
|
||||
gint gimp_projection_get_bytes (const GimpProjection *proj);
|
||||
gdouble gimp_projection_get_opacity (const GimpProjection *proj);
|
||||
|
||||
void gimp_projection_flush (GimpProjection *proj);
|
||||
void gimp_projection_flush_now (GimpProjection *proj);
|
||||
|
|
|
@ -520,7 +520,7 @@ gimp_display_shell_draw_area (GimpDisplayShell *shell,
|
|||
|
||||
level = gimp_projection_get_level (proj, shell->scale_x, shell->scale_y);
|
||||
|
||||
tiles = gimp_projection_get_tiles_at_level (proj, level);
|
||||
tiles = gimp_projection_get_tiles_at_level (proj, level, NULL);
|
||||
|
||||
level_width = tile_manager_width (tiles);
|
||||
level_height = tile_manager_height (tiles);
|
||||
|
|
|
@ -39,8 +39,6 @@
|
|||
#include "core/gimpimage-colormap.h"
|
||||
#include "core/gimpprojection.h"
|
||||
|
||||
#include "widgets/gimprender.h"
|
||||
|
||||
#include "gimpcanvas.h"
|
||||
#include "gimpdisplay.h"
|
||||
#include "gimpdisplayshell.h"
|
||||
|
@ -56,6 +54,9 @@
|
|||
100% and 200% zoom)
|
||||
*/
|
||||
|
||||
#define GIMP_DISPLAY_RENDER_BUF_WIDTH 256
|
||||
|
||||
|
||||
typedef struct _RenderInfo RenderInfo;
|
||||
|
||||
typedef void (* RenderFunc) (RenderInfo *info);
|
||||
|
@ -64,9 +65,9 @@ struct _RenderInfo
|
|||
{
|
||||
GimpDisplayShell *shell;
|
||||
TileManager *src_tiles;
|
||||
const guint *alpha;
|
||||
const guchar *src;
|
||||
guchar *dest;
|
||||
gboolean src_is_premult;
|
||||
gint x, y;
|
||||
gint w, h;
|
||||
gdouble scalex;
|
||||
|
@ -99,7 +100,8 @@ struct _RenderInfo
|
|||
static void gimp_display_shell_render_info_scale (RenderInfo *info,
|
||||
GimpDisplayShell *shell,
|
||||
TileManager *tiles,
|
||||
gint level);
|
||||
gint level,
|
||||
gboolean is_premult);
|
||||
|
||||
static void gimp_display_shell_render_setup_notify (GObject *config,
|
||||
GParamSpec *param_spec,
|
||||
|
@ -110,6 +112,8 @@ static guchar *tile_buf = NULL;
|
|||
|
||||
static guint check_mod = 0;
|
||||
static guint check_shift = 0;
|
||||
static guchar check_dark = 0;
|
||||
static guchar check_light = 0;
|
||||
|
||||
|
||||
void
|
||||
|
@ -126,7 +130,7 @@ gimp_display_shell_render_init (Gimp *gimp)
|
|||
gimp);
|
||||
|
||||
/* allocate a buffer for arranging information from a row of tiles */
|
||||
tile_buf = g_new (guchar, GIMP_RENDER_BUF_WIDTH * MAX_CHANNELS);
|
||||
tile_buf = g_new (guchar, GIMP_DISPLAY_RENDER_BUF_WIDTH * MAX_CHANNELS);
|
||||
|
||||
gimp_display_shell_render_setup_notify (G_OBJECT (gimp->config), NULL, gimp);
|
||||
}
|
||||
|
@ -153,11 +157,15 @@ gimp_display_shell_render_setup_notify (GObject *config,
|
|||
Gimp *gimp)
|
||||
{
|
||||
GimpCheckSize check_size;
|
||||
GimpCheckType check_type;
|
||||
|
||||
g_object_get (config,
|
||||
"transparency-size", &check_size,
|
||||
"transparency-type", &check_type,
|
||||
NULL);
|
||||
|
||||
gimp_checks_get_shades (check_type, &check_light, &check_dark);
|
||||
|
||||
switch (check_size)
|
||||
{
|
||||
case GIMP_CHECK_SIZE_SMALL_CHECKS:
|
||||
|
@ -183,8 +191,6 @@ gimp_display_shell_render_setup_notify (GObject *config,
|
|||
static void render_image_rgb_a (RenderInfo *info);
|
||||
static void render_image_gray_a (RenderInfo *info);
|
||||
|
||||
static const guint * render_image_init_alpha (gint mult);
|
||||
|
||||
static const guchar * render_image_tile_fault (RenderInfo *info);
|
||||
|
||||
|
||||
|
@ -235,7 +241,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
|
|||
info.h = h;
|
||||
|
||||
info.dest_bpp = 3;
|
||||
info.dest_bpl = info.dest_bpp * GIMP_RENDER_BUF_WIDTH;
|
||||
info.dest_bpl = info.dest_bpp * GIMP_DISPLAY_RENDER_BUF_WIDTH;
|
||||
info.dest_width = info.dest_bpp * info.w;
|
||||
|
||||
switch (GIMP_DISPLAY_CONFIG (image->gimp->config)->zoom_quality)
|
||||
|
@ -249,25 +255,19 @@ gimp_display_shell_render (GimpDisplayShell *shell,
|
|||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
TileManager *tiles;
|
||||
gint level;
|
||||
gboolean premult;
|
||||
|
||||
level = gimp_projection_get_level (projection,
|
||||
shell->scale_x,
|
||||
shell->scale_y);
|
||||
|
||||
src_tiles = gimp_projection_get_tiles_at_level (projection, level);
|
||||
tiles = gimp_projection_get_tiles_at_level (projection, level, &premult);
|
||||
|
||||
gimp_display_shell_render_info_scale (&info, shell, src_tiles, level);
|
||||
gimp_display_shell_render_info_scale (&info, shell, tiles, level, premult);
|
||||
}
|
||||
|
||||
/* Currently, only RGBA and GRAYA projection types are used. */
|
||||
|
@ -292,7 +292,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
|
|||
shell->render_buf,
|
||||
w, h,
|
||||
3,
|
||||
3 * GIMP_RENDER_BUF_WIDTH);
|
||||
3 * GIMP_DISPLAY_RENDER_BUF_WIDTH);
|
||||
|
||||
/* dim pixels outside the highlighted rectangle */
|
||||
if (highlight)
|
||||
|
@ -301,10 +301,10 @@ gimp_display_shell_render (GimpDisplayShell *shell,
|
|||
}
|
||||
else if (shell->mask)
|
||||
{
|
||||
TileManager *src_tiles = gimp_drawable_get_tiles (shell->mask);
|
||||
TileManager *tiles = gimp_drawable_get_tiles (shell->mask);
|
||||
|
||||
/* The mask does not (yet) have an image pyramid, use 0 as level, */
|
||||
gimp_display_shell_render_info_scale (&info, shell, src_tiles, 0);
|
||||
gimp_display_shell_render_info_scale (&info, shell, tiles, 0, FALSE);
|
||||
|
||||
gimp_display_shell_render_mask (shell, &info);
|
||||
}
|
||||
|
@ -314,7 +314,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
|
|||
x + shell->disp_xoffset, y + shell->disp_yoffset,
|
||||
w, h,
|
||||
shell->render_buf,
|
||||
3 * GIMP_RENDER_BUF_WIDTH,
|
||||
3 * GIMP_DISPLAY_RENDER_BUF_WIDTH,
|
||||
shell->offset_x, shell->offset_y);
|
||||
}
|
||||
|
||||
|
@ -354,7 +354,7 @@ gimp_display_shell_render_highlight (GimpDisplayShell *shell,
|
|||
for (x = 0; x < w; x++)
|
||||
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
|
||||
|
||||
buf += 3 * GIMP_RENDER_BUF_WIDTH;
|
||||
buf += 3 * GIMP_DISPLAY_RENDER_BUF_WIDTH;
|
||||
}
|
||||
|
||||
for ( ; y < rect.y + rect.height; y++)
|
||||
|
@ -365,7 +365,7 @@ gimp_display_shell_render_highlight (GimpDisplayShell *shell,
|
|||
for (x += rect.width; x < w; x++)
|
||||
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
|
||||
|
||||
buf += 3 * GIMP_RENDER_BUF_WIDTH;
|
||||
buf += 3 * GIMP_DISPLAY_RENDER_BUF_WIDTH;
|
||||
}
|
||||
|
||||
for ( ; y < h; y++)
|
||||
|
@ -373,7 +373,7 @@ gimp_display_shell_render_highlight (GimpDisplayShell *shell,
|
|||
for (x = 0; x < w; x++)
|
||||
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
|
||||
|
||||
buf += 3 * GIMP_RENDER_BUF_WIDTH;
|
||||
buf += 3 * GIMP_DISPLAY_RENDER_BUF_WIDTH;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -383,7 +383,7 @@ gimp_display_shell_render_highlight (GimpDisplayShell *shell,
|
|||
for (x = 0; x < w; x++)
|
||||
GIMP_DISPLAY_SHELL_DIM_PIXEL (buf, x)
|
||||
|
||||
buf += 3 * GIMP_RENDER_BUF_WIDTH;
|
||||
buf += 3 * GIMP_DISPLAY_RENDER_BUF_WIDTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -467,9 +467,8 @@ gimp_display_shell_render_mask (GimpDisplayShell *shell,
|
|||
static void
|
||||
render_image_gray_a (RenderInfo *info)
|
||||
{
|
||||
const guint *alpha = info->alpha;
|
||||
gint y, ye;
|
||||
gint x, xe;
|
||||
gint y, ye;
|
||||
gint x, xe;
|
||||
|
||||
y = info->y;
|
||||
ye = info->y + info->h;
|
||||
|
@ -486,28 +485,21 @@ render_image_gray_a (RenderInfo *info)
|
|||
|
||||
dark_light = (y >> check_shift) + (info->x >> check_shift);
|
||||
|
||||
for (x = info->x; x < xe; x++)
|
||||
for (x = info->x; x < xe; x++, src += 2, dest += 3)
|
||||
{
|
||||
const guint a = alpha[src[ALPHA_G_PIX]];
|
||||
guchar val;
|
||||
guint v;
|
||||
|
||||
if (dark_light & 0x1)
|
||||
val = gimp_render_blend_dark_check[(a | src[GRAY_PIX])];
|
||||
v = ((src[0] << 8) + check_dark * (256 - src[1])) >> 8;
|
||||
else
|
||||
val = gimp_render_blend_light_check[(a | src[GRAY_PIX])];
|
||||
v = ((src[0] << 8) + check_light * (256 - src[1])) >> 8;
|
||||
|
||||
src += 2;
|
||||
|
||||
dest[0] = val;
|
||||
dest[1] = val;
|
||||
dest[2] = val;
|
||||
dest += 3;
|
||||
dest[0] = dest[1] = dest[2] = v;
|
||||
|
||||
if (((x + 1) & check_mod) == 0)
|
||||
dark_light += 1;
|
||||
}
|
||||
|
||||
|
||||
if (++y == ye)
|
||||
break;
|
||||
|
||||
|
@ -524,9 +516,8 @@ render_image_gray_a (RenderInfo *info)
|
|||
static void
|
||||
render_image_rgb_a (RenderInfo *info)
|
||||
{
|
||||
const guint *alpha = info->alpha;
|
||||
gint y, ye;
|
||||
gint x, xe;
|
||||
gint y, ye;
|
||||
gint x, xe;
|
||||
|
||||
y = info->y;
|
||||
ye = info->y + info->h;
|
||||
|
@ -543,25 +534,26 @@ render_image_rgb_a (RenderInfo *info)
|
|||
|
||||
dark_light = (y >> check_shift) + (info->x >> check_shift);
|
||||
|
||||
for (x = info->x; x < xe; x++)
|
||||
for (x = info->x; x < xe; x++, src += 4, dest += 3)
|
||||
{
|
||||
const guint a = alpha[src[ALPHA_PIX]];
|
||||
guint r, g, b;
|
||||
|
||||
if (dark_light & 0x1)
|
||||
{
|
||||
dest[0] = gimp_render_blend_dark_check[(a | src[RED_PIX])];
|
||||
dest[1] = gimp_render_blend_dark_check[(a | src[GREEN_PIX])];
|
||||
dest[2] = gimp_render_blend_dark_check[(a | src[BLUE_PIX])];
|
||||
r = ((src[0] << 8) + check_dark * (256 - src[3])) >> 8;
|
||||
g = ((src[1] << 8) + check_dark * (256 - src[3])) >> 8;
|
||||
b = ((src[2] << 8) + check_dark * (256 - src[3])) >> 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest[0] = gimp_render_blend_light_check[(a | src[RED_PIX])];
|
||||
dest[1] = gimp_render_blend_light_check[(a | src[GREEN_PIX])];
|
||||
dest[2] = gimp_render_blend_light_check[(a | src[BLUE_PIX])];
|
||||
r = ((src[0] << 8) + check_light * (256 - src[3])) >> 8;
|
||||
g = ((src[1] << 8) + check_light * (256 - src[3])) >> 8;
|
||||
b = ((src[2] << 8) + check_light * (256 - src[3])) >> 8;
|
||||
}
|
||||
|
||||
src += 4;
|
||||
dest += 3;
|
||||
dest[0] = r;
|
||||
dest[1] = g;
|
||||
dest[2] = b;
|
||||
|
||||
if (((x + 1) & check_mod) == 0)
|
||||
dark_light += 1;
|
||||
|
@ -585,9 +577,11 @@ static void
|
|||
gimp_display_shell_render_info_scale (RenderInfo *info,
|
||||
GimpDisplayShell *shell,
|
||||
TileManager *tiles,
|
||||
gint level)
|
||||
gint level,
|
||||
gboolean is_premult)
|
||||
{
|
||||
info->src_tiles = tiles;
|
||||
info->src_tiles = tiles;
|
||||
info->src_is_premult = is_premult;
|
||||
|
||||
/* We must reset info->dest because this member is modified in render
|
||||
* functions.
|
||||
|
@ -643,27 +637,7 @@ gimp_display_shell_render_info_scale (RenderInfo *info,
|
|||
}
|
||||
}
|
||||
|
||||
static const guint *
|
||||
render_image_init_alpha (gint mult)
|
||||
{
|
||||
static guint *alpha_mult = NULL;
|
||||
static gint alpha_val = -1;
|
||||
|
||||
if (alpha_val != mult)
|
||||
{
|
||||
gint i;
|
||||
|
||||
if (!alpha_mult)
|
||||
alpha_mult = g_new (guint, 256);
|
||||
|
||||
alpha_val = mult;
|
||||
for (i = 0; i < 256; i++)
|
||||
alpha_mult[i] = ((mult * i) / 255) << 8;
|
||||
}
|
||||
|
||||
return alpha_mult;
|
||||
}
|
||||
|
||||
/* This version assumes that the src data is already pre-multiplied. */
|
||||
static inline void
|
||||
box_filter (const guint left_weight,
|
||||
const guint center_weight,
|
||||
|
@ -674,6 +648,38 @@ box_filter (const guint left_weight,
|
|||
const guchar **src, /* the 9 surrounding source pixels */
|
||||
guchar *dest,
|
||||
const gint bpp)
|
||||
{
|
||||
const guint sum = ((left_weight + center_weight + right_weight) *
|
||||
(top_weight + middle_weight + bottom_weight));
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < bpp; i++)
|
||||
{
|
||||
dest[i] = ( left_weight * ((src[0][i] * top_weight) +
|
||||
(src[3][i] * middle_weight) +
|
||||
(src[6][i] * bottom_weight))
|
||||
+ center_weight * ((src[1][i] * top_weight) +
|
||||
(src[4][i] * middle_weight) +
|
||||
(src[7][i] * bottom_weight))
|
||||
+ right_weight * ((src[2][i] * top_weight) +
|
||||
(src[5][i] * middle_weight) +
|
||||
(src[8][i] * bottom_weight))) / sum;
|
||||
}
|
||||
}
|
||||
|
||||
/* This version assumes that the src data is not pre-multipled.
|
||||
* It creates pre-multiplied output though.
|
||||
*/
|
||||
static inline void
|
||||
box_filter_premult (const guint left_weight,
|
||||
const guint center_weight,
|
||||
const guint right_weight,
|
||||
const guint top_weight,
|
||||
const guint middle_weight,
|
||||
const guint bottom_weight,
|
||||
const guchar **src, /* the 9 surrounding source pixels */
|
||||
guchar *dest,
|
||||
const gint bpp)
|
||||
{
|
||||
const guint sum = ((left_weight + center_weight + right_weight) *
|
||||
(top_weight + middle_weight + bottom_weight)) >> 4;
|
||||
|
@ -699,33 +705,24 @@ box_filter (const guint left_weight,
|
|||
guint a = (center_weight * (factors[0] + factors[1] + factors[2]) +
|
||||
right_weight * (factors[3] + factors[4] + factors[5]) +
|
||||
left_weight * (factors[6] + factors[7] + factors[8]));
|
||||
guint i;
|
||||
|
||||
if (a)
|
||||
for (i = 0; i < ALPHA; i++)
|
||||
{
|
||||
gint i;
|
||||
dest[i] = ((center_weight * (factors[0] * src[1][i] +
|
||||
factors[1] * src[4][i] +
|
||||
factors[2] * src[7][i]) +
|
||||
|
||||
for (i = 0; i < ALPHA; i++)
|
||||
{
|
||||
dest[i] = ((center_weight * (factors[0] * src[1][i] +
|
||||
factors[1] * src[4][i] +
|
||||
factors[2] * src[7][i]) +
|
||||
right_weight * (factors[3] * src[2][i] +
|
||||
factors[4] * src[5][i] +
|
||||
factors[5] * src[8][i]) +
|
||||
|
||||
right_weight * (factors[3] * src[2][i] +
|
||||
factors[4] * src[5][i] +
|
||||
factors[5] * src[8][i]) +
|
||||
|
||||
left_weight * (factors[6] * src[0][i] +
|
||||
factors[7] * src[3][i] +
|
||||
factors[8] * src[6][i])
|
||||
) / a) & 0xff;
|
||||
}
|
||||
|
||||
dest[ALPHA] = (a + (sum >> 1)) / sum;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest[ALPHA] = 0;
|
||||
left_weight * (factors[6] * src[0][i] +
|
||||
factors[7] * src[3][i] +
|
||||
factors[8] * src[6][i])) / sum) >> 8;
|
||||
}
|
||||
|
||||
dest[ALPHA] = (a + (sum >> 1)) / sum;
|
||||
}
|
||||
#undef ALPHA
|
||||
break;
|
||||
|
@ -753,33 +750,24 @@ box_filter (const guint left_weight,
|
|||
guint a = (center_weight * (factors[0] + factors[1] + factors[2]) +
|
||||
right_weight * (factors[3] + factors[4] + factors[5]) +
|
||||
left_weight * (factors[6] + factors[7] + factors[8]));
|
||||
guint i;
|
||||
|
||||
if (a)
|
||||
for (i = 0; i < ALPHA; i++)
|
||||
{
|
||||
gint i;
|
||||
dest[i] = ((center_weight * (factors[0] * src[1][i] +
|
||||
factors[1] * src[4][i] +
|
||||
factors[2] * src[7][i]) +
|
||||
|
||||
for (i = 0; i < ALPHA; i++)
|
||||
{
|
||||
dest[i] = ((center_weight * (factors[0] * src[1][i] +
|
||||
factors[1] * src[4][i] +
|
||||
factors[2] * src[7][i]) +
|
||||
right_weight * (factors[3] * src[2][i] +
|
||||
factors[4] * src[5][i] +
|
||||
factors[5] * src[8][i]) +
|
||||
|
||||
right_weight * (factors[3] * src[2][i] +
|
||||
factors[4] * src[5][i] +
|
||||
factors[5] * src[8][i]) +
|
||||
|
||||
left_weight * (factors[6] * src[0][i] +
|
||||
factors[7] * src[3][i] +
|
||||
factors[8] * src[6][i])
|
||||
) / a) & 0xff;
|
||||
}
|
||||
|
||||
dest[ALPHA] = (a + (sum >> 1)) / sum;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest[ALPHA] = 0;
|
||||
left_weight * (factors[6] * src[0][i] +
|
||||
factors[7] * src[3][i] +
|
||||
factors[8] * src[6][i])) / sum) >> 8;
|
||||
}
|
||||
|
||||
dest[ALPHA] = (a + (sum >> 1)) / sum;
|
||||
}
|
||||
#undef ALPHA
|
||||
break;
|
||||
|
@ -799,7 +787,9 @@ static const guchar * render_image_tile_fault_nearest (RenderInfo *info);
|
|||
* 678
|
||||
*/
|
||||
|
||||
/* function to render a horizontal line of view data */
|
||||
/* Function to render a horizontal line of view data. The data
|
||||
* returned from this function has the alpha channel pre-multiplied.
|
||||
*/
|
||||
static const guchar *
|
||||
render_image_tile_fault (RenderInfo *info)
|
||||
{
|
||||
|
@ -1032,9 +1022,14 @@ render_image_tile_fault (RenderInfo *info)
|
|||
src[8] = src[5];
|
||||
}
|
||||
|
||||
box_filter (left_weight, center_weight, right_weight,
|
||||
top_weight, middle_weight, bottom_weight,
|
||||
src, dest, bpp);
|
||||
if (info->src_is_premult)
|
||||
box_filter (left_weight, center_weight, right_weight,
|
||||
top_weight, middle_weight, bottom_weight,
|
||||
src, dest, bpp);
|
||||
else
|
||||
box_filter_premult (left_weight, center_weight, right_weight,
|
||||
top_weight, middle_weight, bottom_weight,
|
||||
src, dest, bpp);
|
||||
|
||||
dest += bpp;
|
||||
|
||||
|
@ -1253,83 +1248,6 @@ done:
|
|||
return tile_buf;
|
||||
}
|
||||
|
||||
/* function to render a horizontal line of view data */
|
||||
static const guchar *
|
||||
render_image_tile_fault_nearest (RenderInfo *info)
|
||||
{
|
||||
Tile *tile;
|
||||
const guchar *src;
|
||||
guchar *dest;
|
||||
gint width;
|
||||
gint tilex;
|
||||
gint bpp;
|
||||
gint src_x;
|
||||
gint64 dx;
|
||||
|
||||
tile = tile_manager_get_tile (info->src_tiles,
|
||||
info->src_x, info->src_y, TRUE, FALSE);
|
||||
|
||||
g_return_val_if_fail (tile != NULL, tile_buf);
|
||||
|
||||
src = tile_data_pointer (tile, info->src_x, info->src_y);
|
||||
|
||||
bpp = tile_manager_bpp (info->src_tiles);
|
||||
dest = tile_buf;
|
||||
|
||||
dx = info->dx_start;
|
||||
|
||||
width = info->w;
|
||||
|
||||
src_x = info->src_x;
|
||||
tilex = info->src_x / TILE_WIDTH;
|
||||
|
||||
do
|
||||
{
|
||||
const guchar *s = src;
|
||||
gint skipped;
|
||||
|
||||
switch (bpp)
|
||||
{
|
||||
case 4:
|
||||
*dest++ = *s++;
|
||||
case 3:
|
||||
*dest++ = *s++;
|
||||
case 2:
|
||||
*dest++ = *s++;
|
||||
case 1:
|
||||
*dest++ = *s++;
|
||||
}
|
||||
|
||||
dx += info->x_dest_inc;
|
||||
skipped = dx / info->x_src_dec;
|
||||
|
||||
if (skipped)
|
||||
{
|
||||
src += skipped * bpp;
|
||||
src_x += skipped;
|
||||
dx -= skipped * info->x_src_dec;
|
||||
|
||||
if ((src_x / TILE_WIDTH) != tilex)
|
||||
{
|
||||
tile_release (tile, FALSE);
|
||||
tilex += 1;
|
||||
|
||||
tile = tile_manager_get_tile (info->src_tiles,
|
||||
src_x, info->src_y, TRUE, FALSE);
|
||||
if (! tile)
|
||||
return tile_buf;
|
||||
|
||||
src = tile_data_pointer (tile, src_x, info->src_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (--width);
|
||||
|
||||
tile_release (tile, FALSE);
|
||||
|
||||
return tile_buf;
|
||||
}
|
||||
|
||||
static const guchar *
|
||||
render_image_tile_fault_one_row (RenderInfo *info)
|
||||
{
|
||||
|
@ -1476,9 +1394,14 @@ render_image_tile_fault_one_row (RenderInfo *info)
|
|||
src[8] = src[7];
|
||||
}
|
||||
|
||||
box_filter (left_weight, center_weight, right_weight,
|
||||
top_weight, middle_weight, bottom_weight,
|
||||
src, dest, bpp);
|
||||
if (info->src_is_premult)
|
||||
box_filter (left_weight, center_weight, right_weight,
|
||||
top_weight, middle_weight, bottom_weight,
|
||||
src, dest, bpp);
|
||||
else
|
||||
box_filter_premult (left_weight, center_weight, right_weight,
|
||||
top_weight, middle_weight, bottom_weight,
|
||||
src, dest, bpp);
|
||||
|
||||
dest += bpp;
|
||||
|
||||
|
@ -1611,9 +1534,111 @@ render_image_tile_fault_one_row (RenderInfo *info)
|
|||
while (--width);
|
||||
|
||||
done:
|
||||
for (dx=0; dx<3; dx++)
|
||||
for (dx = 0; dx < 3; dx++)
|
||||
if (tile[dx])
|
||||
tile_release (tile[dx], FALSE);
|
||||
|
||||
return tile_buf;
|
||||
}
|
||||
|
||||
/* function to render a horizontal line of view data */
|
||||
static const guchar *
|
||||
render_image_tile_fault_nearest (RenderInfo *info)
|
||||
{
|
||||
Tile *tile;
|
||||
const guchar *src;
|
||||
guchar *d;
|
||||
gint width;
|
||||
gint tilex;
|
||||
gint bpp;
|
||||
gint src_x;
|
||||
gint64 dx;
|
||||
|
||||
tile = tile_manager_get_tile (info->src_tiles,
|
||||
info->src_x, info->src_y, TRUE, FALSE);
|
||||
|
||||
g_return_val_if_fail (tile != NULL, tile_buf);
|
||||
|
||||
src = tile_data_pointer (tile, info->src_x, info->src_y);
|
||||
|
||||
bpp = tile_manager_bpp (info->src_tiles);
|
||||
|
||||
dx = info->dx_start;
|
||||
|
||||
width = info->w;
|
||||
|
||||
src_x = info->src_x;
|
||||
tilex = info->src_x / TILE_WIDTH;
|
||||
|
||||
d = tile_buf;
|
||||
|
||||
do
|
||||
{
|
||||
const guchar *s = src;
|
||||
gint skipped;
|
||||
|
||||
if (info->src_is_premult)
|
||||
{
|
||||
switch (bpp)
|
||||
{
|
||||
case 4:
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
case 2:
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
}
|
||||
}
|
||||
else /* pre-multiply */
|
||||
{
|
||||
switch (bpp)
|
||||
{
|
||||
case 4:
|
||||
d[0] = (s[0] * s[3]) >> 8;
|
||||
d[1] = (s[1] * s[3]) >> 8;
|
||||
d[2] = (s[2] * s[3]) >> 8;
|
||||
d[3] = s[3];
|
||||
|
||||
d += 4;
|
||||
s += 4;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
d[0] = (s[0] * s[1]) >> 8;
|
||||
d[1] = s[1];
|
||||
|
||||
d += 2;
|
||||
s += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dx += info->x_dest_inc;
|
||||
skipped = dx / info->x_src_dec;
|
||||
|
||||
if (skipped)
|
||||
{
|
||||
src += skipped * bpp;
|
||||
src_x += skipped;
|
||||
dx -= skipped * info->x_src_dec;
|
||||
|
||||
if ((src_x / TILE_WIDTH) != tilex)
|
||||
{
|
||||
tile_release (tile, FALSE);
|
||||
tilex += 1;
|
||||
|
||||
tile = tile_manager_get_tile (info->src_tiles,
|
||||
src_x, info->src_y, TRUE, FALSE);
|
||||
if (! tile)
|
||||
return tile_buf;
|
||||
|
||||
src = tile_data_pointer (tile, src_x, info->src_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (--width);
|
||||
|
||||
tile_release (tile, FALSE);
|
||||
|
||||
return tile_buf;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue