diff options
Diffstat (limited to 'gs/base/gdevmr8n.c')
-rw-r--r-- | gs/base/gdevmr8n.c | 396 |
1 files changed, 396 insertions, 0 deletions
diff --git a/gs/base/gdevmr8n.c b/gs/base/gdevmr8n.c new file mode 100644 index 000000000..263140ea4 --- /dev/null +++ b/gs/base/gdevmr8n.c @@ -0,0 +1,396 @@ +/* Copyright (C) 2001-2006 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or + implied. + + This software is distributed under license and may not be copied, modified + or distributed except as expressly authorized under the terms of that + license. Refer to licensing information at http://www.artifex.com/ + or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, + San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. +*/ +/* $Id$ */ +/* RasterOp implementation for 8N-bit memory devices */ +#include "memory_.h" +#include "gx.h" +#include "gsbittab.h" +#include "gserrors.h" +#include "gsropt.h" +#include "gxcindex.h" +#include "gxdcolor.h" +#include "gxdevice.h" +#include "gxdevmem.h" +#include "gxdevrop.h" +#include "gdevmem.h" +#include "gdevmrop.h" +#include "vdtrace.h" + +/* + * NOTE: The 16- and 32-bit cases aren't implemented: they just fall back to + * the default implementation. This is very slow and will be fixed someday. + */ + +#define chunk byte + +/* Calculate the X offset for a given Y value, */ +/* taking shift into account if necessary. */ +#define x_offset(px, ty, textures)\ + ((textures)->shift == 0 ? (px) :\ + (px) + (ty) / (textures)->rep_height * (textures)->rep_shift) + +/* ---------------- RasterOp with 8-bit gray / 24-bit RGB ---------------- */ + +int +mem_gray8_rgb24_strip_copy_rop(gx_device * dev, + const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id, + const gx_color_index * scolors, + const gx_strip_bitmap * textures, const gx_color_index * tcolors, + int x, int y, int width, int height, + int phase_x, int phase_y, gs_logical_operation_t lop) +{ + gx_device_memory *mdev = (gx_device_memory *) dev; + gs_rop3_t rop = lop_rop(lop); + gx_color_index const_source = gx_no_color_index; + gx_color_index const_texture = gx_no_color_index; + uint draster = mdev->raster; + int line_count; + byte *drow, *base; + int depth = dev->color_info.depth; + int bpp = depth >> 3; /* bytes per pixel, 1 or 3 */ + gx_color_index all_ones = ((gx_color_index) 1 << depth) - 1; + gx_color_index strans = + (lop & lop_S_transparent ? all_ones : gx_no_color_index); + gx_color_index ttrans = + (lop & lop_T_transparent ? all_ones : gx_no_color_index); + + /* Check for constant source. */ + if (!rop3_uses_S(rop)) + const_source = 0; /* arbitrary */ + else if (scolors != 0 && scolors[0] == scolors[1]) { + /* Constant source */ + const_source = scolors[0]; + if (const_source == gx_device_black(dev)) + rop = rop3_know_S_0(rop); + else if (const_source == gx_device_white(dev)) + rop = rop3_know_S_1(rop); + } + + /* Check for constant texture. */ + if (!rop3_uses_T(rop)) + const_texture = 0; /* arbitrary */ + else if (tcolors != 0 && tcolors[0] == tcolors[1]) { + /* Constant texture */ + const_texture = tcolors[0]; + if (const_texture == gx_device_black(dev)) + rop = rop3_know_T_0(rop); + else if (const_texture == gx_device_white(dev)) + rop = rop3_know_T_1(rop); + } + + if (bpp == 1 && + (gx_device_has_color(dev) || + (gx_device_black(dev) != 0 || gx_device_white(dev) != all_ones)) + ) { + /* + * This is an 8-bit device but not gray-scale. Except in a few + * simple cases, we have to use the slow algorithm that converts + * values to and from RGB. + */ + gx_color_index bw_pixel; + + switch (rop) { + case rop3_0: + bw_pixel = gx_device_black(dev); + goto bw; + case rop3_1: + bw_pixel = gx_device_white(dev); +bw: if (bw_pixel == 0x00) + rop = rop3_0; + else if (bw_pixel == 0xff) + rop = rop3_1; + else + goto df; + break; + case rop3_D: + break; + case rop3_S: + if (lop & lop_S_transparent) + goto df; + break; + case rop3_T: + if (lop & lop_T_transparent) + goto df; + break; + default: +df: return mem_default_strip_copy_rop(dev, + sdata, sourcex, sraster, id, + scolors, textures, tcolors, + x, y, width, height, + phase_x, phase_y, lop); + } + } + + /* Adjust coordinates to be in bounds. */ + if (const_source == gx_no_color_index) { + fit_copy(dev, sdata, sourcex, sraster, id, + x, y, width, height); + } else { + fit_fill(dev, x, y, width, height); + } + + /* Set up transfer parameters. */ + line_count = height; + base = scan_line_base(mdev, y); + drow = base + x * bpp; + + /* + * There are 18 cases depending on whether each of the source and + * texture is constant, 1-bit, or multi-bit, and on whether the + * depth is 8 or 24 bits. We divide first according to constant + * vs. non-constant, and then according to 1- vs. multi-bit, and + * finally according to pixel depth. This minimizes source code, + * but not necessarily time, since we do some of the divisions + * within 1 or 2 levels of loop. + */ + +#define dbit(base, i) ((base)[(i) >> 3] & (0x80 >> ((i) & 7))) +/* 8-bit */ +#define cbit8(base, i, colors)\ + (dbit(base, i) ? (byte)colors[1] : (byte)colors[0]) +#define rop_body_8(s_pixel, t_pixel)\ + if ( (s_pixel) == strans || /* So = 0, s_tr = 1 */\ + (t_pixel) == ttrans /* Po = 0, p_tr = 1 */\ + )\ + continue;\ + *dptr = (*rop_proc_table[rop])(*dptr, s_pixel, t_pixel) +/* 24-bit */ +#define get24(ptr)\ + (((gx_color_index)(ptr)[0] << 16) | ((gx_color_index)(ptr)[1] << 8) | (ptr)[2]) +#define put24(ptr, pixel)\ + (ptr)[0] = (byte)((pixel) >> 16),\ + (ptr)[1] = (byte)((uint)(pixel) >> 8),\ + (ptr)[2] = (byte)(pixel) +#define cbit24(base, i, colors)\ + (dbit(base, i) ? colors[1] : colors[0]) +#define rop_body_24(s_pixel, t_pixel)\ + if ( (s_pixel) == strans || /* So = 0, s_tr = 1 */\ + (t_pixel) == ttrans /* Po = 0, p_tr = 1 */\ + )\ + continue;\ + { gx_color_index d_pixel = get24(dptr);\ + d_pixel = (*rop_proc_table[rop])(d_pixel, s_pixel, t_pixel);\ + put24(dptr, d_pixel);\ + } + + if (const_texture != gx_no_color_index) { +/**** Constant texture ****/ + if (const_source != gx_no_color_index) { +/**** Constant source & texture ****/ + for (; line_count-- > 0; drow += draster) { + byte *dptr = drow; + int left = width; + + if (bpp == 1) +/**** 8-bit destination ****/ + for (; left > 0; ++dptr, --left) { + vd_pixel(int2fixed((dptr - base) % draster), + int2fixed((dptr - base) / draster + y), const_texture); + rop_body_8((byte)const_source, (byte)const_texture); + } + else +/**** 24-bit destination ****/ + for (; left > 0; dptr += 3, --left) { + vd_pixel(int2fixed((dptr - base) % draster / 3), + int2fixed((dptr - base) / draster + y), const_texture); + rop_body_24(const_source, const_texture); + } + } + } else { +/**** Data source, const texture ****/ + const byte *srow = sdata; + + for (; line_count-- > 0; drow += draster, srow += sraster) { + byte *dptr = drow; + int left = width; + + if (scolors) { +/**** 1-bit source ****/ + int sx = sourcex; + + if (bpp == 1) +/**** 8-bit destination ****/ + for (; left > 0; ++dptr, ++sx, --left) { + byte s_pixel = cbit8(srow, sx, scolors); + + vd_pixel(int2fixed((dptr - base) % draster), + int2fixed((dptr - base) / draster + y), const_texture); + rop_body_8(s_pixel, (byte)const_texture); + } + else +/**** 24-bit destination ****/ + for (; left > 0; dptr += 3, ++sx, --left) { + bits32 s_pixel = cbit24(srow, sx, scolors); + + vd_pixel(int2fixed((dptr - base) % draster / 3), + int2fixed((dptr - base) / draster + y), const_texture); + rop_body_24(s_pixel, const_texture); + } + } else if (bpp == 1) { +/**** 8-bit source & dest ****/ + const byte *sptr = srow + sourcex; + + for (; left > 0; ++dptr, ++sptr, --left) { + byte s_pixel = *sptr; + + vd_pixel(int2fixed((dptr - base) % draster), + int2fixed((dptr - base) / draster + y), const_texture); + rop_body_8(s_pixel, (byte)const_texture); + } + } else { +/**** 24-bit source & dest ****/ + const byte *sptr = srow + sourcex * 3; + + for (; left > 0; dptr += 3, sptr += 3, --left) { + bits32 s_pixel = get24(sptr); + + vd_pixel(int2fixed((dptr - base) % draster / 3), + int2fixed((dptr - base) / draster + y), const_texture); + rop_body_24(s_pixel, const_texture); + } + } + } + } + } else if (const_source != gx_no_color_index) { +/**** Const source, data texture ****/ + uint traster = textures->raster; + int ty = y + phase_y; + + for (; line_count-- > 0; drow += draster, ++ty) { /* Loop over copies of the tile. */ + int dx = x, w = width, nw; + byte *dptr = drow; + const byte *trow = + textures->data + (ty % textures->size.y) * traster; + int xoff = x_offset(phase_x, ty, textures); + + for (; w > 0; dx += nw, w -= nw) { + int tx = (dx + xoff) % textures->rep_width; + int left = nw = min(w, textures->size.x - tx); + const byte *tptr = trow; + + if (tcolors) { +/**** 1-bit texture ****/ + if (bpp == 1) +/**** 8-bit dest ****/ + for (; left > 0; ++dptr, ++tx, --left) { + byte t_pixel = cbit8(tptr, tx, tcolors); + + vd_pixel(int2fixed((dptr - base) % draster), + int2fixed((dptr - base) / draster + y), t_pixel); + rop_body_8((byte)const_source, t_pixel); + } + else +/**** 24-bit dest ****/ + for (; left > 0; dptr += 3, ++tx, --left) { + bits32 t_pixel = cbit24(tptr, tx, tcolors); + + vd_pixel(int2fixed((dptr - base) % draster / 3), + int2fixed((dptr - base) / draster + y), t_pixel); + rop_body_24(const_source, t_pixel); + } + } else if (bpp == 1) { +/**** 8-bit T & D ****/ + tptr += tx; + for (; left > 0; ++dptr, ++tptr, --left) { + byte t_pixel = *tptr; + + vd_pixel(int2fixed((dptr - base) % draster), + int2fixed((dptr - base) / draster + y), t_pixel); + rop_body_8((byte)const_source, t_pixel); + } + } else { +/**** 24-bit T & D ****/ + tptr += tx * 3; + for (; left > 0; dptr += 3, tptr += 3, --left) { + bits32 t_pixel = get24(tptr); + + vd_pixel(int2fixed((dptr - base) % draster / 3), + int2fixed((dptr - base) / draster + y), t_pixel); + rop_body_24(const_source, t_pixel); + } + } + } + } + } else { +/**** Data source & texture ****/ + uint traster = textures->raster; + int ty = y + phase_y; + const byte *srow = sdata; + + /* Loop over scan lines. */ + for (; line_count-- > 0; drow += draster, srow += sraster, ++ty) { /* Loop over copies of the tile. */ + int sx = sourcex; + int dx = x; + int w = width; + int nw; + byte *dptr = drow; + const byte *trow = + textures->data + (ty % textures->size.y) * traster; + int xoff = x_offset(phase_x, ty, textures); + + for (; w > 0; dx += nw, w -= nw) { /* Loop over individual pixels. */ + int tx = (dx + xoff) % textures->rep_width; + int left = nw = min(w, textures->size.x - tx); + const byte *tptr = trow; + + /* + * For maximum speed, we should split this loop + * into 7 cases depending on source & texture + * depth: (1,1), (1,8), (1,24), (8,1), (8,8), + * (24,1), (24,24). But since we expect these + * cases to be relatively uncommon, we just + * divide on the destination depth. + */ + if (bpp == 1) { +/**** 8-bit destination ****/ + const byte *sptr = srow + sx; + + tptr += tx; + for (; left > 0; ++dptr, ++sptr, ++tptr, ++sx, ++tx, --left) { + byte s_pixel = + (scolors ? cbit8(srow, sx, scolors) : *sptr); + byte t_pixel = + (tcolors ? cbit8(tptr, tx, tcolors) : *tptr); + + vd_pixel(int2fixed((dptr - base) % draster), + int2fixed((dptr - base) / draster + y), t_pixel); + rop_body_8(s_pixel, t_pixel); + } + } else { +/**** 24-bit destination ****/ + const byte *sptr = srow + sx * 3; + + tptr += tx * 3; + for (; left > 0; dptr += 3, sptr += 3, tptr += 3, ++sx, ++tx, --left) { + bits32 s_pixel = + (scolors ? cbit24(srow, sx, scolors) : + get24(sptr)); + bits32 t_pixel = + (tcolors ? cbit24(tptr, tx, tcolors) : + get24(tptr)); + + vd_pixel(int2fixed((dptr - base) % draster / 3), + int2fixed((dptr - base) / draster + y), t_pixel); + rop_body_24(s_pixel, t_pixel); + } + } + } + } + } +#undef rop_body_8 +#undef rop_body_24 +#undef dbit +#undef cbit8 +#undef cbit24 + return 0; +} |