17dd7cddfSDavid du Colombier /* Copyright (C) 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
27dd7cddfSDavid du Colombier
3*593dc095SDavid du Colombier This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier implied.
57dd7cddfSDavid du Colombier
6*593dc095SDavid du Colombier This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier
10*593dc095SDavid du Colombier For more information about licensing, please refer to
11*593dc095SDavid du Colombier http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier San Rafael, CA 94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier
17*593dc095SDavid du Colombier /*$Id: gdevdbit.c,v 1.11 2004/08/05 17:02:36 stefan Exp $ */
187dd7cddfSDavid du Colombier /* Default device bitmap copying implementation */
197dd7cddfSDavid du Colombier #include "gx.h"
207dd7cddfSDavid du Colombier #include "gpcheck.h"
217dd7cddfSDavid du Colombier #include "gserrors.h"
227dd7cddfSDavid du Colombier #include "gsbittab.h"
237dd7cddfSDavid du Colombier #include "gsrect.h"
247dd7cddfSDavid du Colombier #include "gsropt.h"
257dd7cddfSDavid du Colombier #include "gxdcolor.h"
267dd7cddfSDavid du Colombier #include "gxdevice.h"
277dd7cddfSDavid du Colombier #include "gxdevmem.h"
287dd7cddfSDavid du Colombier #include "gdevmem.h"
297dd7cddfSDavid du Colombier #undef mdev
307dd7cddfSDavid du Colombier #include "gxcpath.h"
317dd7cddfSDavid du Colombier
327dd7cddfSDavid du Colombier /* By default, implement tile_rectangle using strip_tile_rectangle. */
337dd7cddfSDavid du Colombier int
gx_default_tile_rectangle(gx_device * dev,const gx_tile_bitmap * tile,int x,int y,int w,int h,gx_color_index color0,gx_color_index color1,int px,int py)347dd7cddfSDavid du Colombier gx_default_tile_rectangle(gx_device * dev, const gx_tile_bitmap * tile,
357dd7cddfSDavid du Colombier int x, int y, int w, int h, gx_color_index color0, gx_color_index color1,
367dd7cddfSDavid du Colombier int px, int py)
377dd7cddfSDavid du Colombier {
387dd7cddfSDavid du Colombier gx_strip_bitmap tiles;
397dd7cddfSDavid du Colombier
407dd7cddfSDavid du Colombier *(gx_tile_bitmap *) & tiles = *tile;
417dd7cddfSDavid du Colombier tiles.shift = tiles.rep_shift = 0;
427dd7cddfSDavid du Colombier return (*dev_proc(dev, strip_tile_rectangle))
437dd7cddfSDavid du Colombier (dev, &tiles, x, y, w, h, color0, color1, px, py);
447dd7cddfSDavid du Colombier }
457dd7cddfSDavid du Colombier
467dd7cddfSDavid du Colombier /* Implement copy_mono by filling lots of small rectangles. */
477dd7cddfSDavid du Colombier /* This is very inefficient, but it works as a default. */
487dd7cddfSDavid du Colombier int
gx_default_copy_mono(gx_device * dev,const byte * data,int dx,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one)497dd7cddfSDavid du Colombier gx_default_copy_mono(gx_device * dev, const byte * data,
507dd7cddfSDavid du Colombier int dx, int raster, gx_bitmap_id id, int x, int y, int w, int h,
517dd7cddfSDavid du Colombier gx_color_index zero, gx_color_index one)
527dd7cddfSDavid du Colombier {
537dd7cddfSDavid du Colombier bool invert;
547dd7cddfSDavid du Colombier gx_color_index color;
557dd7cddfSDavid du Colombier gx_device_color devc;
567dd7cddfSDavid du Colombier
577dd7cddfSDavid du Colombier fit_copy(dev, data, dx, raster, id, x, y, w, h);
587dd7cddfSDavid du Colombier if (one != gx_no_color_index) {
597dd7cddfSDavid du Colombier invert = false;
607dd7cddfSDavid du Colombier color = one;
617dd7cddfSDavid du Colombier if (zero != gx_no_color_index) {
627dd7cddfSDavid du Colombier int code = (*dev_proc(dev, fill_rectangle))
637dd7cddfSDavid du Colombier (dev, x, y, w, h, zero);
647dd7cddfSDavid du Colombier
657dd7cddfSDavid du Colombier if (code < 0)
667dd7cddfSDavid du Colombier return code;
677dd7cddfSDavid du Colombier }
687dd7cddfSDavid du Colombier } else {
697dd7cddfSDavid du Colombier invert = true;
707dd7cddfSDavid du Colombier color = zero;
717dd7cddfSDavid du Colombier }
72*593dc095SDavid du Colombier set_nonclient_dev_color(&devc, color);
737dd7cddfSDavid du Colombier return gx_dc_default_fill_masked
747dd7cddfSDavid du Colombier (&devc, data, dx, raster, id, x, y, w, h, dev, rop3_T, invert);
757dd7cddfSDavid du Colombier }
767dd7cddfSDavid du Colombier
777dd7cddfSDavid du Colombier /* Implement copy_color by filling lots of small rectangles. */
787dd7cddfSDavid du Colombier /* This is very inefficient, but it works as a default. */
797dd7cddfSDavid du Colombier int
gx_default_copy_color(gx_device * dev,const byte * data,int dx,int raster,gx_bitmap_id id,int x,int y,int w,int h)807dd7cddfSDavid du Colombier gx_default_copy_color(gx_device * dev, const byte * data,
817dd7cddfSDavid du Colombier int dx, int raster, gx_bitmap_id id,
827dd7cddfSDavid du Colombier int x, int y, int w, int h)
837dd7cddfSDavid du Colombier {
847dd7cddfSDavid du Colombier int depth = dev->color_info.depth;
857dd7cddfSDavid du Colombier byte mask;
867dd7cddfSDavid du Colombier
877dd7cddfSDavid du Colombier dev_proc_fill_rectangle((*fill));
887dd7cddfSDavid du Colombier const byte *row;
897dd7cddfSDavid du Colombier int iy;
907dd7cddfSDavid du Colombier
917dd7cddfSDavid du Colombier if (depth == 1)
927dd7cddfSDavid du Colombier return (*dev_proc(dev, copy_mono)) (dev, data, dx, raster, id,
937dd7cddfSDavid du Colombier x, y, w, h,
947dd7cddfSDavid du Colombier (gx_color_index) 0, (gx_color_index) 1);
957dd7cddfSDavid du Colombier fit_copy(dev, data, dx, raster, id, x, y, w, h);
967dd7cddfSDavid du Colombier fill = dev_proc(dev, fill_rectangle);
977dd7cddfSDavid du Colombier mask = (byte) ((1 << depth) - 1);
987dd7cddfSDavid du Colombier for (row = data, iy = 0; iy < h; row += raster, ++iy) {
997dd7cddfSDavid du Colombier int ix;
1007dd7cddfSDavid du Colombier gx_color_index c0 = gx_no_color_index;
1017dd7cddfSDavid du Colombier const byte *ptr = row + ((dx * depth) >> 3);
1027dd7cddfSDavid du Colombier int i0;
1037dd7cddfSDavid du Colombier
1047dd7cddfSDavid du Colombier for (i0 = ix = 0; ix < w; ++ix) {
1057dd7cddfSDavid du Colombier gx_color_index color;
1067dd7cddfSDavid du Colombier
1077dd7cddfSDavid du Colombier if (depth >= 8) {
1087dd7cddfSDavid du Colombier color = *ptr++;
1097dd7cddfSDavid du Colombier switch (depth) {
110*593dc095SDavid du Colombier case 64:
111*593dc095SDavid du Colombier color = (color << 8) + *ptr++;
112*593dc095SDavid du Colombier case 56:
113*593dc095SDavid du Colombier color = (color << 8) + *ptr++;
114*593dc095SDavid du Colombier case 48:
115*593dc095SDavid du Colombier color = (color << 8) + *ptr++;
116*593dc095SDavid du Colombier case 40:
117*593dc095SDavid du Colombier color = (color << 8) + *ptr++;
1187dd7cddfSDavid du Colombier case 32:
1197dd7cddfSDavid du Colombier color = (color << 8) + *ptr++;
1207dd7cddfSDavid du Colombier case 24:
1217dd7cddfSDavid du Colombier color = (color << 8) + *ptr++;
1227dd7cddfSDavid du Colombier case 16:
1237dd7cddfSDavid du Colombier color = (color << 8) + *ptr++;
1247dd7cddfSDavid du Colombier }
1257dd7cddfSDavid du Colombier } else {
1267dd7cddfSDavid du Colombier uint dbit = (-(ix + dx + 1) * depth) & 7;
1277dd7cddfSDavid du Colombier
1287dd7cddfSDavid du Colombier color = (*ptr >> dbit) & mask;
1297dd7cddfSDavid du Colombier if (dbit == 0)
1307dd7cddfSDavid du Colombier ptr++;
1317dd7cddfSDavid du Colombier }
1327dd7cddfSDavid du Colombier if (color != c0) {
1337dd7cddfSDavid du Colombier if (ix > i0) {
1347dd7cddfSDavid du Colombier int code = (*fill)
1357dd7cddfSDavid du Colombier (dev, i0 + x, iy + y, ix - i0, 1, c0);
1367dd7cddfSDavid du Colombier
1377dd7cddfSDavid du Colombier if (code < 0)
1387dd7cddfSDavid du Colombier return code;
1397dd7cddfSDavid du Colombier }
1407dd7cddfSDavid du Colombier c0 = color;
1417dd7cddfSDavid du Colombier i0 = ix;
1427dd7cddfSDavid du Colombier }
1437dd7cddfSDavid du Colombier }
1447dd7cddfSDavid du Colombier if (ix > i0) {
1457dd7cddfSDavid du Colombier int code = (*fill) (dev, i0 + x, iy + y, ix - i0, 1, c0);
1467dd7cddfSDavid du Colombier
1477dd7cddfSDavid du Colombier if (code < 0)
1487dd7cddfSDavid du Colombier return code;
1497dd7cddfSDavid du Colombier }
1507dd7cddfSDavid du Colombier }
1517dd7cddfSDavid du Colombier return 0;
1527dd7cddfSDavid du Colombier }
1537dd7cddfSDavid du Colombier
1547dd7cddfSDavid du Colombier int
gx_no_copy_alpha(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int width,int height,gx_color_index color,int depth)1557dd7cddfSDavid du Colombier gx_no_copy_alpha(gx_device * dev, const byte * data, int data_x,
1567dd7cddfSDavid du Colombier int raster, gx_bitmap_id id, int x, int y, int width, int height,
1577dd7cddfSDavid du Colombier gx_color_index color, int depth)
1587dd7cddfSDavid du Colombier {
1597dd7cddfSDavid du Colombier return_error(gs_error_unknownerror);
1607dd7cddfSDavid du Colombier }
1617dd7cddfSDavid du Colombier
1627dd7cddfSDavid du Colombier int
gx_default_copy_alpha(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int width,int height,gx_color_index color,int depth)1637dd7cddfSDavid du Colombier gx_default_copy_alpha(gx_device * dev, const byte * data, int data_x,
1647dd7cddfSDavid du Colombier int raster, gx_bitmap_id id, int x, int y, int width, int height,
1657dd7cddfSDavid du Colombier gx_color_index color, int depth)
1667dd7cddfSDavid du Colombier { /* This might be called with depth = 1.... */
1677dd7cddfSDavid du Colombier if (depth == 1)
1687dd7cddfSDavid du Colombier return (*dev_proc(dev, copy_mono)) (dev, data, data_x, raster, id,
1697dd7cddfSDavid du Colombier x, y, width, height,
1707dd7cddfSDavid du Colombier gx_no_color_index, color);
1717dd7cddfSDavid du Colombier /*
1727dd7cddfSDavid du Colombier * Simulate alpha by weighted averaging of RGB values.
1737dd7cddfSDavid du Colombier * This is very slow, but functionally correct.
1747dd7cddfSDavid du Colombier */
1757dd7cddfSDavid du Colombier {
1767dd7cddfSDavid du Colombier const byte *row;
1777dd7cddfSDavid du Colombier gs_memory_t *mem = dev->memory;
1787dd7cddfSDavid du Colombier int bpp = dev->color_info.depth;
179*593dc095SDavid du Colombier int ncomps = dev->color_info.num_components;
1807dd7cddfSDavid du Colombier uint in_size = gx_device_raster(dev, false);
1817dd7cddfSDavid du Colombier byte *lin;
1827dd7cddfSDavid du Colombier uint out_size;
1837dd7cddfSDavid du Colombier byte *lout;
1847dd7cddfSDavid du Colombier int code = 0;
185*593dc095SDavid du Colombier gx_color_value color_cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
1867dd7cddfSDavid du Colombier int ry;
1877dd7cddfSDavid du Colombier
1887dd7cddfSDavid du Colombier fit_copy(dev, data, data_x, raster, id, x, y, width, height);
1897dd7cddfSDavid du Colombier row = data;
1907dd7cddfSDavid du Colombier out_size = bitmap_raster(width * bpp);
1917dd7cddfSDavid du Colombier lin = gs_alloc_bytes(mem, in_size, "copy_alpha(lin)");
1927dd7cddfSDavid du Colombier lout = gs_alloc_bytes(mem, out_size, "copy_alpha(lout)");
1937dd7cddfSDavid du Colombier if (lin == 0 || lout == 0) {
1947dd7cddfSDavid du Colombier code = gs_note_error(gs_error_VMerror);
1957dd7cddfSDavid du Colombier goto out;
1967dd7cddfSDavid du Colombier }
197*593dc095SDavid du Colombier (*dev_proc(dev, decode_color)) (dev, color, color_cv);
1987dd7cddfSDavid du Colombier for (ry = y; ry < y + height; row += raster, ++ry) {
1997dd7cddfSDavid du Colombier byte *line;
2007dd7cddfSDavid du Colombier int sx, rx;
2017dd7cddfSDavid du Colombier
2027dd7cddfSDavid du Colombier DECLARE_LINE_ACCUM_COPY(lout, bpp, x);
2037dd7cddfSDavid du Colombier
2047dd7cddfSDavid du Colombier code = (*dev_proc(dev, get_bits)) (dev, ry, lin, &line);
2057dd7cddfSDavid du Colombier if (code < 0)
2067dd7cddfSDavid du Colombier break;
2077dd7cddfSDavid du Colombier for (sx = data_x, rx = x; sx < data_x + width; ++sx, ++rx) {
2087dd7cddfSDavid du Colombier gx_color_index previous = gx_no_color_index;
2097dd7cddfSDavid du Colombier gx_color_index composite;
2107dd7cddfSDavid du Colombier int alpha2, alpha;
2117dd7cddfSDavid du Colombier
2127dd7cddfSDavid du Colombier if (depth == 2) /* map 0 - 3 to 0 - 15 */
2137dd7cddfSDavid du Colombier alpha = ((row[sx >> 2] >> ((3 - (sx & 3)) << 1)) & 3) * 5;
2147dd7cddfSDavid du Colombier else
2157dd7cddfSDavid du Colombier alpha2 = row[sx >> 1],
2167dd7cddfSDavid du Colombier alpha = (sx & 1 ? alpha2 & 0xf : alpha2 >> 4);
2177dd7cddfSDavid du Colombier blend:if (alpha == 15) { /* Just write the new color. */
2187dd7cddfSDavid du Colombier composite = color;
2197dd7cddfSDavid du Colombier } else {
2207dd7cddfSDavid du Colombier if (previous == gx_no_color_index) { /* Extract the old color. */
2217dd7cddfSDavid du Colombier if (bpp < 8) {
2227dd7cddfSDavid du Colombier const uint bit = rx * bpp;
2237dd7cddfSDavid du Colombier const byte *src = line + (bit >> 3);
2247dd7cddfSDavid du Colombier
2257dd7cddfSDavid du Colombier previous =
226*593dc095SDavid du Colombier (*src >> (8 - ((bit & 7) + bpp))) &
2277dd7cddfSDavid du Colombier ((1 << bpp) - 1);
2287dd7cddfSDavid du Colombier } else {
2297dd7cddfSDavid du Colombier const byte *src = line + (rx * (bpp >> 3));
2307dd7cddfSDavid du Colombier
2317dd7cddfSDavid du Colombier previous = 0;
2327dd7cddfSDavid du Colombier switch (bpp >> 3) {
233*593dc095SDavid du Colombier case 8:
234*593dc095SDavid du Colombier previous += (gx_color_index) * src++
235*593dc095SDavid du Colombier << sample_bound_shift(previous, 56);
236*593dc095SDavid du Colombier case 7:
237*593dc095SDavid du Colombier previous += (gx_color_index) * src++
238*593dc095SDavid du Colombier << sample_bound_shift(previous, 48);
239*593dc095SDavid du Colombier case 6:
240*593dc095SDavid du Colombier previous += (gx_color_index) * src++
241*593dc095SDavid du Colombier << sample_bound_shift(previous, 40);
242*593dc095SDavid du Colombier case 5:
243*593dc095SDavid du Colombier previous += (gx_color_index) * src++
244*593dc095SDavid du Colombier << sample_bound_shift(previous, 32);
2457dd7cddfSDavid du Colombier case 4:
2467dd7cddfSDavid du Colombier previous += (gx_color_index) * src++ << 24;
2477dd7cddfSDavid du Colombier case 3:
2487dd7cddfSDavid du Colombier previous += (gx_color_index) * src++ << 16;
2497dd7cddfSDavid du Colombier case 2:
2507dd7cddfSDavid du Colombier previous += (gx_color_index) * src++ << 8;
2517dd7cddfSDavid du Colombier case 1:
2527dd7cddfSDavid du Colombier previous += *src++;
2537dd7cddfSDavid du Colombier }
2547dd7cddfSDavid du Colombier }
2557dd7cddfSDavid du Colombier }
2567dd7cddfSDavid du Colombier if (alpha == 0) { /* Just write the old color. */
2577dd7cddfSDavid du Colombier composite = previous;
258*593dc095SDavid du Colombier } else { /* Blend values. */
259*593dc095SDavid du Colombier gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
260*593dc095SDavid du Colombier int i;
2617dd7cddfSDavid du Colombier
262*593dc095SDavid du Colombier (*dev_proc(dev, decode_color)) (dev, previous, cv);
2637dd7cddfSDavid du Colombier #if arch_ints_are_short
2647dd7cddfSDavid du Colombier # define b_int long
2657dd7cddfSDavid du Colombier #else
2667dd7cddfSDavid du Colombier # define b_int int
2677dd7cddfSDavid du Colombier #endif
2687dd7cddfSDavid du Colombier #define make_shade(old, clr, alpha, amax) \
2697dd7cddfSDavid du Colombier (old) + (((b_int)(clr) - (b_int)(old)) * (alpha) / (amax))
270*593dc095SDavid du Colombier for (i=0; i<ncomps; i++)
271*593dc095SDavid du Colombier cv[i] = make_shade(cv[i], color_cv[i], alpha, 15);
2727dd7cddfSDavid du Colombier #undef b_int
2737dd7cddfSDavid du Colombier #undef make_shade
2747dd7cddfSDavid du Colombier composite =
275*593dc095SDavid du Colombier (*dev_proc(dev, encode_color)) (dev, cv);
2767dd7cddfSDavid du Colombier if (composite == gx_no_color_index) { /* The device can't represent this color. */
2777dd7cddfSDavid du Colombier /* Move the alpha value towards 0 or 1. */
2787dd7cddfSDavid du Colombier if (alpha == 7) /* move 1/2 towards 1 */
2797dd7cddfSDavid du Colombier ++alpha;
2807dd7cddfSDavid du Colombier alpha = (alpha & 8) | (alpha >> 1);
2817dd7cddfSDavid du Colombier goto blend;
2827dd7cddfSDavid du Colombier }
2837dd7cddfSDavid du Colombier }
2847dd7cddfSDavid du Colombier }
2857dd7cddfSDavid du Colombier LINE_ACCUM(composite, bpp);
2867dd7cddfSDavid du Colombier }
2877dd7cddfSDavid du Colombier LINE_ACCUM_COPY(dev, lout, bpp, x, rx, raster, ry);
2887dd7cddfSDavid du Colombier }
2897dd7cddfSDavid du Colombier out:gs_free_object(mem, lout, "copy_alpha(lout)");
2907dd7cddfSDavid du Colombier gs_free_object(mem, lin, "copy_alpha(lin)");
2917dd7cddfSDavid du Colombier return code;
2927dd7cddfSDavid du Colombier }
2937dd7cddfSDavid du Colombier }
2947dd7cddfSDavid du Colombier
2957dd7cddfSDavid du Colombier int
gx_no_copy_rop(gx_device * dev,const byte * sdata,int sourcex,uint sraster,gx_bitmap_id id,const gx_color_index * scolors,const gx_tile_bitmap * texture,const gx_color_index * tcolors,int x,int y,int width,int height,int phase_x,int phase_y,gs_logical_operation_t lop)2967dd7cddfSDavid du Colombier gx_no_copy_rop(gx_device * dev,
2977dd7cddfSDavid du Colombier const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
2987dd7cddfSDavid du Colombier const gx_color_index * scolors,
2997dd7cddfSDavid du Colombier const gx_tile_bitmap * texture, const gx_color_index * tcolors,
3007dd7cddfSDavid du Colombier int x, int y, int width, int height,
3017dd7cddfSDavid du Colombier int phase_x, int phase_y, gs_logical_operation_t lop)
3027dd7cddfSDavid du Colombier {
3037dd7cddfSDavid du Colombier return_error(gs_error_unknownerror); /* not implemented */
3047dd7cddfSDavid du Colombier }
3057dd7cddfSDavid du Colombier
3067dd7cddfSDavid du Colombier int
gx_default_fill_mask(gx_device * orig_dev,const byte * data,int dx,int raster,gx_bitmap_id id,int x,int y,int w,int h,const gx_drawing_color * pdcolor,int depth,gs_logical_operation_t lop,const gx_clip_path * pcpath)3077dd7cddfSDavid du Colombier gx_default_fill_mask(gx_device * orig_dev,
3087dd7cddfSDavid du Colombier const byte * data, int dx, int raster, gx_bitmap_id id,
3097dd7cddfSDavid du Colombier int x, int y, int w, int h,
3107dd7cddfSDavid du Colombier const gx_drawing_color * pdcolor, int depth,
3117dd7cddfSDavid du Colombier gs_logical_operation_t lop, const gx_clip_path * pcpath)
3127dd7cddfSDavid du Colombier {
3137dd7cddfSDavid du Colombier gx_device *dev;
3147dd7cddfSDavid du Colombier gx_device_clip cdev;
3157dd7cddfSDavid du Colombier
3167dd7cddfSDavid du Colombier if (pcpath != 0) {
3177dd7cddfSDavid du Colombier gx_make_clip_path_device(&cdev, pcpath);
3187dd7cddfSDavid du Colombier cdev.target = orig_dev;
3197dd7cddfSDavid du Colombier dev = (gx_device *) & cdev;
3207dd7cddfSDavid du Colombier (*dev_proc(dev, open_device)) (dev);
3217dd7cddfSDavid du Colombier } else
3227dd7cddfSDavid du Colombier dev = orig_dev;
3237dd7cddfSDavid du Colombier if (depth > 1) {
3247dd7cddfSDavid du Colombier /****** CAN'T DO ROP OR HALFTONE WITH ALPHA ******/
3257dd7cddfSDavid du Colombier return (*dev_proc(dev, copy_alpha))
3267dd7cddfSDavid du Colombier (dev, data, dx, raster, id, x, y, w, h,
327*593dc095SDavid du Colombier gx_dc_pure_color(pdcolor), depth);
328*593dc095SDavid du Colombier } else
329*593dc095SDavid du Colombier return pdcolor->type->fill_masked(pdcolor, data, dx, raster, id,
330*593dc095SDavid du Colombier x, y, w, h, dev, lop, false);
3317dd7cddfSDavid du Colombier }
3327dd7cddfSDavid du Colombier
3337dd7cddfSDavid du Colombier /* Default implementation of strip_tile_rectangle */
3347dd7cddfSDavid du Colombier int
gx_default_strip_tile_rectangle(gx_device * dev,const gx_strip_bitmap * tiles,int x,int y,int w,int h,gx_color_index color0,gx_color_index color1,int px,int py)3357dd7cddfSDavid du Colombier gx_default_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles,
3367dd7cddfSDavid du Colombier int x, int y, int w, int h, gx_color_index color0, gx_color_index color1,
3377dd7cddfSDavid du Colombier int px, int py)
3387dd7cddfSDavid du Colombier { /* Fill the rectangle in chunks. */
3397dd7cddfSDavid du Colombier int width = tiles->size.x;
3407dd7cddfSDavid du Colombier int height = tiles->size.y;
3417dd7cddfSDavid du Colombier int raster = tiles->raster;
3427dd7cddfSDavid du Colombier int rwidth = tiles->rep_width;
3437dd7cddfSDavid du Colombier int rheight = tiles->rep_height;
3447dd7cddfSDavid du Colombier int shift = tiles->shift;
3457dd7cddfSDavid du Colombier gs_id tile_id = tiles->id;
3467dd7cddfSDavid du Colombier
3477dd7cddfSDavid du Colombier fit_fill_xy(dev, x, y, w, h);
3487dd7cddfSDavid du Colombier
3497dd7cddfSDavid du Colombier #ifdef DEBUG
3507dd7cddfSDavid du Colombier if (gs_debug_c('t')) {
3517dd7cddfSDavid du Colombier int ptx, pty;
3527dd7cddfSDavid du Colombier const byte *ptp = tiles->data;
3537dd7cddfSDavid du Colombier
3547dd7cddfSDavid du Colombier dlprintf4("[t]tile %dx%d raster=%d id=%lu;",
3557dd7cddfSDavid du Colombier tiles->size.x, tiles->size.y, tiles->raster, tiles->id);
3567dd7cddfSDavid du Colombier dlprintf6(" x,y=%d,%d w,h=%d,%d p=%d,%d\n",
3577dd7cddfSDavid du Colombier x, y, w, h, px, py);
3587dd7cddfSDavid du Colombier dlputs("");
3597dd7cddfSDavid du Colombier for (pty = 0; pty < tiles->size.y; pty++) {
3607dd7cddfSDavid du Colombier dprintf(" ");
3617dd7cddfSDavid du Colombier for (ptx = 0; ptx < tiles->raster; ptx++)
3627dd7cddfSDavid du Colombier dprintf1("%3x", *ptp++);
3637dd7cddfSDavid du Colombier }
3647dd7cddfSDavid du Colombier dputc('\n');
3657dd7cddfSDavid du Colombier }
3667dd7cddfSDavid du Colombier #endif
3677dd7cddfSDavid du Colombier
3687dd7cddfSDavid du Colombier if (dev_proc(dev, tile_rectangle) != gx_default_tile_rectangle) {
3697dd7cddfSDavid du Colombier if (shift == 0) { /*
3707dd7cddfSDavid du Colombier * Temporarily patch the tile_rectangle procedure in the
3717dd7cddfSDavid du Colombier * device so we don't get into a recursion loop if the
3727dd7cddfSDavid du Colombier * device has a tile_rectangle procedure that conditionally
3737dd7cddfSDavid du Colombier * calls the strip_tile_rectangle procedure.
3747dd7cddfSDavid du Colombier */
3757dd7cddfSDavid du Colombier dev_proc_tile_rectangle((*tile_proc)) =
3767dd7cddfSDavid du Colombier dev_proc(dev, tile_rectangle);
3777dd7cddfSDavid du Colombier int code;
3787dd7cddfSDavid du Colombier
3797dd7cddfSDavid du Colombier set_dev_proc(dev, tile_rectangle, gx_default_tile_rectangle);
3807dd7cddfSDavid du Colombier code = (*tile_proc)
3817dd7cddfSDavid du Colombier (dev, (const gx_tile_bitmap *)tiles, x, y, w, h,
3827dd7cddfSDavid du Colombier color0, color1, px, py);
3837dd7cddfSDavid du Colombier set_dev_proc(dev, tile_rectangle, tile_proc);
3847dd7cddfSDavid du Colombier return code;
3857dd7cddfSDavid du Colombier }
3867dd7cddfSDavid du Colombier /* We should probably optimize this case too, for the benefit */
3877dd7cddfSDavid du Colombier /* of window systems, but we don't yet. */
3887dd7cddfSDavid du Colombier } { /*
3897dd7cddfSDavid du Colombier * Note: we can't do the following computations until after
3907dd7cddfSDavid du Colombier * the fit_fill_xy.
3917dd7cddfSDavid du Colombier */
3927dd7cddfSDavid du Colombier int xoff =
3937dd7cddfSDavid du Colombier (shift == 0 ? px :
3947dd7cddfSDavid du Colombier px + (y + py) / rheight * tiles->rep_shift);
3957dd7cddfSDavid du Colombier int irx = ((rwidth & (rwidth - 1)) == 0 ? /* power of 2 */
3967dd7cddfSDavid du Colombier (x + xoff) & (rwidth - 1) :
3977dd7cddfSDavid du Colombier (x + xoff) % rwidth);
3987dd7cddfSDavid du Colombier int ry = ((rheight & (rheight - 1)) == 0 ? /* power of 2 */
3997dd7cddfSDavid du Colombier (y + py) & (rheight - 1) :
4007dd7cddfSDavid du Colombier (y + py) % rheight);
4017dd7cddfSDavid du Colombier int icw = width - irx;
4027dd7cddfSDavid du Colombier int ch = height - ry;
4037dd7cddfSDavid du Colombier byte *row = tiles->data + ry * raster;
4047dd7cddfSDavid du Colombier
4057dd7cddfSDavid du Colombier dev_proc_copy_mono((*proc_mono));
4067dd7cddfSDavid du Colombier dev_proc_copy_color((*proc_color));
4077dd7cddfSDavid du Colombier int code;
4087dd7cddfSDavid du Colombier
4097dd7cddfSDavid du Colombier if (color0 == gx_no_color_index && color1 == gx_no_color_index)
410*593dc095SDavid du Colombier proc_color = dev_proc(dev, copy_color), proc_mono = 0;
4117dd7cddfSDavid du Colombier else
4127dd7cddfSDavid du Colombier proc_color = 0, proc_mono = dev_proc(dev, copy_mono);
4137dd7cddfSDavid du Colombier
4147dd7cddfSDavid du Colombier #define real_copy_tile(srcx, tx, ty, tw, th, id)\
4157dd7cddfSDavid du Colombier code =\
4167dd7cddfSDavid du Colombier (proc_color != 0 ?\
4177dd7cddfSDavid du Colombier (*proc_color)(dev, row, srcx, raster, id, tx, ty, tw, th) :\
4187dd7cddfSDavid du Colombier (*proc_mono)(dev, row, srcx, raster, id, tx, ty, tw, th, color0, color1));\
4197dd7cddfSDavid du Colombier if (code < 0) return_error(code);\
420*593dc095SDavid du Colombier return_if_interrupt(dev->memory)
4217dd7cddfSDavid du Colombier #ifdef DEBUG
4227dd7cddfSDavid du Colombier #define copy_tile(srcx, tx, ty, tw, th, tid)\
4237dd7cddfSDavid du Colombier if_debug6('t', " copy id=%lu sx=%d => x=%d y=%d w=%d h=%d\n",\
4247dd7cddfSDavid du Colombier tid, srcx, tx, ty, tw, th);\
4257dd7cddfSDavid du Colombier real_copy_tile(srcx, tx, ty, tw, th, tid)
4267dd7cddfSDavid du Colombier #else
4277dd7cddfSDavid du Colombier #define copy_tile(srcx, tx, ty, tw, th, id)\
4287dd7cddfSDavid du Colombier real_copy_tile(srcx, tx, ty, tw, th, id)
4297dd7cddfSDavid du Colombier #endif
4307dd7cddfSDavid du Colombier if (ch >= h) { /* Shallow operation */
4317dd7cddfSDavid du Colombier if (icw >= w) { /* Just one (partial) tile to transfer. */
4327dd7cddfSDavid du Colombier copy_tile(irx, x, y, w, h,
4337dd7cddfSDavid du Colombier (w == width && h == height ? tile_id :
4347dd7cddfSDavid du Colombier gs_no_bitmap_id));
4357dd7cddfSDavid du Colombier } else {
4367dd7cddfSDavid du Colombier int ex = x + w;
4377dd7cddfSDavid du Colombier int fex = ex - width;
4387dd7cddfSDavid du Colombier int cx = x + icw;
4397dd7cddfSDavid du Colombier ulong id = (h == height ? tile_id : gs_no_bitmap_id);
4407dd7cddfSDavid du Colombier
4417dd7cddfSDavid du Colombier copy_tile(irx, x, y, icw, h, gs_no_bitmap_id);
4427dd7cddfSDavid du Colombier while (cx <= fex) {
4437dd7cddfSDavid du Colombier copy_tile(0, cx, y, width, h, id);
4447dd7cddfSDavid du Colombier cx += width;
4457dd7cddfSDavid du Colombier }
4467dd7cddfSDavid du Colombier if (cx < ex) {
4477dd7cddfSDavid du Colombier copy_tile(0, cx, y, ex - cx, h, gs_no_bitmap_id);
4487dd7cddfSDavid du Colombier }
4497dd7cddfSDavid du Colombier }
4507dd7cddfSDavid du Colombier } else if (icw >= w && shift == 0) {
4517dd7cddfSDavid du Colombier /* Narrow operation, no shift */
4527dd7cddfSDavid du Colombier int ey = y + h;
4537dd7cddfSDavid du Colombier int fey = ey - height;
4547dd7cddfSDavid du Colombier int cy = y + ch;
4557dd7cddfSDavid du Colombier ulong id = (w == width ? tile_id : gs_no_bitmap_id);
4567dd7cddfSDavid du Colombier
4577dd7cddfSDavid du Colombier copy_tile(irx, x, y, w, ch, (ch == height ? id : gs_no_bitmap_id));
4587dd7cddfSDavid du Colombier row = tiles->data;
4597dd7cddfSDavid du Colombier do {
4607dd7cddfSDavid du Colombier ch = (cy > fey ? ey - cy : height);
4617dd7cddfSDavid du Colombier copy_tile(irx, x, cy, w, ch,
4627dd7cddfSDavid du Colombier (ch == height ? id : gs_no_bitmap_id));
4637dd7cddfSDavid du Colombier }
4647dd7cddfSDavid du Colombier while ((cy += ch) < ey);
4657dd7cddfSDavid du Colombier } else {
4667dd7cddfSDavid du Colombier /* Full operation. If shift != 0, some scan lines */
4677dd7cddfSDavid du Colombier /* may be narrow. We could test shift == 0 in advance */
4687dd7cddfSDavid du Colombier /* and use a slightly faster loop, but right now */
4697dd7cddfSDavid du Colombier /* we don't bother. */
4707dd7cddfSDavid du Colombier int ex = x + w, ey = y + h;
4717dd7cddfSDavid du Colombier int fex = ex - width, fey = ey - height;
4727dd7cddfSDavid du Colombier int cx, cy;
4737dd7cddfSDavid du Colombier
4747dd7cddfSDavid du Colombier for (cy = y;;) {
4757dd7cddfSDavid du Colombier ulong id = (ch == height ? tile_id : gs_no_bitmap_id);
4767dd7cddfSDavid du Colombier
4777dd7cddfSDavid du Colombier if (icw >= w) {
4787dd7cddfSDavid du Colombier copy_tile(irx, x, cy, w, ch,
4797dd7cddfSDavid du Colombier (w == width ? id : gs_no_bitmap_id));
4807dd7cddfSDavid du Colombier } else {
4817dd7cddfSDavid du Colombier copy_tile(irx, x, cy, icw, ch, gs_no_bitmap_id);
4827dd7cddfSDavid du Colombier cx = x + icw;
4837dd7cddfSDavid du Colombier while (cx <= fex) {
4847dd7cddfSDavid du Colombier copy_tile(0, cx, cy, width, ch, id);
4857dd7cddfSDavid du Colombier cx += width;
4867dd7cddfSDavid du Colombier }
4877dd7cddfSDavid du Colombier if (cx < ex) {
4887dd7cddfSDavid du Colombier copy_tile(0, cx, cy, ex - cx, ch, gs_no_bitmap_id);
4897dd7cddfSDavid du Colombier }
4907dd7cddfSDavid du Colombier }
4917dd7cddfSDavid du Colombier if ((cy += ch) >= ey)
4927dd7cddfSDavid du Colombier break;
4937dd7cddfSDavid du Colombier ch = (cy > fey ? ey - cy : height);
4947dd7cddfSDavid du Colombier if ((irx += shift) >= rwidth)
4957dd7cddfSDavid du Colombier irx -= rwidth;
4967dd7cddfSDavid du Colombier icw = width - irx;
4977dd7cddfSDavid du Colombier row = tiles->data;
4987dd7cddfSDavid du Colombier }
4997dd7cddfSDavid du Colombier }
5007dd7cddfSDavid du Colombier #undef copy_tile
5017dd7cddfSDavid du Colombier #undef real_copy_tile
5027dd7cddfSDavid du Colombier }
5037dd7cddfSDavid du Colombier return 0;
5047dd7cddfSDavid du Colombier }
5057dd7cddfSDavid du Colombier
5067dd7cddfSDavid du Colombier int
gx_no_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)5077dd7cddfSDavid du Colombier gx_no_strip_copy_rop(gx_device * dev,
5087dd7cddfSDavid du Colombier const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
5097dd7cddfSDavid du Colombier const gx_color_index * scolors,
5107dd7cddfSDavid du Colombier const gx_strip_bitmap * textures, const gx_color_index * tcolors,
5117dd7cddfSDavid du Colombier int x, int y, int width, int height,
5127dd7cddfSDavid du Colombier int phase_x, int phase_y, gs_logical_operation_t lop)
5137dd7cddfSDavid du Colombier {
5147dd7cddfSDavid du Colombier return_error(gs_error_unknownerror); /* not implemented */
5157dd7cddfSDavid du Colombier }
5167dd7cddfSDavid du Colombier
5177dd7cddfSDavid du Colombier /* ---------------- Unaligned copy operations ---------------- */
5187dd7cddfSDavid du Colombier
5197dd7cddfSDavid du Colombier /*
5207dd7cddfSDavid du Colombier * Implementing unaligned operations in terms of the standard aligned
5217dd7cddfSDavid du Colombier * operations requires adjusting the bitmap origin and/or the raster to be
5227dd7cddfSDavid du Colombier * aligned. Adjusting the origin is simple; adjusting the raster requires
5237dd7cddfSDavid du Colombier * doing the operation one scan line at a time.
5247dd7cddfSDavid du Colombier */
5257dd7cddfSDavid du Colombier int
gx_copy_mono_unaligned(gx_device * dev,const byte * data,int dx,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one)5267dd7cddfSDavid du Colombier gx_copy_mono_unaligned(gx_device * dev, const byte * data,
5277dd7cddfSDavid du Colombier int dx, int raster, gx_bitmap_id id, int x, int y, int w, int h,
5287dd7cddfSDavid du Colombier gx_color_index zero, gx_color_index one)
5297dd7cddfSDavid du Colombier {
5307dd7cddfSDavid du Colombier dev_proc_copy_mono((*copy_mono)) = dev_proc(dev, copy_mono);
5317dd7cddfSDavid du Colombier uint offset = ALIGNMENT_MOD(data, align_bitmap_mod);
5327dd7cddfSDavid du Colombier int step = raster & (align_bitmap_mod - 1);
5337dd7cddfSDavid du Colombier
5347dd7cddfSDavid du Colombier /* Adjust the origin. */
5357dd7cddfSDavid du Colombier data -= offset;
5367dd7cddfSDavid du Colombier dx += offset << 3;
5377dd7cddfSDavid du Colombier
5387dd7cddfSDavid du Colombier /* Adjust the raster. */
5397dd7cddfSDavid du Colombier if (!step) { /* No adjustment needed. */
5407dd7cddfSDavid du Colombier return (*copy_mono) (dev, data, dx, raster, id,
5417dd7cddfSDavid du Colombier x, y, w, h, zero, one);
5427dd7cddfSDavid du Colombier }
5437dd7cddfSDavid du Colombier /* Do the transfer one scan line at a time. */
5447dd7cddfSDavid du Colombier {
5457dd7cddfSDavid du Colombier const byte *p = data;
5467dd7cddfSDavid du Colombier int d = dx;
5477dd7cddfSDavid du Colombier int code = 0;
5487dd7cddfSDavid du Colombier int i;
5497dd7cddfSDavid du Colombier
5507dd7cddfSDavid du Colombier for (i = 0; i < h && code >= 0;
5517dd7cddfSDavid du Colombier ++i, p += raster - step, d += step << 3
5527dd7cddfSDavid du Colombier )
5537dd7cddfSDavid du Colombier code = (*copy_mono) (dev, p, d, raster, gx_no_bitmap_id,
5547dd7cddfSDavid du Colombier x, y + i, w, 1, zero, one);
5557dd7cddfSDavid du Colombier return code;
5567dd7cddfSDavid du Colombier }
5577dd7cddfSDavid du Colombier }
5587dd7cddfSDavid du Colombier
5597dd7cddfSDavid du Colombier int
gx_copy_color_unaligned(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int width,int height)5607dd7cddfSDavid du Colombier gx_copy_color_unaligned(gx_device * dev, const byte * data,
5617dd7cddfSDavid du Colombier int data_x, int raster, gx_bitmap_id id,
5627dd7cddfSDavid du Colombier int x, int y, int width, int height)
5637dd7cddfSDavid du Colombier {
5647dd7cddfSDavid du Colombier dev_proc_copy_color((*copy_color)) = dev_proc(dev, copy_color);
5657dd7cddfSDavid du Colombier int depth = dev->color_info.depth;
5667dd7cddfSDavid du Colombier uint offset = (uint) (data - (const byte *)0) & (align_bitmap_mod - 1);
5677dd7cddfSDavid du Colombier int step = raster & (align_bitmap_mod - 1);
5687dd7cddfSDavid du Colombier
5697dd7cddfSDavid du Colombier /*
5707dd7cddfSDavid du Colombier * Adjust the origin.
5717dd7cddfSDavid du Colombier * We have to do something very special for 24-bit data,
5727dd7cddfSDavid du Colombier * because that is the only depth that doesn't divide
5737dd7cddfSDavid du Colombier * align_bitmap_mod exactly. In particular, we need to find
5747dd7cddfSDavid du Colombier * M*B + R == 0 mod 3, where M is align_bitmap_mod, R is the
5757dd7cddfSDavid du Colombier * offset value just calculated, and B is an integer unknown;
5767dd7cddfSDavid du Colombier * the new value of offset will be M*B + R.
5777dd7cddfSDavid du Colombier */
5787dd7cddfSDavid du Colombier if (depth == 24)
5797dd7cddfSDavid du Colombier offset += (offset % 3) *
5807dd7cddfSDavid du Colombier (align_bitmap_mod * (3 - (align_bitmap_mod % 3)));
5817dd7cddfSDavid du Colombier data -= offset;
5827dd7cddfSDavid du Colombier data_x += (offset << 3) / depth;
5837dd7cddfSDavid du Colombier
5847dd7cddfSDavid du Colombier /* Adjust the raster. */
5857dd7cddfSDavid du Colombier if (!step) { /* No adjustment needed. */
5867dd7cddfSDavid du Colombier return (*copy_color) (dev, data, data_x, raster, id,
5877dd7cddfSDavid du Colombier x, y, width, height);
5887dd7cddfSDavid du Colombier }
5897dd7cddfSDavid du Colombier /* Do the transfer one scan line at a time. */
5907dd7cddfSDavid du Colombier {
5917dd7cddfSDavid du Colombier const byte *p = data;
5927dd7cddfSDavid du Colombier int d = data_x;
5937dd7cddfSDavid du Colombier int dstep = (step << 3) / depth;
5947dd7cddfSDavid du Colombier int code = 0;
5957dd7cddfSDavid du Colombier int i;
5967dd7cddfSDavid du Colombier
5977dd7cddfSDavid du Colombier for (i = 0; i < height && code >= 0;
5987dd7cddfSDavid du Colombier ++i, p += raster - step, d += dstep
5997dd7cddfSDavid du Colombier )
6007dd7cddfSDavid du Colombier code = (*copy_color) (dev, p, d, raster, gx_no_bitmap_id,
6017dd7cddfSDavid du Colombier x, y + i, width, 1);
6027dd7cddfSDavid du Colombier return code;
6037dd7cddfSDavid du Colombier }
6047dd7cddfSDavid du Colombier }
6057dd7cddfSDavid du Colombier
6067dd7cddfSDavid du Colombier int
gx_copy_alpha_unaligned(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int width,int height,gx_color_index color,int depth)6077dd7cddfSDavid du Colombier gx_copy_alpha_unaligned(gx_device * dev, const byte * data, int data_x,
6087dd7cddfSDavid du Colombier int raster, gx_bitmap_id id, int x, int y, int width, int height,
6097dd7cddfSDavid du Colombier gx_color_index color, int depth)
6107dd7cddfSDavid du Colombier {
6117dd7cddfSDavid du Colombier dev_proc_copy_alpha((*copy_alpha)) = dev_proc(dev, copy_alpha);
6127dd7cddfSDavid du Colombier uint offset = (uint) (data - (const byte *)0) & (align_bitmap_mod - 1);
6137dd7cddfSDavid du Colombier int step = raster & (align_bitmap_mod - 1);
6147dd7cddfSDavid du Colombier
6157dd7cddfSDavid du Colombier /* Adjust the origin. */
6167dd7cddfSDavid du Colombier data -= offset;
6177dd7cddfSDavid du Colombier data_x += (offset << 3) / depth;
6187dd7cddfSDavid du Colombier
6197dd7cddfSDavid du Colombier /* Adjust the raster. */
6207dd7cddfSDavid du Colombier if (!step) { /* No adjustment needed. */
6217dd7cddfSDavid du Colombier return (*copy_alpha) (dev, data, data_x, raster, id,
6227dd7cddfSDavid du Colombier x, y, width, height, color, depth);
6237dd7cddfSDavid du Colombier }
6247dd7cddfSDavid du Colombier /* Do the transfer one scan line at a time. */
6257dd7cddfSDavid du Colombier {
6267dd7cddfSDavid du Colombier const byte *p = data;
6277dd7cddfSDavid du Colombier int d = data_x;
6287dd7cddfSDavid du Colombier int dstep = (step << 3) / depth;
6297dd7cddfSDavid du Colombier int code = 0;
6307dd7cddfSDavid du Colombier int i;
6317dd7cddfSDavid du Colombier
6327dd7cddfSDavid du Colombier for (i = 0; i < height && code >= 0;
6337dd7cddfSDavid du Colombier ++i, p += raster - step, d += dstep
6347dd7cddfSDavid du Colombier )
6357dd7cddfSDavid du Colombier code = (*copy_alpha) (dev, p, d, raster, gx_no_bitmap_id,
6367dd7cddfSDavid du Colombier x, y + i, width, 1, color, depth);
6377dd7cddfSDavid du Colombier return code;
6387dd7cddfSDavid du Colombier }
6397dd7cddfSDavid du Colombier }
640