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: gxclrect.c,v 1.7 2004/08/04 19:36:12 stefan Exp $ */
187dd7cddfSDavid du Colombier /* Rectangle-oriented command writing for command list */
197dd7cddfSDavid du Colombier #include "gx.h"
207dd7cddfSDavid du Colombier #include "gserrors.h"
217dd7cddfSDavid du Colombier #include "gsutil.h" /* for gs_next_ids */
227dd7cddfSDavid du Colombier #include "gxdevice.h"
237dd7cddfSDavid du Colombier #include "gxdevmem.h" /* must precede gxcldev.h */
247dd7cddfSDavid du Colombier #include "gxcldev.h"
257dd7cddfSDavid du Colombier
267dd7cddfSDavid du Colombier /* ---------------- Writing utilities ---------------- */
277dd7cddfSDavid du Colombier
287dd7cddfSDavid du Colombier #define cmd_set_rect(rect)\
297dd7cddfSDavid du Colombier ((rect).x = x, (rect).y = y,\
307dd7cddfSDavid du Colombier (rect).width = width, (rect).height = height)
317dd7cddfSDavid du Colombier
327dd7cddfSDavid du Colombier /* Write a rectangle. */
337dd7cddfSDavid du Colombier private int
cmd_size_rect(register const gx_cmd_rect * prect)347dd7cddfSDavid du Colombier cmd_size_rect(register const gx_cmd_rect * prect)
357dd7cddfSDavid du Colombier {
367dd7cddfSDavid du Colombier return
377dd7cddfSDavid du Colombier cmd_sizew(prect->x) + cmd_sizew(prect->y) +
387dd7cddfSDavid du Colombier cmd_sizew(prect->width) + cmd_sizew(prect->height);
397dd7cddfSDavid du Colombier }
407dd7cddfSDavid du Colombier private byte *
cmd_put_rect(register const gx_cmd_rect * prect,register byte * dp)417dd7cddfSDavid du Colombier cmd_put_rect(register const gx_cmd_rect * prect, register byte * dp)
427dd7cddfSDavid du Colombier {
437dd7cddfSDavid du Colombier cmd_putw(prect->x, dp);
447dd7cddfSDavid du Colombier cmd_putw(prect->y, dp);
457dd7cddfSDavid du Colombier cmd_putw(prect->width, dp);
467dd7cddfSDavid du Colombier cmd_putw(prect->height, dp);
477dd7cddfSDavid du Colombier return dp;
487dd7cddfSDavid du Colombier }
497dd7cddfSDavid du Colombier
507dd7cddfSDavid du Colombier int
cmd_write_rect_cmd(gx_device_clist_writer * cldev,gx_clist_state * pcls,int op,int x,int y,int width,int height)517dd7cddfSDavid du Colombier cmd_write_rect_cmd(gx_device_clist_writer * cldev, gx_clist_state * pcls,
527dd7cddfSDavid du Colombier int op, int x, int y, int width, int height)
537dd7cddfSDavid du Colombier {
547dd7cddfSDavid du Colombier int dx = x - pcls->rect.x;
557dd7cddfSDavid du Colombier int dy = y - pcls->rect.y;
567dd7cddfSDavid du Colombier int dwidth = width - pcls->rect.width;
577dd7cddfSDavid du Colombier int dheight = height - pcls->rect.height;
587dd7cddfSDavid du Colombier byte *dp;
597dd7cddfSDavid du Colombier int code;
607dd7cddfSDavid du Colombier
617dd7cddfSDavid du Colombier #define check_range_xy(rmin, rmax)\
627dd7cddfSDavid du Colombier ((unsigned)(dx - rmin) <= (rmax - rmin) &&\
637dd7cddfSDavid du Colombier (unsigned)(dy - rmin) <= (rmax - rmin))
647dd7cddfSDavid du Colombier #define check_range_w(rmin, rmax)\
657dd7cddfSDavid du Colombier ((unsigned)(dwidth - rmin) <= (rmax - rmin))
667dd7cddfSDavid du Colombier #define check_ranges(rmin, rmax)\
677dd7cddfSDavid du Colombier (check_range_xy(rmin, rmax) && check_range_w(rmin, rmax) &&\
687dd7cddfSDavid du Colombier (unsigned)(dheight - rmin) <= (rmax - rmin))
697dd7cddfSDavid du Colombier cmd_set_rect(pcls->rect);
707dd7cddfSDavid du Colombier if (dheight == 0 && check_range_w(cmd_min_dw_tiny, cmd_max_dw_tiny) &&
717dd7cddfSDavid du Colombier check_range_xy(cmd_min_dxy_tiny, cmd_max_dxy_tiny)
727dd7cddfSDavid du Colombier ) {
737dd7cddfSDavid du Colombier byte op_tiny = op + 0x20 + dwidth - cmd_min_dw_tiny;
747dd7cddfSDavid du Colombier
757dd7cddfSDavid du Colombier if (dx == width - dwidth && dy == 0) {
767dd7cddfSDavid du Colombier code = set_cmd_put_op(dp, cldev, pcls, op_tiny + 8, 1);
777dd7cddfSDavid du Colombier if (code < 0)
787dd7cddfSDavid du Colombier return code;
797dd7cddfSDavid du Colombier } else {
807dd7cddfSDavid du Colombier code = set_cmd_put_op(dp, cldev, pcls, op_tiny, 2);
817dd7cddfSDavid du Colombier if (code < 0)
827dd7cddfSDavid du Colombier return code;
837dd7cddfSDavid du Colombier dp[1] = (dx << 4) + dy - (cmd_min_dxy_tiny * 0x11);
847dd7cddfSDavid du Colombier }
857dd7cddfSDavid du Colombier }
867dd7cddfSDavid du Colombier #define rmin cmd_min_short
877dd7cddfSDavid du Colombier #define rmax cmd_max_short
887dd7cddfSDavid du Colombier else if (check_ranges(rmin, rmax)) {
897dd7cddfSDavid du Colombier int dh = dheight - cmd_min_dxy_tiny;
907dd7cddfSDavid du Colombier
917dd7cddfSDavid du Colombier if ((unsigned)dh <= cmd_max_dxy_tiny - cmd_min_dxy_tiny &&
927dd7cddfSDavid du Colombier dh != 0 && dy == 0
937dd7cddfSDavid du Colombier ) {
947dd7cddfSDavid du Colombier op += dh;
957dd7cddfSDavid du Colombier code = set_cmd_put_op(dp, cldev, pcls, op + 0x10, 3);
967dd7cddfSDavid du Colombier if (code < 0)
977dd7cddfSDavid du Colombier return code;
987dd7cddfSDavid du Colombier if_debug3('L', " rs2:%d,%d,0,%d\n",
997dd7cddfSDavid du Colombier dx, dwidth, dheight);
1007dd7cddfSDavid du Colombier } else {
1017dd7cddfSDavid du Colombier code = set_cmd_put_op(dp, cldev, pcls, op + 0x10, 5);
1027dd7cddfSDavid du Colombier if (code < 0)
1037dd7cddfSDavid du Colombier return code;
1047dd7cddfSDavid du Colombier if_debug4('L', " rs4:%d,%d,%d,%d\n",
1057dd7cddfSDavid du Colombier dx, dwidth, dy, dheight);
1067dd7cddfSDavid du Colombier dp[3] = dy - rmin;
1077dd7cddfSDavid du Colombier dp[4] = dheight - rmin;
1087dd7cddfSDavid du Colombier }
1097dd7cddfSDavid du Colombier dp[1] = dx - rmin;
1107dd7cddfSDavid du Colombier dp[2] = dwidth - rmin;
1117dd7cddfSDavid du Colombier }
1127dd7cddfSDavid du Colombier #undef rmin
1137dd7cddfSDavid du Colombier #undef rmax
1147dd7cddfSDavid du Colombier else if (dy >= -2 && dy <= 1 && dheight >= -2 && dheight <= 1 &&
1157dd7cddfSDavid du Colombier (dy + dheight) != -4
1167dd7cddfSDavid du Colombier ) {
1177dd7cddfSDavid du Colombier int rcsize = 1 + cmd_sizew(x) + cmd_sizew(width);
1187dd7cddfSDavid du Colombier
1197dd7cddfSDavid du Colombier code = set_cmd_put_op(dp, cldev, pcls,
1207dd7cddfSDavid du Colombier op + ((dy + 2) << 2) + dheight + 2, rcsize);
1217dd7cddfSDavid du Colombier if (code < 0)
1227dd7cddfSDavid du Colombier return code;
1237dd7cddfSDavid du Colombier ++dp;
1247dd7cddfSDavid du Colombier cmd_put2w(x, width, dp);
1257dd7cddfSDavid du Colombier } else {
1267dd7cddfSDavid du Colombier int rcsize = 1 + cmd_size_rect(&pcls->rect);
1277dd7cddfSDavid du Colombier
1287dd7cddfSDavid du Colombier code = set_cmd_put_op(dp, cldev, pcls, op, rcsize);
1297dd7cddfSDavid du Colombier if (code < 0)
1307dd7cddfSDavid du Colombier return code;
1317dd7cddfSDavid du Colombier if_debug5('L', " r%d:%d,%d,%d,%d\n",
1327dd7cddfSDavid du Colombier rcsize - 1, dx, dwidth, dy, dheight);
1337dd7cddfSDavid du Colombier cmd_put_rect(&pcls->rect, dp + 1);
1347dd7cddfSDavid du Colombier }
1357dd7cddfSDavid du Colombier return 0;
1367dd7cddfSDavid du Colombier }
1377dd7cddfSDavid du Colombier
1387dd7cddfSDavid du Colombier /* ---------------- Driver procedures ---------------- */
1397dd7cddfSDavid du Colombier
1407dd7cddfSDavid du Colombier int
clist_fill_rectangle(gx_device * dev,int x,int y,int width,int height,gx_color_index color)1417dd7cddfSDavid du Colombier clist_fill_rectangle(gx_device * dev, int x, int y, int width, int height,
1427dd7cddfSDavid du Colombier gx_color_index color)
1437dd7cddfSDavid du Colombier {
1447dd7cddfSDavid du Colombier gx_device_clist_writer * const cdev =
1457dd7cddfSDavid du Colombier &((gx_device_clist *)dev)->writer;
1467dd7cddfSDavid du Colombier int code;
1477dd7cddfSDavid du Colombier
1487dd7cddfSDavid du Colombier fit_fill(dev, x, y, width, height);
1497dd7cddfSDavid du Colombier FOR_RECTS {
1507dd7cddfSDavid du Colombier pcls->colors_used.or |= color;
1517dd7cddfSDavid du Colombier TRY_RECT {
1527dd7cddfSDavid du Colombier code = cmd_disable_lop(cdev, pcls);
1537dd7cddfSDavid du Colombier if (code >= 0 && color != pcls->colors[1])
1547dd7cddfSDavid du Colombier code = cmd_put_color(cdev, pcls, &clist_select_color1,
1557dd7cddfSDavid du Colombier color, &pcls->colors[1]);
1567dd7cddfSDavid du Colombier if (code >= 0)
1577dd7cddfSDavid du Colombier code = cmd_write_rect_cmd(cdev, pcls, cmd_op_fill_rect, x, y,
1587dd7cddfSDavid du Colombier width, height);
1597dd7cddfSDavid du Colombier } HANDLE_RECT(code);
1607dd7cddfSDavid du Colombier } END_RECTS;
1617dd7cddfSDavid du Colombier return 0;
1627dd7cddfSDavid du Colombier }
1637dd7cddfSDavid du Colombier
1647dd7cddfSDavid du Colombier int
clist_strip_tile_rectangle(gx_device * dev,const gx_strip_bitmap * tile,int x,int y,int width,int height,gx_color_index color0,gx_color_index color1,int px,int py)1657dd7cddfSDavid du Colombier clist_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tile,
1667dd7cddfSDavid du Colombier int x, int y, int width, int height,
1677dd7cddfSDavid du Colombier gx_color_index color0, gx_color_index color1, int px, int py)
1687dd7cddfSDavid du Colombier {
1697dd7cddfSDavid du Colombier gx_device_clist_writer * const cdev =
1707dd7cddfSDavid du Colombier &((gx_device_clist *)dev)->writer;
1717dd7cddfSDavid du Colombier int depth =
1727dd7cddfSDavid du Colombier (color1 == gx_no_color_index && color0 == gx_no_color_index ?
1737dd7cddfSDavid du Colombier dev->color_info.depth : 1);
1747dd7cddfSDavid du Colombier gx_color_index colors_used =
1757dd7cddfSDavid du Colombier (color1 == gx_no_color_index && color0 == gx_no_color_index ?
1767dd7cddfSDavid du Colombier /* We can't know what colors will be used: assume the worst. */
1777dd7cddfSDavid du Colombier ((gx_color_index)1 << depth) - 1 :
1787dd7cddfSDavid du Colombier (color0 == gx_no_color_index ? 0 : color0) |
1797dd7cddfSDavid du Colombier (color1 == gx_no_color_index ? 0 : color1));
1807dd7cddfSDavid du Colombier int code;
1817dd7cddfSDavid du Colombier
1827dd7cddfSDavid du Colombier fit_fill(dev, x, y, width, height);
1837dd7cddfSDavid du Colombier FOR_RECTS {
1847dd7cddfSDavid du Colombier ulong offset_temp;
1857dd7cddfSDavid du Colombier
1867dd7cddfSDavid du Colombier pcls->colors_used.or |= colors_used;
1877dd7cddfSDavid du Colombier TRY_RECT {
1887dd7cddfSDavid du Colombier code = cmd_disable_lop(cdev, pcls);
1897dd7cddfSDavid du Colombier } HANDLE_RECT(code);
1907dd7cddfSDavid du Colombier if (!cls_has_tile_id(cdev, pcls, tile->id, offset_temp)) {
1917dd7cddfSDavid du Colombier code = 0;
1927dd7cddfSDavid du Colombier if (tile->id != gx_no_bitmap_id) {
1937dd7cddfSDavid du Colombier TRY_RECT {
1947dd7cddfSDavid du Colombier code = clist_change_tile(cdev, pcls, tile, depth);
1957dd7cddfSDavid du Colombier } HANDLE_RECT_UNLESS(code,
1967dd7cddfSDavid du Colombier (code != gs_error_VMerror || !cdev->error_is_retryable));
1977dd7cddfSDavid du Colombier }
1987dd7cddfSDavid du Colombier if (code < 0) {
1997dd7cddfSDavid du Colombier /* ok if gx_default... does retries internally: */
2007dd7cddfSDavid du Colombier /* it's self-sufficient */
2017dd7cddfSDavid du Colombier code = gx_default_strip_tile_rectangle(dev, tile,
2027dd7cddfSDavid du Colombier x, y, width, height,
2037dd7cddfSDavid du Colombier color0, color1,
2047dd7cddfSDavid du Colombier px, py);
2057dd7cddfSDavid du Colombier if (code < 0)
2067dd7cddfSDavid du Colombier ERROR_RECT(code);
2077dd7cddfSDavid du Colombier goto endr;
2087dd7cddfSDavid du Colombier }
2097dd7cddfSDavid du Colombier }
2107dd7cddfSDavid du Colombier TRY_RECT {
2117dd7cddfSDavid du Colombier code = 0;
2127dd7cddfSDavid du Colombier if (color0 != pcls->tile_colors[0] || color1 != pcls->tile_colors[1])
2137dd7cddfSDavid du Colombier code = cmd_set_tile_colors(cdev, pcls, color0, color1);
2147dd7cddfSDavid du Colombier if (px != pcls->tile_phase.x || py != pcls->tile_phase.y) {
2157dd7cddfSDavid du Colombier if (code >= 0)
2167dd7cddfSDavid du Colombier code = cmd_set_tile_phase(cdev, pcls, px, py);
2177dd7cddfSDavid du Colombier }
2187dd7cddfSDavid du Colombier if (code >= 0)
2197dd7cddfSDavid du Colombier code = cmd_write_rect_cmd(cdev, pcls, cmd_op_tile_rect, x, y,
2207dd7cddfSDavid du Colombier width, height);
2217dd7cddfSDavid du Colombier } HANDLE_RECT(code);
2227dd7cddfSDavid du Colombier endr:;
2237dd7cddfSDavid du Colombier } END_RECTS;
2247dd7cddfSDavid du Colombier return 0;
2257dd7cddfSDavid du Colombier }
2267dd7cddfSDavid du Colombier
2277dd7cddfSDavid du Colombier int
clist_copy_mono(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 color0,gx_color_index color1)2287dd7cddfSDavid du Colombier clist_copy_mono(gx_device * dev,
2297dd7cddfSDavid du Colombier const byte * data, int data_x, int raster, gx_bitmap_id id,
2307dd7cddfSDavid du Colombier int x, int y, int width, int height,
2317dd7cddfSDavid du Colombier gx_color_index color0, gx_color_index color1)
2327dd7cddfSDavid du Colombier {
2337dd7cddfSDavid du Colombier gx_device_clist_writer * const cdev =
2347dd7cddfSDavid du Colombier &((gx_device_clist *)dev)->writer;
2357dd7cddfSDavid du Colombier int y0;
2367dd7cddfSDavid du Colombier gx_bitmap_id orig_id = id;
2377dd7cddfSDavid du Colombier gx_color_index colors_used =
2387dd7cddfSDavid du Colombier (color0 == gx_no_color_index ? 0 : color0) |
2397dd7cddfSDavid du Colombier (color1 == gx_no_color_index ? 0 : color1);
2407dd7cddfSDavid du Colombier
2417dd7cddfSDavid du Colombier fit_copy(dev, data, data_x, raster, id, x, y, width, height);
2427dd7cddfSDavid du Colombier y0 = y;
2437dd7cddfSDavid du Colombier FOR_RECTS {
2447dd7cddfSDavid du Colombier int dx = data_x & 7;
2457dd7cddfSDavid du Colombier int w1 = dx + width;
2467dd7cddfSDavid du Colombier const byte *row = data + (y - y0) * raster + (data_x >> 3);
2477dd7cddfSDavid du Colombier int code;
2487dd7cddfSDavid du Colombier
2497dd7cddfSDavid du Colombier pcls->colors_used.or |= colors_used;
2507dd7cddfSDavid du Colombier TRY_RECT {
2517dd7cddfSDavid du Colombier code = cmd_disable_lop(cdev, pcls);
2527dd7cddfSDavid du Colombier if (code >= 0)
2537dd7cddfSDavid du Colombier code = cmd_disable_clip(cdev, pcls);
2547dd7cddfSDavid du Colombier if (color0 != pcls->colors[0] && code >= 0)
2557dd7cddfSDavid du Colombier code = cmd_set_color0(cdev, pcls, color0);
2567dd7cddfSDavid du Colombier if (color1 != pcls->colors[1] && code >= 0)
2577dd7cddfSDavid du Colombier code = cmd_set_color1(cdev, pcls, color1);
2587dd7cddfSDavid du Colombier } HANDLE_RECT(code);
2597dd7cddfSDavid du Colombier /* Don't bother to check for a possible cache hit: */
2607dd7cddfSDavid du Colombier /* tile_rectangle and fill_mask handle those cases. */
2617dd7cddfSDavid du Colombier copy:{
2627dd7cddfSDavid du Colombier gx_cmd_rect rect;
2637dd7cddfSDavid du Colombier int rsize;
2647dd7cddfSDavid du Colombier byte op = (byte) cmd_op_copy_mono;
2657dd7cddfSDavid du Colombier byte *dp;
2667dd7cddfSDavid du Colombier uint csize;
2677dd7cddfSDavid du Colombier uint compress;
2687dd7cddfSDavid du Colombier int code;
2697dd7cddfSDavid du Colombier
2707dd7cddfSDavid du Colombier rect.x = x, rect.y = y;
2717dd7cddfSDavid du Colombier rect.width = w1, rect.height = height;
2727dd7cddfSDavid du Colombier rsize = (dx ? 3 : 1) + cmd_size_rect(&rect);
2737dd7cddfSDavid du Colombier TRY_RECT {
2747dd7cddfSDavid du Colombier code = cmd_put_bits(cdev, pcls, row, w1, height, raster,
2757dd7cddfSDavid du Colombier rsize, (orig_id == gx_no_bitmap_id ?
2767dd7cddfSDavid du Colombier 1 << cmd_compress_rle :
2777dd7cddfSDavid du Colombier cmd_mask_compress_any),
2787dd7cddfSDavid du Colombier &dp, &csize);
2797dd7cddfSDavid du Colombier } HANDLE_RECT_UNLESS(code, code == gs_error_limitcheck);
2807dd7cddfSDavid du Colombier compress = (uint)code;
2817dd7cddfSDavid du Colombier if (code < 0) {
2827dd7cddfSDavid du Colombier /* The bitmap was too large; split up the transfer. */
2837dd7cddfSDavid du Colombier if (height > 1) {
2847dd7cddfSDavid du Colombier /*
2857dd7cddfSDavid du Colombier * Split the transfer by reducing the height.
2867dd7cddfSDavid du Colombier * See the comment above FOR_RECTS in gxcldev.h.
2877dd7cddfSDavid du Colombier */
2887dd7cddfSDavid du Colombier height >>= 1;
2897dd7cddfSDavid du Colombier goto copy;
2907dd7cddfSDavid du Colombier } else {
2917dd7cddfSDavid du Colombier /* Split a single (very long) row. */
2927dd7cddfSDavid du Colombier int w2 = w1 >> 1;
2937dd7cddfSDavid du Colombier
2947dd7cddfSDavid du Colombier NEST_RECT {
2957dd7cddfSDavid du Colombier code = clist_copy_mono(dev, row, dx,
2967dd7cddfSDavid du Colombier raster, gx_no_bitmap_id, x, y,
2977dd7cddfSDavid du Colombier w2, 1, color0, color1);
2987dd7cddfSDavid du Colombier if (code >= 0)
2997dd7cddfSDavid du Colombier code = clist_copy_mono(dev, row, dx + w2,
3007dd7cddfSDavid du Colombier raster, gx_no_bitmap_id,
3017dd7cddfSDavid du Colombier x + w2, y,
3027dd7cddfSDavid du Colombier w1 - w2, 1, color0, color1);
3037dd7cddfSDavid du Colombier } UNNEST_RECT;
3047dd7cddfSDavid du Colombier if (code < 0)
3057dd7cddfSDavid du Colombier ERROR_RECT(code);
3067dd7cddfSDavid du Colombier continue;
3077dd7cddfSDavid du Colombier }
3087dd7cddfSDavid du Colombier }
3097dd7cddfSDavid du Colombier op += compress;
3107dd7cddfSDavid du Colombier if (dx) {
3117dd7cddfSDavid du Colombier *dp++ = cmd_count_op(cmd_opv_set_misc, 2);
3127dd7cddfSDavid du Colombier *dp++ = cmd_set_misc_data_x + dx;
3137dd7cddfSDavid du Colombier }
3147dd7cddfSDavid du Colombier *dp++ = cmd_count_op(op, csize);
3157dd7cddfSDavid du Colombier cmd_put2w(x, y, dp);
3167dd7cddfSDavid du Colombier cmd_put2w(w1, height, dp);
3177dd7cddfSDavid du Colombier pcls->rect = rect;
3187dd7cddfSDavid du Colombier }
3197dd7cddfSDavid du Colombier } END_RECTS;
3207dd7cddfSDavid du Colombier return 0;
3217dd7cddfSDavid du Colombier }
3227dd7cddfSDavid du Colombier
3237dd7cddfSDavid du Colombier int
clist_copy_color(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int width,int height)3247dd7cddfSDavid du Colombier clist_copy_color(gx_device * dev,
3257dd7cddfSDavid du Colombier const byte * data, int data_x, int raster, gx_bitmap_id id,
3267dd7cddfSDavid du Colombier int x, int y, int width, int height)
3277dd7cddfSDavid du Colombier {
3287dd7cddfSDavid du Colombier gx_device_clist_writer * const cdev =
3297dd7cddfSDavid du Colombier &((gx_device_clist *)dev)->writer;
3307dd7cddfSDavid du Colombier int depth = dev->color_info.depth;
3317dd7cddfSDavid du Colombier int y0;
3327dd7cddfSDavid du Colombier int data_x_bit;
3337dd7cddfSDavid du Colombier /* We can't know what colors will be used: assume the worst. */
3347dd7cddfSDavid du Colombier gx_color_index colors_used = ((gx_color_index)1 << depth) - 1;
3357dd7cddfSDavid du Colombier
3367dd7cddfSDavid du Colombier fit_copy(dev, data, data_x, raster, id, x, y, width, height);
3377dd7cddfSDavid du Colombier y0 = y;
3387dd7cddfSDavid du Colombier data_x_bit = data_x * depth;
3397dd7cddfSDavid du Colombier FOR_RECTS {
3407dd7cddfSDavid du Colombier int dx = (data_x_bit & 7) / depth;
3417dd7cddfSDavid du Colombier int w1 = dx + width;
3427dd7cddfSDavid du Colombier const byte *row = data + (y - y0) * raster + (data_x_bit >> 3);
3437dd7cddfSDavid du Colombier int code;
3447dd7cddfSDavid du Colombier
3457dd7cddfSDavid du Colombier pcls->colors_used.or |= colors_used;
3467dd7cddfSDavid du Colombier TRY_RECT {
3477dd7cddfSDavid du Colombier code = cmd_disable_lop(cdev, pcls);
3487dd7cddfSDavid du Colombier if (code >= 0)
3497dd7cddfSDavid du Colombier code = cmd_disable_clip(cdev, pcls);
3507dd7cddfSDavid du Colombier } HANDLE_RECT(code);
3517dd7cddfSDavid du Colombier if (pcls->color_is_alpha) {
3527dd7cddfSDavid du Colombier byte *dp;
3537dd7cddfSDavid du Colombier
3547dd7cddfSDavid du Colombier TRY_RECT {
3557dd7cddfSDavid du Colombier code =
3567dd7cddfSDavid du Colombier set_cmd_put_op(dp, cdev, pcls, cmd_opv_set_copy_color, 1);
3577dd7cddfSDavid du Colombier } HANDLE_RECT(code);
3587dd7cddfSDavid du Colombier pcls->color_is_alpha = 0;
3597dd7cddfSDavid du Colombier }
3607dd7cddfSDavid du Colombier copy:{
3617dd7cddfSDavid du Colombier gx_cmd_rect rect;
3627dd7cddfSDavid du Colombier int rsize;
3637dd7cddfSDavid du Colombier byte op = (byte) cmd_op_copy_color_alpha;
3647dd7cddfSDavid du Colombier byte *dp;
3657dd7cddfSDavid du Colombier uint csize;
3667dd7cddfSDavid du Colombier uint compress;
3677dd7cddfSDavid du Colombier
3687dd7cddfSDavid du Colombier rect.x = x, rect.y = y;
3697dd7cddfSDavid du Colombier rect.width = w1, rect.height = height;
3707dd7cddfSDavid du Colombier rsize = (dx ? 3 : 1) + cmd_size_rect(&rect);
3717dd7cddfSDavid du Colombier TRY_RECT {
3727dd7cddfSDavid du Colombier code = cmd_put_bits(cdev, pcls, row, w1 * depth,
3737dd7cddfSDavid du Colombier height, raster, rsize,
3747dd7cddfSDavid du Colombier 1 << cmd_compress_rle, &dp, &csize);
3757dd7cddfSDavid du Colombier } HANDLE_RECT_UNLESS(code, code == gs_error_limitcheck);
3767dd7cddfSDavid du Colombier compress = (uint)code;
3777dd7cddfSDavid du Colombier if (code < 0) {
3787dd7cddfSDavid du Colombier /* The bitmap was too large; split up the transfer. */
3797dd7cddfSDavid du Colombier if (height > 1) {
3807dd7cddfSDavid du Colombier /* Split the transfer by reducing the height.
3817dd7cddfSDavid du Colombier * See the comment above FOR_RECTS in gxcldev.h.
3827dd7cddfSDavid du Colombier */
3837dd7cddfSDavid du Colombier height >>= 1;
3847dd7cddfSDavid du Colombier goto copy;
3857dd7cddfSDavid du Colombier } else {
3867dd7cddfSDavid du Colombier /* Split a single (very long) row. */
3877dd7cddfSDavid du Colombier int w2 = w1 >> 1;
3887dd7cddfSDavid du Colombier
3897dd7cddfSDavid du Colombier NEST_RECT {
3907dd7cddfSDavid du Colombier code = clist_copy_color(dev, row, dx,
3917dd7cddfSDavid du Colombier raster, gx_no_bitmap_id,
3927dd7cddfSDavid du Colombier x, y, w2, 1);
3937dd7cddfSDavid du Colombier if (code >= 0)
3947dd7cddfSDavid du Colombier code = clist_copy_color(dev, row, dx + w2,
3957dd7cddfSDavid du Colombier raster, gx_no_bitmap_id,
3967dd7cddfSDavid du Colombier x + w2, y, w1 - w2, 1);
3977dd7cddfSDavid du Colombier } UNNEST_RECT;
3987dd7cddfSDavid du Colombier if (code < 0)
3997dd7cddfSDavid du Colombier ERROR_RECT(code);
4007dd7cddfSDavid du Colombier continue;
4017dd7cddfSDavid du Colombier }
4027dd7cddfSDavid du Colombier }
4037dd7cddfSDavid du Colombier op += compress;
4047dd7cddfSDavid du Colombier if (dx) {
4057dd7cddfSDavid du Colombier *dp++ = cmd_count_op(cmd_opv_set_misc, 2);
4067dd7cddfSDavid du Colombier *dp++ = cmd_set_misc_data_x + dx;
4077dd7cddfSDavid du Colombier }
4087dd7cddfSDavid du Colombier *dp++ = cmd_count_op(op, csize);
4097dd7cddfSDavid du Colombier cmd_put2w(x, y, dp);
4107dd7cddfSDavid du Colombier cmd_put2w(w1, height, dp);
4117dd7cddfSDavid du Colombier pcls->rect = rect;
4127dd7cddfSDavid du Colombier }
4137dd7cddfSDavid du Colombier } END_RECTS;
4147dd7cddfSDavid du Colombier return 0;
4157dd7cddfSDavid du Colombier }
4167dd7cddfSDavid du Colombier
4177dd7cddfSDavid du Colombier int
clist_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)4187dd7cddfSDavid du Colombier clist_copy_alpha(gx_device * dev, const byte * data, int data_x,
4197dd7cddfSDavid du Colombier int raster, gx_bitmap_id id, int x, int y, int width, int height,
4207dd7cddfSDavid du Colombier gx_color_index color, int depth)
4217dd7cddfSDavid du Colombier {
4227dd7cddfSDavid du Colombier gx_device_clist_writer * const cdev =
4237dd7cddfSDavid du Colombier &((gx_device_clist *)dev)->writer;
4247dd7cddfSDavid du Colombier /* I don't like copying the entire body of clist_copy_color */
4257dd7cddfSDavid du Colombier /* just to change 2 arguments and 1 opcode, */
4267dd7cddfSDavid du Colombier /* but I don't see any alternative that doesn't require */
4277dd7cddfSDavid du Colombier /* another level of procedure call even in the common case. */
4287dd7cddfSDavid du Colombier int log2_depth = ilog2(depth);
4297dd7cddfSDavid du Colombier int y0;
4307dd7cddfSDavid du Colombier int data_x_bit;
4317dd7cddfSDavid du Colombier
432*593dc095SDavid du Colombier /* If the target can't perform copy_alpha, exit now */
433*593dc095SDavid du Colombier if (depth > 1 && (cdev->disable_mask & clist_disable_copy_alpha) != 0)
434*593dc095SDavid du Colombier return_error(gs_error_unknownerror);
435*593dc095SDavid du Colombier
4367dd7cddfSDavid du Colombier fit_copy(dev, data, data_x, raster, id, x, y, width, height);
4377dd7cddfSDavid du Colombier y0 = y;
4387dd7cddfSDavid du Colombier data_x_bit = data_x << log2_depth;
4397dd7cddfSDavid du Colombier FOR_RECTS {
4407dd7cddfSDavid du Colombier int dx = (data_x_bit & 7) >> log2_depth;
4417dd7cddfSDavid du Colombier int w1 = dx + width;
4427dd7cddfSDavid du Colombier const byte *row = data + (y - y0) * raster + (data_x_bit >> 3);
4437dd7cddfSDavid du Colombier int code;
4447dd7cddfSDavid du Colombier
4457dd7cddfSDavid du Colombier pcls->colors_used.or |= color;
4467dd7cddfSDavid du Colombier TRY_RECT {
4477dd7cddfSDavid du Colombier code = cmd_disable_lop(cdev, pcls);
4487dd7cddfSDavid du Colombier if (code >= 0)
4497dd7cddfSDavid du Colombier code = cmd_disable_clip(cdev, pcls);
4507dd7cddfSDavid du Colombier } HANDLE_RECT(code);
4517dd7cddfSDavid du Colombier if (!pcls->color_is_alpha) {
4527dd7cddfSDavid du Colombier byte *dp;
4537dd7cddfSDavid du Colombier
4547dd7cddfSDavid du Colombier TRY_RECT {
4557dd7cddfSDavid du Colombier code =
4567dd7cddfSDavid du Colombier set_cmd_put_op(dp, cdev, pcls, cmd_opv_set_copy_alpha, 1);
4577dd7cddfSDavid du Colombier } HANDLE_RECT(code);
4587dd7cddfSDavid du Colombier pcls->color_is_alpha = 1;
4597dd7cddfSDavid du Colombier }
4607dd7cddfSDavid du Colombier if (color != pcls->colors[1]) {
4617dd7cddfSDavid du Colombier TRY_RECT {
4627dd7cddfSDavid du Colombier code = cmd_set_color1(cdev, pcls, color);
4637dd7cddfSDavid du Colombier } HANDLE_RECT(code);
4647dd7cddfSDavid du Colombier }
4657dd7cddfSDavid du Colombier copy:{
4667dd7cddfSDavid du Colombier gx_cmd_rect rect;
4677dd7cddfSDavid du Colombier int rsize;
4687dd7cddfSDavid du Colombier byte op = (byte) cmd_op_copy_color_alpha;
4697dd7cddfSDavid du Colombier byte *dp;
4707dd7cddfSDavid du Colombier uint csize;
4717dd7cddfSDavid du Colombier uint compress;
4727dd7cddfSDavid du Colombier
4737dd7cddfSDavid du Colombier rect.x = x, rect.y = y;
4747dd7cddfSDavid du Colombier rect.width = w1, rect.height = height;
4757dd7cddfSDavid du Colombier rsize = (dx ? 4 : 2) + cmd_size_rect(&rect);
4767dd7cddfSDavid du Colombier TRY_RECT {
4777dd7cddfSDavid du Colombier code = cmd_put_bits(cdev, pcls, row, w1 << log2_depth,
4787dd7cddfSDavid du Colombier height, raster, rsize,
4797dd7cddfSDavid du Colombier 1 << cmd_compress_rle, &dp, &csize);
4807dd7cddfSDavid du Colombier } HANDLE_RECT_UNLESS(code, code == gs_error_limitcheck);
4817dd7cddfSDavid du Colombier compress = (uint)code;
4827dd7cddfSDavid du Colombier if (code < 0) {
4837dd7cddfSDavid du Colombier /* The bitmap was too large; split up the transfer. */
4847dd7cddfSDavid du Colombier if (height > 1) {
4857dd7cddfSDavid du Colombier /* Split the transfer by reducing the height.
4867dd7cddfSDavid du Colombier * See the comment above FOR_RECTS in gxcldev.h.
4877dd7cddfSDavid du Colombier */
4887dd7cddfSDavid du Colombier height >>= 1;
4897dd7cddfSDavid du Colombier goto copy;
4907dd7cddfSDavid du Colombier } else {
4917dd7cddfSDavid du Colombier /* Split a single (very long) row. */
4927dd7cddfSDavid du Colombier int w2 = w1 >> 1;
4937dd7cddfSDavid du Colombier
4947dd7cddfSDavid du Colombier NEST_RECT {
4957dd7cddfSDavid du Colombier code = clist_copy_alpha(dev, row, dx,
4967dd7cddfSDavid du Colombier raster, gx_no_bitmap_id, x, y,
4977dd7cddfSDavid du Colombier w2, 1, color, depth);
4987dd7cddfSDavid du Colombier if (code >= 0)
4997dd7cddfSDavid du Colombier code = clist_copy_alpha(dev, row, dx + w2,
5007dd7cddfSDavid du Colombier raster, gx_no_bitmap_id,
5017dd7cddfSDavid du Colombier x + w2, y, w1 - w2, 1,
5027dd7cddfSDavid du Colombier color, depth);
5037dd7cddfSDavid du Colombier } UNNEST_RECT;
5047dd7cddfSDavid du Colombier if (code < 0)
5057dd7cddfSDavid du Colombier ERROR_RECT(code);
5067dd7cddfSDavid du Colombier continue;
5077dd7cddfSDavid du Colombier }
5087dd7cddfSDavid du Colombier }
5097dd7cddfSDavid du Colombier op += compress;
5107dd7cddfSDavid du Colombier if (dx) {
5117dd7cddfSDavid du Colombier *dp++ = cmd_count_op(cmd_opv_set_misc, 2);
5127dd7cddfSDavid du Colombier *dp++ = cmd_set_misc_data_x + dx;
5137dd7cddfSDavid du Colombier }
5147dd7cddfSDavid du Colombier *dp++ = cmd_count_op(op, csize);
5157dd7cddfSDavid du Colombier *dp++ = depth;
5167dd7cddfSDavid du Colombier cmd_put2w(x, y, dp);
5177dd7cddfSDavid du Colombier cmd_put2w(w1, height, dp);
5187dd7cddfSDavid du Colombier pcls->rect = rect;
5197dd7cddfSDavid du Colombier }
5207dd7cddfSDavid du Colombier } END_RECTS;
5217dd7cddfSDavid du Colombier return 0;
5227dd7cddfSDavid du Colombier }
5237dd7cddfSDavid du Colombier
5247dd7cddfSDavid du Colombier int
clist_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)5257dd7cddfSDavid du Colombier clist_strip_copy_rop(gx_device * dev,
5267dd7cddfSDavid du Colombier const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
5277dd7cddfSDavid du Colombier const gx_color_index * scolors,
5287dd7cddfSDavid du Colombier const gx_strip_bitmap * textures, const gx_color_index * tcolors,
5297dd7cddfSDavid du Colombier int x, int y, int width, int height,
5307dd7cddfSDavid du Colombier int phase_x, int phase_y, gs_logical_operation_t lop)
5317dd7cddfSDavid du Colombier {
5327dd7cddfSDavid du Colombier gx_device_clist_writer * const cdev =
5337dd7cddfSDavid du Colombier &((gx_device_clist *)dev)->writer;
5347dd7cddfSDavid du Colombier gs_rop3_t rop = lop_rop(lop);
5357dd7cddfSDavid du Colombier gx_strip_bitmap tile_with_id;
5367dd7cddfSDavid du Colombier const gx_strip_bitmap *tiles = textures;
5377dd7cddfSDavid du Colombier int y0;
5387dd7cddfSDavid du Colombier /* Compute the set of possible colors that this operation can generate. */
5397dd7cddfSDavid du Colombier gx_color_index all = ((gx_color_index)1 << dev->color_info.depth) - 1;
5407dd7cddfSDavid du Colombier bool subtractive = dev->color_info.num_components == 4; /****** HACK ******/
5417dd7cddfSDavid du Colombier gx_color_index S =
5427dd7cddfSDavid du Colombier (scolors ? scolors[0] | scolors[1] : sdata ? all : 0);
5437dd7cddfSDavid du Colombier gx_color_index T =
5447dd7cddfSDavid du Colombier (tcolors ? tcolors[0] | tcolors[1] : textures ? all : 0);
5457dd7cddfSDavid du Colombier gs_rop3_t color_rop =
5467dd7cddfSDavid du Colombier (subtractive ? byte_reverse_bits[rop ^ 0xff] : rop);
5477dd7cddfSDavid du Colombier bool slow_rop;
5487dd7cddfSDavid du Colombier
5497dd7cddfSDavid du Colombier if (scolors != 0 && scolors[0] != scolors[1]) {
5507dd7cddfSDavid du Colombier fit_fill(dev, x, y, width, height);
5517dd7cddfSDavid du Colombier } else {
5527dd7cddfSDavid du Colombier fit_copy(dev, sdata, sourcex, sraster, id, x, y, width, height);
5537dd7cddfSDavid du Colombier }
5547dd7cddfSDavid du Colombier /*
5557dd7cddfSDavid du Colombier * On CMYK devices, RasterOps must be executed with complete pixels
5567dd7cddfSDavid du Colombier * if the operation involves the destination.
5577dd7cddfSDavid du Colombier * This is because the black plane interacts with the other planes
5587dd7cddfSDavid du Colombier * in the conversion between RGB and CMYK. Check for this now.
5597dd7cddfSDavid du Colombier */
5607dd7cddfSDavid du Colombier {
5617dd7cddfSDavid du Colombier gs_rop3_t rop_used = rop;
5627dd7cddfSDavid du Colombier
5637dd7cddfSDavid du Colombier if (scolors && (scolors[0] == scolors[1]))
5647dd7cddfSDavid du Colombier rop_used = (scolors[0] == gx_device_black(dev) ?
5657dd7cddfSDavid du Colombier rop3_know_S_0(rop_used) :
5667dd7cddfSDavid du Colombier scolors[0] == gx_device_white(dev) ?
5677dd7cddfSDavid du Colombier rop3_know_S_1(rop_used) : rop_used);
5687dd7cddfSDavid du Colombier if (tcolors && (tcolors[0] == tcolors[1]))
5697dd7cddfSDavid du Colombier rop_used = (tcolors[0] == gx_device_black(dev) ?
5707dd7cddfSDavid du Colombier rop3_know_T_0(rop_used) :
5717dd7cddfSDavid du Colombier tcolors[0] == gx_device_white(dev) ?
5727dd7cddfSDavid du Colombier rop3_know_T_1(rop_used) : rop_used);
5737dd7cddfSDavid du Colombier slow_rop = !(rop == rop3_0 || rop == rop3_1 ||
5747dd7cddfSDavid du Colombier rop == rop3_D || rop == rop3_S || rop == rop3_T);
5757dd7cddfSDavid du Colombier }
5767dd7cddfSDavid du Colombier y0 = y;
5777dd7cddfSDavid du Colombier /*
5787dd7cddfSDavid du Colombier * We shouldn't need to put the logic below inside FOR/END_RECTS,
5797dd7cddfSDavid du Colombier * but the lop_enabled flags are per-band.
5807dd7cddfSDavid du Colombier */
5817dd7cddfSDavid du Colombier FOR_RECTS {
5827dd7cddfSDavid du Colombier const byte *row = sdata + (y - y0) * sraster;
5837dd7cddfSDavid du Colombier gx_color_index D = pcls->colors_used.or;
5847dd7cddfSDavid du Colombier int code;
5857dd7cddfSDavid du Colombier
586*593dc095SDavid du Colombier /* Reducing D, S, T to rop_operand (which apparently is 32 bit) appears safe
587*593dc095SDavid du Colombier due to 'all' a has smaller snumber of significant bits. */
5887dd7cddfSDavid du Colombier pcls->colors_used.or =
589*593dc095SDavid du Colombier ((rop_proc_table[color_rop])((rop_operand)D, (rop_operand)S, (rop_operand)T) & all) | D;
5907dd7cddfSDavid du Colombier pcls->colors_used.slow_rop |= slow_rop;
5917dd7cddfSDavid du Colombier if (rop3_uses_T(rop)) {
5927dd7cddfSDavid du Colombier if (tcolors == 0 || tcolors[0] != tcolors[1]) {
5937dd7cddfSDavid du Colombier ulong offset_temp;
5947dd7cddfSDavid du Colombier
5957dd7cddfSDavid du Colombier if (!cls_has_tile_id(cdev, pcls, tiles->id, offset_temp)) {
5967dd7cddfSDavid du Colombier /* Change tile. If there is no id, generate one. */
5977dd7cddfSDavid du Colombier if (tiles->id == gx_no_bitmap_id) {
5987dd7cddfSDavid du Colombier tile_with_id = *tiles;
599*593dc095SDavid du Colombier tile_with_id.id = gs_next_ids(dev->memory, 1);
6007dd7cddfSDavid du Colombier tiles = &tile_with_id;
6017dd7cddfSDavid du Colombier }
6027dd7cddfSDavid du Colombier TRY_RECT {
6037dd7cddfSDavid du Colombier code = clist_change_tile(cdev, pcls, tiles,
6047dd7cddfSDavid du Colombier (tcolors != 0 ? 1 :
6057dd7cddfSDavid du Colombier dev->color_info.depth));
6067dd7cddfSDavid du Colombier } HANDLE_RECT_UNLESS(code, code == gs_error_limitcheck);
6077dd7cddfSDavid du Colombier if (code < 0) {
6087dd7cddfSDavid du Colombier /*
6097dd7cddfSDavid du Colombier * The error is a limitcheck: we have a tile that
6107dd7cddfSDavid du Colombier * is too big to fit in the command reading buffer.
6117dd7cddfSDavid du Colombier * For now, just divide up the transfer into scan
6127dd7cddfSDavid du Colombier * lines. (If a single scan line won't fit, punt.)
6137dd7cddfSDavid du Colombier * Eventually, we'll need a way to transfer the tile
6147dd7cddfSDavid du Colombier * in pieces.
6157dd7cddfSDavid du Colombier */
6167dd7cddfSDavid du Colombier uint rep_height = tiles->rep_height;
6177dd7cddfSDavid du Colombier gs_id ids;
6187dd7cddfSDavid du Colombier gx_strip_bitmap line_tile;
6197dd7cddfSDavid du Colombier int iy;
6207dd7cddfSDavid du Colombier
6217dd7cddfSDavid du Colombier if (rep_height == 1 ||
6227dd7cddfSDavid du Colombier /****** CAN'T HANDLE SHIFT YET ******/
6237dd7cddfSDavid du Colombier tiles->rep_shift != 0
6247dd7cddfSDavid du Colombier )
6257dd7cddfSDavid du Colombier return code;
6267dd7cddfSDavid du Colombier /*
6277dd7cddfSDavid du Colombier * Allocate enough fake IDs, since the inner call on
6287dd7cddfSDavid du Colombier * clist_strip_copy_rop will need them anyway.
6297dd7cddfSDavid du Colombier */
630*593dc095SDavid du Colombier ids = gs_next_ids(dev->memory, min(height, rep_height));
6317dd7cddfSDavid du Colombier line_tile = *tiles;
6327dd7cddfSDavid du Colombier line_tile.size.y = 1;
6337dd7cddfSDavid du Colombier line_tile.rep_height = 1;
6347dd7cddfSDavid du Colombier for (iy = 0; iy < height; ++iy) {
6357dd7cddfSDavid du Colombier line_tile.data = tiles->data + line_tile.raster *
6367dd7cddfSDavid du Colombier ((y + iy + phase_y) % rep_height);
6377dd7cddfSDavid du Colombier line_tile.id = ids + (iy % rep_height);
6387dd7cddfSDavid du Colombier /*
6397dd7cddfSDavid du Colombier * Note that since we're only transferring
6407dd7cddfSDavid du Colombier * a single scan line, phase_y is irrelevant;
6417dd7cddfSDavid du Colombier * we may as well use the current tile phase
6427dd7cddfSDavid du Colombier * so we don't have to write extra commands.
6437dd7cddfSDavid du Colombier */
6447dd7cddfSDavid du Colombier NEST_RECT {
6457dd7cddfSDavid du Colombier code = clist_strip_copy_rop(dev,
6467dd7cddfSDavid du Colombier (sdata == 0 ? 0 : row + iy * sraster),
6477dd7cddfSDavid du Colombier sourcex, sraster,
6487dd7cddfSDavid du Colombier gx_no_bitmap_id, scolors,
6497dd7cddfSDavid du Colombier &line_tile, tcolors,
6507dd7cddfSDavid du Colombier x, y + iy, width, 1,
6517dd7cddfSDavid du Colombier phase_x, pcls->tile_phase.y, lop);
6527dd7cddfSDavid du Colombier } UNNEST_RECT;
6537dd7cddfSDavid du Colombier if (code < 0)
6547dd7cddfSDavid du Colombier ERROR_RECT(code);
6557dd7cddfSDavid du Colombier }
6567dd7cddfSDavid du Colombier continue;
6577dd7cddfSDavid du Colombier }
6587dd7cddfSDavid du Colombier if (phase_x != pcls->tile_phase.x ||
6597dd7cddfSDavid du Colombier phase_y != pcls->tile_phase.y
6607dd7cddfSDavid du Colombier ) {
6617dd7cddfSDavid du Colombier TRY_RECT {
6627dd7cddfSDavid du Colombier code = cmd_set_tile_phase(cdev, pcls, phase_x,
6637dd7cddfSDavid du Colombier phase_y);
6647dd7cddfSDavid du Colombier } HANDLE_RECT(code);
6657dd7cddfSDavid du Colombier }
6667dd7cddfSDavid du Colombier }
6677dd7cddfSDavid du Colombier }
6687dd7cddfSDavid du Colombier /* Set the tile colors. */
6697dd7cddfSDavid du Colombier TRY_RECT {
6707dd7cddfSDavid du Colombier code =
6717dd7cddfSDavid du Colombier (tcolors != 0 ?
6727dd7cddfSDavid du Colombier cmd_set_tile_colors(cdev, pcls, tcolors[0], tcolors[1]) :
6737dd7cddfSDavid du Colombier cmd_set_tile_colors(cdev, pcls, gx_no_color_index,
6747dd7cddfSDavid du Colombier gx_no_color_index));
6757dd7cddfSDavid du Colombier } HANDLE_RECT(code);
6767dd7cddfSDavid du Colombier }
6777dd7cddfSDavid du Colombier TRY_RECT {
6787dd7cddfSDavid du Colombier code = 0;
6797dd7cddfSDavid du Colombier if (lop != pcls->lop)
6807dd7cddfSDavid du Colombier code = cmd_set_lop(cdev, pcls, lop);
6817dd7cddfSDavid du Colombier if (code >= 0)
6827dd7cddfSDavid du Colombier code = cmd_enable_lop(cdev, pcls);
6837dd7cddfSDavid du Colombier } HANDLE_RECT(code);
6847dd7cddfSDavid du Colombier
6857dd7cddfSDavid du Colombier /* Set lop_enabled to -1 so that fill_rectangle / copy_* */
6867dd7cddfSDavid du Colombier /* won't attempt to set it to 0. */
6877dd7cddfSDavid du Colombier pcls->lop_enabled = -1;
6887dd7cddfSDavid du Colombier NEST_RECT {
6897dd7cddfSDavid du Colombier if (scolors != 0) {
6907dd7cddfSDavid du Colombier if (scolors[0] == scolors[1])
6917dd7cddfSDavid du Colombier code = clist_fill_rectangle(dev, x, y, width, height,
6927dd7cddfSDavid du Colombier scolors[1]);
6937dd7cddfSDavid du Colombier else
6947dd7cddfSDavid du Colombier code = clist_copy_mono(dev, row, sourcex, sraster, id,
6957dd7cddfSDavid du Colombier x, y, width, height,
6967dd7cddfSDavid du Colombier scolors[0], scolors[1]);
6977dd7cddfSDavid du Colombier } else
6987dd7cddfSDavid du Colombier code = clist_copy_color(dev, row, sourcex, sraster, id,
6997dd7cddfSDavid du Colombier x, y, width, height);
7007dd7cddfSDavid du Colombier } UNNEST_RECT;
7017dd7cddfSDavid du Colombier pcls->lop_enabled = 1;
7027dd7cddfSDavid du Colombier if (code < 0)
7037dd7cddfSDavid du Colombier ERROR_RECT(code);
7047dd7cddfSDavid du Colombier } END_RECTS;
7057dd7cddfSDavid du Colombier return 0;
7067dd7cddfSDavid du Colombier }
707