Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/base/gxclrect.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2022 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
17
/* Rectangle-oriented command writing for command list */
18
#include "gx.h"
19
#include "gserrors.h"
20
#include "gsutil.h"   /* for gs_next_ids */
21
#include "gxdevice.h"
22
#include "gxdevmem.h"   /* must precede gxcldev.h */
23
#include "gxcldev.h"
24
#include "gxclpath.h"
25
#include "gxdevsop.h"
26
27
/* ---------------- Writing utilities ---------------- */
28
29
#define cmd_set_rect(rect)\
30
49.7M
  ((rect).x = x, (rect).y = y,\
31
49.7M
   (rect).width = width, (rect).height = height)
32
33
/* Write a rectangle. */
34
static int
35
cmd_size_rect(register const gx_cmd_rect * prect)
36
13.9M
{
37
13.9M
    return
38
13.9M
        cmd_sizew(prect->x) + cmd_sizew(prect->y) +
39
13.9M
        cmd_sizew(prect->width) + cmd_sizew(prect->height);
40
13.9M
}
41
static inline byte *
42
cmd_put_rect(const gx_cmd_rect * prect, byte * dp)
43
12.5M
{
44
12.5M
    cmd_putw(prect->x, &dp);
45
12.5M
    cmd_putw(prect->y, &dp);
46
12.5M
    cmd_putw(prect->width, &dp);
47
12.5M
    cmd_putw(prect->height, &dp);
48
12.5M
    return dp;
49
12.5M
}
50
51
int
52
cmd_write_rect_hl_cmd(gx_device_clist_writer * cldev, gx_clist_state * pcls,
53
                      int op, int x, int y, int width, int height,
54
                      bool extended_command)
55
11.8M
{
56
11.8M
    byte *dp;
57
11.8M
    int code;
58
11.8M
    int rcsize;
59
60
11.8M
    cmd_set_rect(pcls->rect);
61
11.8M
    if (extended_command) {
62
948
        rcsize = 2 + cmd_size_rect(&pcls->rect);
63
948
        code = set_cmd_put_extended_op(&dp, cldev, pcls, op, rcsize);
64
948
        dp += 2;
65
11.8M
    } else {
66
11.8M
        rcsize = 1 + cmd_size_rect(&pcls->rect);
67
11.8M
        code = set_cmd_put_op(&dp, cldev, pcls, op, rcsize);
68
11.8M
        dp += 1;
69
11.8M
    }
70
11.8M
    if (code < 0)
71
0
        return code;
72
11.8M
    if_debug5m('L', cldev->memory, "[L]  rect hl r%d:%d,%d,%d,%d\n",
73
11.8M
               rcsize - 1, pcls->rect.x, pcls->rect.y,
74
11.8M
               pcls->rect.width, pcls->rect.height);
75
11.8M
    cmd_put_rect(&pcls->rect, dp);
76
11.8M
    return 0;
77
11.8M
}
78
79
int
80
cmd_write_rect_cmd(gx_device_clist_writer * cldev, gx_clist_state * pcls,
81
                   int op, int x, int y, int width, int height)
82
24.6M
{
83
24.6M
    int dx = x - pcls->rect.x;
84
24.6M
    int dy = y - pcls->rect.y;
85
24.6M
    int dwidth = width - pcls->rect.width;
86
24.6M
    int dheight = height - pcls->rect.height;
87
24.6M
    byte *dp;
88
24.6M
    int code;
89
90
24.6M
#define check_range_xy(rmin, rmax)\
91
29.5M
  ((unsigned)(dx - rmin) <= (rmax - rmin) &&\
92
29.5M
   (unsigned)(dy - rmin) <= (rmax - rmin))
93
24.6M
#define check_range_w(rmin, rmax)\
94
55.0M
  ((unsigned)(dwidth - rmin) <= (rmax - rmin))
95
24.6M
#define check_ranges(rmin, rmax)\
96
24.6M
  (check_range_xy(rmin, rmax) && check_range_w(rmin, rmax) &&\
97
3.76M
   (unsigned)(dheight - rmin) <= (rmax - rmin))
98
24.6M
    cmd_set_rect(pcls->rect);
99
24.6M
    if (dheight == 0 && check_range_w(cmd_min_dw_tiny, cmd_max_dw_tiny) &&
100
24.6M
        check_range_xy(cmd_min_dxy_tiny, cmd_max_dxy_tiny)
101
24.6M
        ) {
102
20.8M
        byte op_tiny = op + 0x20 + dwidth - cmd_min_dw_tiny;
103
104
20.8M
        if (dx == width - dwidth && dy == 0) {
105
15.7M
            code = set_cmd_put_op(&dp, cldev, pcls, op_tiny + 8, 1);
106
15.7M
            if (code < 0)
107
0
                return code;
108
15.7M
        } else {
109
5.08M
            code = set_cmd_put_op(&dp, cldev, pcls, op_tiny, 2);
110
5.08M
            if (code < 0)
111
0
                return code;
112
5.08M
            dp[1] = (dx << 4) + dy - (cmd_min_dxy_tiny * 0x11);
113
5.08M
        }
114
20.8M
    }
115
7.64M
#define rmin cmd_min_short
116
3.76M
#define rmax cmd_max_short
117
3.76M
    else if (check_ranges(rmin, rmax)) {
118
2.65M
        int dh = dheight - cmd_min_dxy_tiny;
119
120
2.65M
        if ((unsigned)dh <= cmd_max_dxy_tiny - cmd_min_dxy_tiny &&
121
2.65M
            dh != 0 && dy == 0
122
2.65M
            ) {
123
1.49M
            op += dh;
124
1.49M
            code = set_cmd_put_op(&dp, cldev, pcls, op + 0x10, 3);
125
1.49M
            if (code < 0)
126
0
                return code;
127
1.49M
            if_debug3m('L', cldev->memory, "    rs2:%d,%d,0,%d\n",
128
1.49M
                       dx, dwidth, dheight);
129
1.49M
        } else {
130
1.16M
            code = set_cmd_put_op(&dp, cldev, pcls, op + 0x10, 5);
131
1.16M
            if (code < 0)
132
0
                return code;
133
1.16M
            if_debug4m('L', cldev->memory, "    rs4:%d,%d,%d,%d\n",
134
1.16M
                       dx, dwidth, dy, dheight);
135
1.16M
            dp[3] = dy - rmin;
136
1.16M
            dp[4] = dheight - rmin;
137
1.16M
        }
138
2.65M
        dp[1] = dx - rmin;
139
2.65M
        dp[2] = dwidth - rmin;
140
2.65M
    }
141
1.10M
#undef rmin
142
1.10M
#undef rmax
143
1.10M
    else if (dy >= -2 && dy <= 1 && dheight >= -2 && dheight <= 1 &&
144
1.10M
             (dy + dheight) != -4
145
1.10M
        ) {
146
452k
        int rcsize = 1 + cmd_sizew(x) + cmd_sizew(width);
147
148
452k
        code = set_cmd_put_op(&dp, cldev, pcls,
149
452k
                              op + ((dy + 2) << 2) + dheight + 2, rcsize);
150
452k
        if (code < 0)
151
0
            return code;
152
452k
        ++dp;
153
452k
        cmd_put2w(x, width, &dp);
154
656k
    } else {
155
656k
        int rcsize = 1 + cmd_size_rect(&pcls->rect);
156
157
656k
        code = set_cmd_put_op(&dp, cldev, pcls, op, rcsize);
158
656k
        if (code < 0)
159
0
            return code;
160
656k
        if_debug5m('L', cldev->memory, "[L]  r%d:%d,%d,%d,%d\n",
161
656k
                   rcsize - 1, dx, dwidth, dy, dheight);
162
656k
        cmd_put_rect(&pcls->rect, dp + 1);
163
656k
    }
164
24.6M
    return 0;
165
24.6M
}
166
167
/* Put out a fill or tile rectangle command for fillpage. */
168
int
169
cmd_write_page_rect_cmd(gx_device_clist_writer * cldev, int op)
170
368k
{
171
    /* Since cmd_write_rect_cmd always writes 0x0 rectangle as a tiny one,
172
       here we write a "big" rectangle with the size 0x0.
173
       The clist reader must handle this case especially.
174
     */
175
368k
    int rcsize = 1 + 4 * cmd_sizew(0);
176
368k
    byte *dp;
177
368k
    int x = 0, y = 0, width = 0, height = 0; /* For cmd_set_rect */
178
368k
    gx_clist_state *pcls1;
179
368k
    int code;
180
181
368k
    if_debug0m('L', cldev->memory, "[L]fillpage beg\n");
182
368k
    code = set_cmd_put_all_op(&dp, cldev, op, rcsize);
183
368k
    if (code < 0)
184
0
        return code;
185
13.2M
    for (pcls1 = cldev->states; pcls1 < cldev->states + cldev->nbands; pcls1++)
186
12.9M
        cmd_set_rect(pcls1->rect);
187
368k
    ++dp;
188
368k
    cmd_putw(0, &dp);
189
368k
    cmd_putw(0, &dp);
190
368k
    cmd_putw(0, &dp);
191
368k
    cmd_putw(0, &dp);
192
368k
    if_debug0m('L', cldev->memory, "[L]fillpage end\n");
193
368k
    return 0;
194
368k
}
195
196
static inline byte *
197
cmd_put_frac31_color(gx_device_clist_writer * cldev, const frac31 *c, byte *dp)
198
3.22M
{
199
3.22M
    uchar num_components = cldev->clist_color_info.num_components;
200
3.22M
    uchar j;
201
202
16.1M
    for (j = 0; j < num_components; j++)
203
12.9M
        dp = cmd_put_frac31(c[j], dp);
204
3.22M
    return dp;
205
3.22M
}
206
207
static inline int
208
cmd_size_frac31_color(gx_device_clist_writer * cldev, const frac31 *c)
209
3.22M
{
210
3.22M
    uchar j;
211
3.22M
    int s = 0;
212
3.22M
    uchar num_components = cldev->clist_color_info.num_components;
213
214
16.1M
    for (j = 0; j < num_components; j++)
215
12.9M
        s += cmd_size_frac31(c[j]);
216
3.22M
    return s;
217
3.22M
}
218
219
static int
220
cmd_write_trapezoid_cmd(gx_device_clist_writer * cldev, gx_clist_state * pcls,
221
                    int op,  const gs_fixed_edge *left, const gs_fixed_edge *right,
222
                    fixed ybot, fixed ytop, int options,
223
                    const gs_fill_attributes *fa,
224
                    const frac31 *c0, const frac31 *c1,
225
                    const frac31 *c2, const frac31 *c3)
226
41.4M
{
227
41.4M
    byte *dp;
228
41.4M
    int rcsize;
229
41.4M
    int code;
230
41.4M
    int colors_mask = 0;
231
232
41.4M
    rcsize = 1 + cmd_sizew(left->start.x) + cmd_sizew(left->start.y)
233
41.4M
               + cmd_sizew(left->end.x) + cmd_sizew(left->end.y)
234
41.4M
               + cmd_sizew(right->start.x) + cmd_sizew(right->start.y)
235
41.4M
               + cmd_sizew(right->end.x) + cmd_sizew(right->end.y)
236
41.4M
               + cmd_sizew(options);
237
238
41.4M
    if (!(options & 4))
239
40.7M
        rcsize += cmd_sizew(ybot) + cmd_sizew(ytop);
240
41.4M
    if (options & 2) {
241
1.25M
        rcsize += cmd_sizew(fa->clip->p.x) + cmd_sizew(fa->clip->p.y)
242
1.25M
                + cmd_sizew(fa->clip->q.x) + cmd_sizew(fa->clip->q.y);
243
1.25M
        if (c0 != NULL) {
244
1.25M
            colors_mask += 1;
245
1.25M
            rcsize += cmd_size_frac31_color(cldev, c0);
246
1.25M
        }
247
1.25M
        if (c1 != NULL) {
248
1.25M
            colors_mask += 2;
249
1.25M
            rcsize += cmd_size_frac31_color(cldev, c1);
250
1.25M
        }
251
1.25M
        if (c2 != NULL) {
252
717k
            colors_mask += 4;
253
717k
            rcsize += cmd_size_frac31_color(cldev, c2);
254
717k
        }
255
1.25M
        if (c3 != NULL) {
256
0
            colors_mask += 8;
257
0
            rcsize += cmd_size_frac31_color(cldev, c3);
258
0
        }
259
1.25M
        rcsize += cmd_sizew(colors_mask);
260
1.25M
    }
261
41.4M
    code = set_cmd_put_op(&dp, cldev, pcls, op, rcsize);
262
41.4M
    if (code < 0)
263
0
        return code;
264
41.4M
    dp++;
265
41.4M
    cmd_putw(left->start.x, &dp);
266
41.4M
    cmd_putw(left->start.y, &dp);
267
41.4M
    cmd_putw(left->end.x, &dp);
268
41.4M
    cmd_putw(left->end.y, &dp);
269
41.4M
    cmd_putw(right->start.x, &dp);
270
41.4M
    cmd_putw(right->start.y, &dp);
271
41.4M
    cmd_putw(right->end.x, &dp);
272
41.4M
    cmd_putw(right->end.y, &dp);
273
41.4M
    cmd_putw(options, &dp);
274
41.4M
    if (!(options & 4)) {
275
40.7M
        cmd_putw(ybot, &dp);
276
40.7M
        cmd_putw(ytop, &dp);
277
40.7M
    }
278
41.4M
    if_debug6m('L', cldev->memory, "    t%d:%ld,%ld,%ld,%ld   %ld\n",
279
41.4M
               rcsize - 1, (long int)left->start.x, (long int)left->start.y,
280
41.4M
               (long int)left->end.x, (long int)left->end.y, (long int)ybot);
281
41.4M
    if_debug6m('L', cldev->memory, "    t%ld,%ld,%ld,%ld   %ld   o=%d\n",
282
41.4M
               (long int)right->start.x, (long int)right->start.y,
283
41.4M
               (long int)right->end.x, (long int)right->end.y, (long int)ytop,
284
41.4M
               options);
285
41.4M
    if (options & 2) {
286
1.25M
        cmd_putw(fa->clip->p.x, &dp);
287
1.25M
        cmd_putw(fa->clip->p.y, &dp);
288
1.25M
        cmd_putw(fa->clip->q.x, &dp);
289
1.25M
        cmd_putw(fa->clip->q.y, &dp);
290
1.25M
        cmd_putw(colors_mask, &dp);
291
1.25M
        if (c0 != NULL)
292
1.25M
            dp = cmd_put_frac31_color(cldev, c0, dp);
293
1.25M
        if (c1 != NULL)
294
1.25M
            dp = cmd_put_frac31_color(cldev, c1, dp);
295
1.25M
        if (c2 != NULL)
296
717k
            dp = cmd_put_frac31_color(cldev, c2, dp);
297
1.25M
        if (c3 != NULL)
298
0
            cmd_put_frac31_color(cldev, c3, dp);
299
1.25M
    }
300
41.4M
    return 0;
301
41.4M
}
302
303
/* ---------------- Driver procedures ---------------- */
304
305
int
306
clist_fillpage(gx_device * dev, gs_gstate *pgs, gx_drawing_color *pdcolor)
307
368k
{
308
368k
    gx_device_clist * const cldev = (gx_device_clist *)dev;
309
368k
    gx_device_clist_writer * const cdev = &(cldev->writer);
310
368k
    gx_clist_state * pcls;
311
368k
    int code;
312
313
    /* flush previous contents */
314
368k
    if ((code = clist_close_writer_and_init_reader(cldev) < 0))
315
368k
        return code;;
316
368k
    if ((code = clist_finish_page(dev, true)) < 0)
317
368k
        return code;;
318
319
368k
    pcls = cdev->states; /* Use any. */
320
321
368k
    code = cmd_put_drawing_color(cdev, pcls, pdcolor, NULL, devn_not_tile_fill);
322
368k
    if (code >= 0)
323
368k
        code = cmd_write_page_rect_cmd(cdev, cmd_op_fill_rect);
324
368k
    return code;
325
368k
}
326
327
int
328
clist_fill_rectangle(gx_device * dev, int rx, int ry, int rwidth, int rheight,
329
                     gx_color_index color)
330
22.6M
{
331
22.6M
    gx_device_clist_writer * const cdev =
332
22.6M
        &((gx_device_clist *)dev)->writer;
333
22.6M
    int code;
334
22.6M
    cmd_rects_enum_t re;
335
22.6M
    gx_color_usage_bits color_usage;
336
337
22.6M
    crop_fill(cdev, rx, ry, rwidth, rheight);
338
22.6M
    if (rwidth <= 0 || rheight <= 0)
339
27.1k
        return 0;
340
22.6M
    if (cdev->permanent_error < 0)
341
0
      return (cdev->permanent_error);
342
    /* If needed, update the trans_bbox */
343
22.6M
    if (cdev->pdf14_needed) {
344
21.4M
        gs_int_rect bbox;
345
346
21.4M
        bbox.p.x = rx;
347
21.4M
        bbox.q.x = rx + rwidth - 1;
348
21.4M
        bbox.p.y = ry;
349
21.4M
        bbox.q.y = ry + rheight - 1;
350
351
21.4M
        clist_update_trans_bbox(cdev, &bbox);
352
21.4M
    }
353
22.6M
    RECT_ENUM_INIT(re, ry, rheight);
354
22.6M
    color_usage = gx_color_index2usage(dev, color);
355
22.8M
    do {
356
22.8M
        RECT_STEP_INIT(re);
357
22.8M
        re.pcls->color_usage.or |= color_usage;
358
22.8M
        code = cmd_disable_lop(cdev, re.pcls);
359
22.8M
        if (code >= 0 && color != re.pcls->colors[1]) {
360
17.9M
            code = cmd_put_color(cdev, re.pcls, &clist_select_color1,
361
17.9M
                                 color, &re.pcls->colors[1]);
362
17.9M
        }
363
22.8M
        if (code >= 0) {
364
22.8M
            code = cmd_write_rect_cmd(cdev, re.pcls, cmd_op_fill_rect, rx, re.y,
365
22.8M
                                      rwidth, re.height);
366
22.8M
        }
367
22.8M
        if (code < 0)
368
0
            return code;
369
22.8M
        re.y += re.height;
370
22.8M
    } while (re.y < re.yend);
371
22.6M
    return 0;
372
22.6M
}
373
374
/* This is used in fills from devn color types */
375
int
376
clist_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect,
377
    const gs_gstate *pgs, const gx_drawing_color *pdcolor,
378
    const gx_clip_path *pcpath)
379
11.8M
{
380
11.8M
    gx_device_clist_writer * const cdev =
381
11.8M
        &((gx_device_clist *)dev)->writer;
382
11.8M
    int code;
383
11.8M
    int rx, ry, rwidth, rheight;
384
11.8M
    cmd_rects_enum_t re;
385
11.8M
    gx_color_usage_bits color_usage = cmd_drawing_color_usage(cdev, pdcolor);
386
387
11.8M
    rx = fixed2int(rect->p.x);
388
11.8M
    ry = fixed2int(rect->p.y);
389
11.8M
    rwidth = fixed2int(rect->q.x) - rx;
390
11.8M
    rheight = fixed2int(rect->q.y) - ry;
391
392
11.8M
    crop_fill(cdev, rx, ry, rwidth, rheight);
393
11.8M
    if (rwidth <= 0 || rheight <= 0)
394
15.3k
        return 0;
395
11.8M
    if (cdev->permanent_error < 0)
396
0
      return (cdev->permanent_error);
397
    /* If needed, update the trans_bbox */
398
11.8M
    if (cdev->pdf14_needed) {
399
8.34M
        gs_int_rect bbox;
400
401
8.34M
        bbox.p.x = rx;
402
8.34M
        bbox.q.x = rx + rwidth - 1;
403
8.34M
        bbox.p.y = ry;
404
8.34M
        bbox.q.y = ry + rheight - 1;
405
406
8.34M
        clist_update_trans_bbox(cdev, &bbox);
407
8.34M
    }
408
11.8M
    RECT_ENUM_INIT(re, ry, rheight);
409
11.8M
    do {
410
11.8M
        RECT_STEP_INIT(re);
411
11.8M
        re.pcls->color_usage.or |= color_usage;
412
11.8M
        code = cmd_disable_lop(cdev, re.pcls);
413
11.8M
        code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re,
414
11.8M
                                     devn_not_tile_fill);
415
11.8M
        if (code >= 0) {
416
11.8M
            code = cmd_write_rect_hl_cmd(cdev, re.pcls, cmd_op_fill_rect_hl,
417
11.8M
                                         rx, re.y, rwidth, re.height, false);
418
11.8M
        }
419
11.8M
        if (code < 0)
420
0
            return code;
421
11.8M
        re.y += re.height;
422
11.8M
    } while (re.y < re.yend);
423
11.8M
    return 0;
424
11.8M
}
425
426
static inline int
427
clist_write_fill_trapezoid(gx_device * dev,
428
    const gs_fixed_edge *left, const gs_fixed_edge *right,
429
    fixed ybot, fixed ytop, int options,
430
    const gx_drawing_color *pdcolor, gs_logical_operation_t lop,
431
    const gs_fill_attributes *fa,
432
    const frac31 *c0, const frac31 *c1,
433
    const frac31 *c2, const frac31 *c3)
434
40.1M
{
435
40.1M
    gx_device_clist_writer * const cdev =
436
40.1M
        &((gx_device_clist *)dev)->writer;
437
40.1M
    int code;
438
40.1M
    cmd_rects_enum_t re;
439
40.1M
    int ry, rheight, rx, rxe;
440
40.1M
    bool swap_axes = (options & 1);
441
442
40.1M
    if (options & 4) {
443
561k
        if (swap_axes) {
444
0
            rx =  fixed2int(max(min(min(left->start.y, left->end.y), right->start.y), fa->clip->p.y));
445
0
            rxe =  fixed2int_ceiling(min(max(max(left->start.y, left->end.y), right->start.y), fa->clip->q.y));
446
0
            ry = fixed2int(max(min(min(left->start.x, left->end.x), right->start.x), fa->clip->p.x));
447
0
            rheight = fixed2int_ceiling(min(max(max(left->start.x, left->end.x), right->start.x), fa->clip->q.x)) - ry;
448
561k
        } else {
449
561k
            rx = fixed2int(max(min(min(left->start.x, left->end.x), right->start.x), fa->clip->p.x));
450
561k
            rxe = fixed2int_ceiling(min(max(max(left->start.x, left->end.x), right->start.x), fa->clip->q.x));
451
561k
            ry = fixed2int(max(min(min(left->start.y, left->end.y), right->start.y), fa->clip->p.y));
452
561k
            rheight = fixed2int_ceiling(min(max(max(left->start.y, left->end.y), right->start.y), fa->clip->q.y)) - ry;
453
561k
        }
454
39.5M
    } else {
455
        /* fixme: this may give a significant overestimation,
456
           so the command will be written to many bands.
457
           Would like to know a better range by X
458
           with computing intersections of sides with ybot, ytop. */
459
39.5M
        if (swap_axes) {
460
2.39M
            rx = fixed2int(ybot);
461
2.39M
            rxe = fixed2int_ceiling(ytop);
462
2.39M
            ry = fixed2int(min(left->start.x, left->end.x));
463
2.39M
            rheight = fixed2int_ceiling(max(right->start.x, right->end.x)) - ry;
464
37.1M
        } else {
465
37.1M
            rx = fixed2int(min(left->start.x, left->end.x));
466
37.1M
            rxe = fixed2int_ceiling(max(right->start.x, right->end.x));
467
37.1M
            ry = fixed2int(ybot);
468
37.1M
            rheight = fixed2int_ceiling(ytop) - ry;
469
37.1M
        }
470
39.5M
    }
471
40.1M
    crop_fill_y(cdev, ry, rheight);
472
40.1M
    if (rheight <= 0)
473
1.82M
        return 0;
474
38.2M
    if (cdev->permanent_error < 0)
475
0
        return (cdev->permanent_error);
476
    /* If needed, update the trans_bbox */
477
38.2M
    if (cdev->pdf14_needed) {
478
16
        gs_int_rect bbox;
479
480
16
        bbox.p.x = rx;
481
16
        bbox.q.x = rxe;
482
16
        bbox.p.y = ry;
483
16
        bbox.q.y = ry + rheight;
484
485
16
        clist_update_trans_bbox(cdev, &bbox);
486
16
    }
487
38.2M
    RECT_ENUM_INIT(re, ry, rheight);
488
41.4M
    do {
489
41.4M
        RECT_STEP_INIT(re);
490
41.4M
        if (pdcolor != NULL) {
491
40.1M
            code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re,
492
40.1M
                                         devn_not_tile_fill);
493
40.1M
            if (code == gs_error_unregistered)
494
0
                return code;
495
40.1M
            if (code < 0) {
496
                /* Something went wrong, use the default implementation. */
497
30
                return gx_default_fill_trapezoid(dev, left, right, ybot, ytop, swap_axes, pdcolor, lop);
498
30
            }
499
40.1M
            code = cmd_update_lop(cdev, re.pcls, lop);
500
40.1M
        } else {
501
            /* Even with pdcolor NULL, we may still have colors packed in
502
               c0, c1, c2 or c3 */
503
1.25M
            re.pcls->color_usage.or |= gx_color_usage_all(cdev);
504
1.25M
            code = 0;
505
1.25M
        }
506
41.4M
        if (code >= 0) {
507
            /* Don't want to shorten the trapezoid by the band boundary,
508
               keeping in mind a further optimization with writing same data to all bands. */
509
41.4M
            code = cmd_write_trapezoid_cmd(cdev, re.pcls, cmd_opv_fill_trapezoid, left, right,
510
41.4M
                                      ybot, ytop, options, fa, c0, c1, c2, c3);
511
41.4M
        }
512
41.4M
        if (code < 0)
513
0
            return code;
514
41.4M
        re.y += re.height;
515
41.4M
    } while (re.y < re.yend);
516
38.2M
    return 0;
517
38.2M
}
518
519
int
520
clist_fill_trapezoid(gx_device * dev,
521
    const gs_fixed_edge *left, const gs_fixed_edge *right,
522
    fixed ybot, fixed ytop, bool swap_axes,
523
    const gx_drawing_color *pdcolor, gs_logical_operation_t lop)
524
39.2M
{
525
39.2M
    return clist_write_fill_trapezoid(dev, left, right,
526
39.2M
        ybot, ytop, swap_axes, pdcolor, lop, NULL, NULL, NULL, NULL, NULL);
527
39.2M
}
528
529
int
530
clist_fill_linear_color_trapezoid(gx_device * dev, const gs_fill_attributes *fa,
531
        const gs_fixed_point *p0, const gs_fixed_point *p1,
532
        const gs_fixed_point *p2, const gs_fixed_point *p3,
533
        const frac31 *c0, const frac31 *c1,
534
        const frac31 *c2, const frac31 *c3)
535
341k
{
536
341k
    gs_fixed_edge left, right;
537
341k
    int code;
538
539
341k
    left.start = *p0;
540
341k
    left.end = *p1;
541
341k
    right.start = *p2;
542
341k
    right.end = *p3;
543
341k
    code = clist_write_fill_trapezoid(dev, &left, &right,
544
341k
        fa->ystart, fa->yend, fa->swap_axes | 2, NULL, fa->lop, fa, c0, c1, c2, c3);
545
341k
    if (code < 0)
546
0
        return code;
547
    /* NOTE : The return value 0 for the fill_linear_color_trapezoid method means
548
       that the device requests a further decomposition of the trapezoid.
549
       Currently we have no interface for checking whether the target device
550
       can handle a trapezoid without an attempt to fill it.
551
       Therefore the clist writer device must always return 1,
552
       and the clist reader must perform a further decomposition
553
       if the target device requests it.
554
     */
555
341k
    return 1;
556
341k
}
557
558
int
559
clist_fill_linear_color_triangle(gx_device * dev, const gs_fill_attributes *fa,
560
        const gs_fixed_point *p0, const gs_fixed_point *p1,
561
        const gs_fixed_point *p2,
562
        const frac31 *c0, const frac31 *c1, const frac31 *c2)
563
561k
{
564
561k
    gs_fixed_edge left, right;
565
561k
    int code;
566
567
561k
    left.start = *p0;
568
561k
    left.end = *p1;
569
561k
    right.start = *p2;
570
561k
    right.end.x = right.end.y = 0; /* unused. */
571
572
561k
    code = clist_write_fill_trapezoid(dev, &left, &right,
573
561k
        0, 0, fa->swap_axes | 2 | 4, NULL, fa->lop, fa, c0, c1, c2, NULL);
574
561k
    if (code < 0)
575
0
        return code;
576
    /* NOTE : The return value 0 for the fill_linear_color_triangle method means
577
       that the device requests a further decomposition of the trapezoid.
578
       Currently we have no interface for checking whether the target device
579
       can handle a trapezoid without an attempt to fill it.
580
       Therefore the clist writer device must always return 1,
581
       and the clist reader must perform a further decomposition
582
       if the target device requests it.
583
     */
584
561k
    return 1;
585
561k
}
586
587
extern dev_proc_open_device(pattern_clist_open_device);
588
extern dev_proc_dev_spec_op(pattern_accum_dev_spec_op);
589
590
int
591
clist_dev_spec_op(gx_device *pdev, int dev_spec_op, void *data, int size)
592
60.3M
{
593
60.3M
    gx_device_clist_common * const cdev = &((gx_device_clist *)pdev)->common;
594
595
60.3M
    if (dev_spec_op == gxdso_pattern_handles_clip_path)
596
274
        return 1;
597
60.3M
    if (dev_spec_op == gxdso_pattern_shfill_doesnt_need_path)
598
140
        return 1;
599
60.3M
    if (dev_spec_op == gxdso_copy_alpha_disabled) {
600
0
        gx_device_clist_writer * const cdev = &((gx_device_clist *)pdev)->writer;
601
0
        return (cdev->disable_mask & clist_disable_copy_alpha) != 0;
602
0
    }
603
60.3M
    if (dev_spec_op == gxdso_supports_devn
604
60.3M
     || dev_spec_op == gxdso_skip_icc_component_validation) {
605
2.98M
        cmm_dev_profile_t *dev_profile;
606
2.98M
        int code;
607
2.98M
        code = dev_proc(cdev, get_profile)((gx_device*) cdev, &dev_profile);
608
2.98M
        if (code == 0) {
609
2.98M
            return dev_profile->supports_devn;
610
2.98M
        } else {
611
0
            return 0;
612
0
        }
613
2.98M
    }
614
57.3M
    if (dev_spec_op == gxdso_restrict_bbox) {
615
0
        gx_device_clist_writer *cwdev = &((gx_device_clist *)pdev)->writer;
616
0
        gs_int_rect *ibox = (gs_int_rect *)data;
617
0
        if (ibox->p.y < cwdev->cropping_min)
618
0
            ibox->p.y = cwdev->cropping_min;
619
0
        if (ibox->q.y > cwdev->cropping_max)
620
0
            ibox->q.y = cwdev->cropping_max;
621
0
        return 0;
622
0
    }
623
57.3M
    if (dev_spec_op == gxdso_is_clist_device)
624
2.65k
        return 1;
625
57.3M
    if (dev_spec_op == gxdso_overprint_active) {
626
5.81M
        gx_device_clist_writer* cwdev = &((gx_device_clist*)pdev)->writer;
627
5.81M
        return cwdev->op_fill_active || cwdev->op_stroke_active;
628
5.81M
    }
629
    /* This is a horrible hack. Accumulator devices have their procs
630
     * overriden by clist ones in gdev_prn_open. */
631
51.5M
    if (strncmp(pdev->dname, "pdf14-accum-", 12) == 0) {
632
3.06M
        return pdf14_accum_dev_spec_op(pdev, dev_spec_op, data, size);
633
3.06M
    }
634
    /* forward to the appropriate super class */
635
48.4M
    if (cdev->orig_spec_op)
636
48.4M
        return cdev->orig_spec_op(pdev, dev_spec_op, data, size);
637
2.56k
    if (dev_proc(cdev, open_device) == pattern_clist_open_device)
638
2.56k
        return pattern_accum_dev_spec_op(pdev, dev_spec_op, data, size);
639
0
    return gx_default_dev_spec_op(pdev, dev_spec_op, data, size);
640
2.56k
}
641
642
/* Based heavily off of clist_strip_tile_rectangle */
643
int
644
clist_strip_tile_rect_devn(gx_device * dev, const gx_strip_bitmap * tile,
645
                           int rx, int ry, int rwidth, int rheight,
646
                           const gx_drawing_color *pdcolor0,
647
                           const gx_drawing_color *pdcolor1, int px, int py)
648
860
{
649
860
    gx_device_clist_writer * const cdev =
650
860
        &((gx_device_clist *)dev)->writer;
651
860
    int depth = 1;
652
860
    int code;
653
860
    cmd_rects_enum_t re;
654
860
    gx_color_usage_bits color_usage = cmd_drawing_color_usage(cdev, pdcolor0);
655
656
860
    crop_fill(cdev, rx, ry, rwidth, rheight);
657
860
    if (rwidth <= 0 || rheight <= 0)
658
0
        return 0;
659
860
    if (cdev->permanent_error < 0)
660
0
      return (cdev->permanent_error);
661
    /* If needed, update the trans_bbox */
662
860
    if (cdev->pdf14_needed) {
663
167
        gs_int_rect bbox;
664
665
167
        bbox.p.x = rx;
666
167
        bbox.q.x = rx + rwidth - 1;
667
167
        bbox.p.y = ry;
668
167
        bbox.q.y = ry + rheight - 1;
669
670
167
        clist_update_trans_bbox(cdev, &bbox);
671
167
    }
672
860
    color_usage |= cmd_drawing_color_usage(cdev, pdcolor1);
673
860
    RECT_ENUM_INIT(re, ry, rheight);
674
948
    do {
675
948
        ulong offset_temp;
676
677
948
        RECT_STEP_INIT(re);
678
948
        re.pcls->color_usage.or |= color_usage;
679
948
        code = cmd_disable_lop(cdev, re.pcls);
680
948
        if (code < 0)
681
0
            return code;
682
        /* Change the tile if needed */
683
948
        if (!cls_has_tile_id(cdev, re.pcls, tile->id, offset_temp)) {
684
11
            if (tile->id != gx_no_bitmap_id) {
685
11
                code = clist_change_tile(cdev, re.pcls, tile, depth);
686
11
                if (code < 0)
687
0
                    return code;
688
11
            } else {
689
0
                return_error(gs_error_unregistered);
690
0
            }
691
11
        }
692
948
        code = 0;
693
        /* Write out the devn colors */
694
948
        code = cmd_put_drawing_color(cdev, re.pcls, pdcolor0, &re,
695
948
                                     devn_tile0);
696
948
        code = cmd_put_drawing_color(cdev, re.pcls, pdcolor1, &re,
697
948
                                     devn_tile1);
698
        /* Set the tile phase */
699
948
        if (px != re.pcls->tile_phase.x || py != re.pcls->tile_phase.y) {
700
808
            if (code >= 0)
701
808
                code = cmd_set_tile_phase(cdev, re.pcls, px, py);
702
808
        }
703
        /* Write out the actually command to fill with the devn colors */
704
948
        if (code >= 0) {
705
948
            code = cmd_write_rect_hl_cmd(cdev, re.pcls,
706
948
                                         cmd_opv_ext_tile_rect_hl, rx, re.y,
707
948
                                         rwidth, re.height, true);
708
948
        }
709
948
        if (code < 0)
710
0
            return code;
711
948
        re.y += re.height;
712
948
    } while (re.y < re.yend);
713
860
    return 0;
714
860
}
715
716
int
717
clist_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tile,
718
                           int rx, int ry, int rwidth, int rheight,
719
               gx_color_index color0, gx_color_index color1, int px, int py)
720
588k
{
721
588k
    gx_device_clist_writer * const cdev =
722
588k
        &((gx_device_clist *)dev)->writer;
723
588k
    int depth =
724
588k
        (color1 == gx_no_color_index && color0 == gx_no_color_index ?
725
588k
         cdev->clist_color_info.depth : 1);
726
588k
    gx_color_usage_bits color_usage =
727
588k
        (color1 == gx_no_color_index && color0 == gx_no_color_index ?
728
         /* We can't know what colors will be used: assume the worst. */
729
0
         gx_color_usage_all(dev) :
730
588k
         (color0 == gx_no_color_index ? 0 : gx_color_index2usage(dev, color0)) |
731
588k
         (color1 == gx_no_color_index ? 0 : gx_color_index2usage(dev, color1)));
732
588k
    int code;
733
588k
    cmd_rects_enum_t re;
734
735
588k
    crop_fill(cdev, rx, ry, rwidth, rheight);
736
588k
    if (rwidth <= 0 || rheight <= 0)
737
0
        return 0;
738
588k
    if (cdev->permanent_error < 0)
739
0
        return (cdev->permanent_error);
740
    /* If needed, update the trans_bbox */
741
588k
    if (cdev->pdf14_needed) {
742
1.16k
        gs_int_rect bbox;
743
744
1.16k
        bbox.p.x = rx;
745
1.16k
        bbox.q.x = rx + rwidth - 1;
746
1.16k
        bbox.p.y = ry;
747
1.16k
        bbox.q.y = ry + rheight - 1;
748
749
1.16k
        clist_update_trans_bbox(cdev, &bbox);
750
1.16k
    }
751
588k
    RECT_ENUM_INIT(re, ry, rheight);
752
589k
    do {
753
589k
        ulong offset_temp;
754
755
589k
        RECT_STEP_INIT(re);
756
589k
        re.pcls->color_usage.or |= color_usage;
757
589k
        code = cmd_disable_lop(cdev, re.pcls);
758
589k
        if (code < 0)
759
0
            return code;
760
589k
        if (!cls_has_tile_id(cdev, re.pcls, tile->id, offset_temp)) {
761
285k
            if (tile->id != gx_no_bitmap_id) {
762
285k
                code = clist_change_tile(cdev, re.pcls, tile, depth);
763
285k
            } else
764
0
                code = -1; /* Force the default implementation. Should never happen. */
765
285k
            if (code < 0) {
766
                /* ok if gx_default... does retries internally: */
767
                /* it's self-sufficient */
768
0
                code = gx_default_strip_tile_rectangle(dev, tile,
769
0
                                                       rx, re.y, rwidth, re.height,
770
0
                                                       color0, color1,
771
0
                                                       px, py);
772
0
                if (code < 0)
773
0
                    return code;
774
0
                goto endr;
775
0
            }
776
285k
        }
777
589k
        code = 0;
778
589k
        if (color0 != re.pcls->tile_colors[0] || color1 != re.pcls->tile_colors[1])
779
48.2k
            code = cmd_set_tile_colors(cdev, re.pcls, color0, color1);
780
589k
        if (px != re.pcls->tile_phase.x || py != re.pcls->tile_phase.y) {
781
5.63k
            if (code >= 0)
782
5.63k
                code = cmd_set_tile_phase(cdev, re.pcls, px, py);
783
5.63k
        }
784
589k
        if (code >= 0)
785
589k
            code = cmd_write_rect_cmd(cdev, re.pcls, cmd_op_tile_rect, rx, re.y,
786
589k
                                      rwidth, re.height);
787
589k
        if (code < 0)
788
0
            return code;
789
589k
endr:;
790
589k
        re.y += re.height;
791
589k
    } while (re.y < re.yend);
792
588k
    return 0;
793
588k
}
794
795
int
796
clist_copy_mono(gx_device * dev,
797
                const byte * data, int data_x, int raster, gx_bitmap_id id,
798
                int rx, int ry, int rwidth, int rheight,
799
                gx_color_index color0, gx_color_index color1)
800
92.8k
{
801
92.8k
    gx_device_clist_writer * const cdev =
802
92.8k
        &((gx_device_clist *)dev)->writer;
803
92.8k
    int y0;
804
92.8k
    gx_bitmap_id orig_id = id;
805
92.8k
    gx_color_usage_bits color_usage =
806
92.8k
        (color0 == gx_no_color_index ? 0 : gx_color_index2usage(dev, color0)) |
807
92.8k
        (color1 == gx_no_color_index ? 0 : gx_color_index2usage(dev, color1));
808
92.8k
    cmd_rects_enum_t re;
809
810
92.8k
    fit_copy(dev, data, data_x, raster, id, rx, ry, rwidth, rheight);
811
92.7k
    y0 = ry;
812
92.7k
    if (cdev->permanent_error < 0)
813
0
      return (cdev->permanent_error);
814
    /* If needed, update the trans_bbox */
815
92.7k
    if (cdev->pdf14_needed) {
816
16.8k
        gs_int_rect bbox;
817
818
16.8k
        bbox.p.x = rx;
819
16.8k
        bbox.q.x = rx + rwidth - 1;
820
16.8k
        bbox.p.y = ry;
821
16.8k
        bbox.q.y = ry + rheight - 1;
822
823
16.8k
        clist_update_trans_bbox(cdev, &bbox);
824
16.8k
    }
825
92.7k
    RECT_ENUM_INIT(re, ry, rheight);
826
122k
    do {
827
122k
        int dx = data_x & 7;
828
122k
        int w1 = dx + rwidth;
829
122k
        const byte *row = data + (re.y - y0) * raster + (data_x >> 3);
830
122k
        int code;
831
832
122k
        RECT_STEP_INIT(re);
833
122k
        re.pcls->color_usage.or |= color_usage;
834
122k
        code = cmd_disable_lop(cdev, re.pcls);
835
122k
        if (code >= 0)
836
122k
            code = cmd_disable_clip(cdev, re.pcls);
837
122k
        if (color0 != re.pcls->colors[0] && code >= 0)
838
252
            code = cmd_set_color0(cdev, re.pcls, color0);
839
122k
        if (color1 != re.pcls->colors[1] && code >= 0)
840
3.89k
            code = cmd_set_color1(cdev, re.pcls, color1);
841
122k
        if (code < 0)
842
0
            return code;
843
        /* Don't bother to check for a possible cache hit: */
844
        /* tile_rectangle and fill_mask handle those cases. */
845
124k
copy:{
846
124k
        gx_cmd_rect rect;
847
124k
        int rsize;
848
124k
        byte op = (byte) cmd_op_copy_mono_planes;
849
124k
        byte *dp;
850
124k
        uint csize;
851
124k
        uint compress;
852
124k
        int code;
853
854
124k
        rect.x = rx, rect.y = re.y;
855
124k
        rect.width = w1, rect.height = re.height;
856
124k
        rsize = (dx ? 3 : 1) + cmd_size_rect(&rect) + cmd_sizew(0); /* planar_height 0 */
857
124k
        code = cmd_put_bits(cdev, re.pcls, row, w1, re.height, raster,
858
124k
                            rsize, (orig_id == gx_no_bitmap_id ?
859
121k
                                    1 << cmd_compress_rle :
860
124k
                                    cmd_mask_compress_any),
861
124k
                            &dp, &csize);
862
124k
        if (code < 0 && !(code == gs_error_limitcheck))
863
16
            return code;
864
124k
        compress = (uint)code;
865
124k
        if (code < 0) {
866
            /* The bitmap was too large; split up the transfer. */
867
2.69k
            if (re.height > 1) {
868
                /*
869
                 * Split the transfer by reducing the height.
870
                 * See the comment above FOR_RECTS in gxcldev.h.
871
                 */
872
2.69k
                re.height >>= 1;
873
2.69k
                goto copy;
874
2.69k
            } else {
875
                /* Split a single (very long) row. */
876
0
                int w2 = w1 >> 1;
877
878
0
                code = clist_copy_mono(dev, row, dx,
879
0
                                       raster, gx_no_bitmap_id, rx, re.y,
880
0
                                       w2, 1, color0, color1);
881
0
                if (code >= 0)
882
0
                    code = clist_copy_mono(dev, row, dx + w2,
883
0
                                           raster, gx_no_bitmap_id,
884
0
                                           rx + w2, re.y,
885
0
                                           w1 - w2, 1, color0, color1);
886
0
                if (code < 0)
887
0
                    return code;
888
0
                continue;
889
0
            }
890
2.69k
        }
891
122k
        op += compress;
892
122k
        if (dx) {
893
13.3k
            if_debug0m('L', dev->memory,
894
13.3k
                       "[L] fake end_run: really set_misc_data_x[2]\n");
895
13.3k
            *dp++ = cmd_count_op(cmd_opv_set_misc, 2, dev->memory);
896
13.3k
            *dp++ = cmd_set_misc_data_x + dx;
897
13.3k
        }
898
#ifdef DEBUG
899
        if (gs_debug_c('L')) {
900
            const char *const *sub = cmd_sub_op_names[op >> 4];
901
902
            if (sub)
903
                dmlprintf1(dev->memory, "[L] fake end_run: really %s\n", sub[op & 0xf]);
904
            else
905
                dmlprintf2(dev->memory, "[L] fake end_run: really %s %d\n", cmd_op_names[op >> 4], op & 0xf);
906
        }
907
#endif
908
122k
        *dp++ = cmd_count_op(op, csize, dev->memory);
909
        /* Store the plane_height */
910
122k
        cmd_putw(0, &dp);
911
122k
        cmd_put2w(rx, re.y, &dp);
912
122k
        cmd_put2w(w1, re.height, &dp);
913
122k
        re.pcls->rect = rect;
914
122k
        }
915
122k
    } while ((re.y += re.height) < re.yend);
916
92.7k
    return 0;
917
92.7k
}
918
919
/* The code duplication between this and clist_copy_mono needs to be removed */
920
int
921
clist_copy_planes(gx_device * dev,
922
                  const byte * data, int data_x, int raster, gx_bitmap_id id,
923
                  int rx, int ry, int rwidth, int rheight, int plane_height)
924
3.47k
{
925
3.47k
    gx_device_clist_writer * const cdev =
926
3.47k
        &((gx_device_clist *)dev)->writer;
927
3.47k
    int y0;
928
3.47k
    gx_bitmap_id orig_id = id;
929
3.47k
    cmd_rects_enum_t re;
930
3.47k
    int bpc = dev->color_info.depth / dev->color_info.num_components;
931
3.47k
    int pix_in_byte = bpc <= 8 ? 8/bpc : 1;
932
3.47k
    int byte_in_pix = bpc >= 8 ? bpc/8 : 1;
933
934
3.47k
    if (rwidth <= 0 || rheight <= 0)
935
0
        return 0;
936
937
3.47k
    fit_copy(dev, data, data_x, raster, id, rx, ry, rwidth, rheight);
938
939
3.47k
    y0 = ry;
940
3.47k
    if (cdev->permanent_error < 0)
941
0
      return (cdev->permanent_error);
942
943
#ifdef DEBUG
944
    if (plane_height == 0) {
945
        dprintf("clist_copy_planes called with plane_height == 0.\n");
946
    }
947
#endif
948
949
    /* If needed, update the trans_bbox */
950
3.47k
    if (cdev->pdf14_needed) {
951
0
        gs_int_rect bbox;
952
953
0
        bbox.p.x = rx;
954
0
        bbox.q.x = rx + rwidth - 1;
955
0
        bbox.p.y = ry;
956
0
        bbox.q.y = ry + rheight - 1;
957
958
0
        clist_update_trans_bbox(cdev, &bbox);
959
0
    }
960
961
3.47k
    RECT_ENUM_INIT(re, ry, rheight);
962
3.47k
    do {
963
3.47k
        int code;
964
3.47k
        gx_cmd_rect rect;
965
3.47k
        int rsize;
966
3.47k
        byte *dp, *dp2;
967
3.47k
        uint csize;
968
3.47k
        byte op = (byte) cmd_op_copy_mono_planes;
969
3.47k
        int dx = data_x % pix_in_byte;
970
3.47k
        int w1 = dx + rwidth;
971
3.47k
        const byte *row = data + (re.y - y0) * raster + (data_x * byte_in_pix / pix_in_byte);
972
3.47k
        int bytes_row = ((w1*bpc+7)/8 + 7) & ~7;
973
3.47k
        int maxheight = data_bits_size / bytes_row / cdev->color_info.num_components;
974
3.47k
        int plane;
975
976
3.47k
        RECT_STEP_INIT(re);
977
3.47k
        code = cmd_disable_lop(cdev, re.pcls);
978
3.47k
        if (code >= 0)
979
3.47k
            code = cmd_disable_clip(cdev, re.pcls);
980
3.47k
        if (code < 0)
981
0
            return code;
982
        /* Don't bother to check for a possible cache hit: */
983
        /* tile_rectangle and fill_mask handle those cases. */
984
985
        /* We require that in the copy_planes case all the planes fit into
986
         * the data_bits area (for the copy_planes call by the clist reader) */
987
3.47k
        if (re.height > maxheight)
988
0
            re.height = maxheight;
989
990
3.47k
        if (re.height == 0) {
991
            /* Not even a single row fits. Revert to a single row and split it in two recursively */
992
0
            int w2 = w1 >> 1;
993
994
0
            re.height = 1;
995
0
            code = clist_copy_planes(dev, row, dx, raster,
996
0
                                     gx_no_bitmap_id, rx, re.y,
997
0
                                     w2, 1, plane_height);
998
0
            if (code >= 0)
999
0
                code = clist_copy_planes(dev, row, dx + w2,
1000
0
                                         raster, gx_no_bitmap_id,
1001
0
                                         rx + w2, re.y,
1002
0
                                         w1 - w2, 1, plane_height);
1003
0
            if (code < 0)
1004
0
                return code;
1005
0
            continue;
1006
0
        }
1007
1008
        /* 0x100 fudge is arbitrary, but the BufferSpace is large w.r.t. cbuf size so it doesn't matter */
1009
3.47k
        if ((cdev->cend - cdev->cnext) < 0x100 + ((long)cdev->color_info.num_components * re.height * bytes_row))
1010
2
            cmd_write_buffer(cdev, cmd_opv_end_run); /* Insure that all planes fit in the bufferspace */
1011
1012
3.47k
        rect.x = rx, rect.y = re.y;
1013
3.47k
        rect.width = w1, rect.height = re.height;
1014
3.47k
        rsize = (dx ? 3 : 1) + cmd_size_rect(&rect) + cmd_sizew(plane_height);
1015
        /* Copy the 0th plane - this is the one the op goes in. */
1016
3.47k
        code = cmd_put_bits(cdev, re.pcls, row, w1*bpc, re.height, raster,
1017
3.47k
                            rsize, (bpc == 1 ? (orig_id == gx_no_bitmap_id ?
1018
3.47k
                                                1 << cmd_compress_rle :
1019
3.47k
                                                cmd_mask_compress_any) : 0),
1020
3.47k
                            &dp, &csize);
1021
3.47k
        if (code < 0)
1022
0
            continue;
1023
        /* Write the command header out now, in case the following
1024
         * cmd_put_bits fill the buffer up. */
1025
3.47k
        dp2 = dp;
1026
3.47k
        if (dx) {
1027
0
            if_debug0m('L', cdev->memory,
1028
0
                       "[L] fake end_run: really set_misc_data_x[2]\n");
1029
0
            *dp2++ = cmd_count_op(cmd_opv_set_misc, 2, cdev->memory);
1030
0
            *dp2++ = cmd_set_misc_data_x + dx;
1031
0
        }
1032
#ifdef DEBUG
1033
        if (gs_debug_c('L')) {
1034
            const char *const *sub = cmd_sub_op_names[(op+code) >> 4];
1035
1036
            if (sub)
1037
                dmlprintf1(cdev->memory, "[L] fake end_run: really %s\n", sub[(op+code) & 0xf]);
1038
            else
1039
                dmlprintf2(cdev->memory, "[L] fake end_run: really %s %d\n", cmd_op_names[(op+code) >> 4], (op+code) & 0xf);
1040
        }
1041
#endif
1042
3.47k
        *dp2++ = cmd_count_op(op + code, csize, cdev->memory);
1043
3.47k
        cmd_putw(plane_height, &dp2);
1044
3.47k
        cmd_put2w(rx, re.y, &dp2);
1045
3.47k
        cmd_put2w(w1, re.height, &dp2);
1046
13.9k
        for (plane = 1; plane < cdev->color_info.num_components && (code >= 0); plane++)
1047
10.4k
        {
1048
10.4k
            byte *dummy_dp;
1049
10.4k
            uint csize2;
1050
            /* Copy subsequent planes - 1 byte header used to send the
1051
             * compression type. */
1052
10.4k
            code = cmd_put_bits(cdev, re.pcls,
1053
10.4k
                                row + plane_height * raster * plane,
1054
10.4k
                                w1*bpc, re.height, raster, 1,
1055
10.4k
                                (bpc == 1 ?
1056
10.4k
                                 (orig_id == gx_no_bitmap_id ?
1057
10.4k
                                  1 << cmd_compress_rle :
1058
10.4k
                                  cmd_mask_compress_any) : 0),
1059
10.4k
                                &dummy_dp, &csize2);
1060
10.4k
            if (code >= 0)
1061
10.4k
                *dummy_dp = code;
1062
1063
10.4k
            csize += csize2;
1064
10.4k
        }
1065
3.47k
        if (code < 0 && !(code == gs_error_limitcheck))
1066
0
            return code;
1067
1068
3.47k
        re.pcls->rect = rect;
1069
3.47k
    } while ((re.y += re.height) < re.yend);
1070
3.47k
    return 0;
1071
3.47k
}
1072
1073
int
1074
clist_copy_color(gx_device * dev,
1075
                 const byte * data, int data_x, int raster, gx_bitmap_id id,
1076
                 int rx, int ry, int rwidth, int rheight)
1077
1.32M
{
1078
1.32M
    gx_device_clist_writer * const cdev =
1079
1.32M
        &((gx_device_clist *)dev)->writer;
1080
1.32M
    int depth = cdev->clist_color_info.depth; /* Could be different than target
1081
                                                 if 1.4 device */
1082
1.32M
    int y0;
1083
1.32M
    int data_x_bit;
1084
    /* We can't know what colors will be used: assume the worst. */
1085
1.32M
    gx_color_usage_bits all = gx_color_usage_all(cdev);
1086
1.32M
    cmd_rects_enum_t re;
1087
1088
1.32M
    fit_copy(dev, data, data_x, raster, id, rx, ry, rwidth, rheight);
1089
1.31M
    y0 = ry;
1090
1.31M
    data_x_bit = data_x * depth;
1091
1.31M
    if (cdev->permanent_error < 0)
1092
0
      return (cdev->permanent_error);
1093
    /* If needed, update the trans_bbox */
1094
1.31M
    if (cdev->pdf14_needed) {
1095
0
        gs_int_rect bbox;
1096
1097
0
        bbox.p.x = rx;
1098
0
        bbox.q.x = rx + rwidth - 1;
1099
0
        bbox.p.y = ry;
1100
0
        bbox.q.y = ry + rheight - 1;
1101
1102
0
        clist_update_trans_bbox(cdev, &bbox);
1103
0
    }
1104
1.31M
    RECT_ENUM_INIT(re, ry, rheight);
1105
1.31M
    do {
1106
1.31M
        int dx = (data_x_bit & 7) / depth;
1107
1.31M
        int w1 = dx + rwidth;
1108
1.31M
        const byte *row = data + (re.y - y0) * raster + (data_x_bit >> 3);
1109
1.31M
        int code;
1110
1111
1.31M
        RECT_STEP_INIT(re);
1112
1.31M
        re.pcls->color_usage.or |= all;
1113
1114
1.31M
        code = cmd_disable_lop(cdev, re.pcls);
1115
1.31M
        if (code >= 0)
1116
1.31M
            code = cmd_disable_clip(cdev, re.pcls);
1117
1.31M
        if (code < 0)
1118
0
            return code;
1119
1.31M
        if (re.pcls->color_is_alpha) {
1120
0
            byte *dp;
1121
1122
0
            code =
1123
0
                set_cmd_put_op(&dp, cdev, re.pcls, cmd_opv_set_copy_color, 1);
1124
0
            if (code < 0)
1125
0
                return code;
1126
0
            re.pcls->color_is_alpha = 0;
1127
0
        }
1128
1.31M
copy:{
1129
1.31M
            gx_cmd_rect rect;
1130
1.31M
            int rsize;
1131
1.31M
            byte op = (byte) cmd_op_copy_color_alpha;
1132
1.31M
            byte *dp;
1133
1.31M
            uint csize;
1134
1.31M
            uint compress;
1135
1136
1.31M
            rect.x = rx, rect.y = re.y;
1137
1.31M
            rect.width = w1, rect.height = re.height;
1138
1.31M
            rsize = (dx ? 3 : 1) + cmd_size_rect(&rect);
1139
1.31M
            code = cmd_put_bits(cdev, re.pcls, row, w1 * depth,
1140
1.31M
                                re.height, raster, rsize,
1141
1.31M
                                1 << cmd_compress_rle, &dp, &csize);
1142
1.31M
            if (code < 0 && !(code == gs_error_limitcheck))
1143
0
                return code;
1144
1.31M
            compress = (uint)code;
1145
1.31M
            if (code < 0) {
1146
                /* The bitmap was too large; split up the transfer. */
1147
0
                if (re.height > 1) {
1148
                    /* Split the transfer by reducing the height.
1149
                     * See the comment above FOR_RECTS in gxcldev.h.
1150
                     */
1151
0
                    re.height >>= 1;
1152
0
                    goto copy;
1153
0
                } else {
1154
                    /* Split a single (very long) row. */
1155
0
                    int w2 = w1 >> 1;
1156
1157
0
                    code = clist_copy_color(dev, row, dx,
1158
0
                                            raster, gx_no_bitmap_id,
1159
0
                                            rx, re.y, w2, 1);
1160
0
                    if (code >= 0)
1161
0
                        code = clist_copy_color(dev, row, dx + w2,
1162
0
                                                raster, gx_no_bitmap_id,
1163
0
                                                rx + w2, re.y, w1 - w2, 1);
1164
0
                    if (code < 0)
1165
0
                        return code;
1166
0
                    continue;
1167
0
                }
1168
0
            }
1169
1.31M
            op += compress;
1170
1.31M
            if (dx) {
1171
81.5k
                if_debug0m('L', dev->memory,
1172
81.5k
                           "[L] fake end_run: really set_misc_data_x[2]\n");
1173
81.5k
                *dp++ = cmd_count_op(cmd_opv_set_misc, 2, dev->memory);
1174
81.5k
                *dp++ = cmd_set_misc_data_x + dx;
1175
81.5k
            }
1176
#ifdef DEBUG
1177
            if (gs_debug_c('L')) {
1178
                const char *const *sub = cmd_sub_op_names[op >> 4];
1179
1180
                if (sub)
1181
                    dmlprintf1(dev->memory, "[L] fake end_run: really %s\n", sub[op & 0xf]);
1182
                else
1183
                    dmlprintf2(dev->memory, "[L] fake end_run: really %s %d\n", cmd_op_names[op >> 4], op & 0xf);
1184
            }
1185
#endif
1186
1.31M
            *dp++ = cmd_count_op(op, csize, dev->memory);
1187
1.31M
            cmd_put2w(rx, re.y, &dp);
1188
1.31M
            cmd_put2w(w1, re.height, &dp);
1189
1.31M
            re.pcls->rect = rect;
1190
1.31M
        }
1191
1.31M
    } while ((re.y += re.height) < re.yend);
1192
1.31M
    return 0;
1193
1.31M
}
1194
1195
/* Patterned after clist_copy_alpha and sharing a command with
1196
   cmd_op_copy_color_alpha.  This was done due to avoid difficult
1197
   to follow code in the read back logic in gxclrast.c.  Due to the
1198
   recursive nature of this call, it would be a bit painful to do much
1199
   sharing between clist_copy_alpha_hl_color and clist_copy_alpha */
1200
int
1201
clist_copy_alpha_hl_color(gx_device * dev, const byte * data, int data_x,
1202
           int raster, gx_bitmap_id id, int rx, int ry, int rwidth, int rheight,
1203
                 const gx_drawing_color *pdcolor, int depth)
1204
0
{
1205
0
    gx_device_clist_writer * const cdev =
1206
0
        &((gx_device_clist *)dev)->writer;
1207
1208
0
    int log2_depth = ilog2(depth);
1209
0
    int y0;
1210
0
    int data_x_bit;
1211
0
    cmd_rects_enum_t re;
1212
0
    gx_color_usage_bits all = gx_color_usage_all(cdev);
1213
1214
    /* If the target can't perform copy_alpha, exit now */
1215
0
    if (depth > 1 && (cdev->disable_mask & clist_disable_copy_alpha) != 0)
1216
0
        return_error(gs_error_unknownerror);
1217
1218
0
    fit_copy(dev, data, data_x, raster, id, rx, ry, rwidth, rheight);
1219
0
    y0 = ry;
1220
0
    data_x_bit = data_x << log2_depth;
1221
0
    if (cdev->permanent_error < 0)
1222
0
      return (cdev->permanent_error);
1223
    /* If needed, update the trans_bbox */
1224
0
    if (cdev->pdf14_needed) {
1225
0
        gs_int_rect bbox;
1226
1227
0
        bbox.p.x = rx;
1228
0
        bbox.q.x = rx + rwidth - 1;
1229
0
        bbox.p.y = ry;
1230
0
        bbox.q.y = ry + rheight - 1;
1231
1232
0
        clist_update_trans_bbox(cdev, &bbox);
1233
0
    }
1234
0
    RECT_ENUM_INIT(re, ry, rheight);
1235
0
    do {
1236
0
        int dx = (data_x_bit & 7) >> log2_depth;
1237
0
        int w1 = dx + rwidth;
1238
0
        const byte *row = data + (re.y - y0) * raster + (data_x_bit >> 3);
1239
0
        int code;
1240
1241
0
        RECT_STEP_INIT(re);
1242
0
        re.pcls->color_usage.or = all;
1243
0
        code = cmd_disable_lop(cdev, re.pcls);
1244
0
        if (code >= 0)
1245
0
            code = cmd_disable_clip(cdev, re.pcls);
1246
0
        if (code < 0)
1247
0
            return code;
1248
0
        if (!re.pcls->color_is_alpha) {
1249
0
            byte *dp;
1250
1251
0
            code = set_cmd_put_op(&dp, cdev, re.pcls, cmd_opv_set_copy_alpha, 1);
1252
0
            if (code < 0)
1253
0
                return code;
1254
0
            re.pcls->color_is_alpha = 1;
1255
0
        }
1256
        /* Set extended command for overload of copy_color_alpha with devn type */
1257
0
        if (!re.pcls->color_is_devn) {
1258
0
            byte *dp;
1259
1260
0
            code = set_cmd_put_extended_op(&dp, cdev, re.pcls, cmd_opv_ext_set_color_is_devn, 2);
1261
0
            dp += 2;
1262
0
            if (code < 0)
1263
0
                  return code;
1264
0
            re.pcls->color_is_alpha = 1;
1265
0
        }
1266
        /* Set the color */
1267
0
        code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re, devn_not_tile_fill);
1268
0
copy:{
1269
0
            gx_cmd_rect rect;
1270
0
            int rsize;
1271
0
            byte op = (byte) cmd_op_copy_color_alpha;
1272
0
            byte *dp;
1273
0
            uint csize;
1274
0
            uint compress;
1275
1276
0
            rect.x = rx, rect.y = re.y;
1277
0
            rect.width = w1, rect.height = re.height;
1278
0
            rsize = (dx ? 4 : 2) + cmd_size_rect(&rect);
1279
0
            code = cmd_put_bits(cdev, re.pcls, row, w1 << log2_depth,
1280
0
                                re.height, raster, rsize,
1281
0
                                1 << cmd_compress_rle, &dp, &csize);
1282
0
            if (code < 0 && !(code == gs_error_limitcheck))
1283
0
                return code;
1284
0
            compress = (uint)code;
1285
0
            if (code < 0) {
1286
                /* The bitmap was too large; split up the transfer. */
1287
0
                if (re.height > 1) {
1288
                    /* Split the transfer by reducing the height.
1289
                     * See the comment above FOR_RECTS in gxcldev.h.
1290
                     */
1291
0
                    re.height >>= 1;
1292
0
                    goto copy;
1293
0
                } else {
1294
                    /* Split a single (very long) row. */
1295
0
                    int w2 = w1 >> 1;
1296
1297
0
                    code = clist_copy_alpha_hl_color(dev, row, dx,
1298
0
                                            raster, gx_no_bitmap_id, rx, re.y,
1299
0
                                            w2, 1, pdcolor, depth);
1300
0
                    if (code >= 0)
1301
0
                            code = clist_copy_alpha_hl_color(dev, row, dx + w2,
1302
0
                                                    raster, gx_no_bitmap_id,
1303
0
                                                    rx + w2, re.y, w1 - w2, 1,
1304
0
                                                    pdcolor, depth);
1305
0
                    if (code < 0)
1306
0
                        return code;
1307
0
                    continue;
1308
0
                }
1309
0
            }
1310
0
            op += compress;
1311
0
            if (dx) {
1312
0
                if_debug0m('L', dev->memory,
1313
0
                           "[L] fake end_run: really set_misc_data_x[2]\n");
1314
0
                *dp++ = cmd_count_op(cmd_opv_set_misc, 2, dev->memory);
1315
0
                *dp++ = cmd_set_misc_data_x + dx;
1316
0
            }
1317
#ifdef DEBUG
1318
            if (gs_debug_c('L')) {
1319
                const char *const *sub = cmd_sub_op_names[op >> 4];
1320
1321
                if (sub)
1322
                    dmlprintf1(dev->memory, "[L] fake end_run: really %s\n", sub[op & 0xf]);
1323
                else
1324
                    dmlprintf2(dev->memory, "[L] fake end_run: really %s %d\n", cmd_op_names[op >> 4], op & 0xf);
1325
            }
1326
#endif
1327
0
            *dp++ = cmd_count_op(op, csize, dev->memory);
1328
0
            *dp++ = depth;
1329
0
            cmd_put2w(rx, re.y, &dp);
1330
0
            cmd_put2w(w1, re.height, &dp);
1331
0
            re.pcls->rect = rect;
1332
0
        }
1333
0
    } while ((re.y += re.height) < re.yend);
1334
0
    return 0;
1335
0
}
1336
1337
int
1338
clist_copy_alpha(gx_device * dev, const byte * data, int data_x,
1339
           int raster, gx_bitmap_id id, int rx, int ry, int rwidth, int rheight,
1340
                 gx_color_index color, int depth)
1341
0
{
1342
0
    gx_device_clist_writer * const cdev =
1343
0
        &((gx_device_clist *)dev)->writer;
1344
    /* I don't like copying the entire body of clist_copy_color */
1345
    /* just to change 2 arguments and 1 opcode, */
1346
    /* but I don't see any alternative that doesn't require */
1347
    /* another level of procedure call even in the common case. */
1348
0
    int log2_depth = ilog2(depth);
1349
0
    int y0;
1350
0
    int data_x_bit;
1351
0
    cmd_rects_enum_t re;
1352
0
    gx_color_usage_bits color_usage = gx_color_index2usage(dev, color);
1353
1354
    /* If the target can't perform copy_alpha, exit now */
1355
0
    if (depth > 1 && (cdev->disable_mask & clist_disable_copy_alpha) != 0)
1356
0
        return_error(gs_error_unknownerror);
1357
1358
0
    fit_copy(dev, data, data_x, raster, id, rx, ry, rwidth, rheight);
1359
0
    y0 = ry;
1360
0
    data_x_bit = data_x << log2_depth;
1361
0
    if (cdev->permanent_error < 0)
1362
0
      return (cdev->permanent_error);
1363
    /* If needed, update the trans_bbox */
1364
0
    if (cdev->pdf14_needed) {
1365
0
        gs_int_rect bbox;
1366
1367
0
        bbox.p.x = rx;
1368
0
        bbox.q.x = rx + rwidth - 1;
1369
0
        bbox.p.y = ry;
1370
0
        bbox.q.y = ry + rheight - 1;
1371
1372
0
        clist_update_trans_bbox(cdev, &bbox);
1373
0
    }
1374
0
    RECT_ENUM_INIT(re, ry, rheight);
1375
0
    do {
1376
0
        int dx = (data_x_bit & 7) >> log2_depth;
1377
0
        int w1 = dx + rwidth;
1378
0
        const byte *row = data + (re.y - y0) * raster + (data_x_bit >> 3);
1379
0
        int code;
1380
1381
0
        RECT_STEP_INIT(re);
1382
0
        re.pcls->color_usage.or |= color_usage;
1383
0
        code = cmd_disable_lop(cdev, re.pcls);
1384
0
        if (code >= 0)
1385
0
            code = cmd_disable_clip(cdev, re.pcls);
1386
0
        if (code < 0)
1387
0
            return code;
1388
0
        if (!re.pcls->color_is_alpha) {
1389
0
            byte *dp;
1390
1391
0
            code = set_cmd_put_op(&dp, cdev, re.pcls, cmd_opv_set_copy_alpha, 1);
1392
0
            if (code < 0)
1393
0
                return code;
1394
0
            re.pcls->color_is_alpha = 1;
1395
0
        }
1396
0
        if (re.pcls->color_is_devn) {
1397
0
            byte *dp;
1398
1399
0
            code = set_cmd_put_extended_op(&dp, cdev, re.pcls, cmd_opv_ext_unset_color_is_devn, 1);
1400
0
            if (code < 0)
1401
0
                return code;
1402
0
            dp++;
1403
0
            re.pcls->color_is_alpha = 1;
1404
0
        }
1405
0
        if (color != re.pcls->colors[1]) {
1406
0
            code = cmd_set_color1(cdev, re.pcls, color);
1407
0
            if (code < 0)
1408
0
                return code;
1409
0
        }
1410
0
copy:{
1411
0
            gx_cmd_rect rect;
1412
0
            int rsize;
1413
0
            byte op = (byte) cmd_op_copy_color_alpha;
1414
0
            byte *dp;
1415
0
            uint csize;
1416
0
            uint compress;
1417
1418
0
            rect.x = rx, rect.y = re.y;
1419
0
            rect.width = w1, rect.height = re.height;
1420
0
            rsize = (dx ? 4 : 2) + cmd_size_rect(&rect);
1421
0
            code = cmd_put_bits(cdev, re.pcls, row, w1 << log2_depth,
1422
0
                                re.height, raster, rsize,
1423
0
                                1 << cmd_compress_rle, &dp, &csize);
1424
0
            if (code < 0 && !(code == gs_error_limitcheck))
1425
0
                return code;
1426
0
            compress = (uint)code;
1427
0
            if (code < 0) {
1428
                /* The bitmap was too large; split up the transfer. */
1429
0
                if (re.height > 1) {
1430
                    /* Split the transfer by reducing the height.
1431
                     * See the comment above FOR_RECTS in gxcldev.h.
1432
                     */
1433
0
                    re.height >>= 1;
1434
0
                    goto copy;
1435
0
                } else {
1436
                    /* Split a single (very long) row. */
1437
0
                    int w2 = w1 >> 1;
1438
1439
0
                    code = clist_copy_alpha(dev, row, dx,
1440
0
                                            raster, gx_no_bitmap_id, rx, re.y,
1441
0
                                            w2, 1, color, depth);
1442
0
                    if (code >= 0)
1443
0
                        code = clist_copy_alpha(dev, row, dx + w2,
1444
0
                                                raster, gx_no_bitmap_id,
1445
0
                                                rx + w2, re.y, w1 - w2, 1,
1446
0
                                                color, depth);
1447
0
                    if (code < 0)
1448
0
                        return code;
1449
0
                    continue;
1450
0
                }
1451
0
            }
1452
0
            op += compress;
1453
0
            if (dx) {
1454
0
                if_debug0m('L', dev->memory,
1455
0
                           "[L] fake end_run: really set_misc_data_x[2]\n");
1456
0
                *dp++ = cmd_count_op(cmd_opv_set_misc, 2, dev->memory);
1457
0
                *dp++ = cmd_set_misc_data_x + dx;
1458
0
            }
1459
#ifdef DEBUG
1460
            if (gs_debug_c('L')) {
1461
                const char *const *sub = cmd_sub_op_names[op >> 4];
1462
1463
                if (sub)
1464
                    dmlprintf1(dev->memory, "[L] fake end_run: really %s\n", sub[op & 0xf]);
1465
                else
1466
                    dmlprintf2(dev->memory, "[L] fake end_run: really %s %d\n", cmd_op_names[op >> 4], op & 0xf);
1467
            }
1468
#endif
1469
0
            *dp++ = cmd_count_op(op, csize, dev->memory);
1470
0
            *dp++ = depth;
1471
0
            cmd_put2w(rx, re.y, &dp);
1472
0
            cmd_put2w(w1, re.height, &dp);
1473
0
            re.pcls->rect = rect;
1474
0
        }
1475
0
    } while ((re.y += re.height) < re.yend);
1476
0
    return 0;
1477
0
}
1478
1479
int
1480
clist_strip_copy_rop2(gx_device * dev,
1481
             const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
1482
                     const gx_color_index * scolors,
1483
           const gx_strip_bitmap * textures, const gx_color_index * tcolors,
1484
                     int rx, int ry, int rwidth, int rheight,
1485
                     int phase_x, int phase_y, gs_logical_operation_t lop,
1486
                     uint planar_height)
1487
0
{
1488
0
    gx_device_clist_writer * const cdev =
1489
0
        &((gx_device_clist *)dev)->writer;
1490
0
    gs_rop3_t rop = lop_rop(lop);
1491
0
    gx_strip_bitmap tile_with_id;
1492
0
    const gx_strip_bitmap *tiles = textures;
1493
0
    int y0;
1494
    /* Compute the set of possible colors that this operation can generate. */
1495
0
    gx_color_usage_bits all = gx_color_usage_all(cdev);
1496
0
    bool subtractive = dev->color_info.num_components >= 4; /****** HACK ******/
1497
0
    gx_color_usage_bits S =
1498
0
        (scolors ? gx_color_index2usage(dev, scolors[0] | scolors[1]) : sdata ? all : 0);
1499
0
    gx_color_usage_bits T =
1500
0
        (tcolors ? gx_color_index2usage(dev, tcolors[0] | tcolors[1]) : textures ? all : 0);
1501
0
    gs_rop3_t color_rop =
1502
0
        (subtractive ? byte_reverse_bits[rop ^ 0xff] : rop);
1503
0
    bool slow_rop;
1504
0
    cmd_rects_enum_t re;
1505
1506
0
    if (scolors != 0 && scolors[0] != scolors[1]) {
1507
0
        crop_fill(cdev, rx, ry, rwidth, rheight);
1508
0
    } else {
1509
0
        crop_copy(cdev, sdata, sourcex, sraster, id, rx, ry, rwidth, rheight);
1510
0
    }
1511
0
    if (rwidth <= 0 || rheight <= 0)
1512
0
        return 0;
1513
1514
    /* If needed, update the trans_bbox */
1515
0
    if (cdev->pdf14_needed) {
1516
0
        gs_int_rect bbox;
1517
1518
0
        bbox.p.x = rx;
1519
0
        bbox.q.x = rx + rwidth - 1;
1520
0
        bbox.p.y = ry;
1521
0
        bbox.q.y = ry + rheight - 1;
1522
1523
0
        clist_update_trans_bbox(cdev, &bbox);
1524
0
    }
1525
    /*
1526
     * On CMYK devices, RasterOps must be executed with complete pixels
1527
     * if the operation involves the destination.
1528
     * This is because the black plane interacts with the other planes
1529
     * in the conversion between RGB and CMYK.  Check for this now.
1530
     */
1531
0
    {
1532
0
        gs_rop3_t rop_used = rop;
1533
1534
0
        if (scolors && (scolors[0] == scolors[1]))
1535
0
            rop_used = (scolors[0] == gx_device_black(dev) ?
1536
0
                        rop3_know_S_0(rop_used) :
1537
0
                        scolors[0] == gx_device_white(dev) ?
1538
0
                        rop3_know_S_1(rop_used) : rop_used);
1539
0
        if (tcolors && (tcolors[0] == tcolors[1]))
1540
0
            rop_used = (tcolors[0] == gx_device_black(dev) ?
1541
0
                        rop3_know_T_0(rop_used) :
1542
0
                        tcolors[0] == gx_device_white(dev) ?
1543
0
                        rop3_know_T_1(rop_used) : rop_used);
1544
0
        slow_rop = !(rop == rop3_0 || rop == rop3_1 ||
1545
0
                     rop == rop3_S || rop == rop3_T);
1546
0
    }
1547
0
    y0 = ry;
1548
0
    if (cdev->permanent_error < 0)
1549
0
      return (cdev->permanent_error);
1550
    /* If needed, update the trans_bbox */
1551
0
    if (cdev->pdf14_needed) {
1552
0
        gs_int_rect bbox;
1553
1554
0
        bbox.p.x = rx;
1555
0
        bbox.q.x = rx + rwidth - 1;
1556
0
        bbox.p.y = ry;
1557
0
        bbox.q.y = ry + rheight - 1;
1558
1559
0
        clist_update_trans_bbox(cdev, &bbox);
1560
0
    }
1561
0
    RECT_ENUM_INIT(re, ry, rheight);
1562
0
    do {
1563
0
        const byte *row = sdata + (re.y - y0) * sraster;
1564
0
        int code;
1565
1566
0
        RECT_STEP_INIT(re);
1567
        /* rops are defined to work on rop_operands, which are typically 32
1568
         * bits (unsigned long). We need to use gx_color_usage_bits, which
1569
         * are usually 64 bits. So, the following funky bit of code; although
1570
         * this is an if rather than a #if (as sizeof cannot be evaluated at
1571
         * preprocess time), it should resolve properly at compile time. */
1572
0
        if (sizeof(rop_operand) >= sizeof(gx_color_usage_bits)) {
1573
0
            gx_color_usage_bits D = re.pcls->color_usage.or;
1574
0
            re.pcls->color_usage.or =
1575
0
                    ((rop_proc_table[color_rop])((rop_operand)D, (rop_operand)S, (rop_operand)T) & all) | D;
1576
0
        } else if (2*sizeof(rop_operand) >= sizeof(gx_color_usage_bits)) {
1577
0
            rop_operand D;
1578
0
            D = (rop_operand)re.pcls->color_usage.or;
1579
0
            re.pcls->color_usage.or |=
1580
0
                    ((rop_proc_table[color_rop])(D, (rop_operand)S, (rop_operand)T) & all);
1581
0
#define DOWN(x) ((rop_operand)(((x)>>(4*sizeof(rop_operand)))>>(4*sizeof(rop_operand))))
1582
0
#define UP(x)   ((((gx_color_usage_bits)(x))<<(4*sizeof(rop_operand)))<<(4*sizeof(rop_operand)))
1583
0
            D = DOWN(re.pcls->color_usage.or);
1584
0
            re.pcls->color_usage.or |=
1585
0
                    UP((rop_proc_table[color_rop])(D, DOWN(S), DOWN(T))) & all;
1586
0
#undef DOWN
1587
0
#undef UP
1588
0
        }
1589
0
        re.pcls->color_usage.slow_rop |= slow_rop;
1590
0
        if (rop3_uses_T(rop)) {
1591
0
            if (tcolors == 0 || tcolors[0] != tcolors[1]) {
1592
0
                ulong offset_temp;
1593
1594
0
                if (!cls_has_tile_id(cdev, re.pcls, tiles->id, offset_temp)) {
1595
                    /* Change tile.  If there is no id, generate one. */
1596
0
                    if (tiles->id == gx_no_bitmap_id) {
1597
0
                        tile_with_id = *tiles;
1598
0
                        tile_with_id.id = gs_next_ids(dev->memory, 1);
1599
0
                        tiles = &tile_with_id;
1600
0
                    }
1601
0
                    code = clist_change_bits(cdev, re.pcls, tiles,
1602
0
                                            (tcolors != 0 ? 1 :
1603
0
                                                 cdev->clist_color_info.depth));
1604
0
                    if (code < 0 && !(code == gs_error_limitcheck))
1605
0
                        return code;
1606
0
                    if (code < 0) {
1607
                        /*
1608
                         * The error is a limitcheck: we have a tile that
1609
                         * is too big to fit in the command reading buffer.
1610
                         * For now, just divide up the transfer into scan
1611
                         * lines.  (If a single scan line won't fit, punt.)
1612
                         * Eventually, we'll need a way to transfer the tile
1613
                         * in pieces.
1614
                         */
1615
0
                        uint rep_height = tiles->rep_height;
1616
0
                        gs_id ids;
1617
0
                        gx_strip_bitmap line_tile;
1618
0
                        int data_shift = 0, phase_shift = 0, raster;
1619
0
                        int new_phase = phase_x;
1620
0
                        int tile_space_phase;
1621
0
                        int iy;
1622
1623
0
                        if (rep_height == 1 ||
1624
                            /****** CAN'T HANDLE SHIFT YET ******/
1625
0
                            tiles->rep_shift != 0
1626
0
                            )
1627
0
                            return code;
1628
                        /*
1629
                         * Allocate enough fake IDs, since the inner call on
1630
                         * clist_strip_copy_rop will need them anyway.
1631
                         */
1632
0
                        ids = gs_next_ids(dev->memory, min(re.height, rep_height));
1633
0
                        line_tile = *tiles;
1634
0
                        line_tile.size.y = 1;
1635
0
                        line_tile.rep_height = 1;
1636
0
                        raster = line_tile.raster;
1637
0
                        if (line_tile.num_planes > 0)
1638
0
                            line_tile.raster *= tiles->size.y;
1639
                        /* The rasterizer assumes tile phase relatively to the rectangle origin,
1640
                           (see x_offset in gdevmr8n.c), so compute "the tile phase in the tile space"
1641
                           with same expression : */
1642
0
                        tile_space_phase = (rx + phase_x) % tiles->rep_width;
1643
0
                        if (tile_space_phase + rwidth <= tiles->rep_width) {
1644
                            /* Narrow the tile to prevent buffer overflow - bug 689588.
1645
                               Note currently we don't narrow "wrapped" tiles (because bug 689588 doesn't need) :
1646
                               when tile_space_phase < rep_width && tile_space_phase + rwidth > rep_width,
1647
                               each line to be converted into 2 ones.
1648
                            */
1649
0
                            int depth = cdev->clist_color_info.depth;
1650
1651
0
                            if (line_tile.num_planes > 0)
1652
0
                                depth /= line_tile.num_planes;
1653
#         if 0
1654
                            /* Align bitmap data : */
1655
                            data_shift = ((tile_space_phase * depth) >> (log2_align_bitmap_mod + 3)) << log2_align_bitmap_mod;
1656
#         else
1657
0
                            data_shift = tile_space_phase * depth / 8; /* No bitmap data alignment because we'll only write it to clist.  */
1658
0
#         endif
1659
0
                            phase_shift = data_shift * 8 / depth;
1660
0
                            line_tile.rep_width = rwidth + (tile_space_phase - phase_shift);
1661
                            /* Normally line_tile.raster must account trailing row alignment bytes and
1662
                               to be computed as bitmap_raster(line_tile.rep_width * depth);
1663
                               but we can't apply it here because the trailing alignment bytes may be absent
1664
                               due to data_shift. We believe it is not harmful because we just write the data to clist,
1665
                               and because the bitmap height is 1.
1666
                               The clist reader must provide the trailing bytes if the rasterizer needs them.
1667
                             */
1668
0
                            if (line_tile.num_planes <= 1)
1669
0
                                line_tile.raster = (line_tile.rep_width * depth + 7) / 8;
1670
0
                            line_tile.size.x = line_tile.rep_width;
1671
0
                            line_tile.shift = 0;
1672
0
                            new_phase = (tile_space_phase - phase_shift - rx % line_tile.rep_width);
1673
                            /* Provide a positive phase for clist reader : */
1674
0
                            new_phase = (new_phase + line_tile.rep_width) % line_tile.rep_width;
1675
0
                        }
1676
0
                        for (iy = 0; iy < re.height; ++iy) {
1677
0
                            line_tile.data = tiles->data + raster *
1678
0
                                ((re.y + iy + phase_y) % rep_height) + data_shift;
1679
0
                            line_tile.id = ids + (iy % rep_height);
1680
0
                            code = clist_strip_copy_rop2(dev,
1681
0
                                    (sdata == 0 ? 0 : row + iy * sraster),
1682
0
                                    sourcex, sraster,
1683
0
                                    gx_no_bitmap_id, scolors,
1684
0
                                    &line_tile, tcolors,
1685
0
                                    rx, re.y + iy, rwidth, 1,
1686
0
                                    new_phase, 0, lop, planar_height);
1687
0
                            if (code < 0)
1688
0
                                return code;
1689
0
                        }
1690
0
                        continue;
1691
0
                    }
1692
0
                }
1693
0
                if (((phase_x != re.pcls->tile_phase.x) && (tiles->rep_width > 1)) ||
1694
0
                    ((phase_y != re.pcls->tile_phase.y) && (tiles->rep_height > 1))) {
1695
0
                    code = cmd_set_tile_phase(cdev, re.pcls, phase_x,
1696
0
                                              phase_y);
1697
0
                    if (code < 0)
1698
0
                        return code;
1699
0
                }
1700
0
            }
1701
            /* Set the tile colors. */
1702
0
            code =
1703
0
                (tcolors != 0 ?
1704
0
                 cmd_set_tile_colors(cdev, re.pcls, tcolors[0], tcolors[1]) :
1705
0
                 cmd_set_tile_colors(cdev, re.pcls, gx_no_color_index,
1706
0
                                     gx_no_color_index));
1707
0
            if (code < 0)
1708
0
                return code;
1709
0
        }
1710
0
        code = 0;
1711
0
        if (lop != re.pcls->lop)
1712
0
            code = cmd_set_lop(cdev, re.pcls, lop);
1713
0
        if (code >= 0)
1714
0
            code = cmd_enable_lop(cdev, re.pcls);
1715
0
        if (code < 0)
1716
0
            return code;
1717
        /* Set lop_enabled to -1 so that fill_rectangle / copy_* */
1718
        /* won't attempt to set it to 0. */
1719
0
        re.pcls->lop_enabled = -1;
1720
0
        if (scolors != NULL) {
1721
0
            if (scolors[0] == scolors[1])
1722
0
                code = clist_fill_rectangle(dev, rx, re.y, rwidth, re.height,
1723
0
                                            scolors[1]);
1724
0
            else
1725
0
                code = clist_copy_mono(dev, row, sourcex, sraster, id,
1726
0
                                       rx, re.y, rwidth, re.height,
1727
0
                                       scolors[0], scolors[1]);
1728
0
        } else if (planar_height) {
1729
0
            code = clist_copy_planes(dev, row, sourcex, sraster, id,
1730
0
                                     rx, re.y, rwidth, re.height,
1731
0
                                     planar_height);
1732
0
        } else {
1733
0
            code = clist_copy_color(dev, row, sourcex, sraster, id,
1734
0
                                    rx, re.y, rwidth, re.height);
1735
0
        }
1736
0
        re.pcls->lop_enabled = 1;
1737
0
        if (code < 0)
1738
0
            return code;
1739
0
    } while ((re.y += re.height) < re.yend);
1740
0
    return 0;
1741
0
}