Coverage Report

Created: 2026-08-08 08:00

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