Coverage Report

Created: 2025-11-16 07:40

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
284M
  ((rect).x = x, (rect).y = y,\
31
284M
   (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
78.1M
{
37
78.1M
    return
38
78.1M
        cmd_sizew(prect->x) + cmd_sizew(prect->y) +
39
78.1M
        cmd_sizew(prect->width) + cmd_sizew(prect->height);
40
78.1M
}
41
static inline byte *
42
cmd_put_rect(const gx_cmd_rect * prect, byte * dp)
43
71.8M
{
44
71.8M
    cmd_putw(prect->x, &dp);
45
71.8M
    cmd_putw(prect->y, &dp);
46
71.8M
    cmd_putw(prect->width, &dp);
47
71.8M
    cmd_putw(prect->height, &dp);
48
71.8M
    return dp;
49
71.8M
}
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
67.8M
{
56
67.8M
    byte *dp;
57
67.8M
    int code;
58
67.8M
    int rcsize;
59
60
67.8M
    cmd_set_rect(pcls->rect);
61
67.8M
    if (extended_command) {
62
8.19k
        rcsize = 2 + cmd_size_rect(&pcls->rect);
63
8.19k
        code = set_cmd_put_extended_op(&dp, cldev, pcls, op, rcsize);
64
8.19k
        dp += 2;
65
67.8M
    } else {
66
67.8M
        rcsize = 1 + cmd_size_rect(&pcls->rect);
67
67.8M
        code = set_cmd_put_op(&dp, cldev, pcls, op, rcsize);
68
67.8M
        dp += 1;
69
67.8M
    }
70
67.8M
    if (code < 0)
71
0
        return code;
72
67.8M
    if_debug5m('L', cldev->memory, "[L]  rect hl r%d:%d,%d,%d,%d\n",
73
67.8M
               rcsize - 1, pcls->rect.x, pcls->rect.y,
74
67.8M
               pcls->rect.width, pcls->rect.height);
75
67.8M
    cmd_put_rect(&pcls->rect, dp);
76
67.8M
    return 0;
77
67.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
182M
{
83
182M
    int dx = x - pcls->rect.x;
84
182M
    int dy = y - pcls->rect.y;
85
182M
    int dwidth = width - pcls->rect.width;
86
182M
    int dheight = height - pcls->rect.height;
87
182M
    byte *dp;
88
182M
    int code;
89
90
182M
#define check_range_xy(rmin, rmax)\
91
212M
  ((unsigned)(dx - rmin) <= (rmax - rmin) &&\
92
212M
   (unsigned)(dy - rmin) <= (rmax - rmin))
93
182M
#define check_range_w(rmin, rmax)\
94
399M
  ((unsigned)(dwidth - rmin) <= (rmax - rmin))
95
182M
#define check_ranges(rmin, rmax)\
96
182M
  (check_range_xy(rmin, rmax) && check_range_w(rmin, rmax) &&\
97
22.2M
   (unsigned)(dheight - rmin) <= (rmax - rmin))
98
182M
    cmd_set_rect(pcls->rect);
99
182M
    if (dheight == 0 && check_range_w(cmd_min_dw_tiny, cmd_max_dw_tiny) &&
100
168M
        check_range_xy(cmd_min_dxy_tiny, cmd_max_dxy_tiny)
101
182M
        ) {
102
160M
        byte op_tiny = op + 0x20 + dwidth - cmd_min_dw_tiny;
103
104
160M
        if (dx == width - dwidth && dy == 0) {
105
110M
            code = set_cmd_put_op(&dp, cldev, pcls, op_tiny + 8, 1);
106
110M
            if (code < 0)
107
0
                return code;
108
110M
        } else {
109
49.3M
            code = set_cmd_put_op(&dp, cldev, pcls, op_tiny, 2);
110
49.3M
            if (code < 0)
111
0
                return code;
112
49.3M
            dp[1] = (dx << 4) + dy - (cmd_min_dxy_tiny * 0x11);
113
49.3M
        }
114
160M
    }
115
49.9M
#define rmin cmd_min_short
116
22.2M
#define rmax cmd_max_short
117
22.2M
    else if (check_ranges(rmin, rmax)) {
118
16.0M
        int dh = dheight - cmd_min_dxy_tiny;
119
120
16.0M
        if ((unsigned)dh <= cmd_max_dxy_tiny - cmd_min_dxy_tiny &&
121
15.9M
            dh != 0 && dy == 0
122
16.0M
            ) {
123
7.17M
            op += dh;
124
7.17M
            code = set_cmd_put_op(&dp, cldev, pcls, op + 0x10, 3);
125
7.17M
            if (code < 0)
126
0
                return code;
127
7.17M
            if_debug3m('L', cldev->memory, "    rs2:%d,%d,0,%d\n",
128
7.17M
                       dx, dwidth, dheight);
129
8.89M
        } else {
130
8.89M
            code = set_cmd_put_op(&dp, cldev, pcls, op + 0x10, 5);
131
8.89M
            if (code < 0)
132
0
                return code;
133
8.89M
            if_debug4m('L', cldev->memory, "    rs4:%d,%d,%d,%d\n",
134
8.89M
                       dx, dwidth, dy, dheight);
135
8.89M
            dp[3] = dy - rmin;
136
8.89M
            dp[4] = dheight - rmin;
137
8.89M
        }
138
16.0M
        dp[1] = dx - rmin;
139
16.0M
        dp[2] = dwidth - rmin;
140
16.0M
    }
141
6.13M
#undef rmin
142
6.13M
#undef rmax
143
6.13M
    else if (dy >= -2 && dy <= 1 && dheight >= -2 && dheight <= 1 &&
144
2.12M
             (dy + dheight) != -4
145
6.13M
        ) {
146
2.12M
        int rcsize = 1 + cmd_sizew(x) + cmd_sizew(width);
147
148
2.12M
        code = set_cmd_put_op(&dp, cldev, pcls,
149
2.12M
                              op + ((dy + 2) << 2) + dheight + 2, rcsize);
150
2.12M
        if (code < 0)
151
0
            return code;
152
2.12M
        ++dp;
153
2.12M
        cmd_put2w(x, width, &dp);
154
4.00M
    } else {
155
4.00M
        int rcsize = 1 + cmd_size_rect(&pcls->rect);
156
157
4.00M
        code = set_cmd_put_op(&dp, cldev, pcls, op, rcsize);
158
4.00M
        if (code < 0)
159
0
            return code;
160
4.00M
        if_debug5m('L', cldev->memory, "[L]  r%d:%d,%d,%d,%d\n",
161
4.00M
                   rcsize - 1, dx, dwidth, dy, dheight);
162
4.00M
        cmd_put_rect(&pcls->rect, dp + 1);
163
4.00M
    }
164
182M
    return 0;
165
182M
}
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
753k
{
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
753k
    int rcsize = 1 + 4 * cmd_sizew(0);
176
753k
    byte *dp;
177
753k
    int x = 0, y = 0, width = 0, height = 0; /* For cmd_set_rect */
178
753k
    gx_clist_state *pcls1;
179
753k
    int code;
180
181
753k
    if_debug0m('L', cldev->memory, "[L]fillpage beg\n");
182
753k
    code = set_cmd_put_all_op(&dp, cldev, op, rcsize);
183
753k
    if (code < 0)
184
0
        return code;
185
34.0M
    for (pcls1 = cldev->states; pcls1 < cldev->states + cldev->nbands; pcls1++)
186
33.3M
        cmd_set_rect(pcls1->rect);
187
753k
    ++dp;
188
753k
    cmd_putw(0, &dp);
189
753k
    cmd_putw(0, &dp);
190
753k
    cmd_putw(0, &dp);
191
753k
    cmd_putw(0, &dp);
192
753k
    if_debug0m('L', cldev->memory, "[L]fillpage end\n");
193
753k
    return 0;
194
753k
}
195
196
static inline byte *
197
cmd_put_frac31_color(gx_device_clist_writer * cldev, const frac31 *c, byte *dp)
198
80.5M
{
199
80.5M
    uchar num_components = cldev->clist_color_info.num_components;
200
80.5M
    uchar j;
201
202
377M
    for (j = 0; j < num_components; j++)
203
296M
        dp = cmd_put_frac31(c[j], dp);
204
80.5M
    return dp;
205
80.5M
}
206
207
static inline int
208
cmd_size_frac31_color(gx_device_clist_writer * cldev, const frac31 *c)
209
80.5M
{
210
80.5M
    uchar j;
211
80.5M
    int s = 0;
212
80.5M
    uchar num_components = cldev->clist_color_info.num_components;
213
214
377M
    for (j = 0; j < num_components; j++)
215
296M
        s += cmd_size_frac31(c[j]);
216
80.5M
    return s;
217
80.5M
}
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
132M
{
227
132M
    byte *dp;
228
132M
    int rcsize;
229
132M
    int code;
230
132M
    int colors_mask = 0;
231
232
132M
    rcsize = 1 + cmd_sizew(left->start.x) + cmd_sizew(left->start.y)
233
132M
               + cmd_sizew(left->end.x) + cmd_sizew(left->end.y)
234
132M
               + cmd_sizew(right->start.x) + cmd_sizew(right->start.y)
235
132M
               + cmd_sizew(right->end.x) + cmd_sizew(right->end.y)
236
132M
               + cmd_sizew(options);
237
238
132M
    if (!(options & 4))
239
107M
        rcsize += cmd_sizew(ybot) + cmd_sizew(ytop);
240
132M
    if (options & 2) {
241
27.7M
        rcsize += cmd_sizew(fa->clip->p.x) + cmd_sizew(fa->clip->p.y)
242
27.7M
                + cmd_sizew(fa->clip->q.x) + cmd_sizew(fa->clip->q.y);
243
27.7M
        if (c0 != NULL) {
244
27.7M
            colors_mask += 1;
245
27.7M
            rcsize += cmd_size_frac31_color(cldev, c0);
246
27.7M
        }
247
27.7M
        if (c1 != NULL) {
248
27.7M
            colors_mask += 2;
249
27.7M
            rcsize += cmd_size_frac31_color(cldev, c1);
250
27.7M
        }
251
27.7M
        if (c2 != NULL) {
252
25.0M
            colors_mask += 4;
253
25.0M
            rcsize += cmd_size_frac31_color(cldev, c2);
254
25.0M
        }
255
27.7M
        if (c3 != NULL) {
256
0
            colors_mask += 8;
257
0
            rcsize += cmd_size_frac31_color(cldev, c3);
258
0
        }
259
27.7M
        rcsize += cmd_sizew(colors_mask);
260
27.7M
    }
261
132M
    code = set_cmd_put_op(&dp, cldev, pcls, op, rcsize);
262
132M
    if (code < 0)
263
0
        return code;
264
132M
    dp++;
265
132M
    cmd_putw(left->start.x, &dp);
266
132M
    cmd_putw(left->start.y, &dp);
267
132M
    cmd_putw(left->end.x, &dp);
268
132M
    cmd_putw(left->end.y, &dp);
269
132M
    cmd_putw(right->start.x, &dp);
270
132M
    cmd_putw(right->start.y, &dp);
271
132M
    cmd_putw(right->end.x, &dp);
272
132M
    cmd_putw(right->end.y, &dp);
273
132M
    cmd_putw(options, &dp);
274
132M
    if (!(options & 4)) {
275
107M
        cmd_putw(ybot, &dp);
276
107M
        cmd_putw(ytop, &dp);
277
107M
    }
278
132M
    if_debug6m('L', cldev->memory, "    t%d:%ld,%ld,%ld,%ld   %ld\n",
279
132M
               rcsize - 1, (long int)left->start.x, (long int)left->start.y,
280
132M
               (long int)left->end.x, (long int)left->end.y, (long int)ybot);
281
132M
    if_debug6m('L', cldev->memory, "    t%ld,%ld,%ld,%ld   %ld   o=%d\n",
282
132M
               (long int)right->start.x, (long int)right->start.y,
283
132M
               (long int)right->end.x, (long int)right->end.y, (long int)ytop,
284
132M
               options);
285
132M
    if (options & 2) {
286
27.7M
        cmd_putw(fa->clip->p.x, &dp);
287
27.7M
        cmd_putw(fa->clip->p.y, &dp);
288
27.7M
        cmd_putw(fa->clip->q.x, &dp);
289
27.7M
        cmd_putw(fa->clip->q.y, &dp);
290
27.7M
        cmd_putw(colors_mask, &dp);
291
27.7M
        if (c0 != NULL)
292
27.7M
            dp = cmd_put_frac31_color(cldev, c0, dp);
293
27.7M
        if (c1 != NULL)
294
27.7M
            dp = cmd_put_frac31_color(cldev, c1, dp);
295
27.7M
        if (c2 != NULL)
296
25.0M
            dp = cmd_put_frac31_color(cldev, c2, dp);
297
27.7M
        if (c3 != NULL)
298
0
            cmd_put_frac31_color(cldev, c3, dp);
299
27.7M
    }
300
132M
    return 0;
301
132M
}
302
303
/* ---------------- Driver procedures ---------------- */
304
305
int
306
clist_fillpage(gx_device * dev, gs_gstate *pgs, gx_drawing_color *pdcolor)
307
753k
{
308
753k
    gx_device_clist * const cldev = (gx_device_clist *)dev;
309
753k
    gx_device_clist_writer * const cdev = &(cldev->writer);
310
753k
    gx_clist_state * pcls;
311
753k
    int code;
312
313
    /* flush previous contents */
314
753k
    if ((code = clist_close_writer_and_init_reader(cldev) < 0))
315
753k
        return code;;
316
753k
    if ((code = clist_finish_page(dev, true)) < 0)
317
753k
        return code;;
318
319
753k
    pcls = cdev->states; /* Use any. */
320
321
753k
    code = cmd_put_drawing_color(cdev, pcls, pdcolor, NULL, devn_not_tile_fill);
322
753k
    if (code >= 0)
323
753k
        code = cmd_write_page_rect_cmd(cdev, cmd_op_fill_rect);
324
753k
    return code;
325
753k
}
326
327
int
328
clist_fill_rectangle(gx_device * dev, int rx, int ry, int rwidth, int rheight,
329
                     gx_color_index color)
330
177M
{
331
177M
    gx_device_clist_writer * const cdev =
332
177M
        &((gx_device_clist *)dev)->writer;
333
177M
    int code;
334
177M
    cmd_rects_enum_t re;
335
177M
    gx_color_usage_bits color_usage;
336
337
177M
    crop_fill(cdev, rx, ry, rwidth, rheight);
338
177M
    if (rwidth <= 0 || rheight <= 0)
339
5.90M
        return 0;
340
171M
    if (cdev->permanent_error < 0)
341
0
      return (cdev->permanent_error);
342
    /* If needed, update the trans_bbox */
343
171M
    if (cdev->pdf14_needed) {
344
162M
        gs_int_rect bbox;
345
346
162M
        bbox.p.x = rx;
347
162M
        bbox.q.x = rx + rwidth - 1;
348
162M
        bbox.p.y = ry;
349
162M
        bbox.q.y = ry + rheight - 1;
350
351
162M
        clist_update_trans_bbox(cdev, &bbox);
352
162M
    }
353
171M
    RECT_ENUM_INIT(re, ry, rheight);
354
171M
    color_usage = gx_color_index2usage(dev, color);
355
173M
    do {
356
173M
        RECT_STEP_INIT(re);
357
173M
        re.pcls->color_usage.or |= color_usage;
358
173M
        code = cmd_disable_lop(cdev, re.pcls);
359
173M
        if (code >= 0 && color != re.pcls->colors[1]) {
360
125M
            code = cmd_put_color(cdev, re.pcls, &clist_select_color1,
361
125M
                                 color, &re.pcls->colors[1]);
362
125M
        }
363
173M
        if (code >= 0) {
364
173M
            code = cmd_write_rect_cmd(cdev, re.pcls, cmd_op_fill_rect, rx, re.y,
365
173M
                                      rwidth, re.height);
366
173M
        }
367
173M
        if (code < 0)
368
0
            return code;
369
173M
        re.y += re.height;
370
173M
    } while (re.y < re.yend);
371
171M
    return 0;
372
171M
}
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
68.0M
{
380
68.0M
    gx_device_clist_writer * const cdev =
381
68.0M
        &((gx_device_clist *)dev)->writer;
382
68.0M
    int code;
383
68.0M
    int rx, ry, rwidth, rheight;
384
68.0M
    cmd_rects_enum_t re;
385
68.0M
    gx_color_usage_bits color_usage = cmd_drawing_color_usage(cdev, pdcolor);
386
387
68.0M
    rx = fixed2int(rect->p.x);
388
68.0M
    ry = fixed2int(rect->p.y);
389
68.0M
    rwidth = fixed2int(rect->q.x) - rx;
390
68.0M
    rheight = fixed2int(rect->q.y) - ry;
391
392
68.0M
    crop_fill(cdev, rx, ry, rwidth, rheight);
393
68.0M
    if (rwidth <= 0 || rheight <= 0)
394
376k
        return 0;
395
67.6M
    if (cdev->permanent_error < 0)
396
0
      return (cdev->permanent_error);
397
    /* If needed, update the trans_bbox */
398
67.6M
    if (cdev->pdf14_needed) {
399
43.0M
        gs_int_rect bbox;
400
401
43.0M
        bbox.p.x = rx;
402
43.0M
        bbox.q.x = rx + rwidth - 1;
403
43.0M
        bbox.p.y = ry;
404
43.0M
        bbox.q.y = ry + rheight - 1;
405
406
43.0M
        clist_update_trans_bbox(cdev, &bbox);
407
43.0M
    }
408
67.6M
    RECT_ENUM_INIT(re, ry, rheight);
409
67.8M
    do {
410
67.8M
        RECT_STEP_INIT(re);
411
67.8M
        re.pcls->color_usage.or |= color_usage;
412
67.8M
        code = cmd_disable_lop(cdev, re.pcls);
413
67.8M
        code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re,
414
67.8M
                                     devn_not_tile_fill);
415
67.8M
        if (code >= 0) {
416
67.8M
            code = cmd_write_rect_hl_cmd(cdev, re.pcls, cmd_op_fill_rect_hl,
417
67.8M
                                         rx, re.y, rwidth, re.height, false);
418
67.8M
        }
419
67.8M
        if (code < 0)
420
0
            return code;
421
67.8M
        re.y += re.height;
422
67.8M
    } while (re.y < re.yend);
423
67.6M
    return 0;
424
67.6M
}
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
117M
{
435
117M
    gx_device_clist_writer * const cdev =
436
117M
        &((gx_device_clist *)dev)->writer;
437
117M
    int code;
438
117M
    cmd_rects_enum_t re;
439
117M
    int ry, rheight, rx, rxe;
440
117M
    bool swap_axes = (options & 1);
441
442
117M
    if (options & 4) {
443
10.9M
        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
10.9M
        } else {
449
10.9M
            rx = fixed2int(max(min(min(left->start.x, left->end.x), right->start.x), fa->clip->p.x));
450
10.9M
            rxe = fixed2int_ceiling(min(max(max(left->start.x, left->end.x), right->start.x), fa->clip->q.x));
451
10.9M
            ry = fixed2int(max(min(min(left->start.y, left->end.y), right->start.y), fa->clip->p.y));
452
10.9M
            rheight = fixed2int_ceiling(min(max(max(left->start.y, left->end.y), right->start.y), fa->clip->q.y)) - ry;
453
10.9M
        }
454
106M
    } 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
106M
        if (swap_axes) {
460
7.87M
            rx = fixed2int(ybot);
461
7.87M
            rxe = fixed2int_ceiling(ytop);
462
7.87M
            ry = fixed2int(min(left->start.x, left->end.x));
463
7.87M
            rheight = fixed2int_ceiling(max(right->start.x, right->end.x)) - ry;
464
98.9M
        } else {
465
98.9M
            rx = fixed2int(min(left->start.x, left->end.x));
466
98.9M
            rxe = fixed2int_ceiling(max(right->start.x, right->end.x));
467
98.9M
            ry = fixed2int(ybot);
468
98.9M
            rheight = fixed2int_ceiling(ytop) - ry;
469
98.9M
        }
470
106M
    }
471
117M
    crop_fill_y(cdev, ry, rheight);
472
117M
    if (rheight <= 0)
473
6.15M
        return 0;
474
111M
    if (cdev->permanent_error < 0)
475
0
        return (cdev->permanent_error);
476
    /* If needed, update the trans_bbox */
477
111M
    if (cdev->pdf14_needed) {
478
65
        gs_int_rect bbox;
479
480
65
        bbox.p.x = rx;
481
65
        bbox.q.x = rxe;
482
65
        bbox.p.y = ry;
483
65
        bbox.q.y = ry + rheight;
484
485
65
        clist_update_trans_bbox(cdev, &bbox);
486
65
    }
487
111M
    RECT_ENUM_INIT(re, ry, rheight);
488
132M
    do {
489
132M
        RECT_STEP_INIT(re);
490
132M
        if (pdcolor != NULL) {
491
105M
            code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re,
492
105M
                                         devn_not_tile_fill);
493
105M
            if (code == gs_error_unregistered)
494
0
                return code;
495
105M
            if (code < 0) {
496
                /* Something went wrong, use the default implementation. */
497
181
                return gx_default_fill_trapezoid(dev, left, right, ybot, ytop, swap_axes, pdcolor, lop);
498
181
            }
499
105M
            code = cmd_update_lop(cdev, re.pcls, lop);
500
105M
        } else {
501
            /* Even with pdcolor NULL, we may still have colors packed in
502
               c0, c1, c2 or c3 */
503
27.7M
            re.pcls->color_usage.or |= gx_color_usage_all(cdev);
504
27.7M
            code = 0;
505
27.7M
        }
506
132M
        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
132M
            code = cmd_write_trapezoid_cmd(cdev, re.pcls, cmd_opv_fill_trapezoid, left, right,
510
132M
                                      ybot, ytop, options, fa, c0, c1, c2, c3);
511
132M
        }
512
132M
        if (code < 0)
513
0
            return code;
514
132M
        re.y += re.height;
515
132M
    } while (re.y < re.yend);
516
111M
    return 0;
517
111M
}
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
104M
{
525
104M
    return clist_write_fill_trapezoid(dev, left, right,
526
104M
        ybot, ytop, swap_axes, pdcolor, lop, NULL, NULL, NULL, NULL, NULL);
527
104M
}
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
1.88M
{
536
1.88M
    gs_fixed_edge left, right;
537
1.88M
    int code;
538
539
1.88M
    left.start = *p0;
540
1.88M
    left.end = *p1;
541
1.88M
    right.start = *p2;
542
1.88M
    right.end = *p3;
543
1.88M
    code = clist_write_fill_trapezoid(dev, &left, &right,
544
1.88M
        fa->ystart, fa->yend, fa->swap_axes | 2, NULL, fa->lop, fa, c0, c1, c2, c3);
545
1.88M
    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
1.88M
    return 1;
556
1.88M
}
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
10.9M
{
564
10.9M
    gs_fixed_edge left, right;
565
10.9M
    int code;
566
567
10.9M
    left.start = *p0;
568
10.9M
    left.end = *p1;
569
10.9M
    right.start = *p2;
570
10.9M
    right.end.x = right.end.y = 0; /* unused. */
571
572
10.9M
    code = clist_write_fill_trapezoid(dev, &left, &right,
573
10.9M
        0, 0, fa->swap_axes | 2 | 4, NULL, fa->lop, fa, c0, c1, c2, NULL);
574
10.9M
    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
10.9M
    return 1;
585
10.9M
}
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
928M
{
593
928M
    gx_device_clist_common * const cdev = &((gx_device_clist *)pdev)->common;
594
595
928M
    if (dev_spec_op == gxdso_pattern_handles_clip_path)
596
2.62k
        return 1;
597
928M
    if (dev_spec_op == gxdso_pattern_shfill_doesnt_need_path)
598
1.74k
        return 1;
599
928M
    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
928M
    if (dev_spec_op == gxdso_supports_devn
604
674M
     || dev_spec_op == gxdso_skip_icc_component_validation) {
605
674M
        cmm_dev_profile_t *dev_profile;
606
674M
        int code;
607
674M
        code = dev_proc(cdev, get_profile)((gx_device*) cdev, &dev_profile);
608
674M
        if (code == 0) {
609
674M
            return dev_profile->supports_devn;
610
674M
        } else {
611
0
            return 0;
612
0
        }
613
674M
    }
614
254M
    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
254M
    if (dev_spec_op == gxdso_is_clist_device)
624
16.4k
        return 1;
625
254M
    if (dev_spec_op == gxdso_overprint_active) {
626
28.6M
        gx_device_clist_writer* cwdev = &((gx_device_clist*)pdev)->writer;
627
28.6M
        return cwdev->op_fill_active || cwdev->op_stroke_active;
628
28.6M
    }
629
    /* This is a horrible hack. Accumulator devices have their procs
630
     * overriden by clist ones in gdev_prn_open. */
631
225M
    if (strncmp(pdev->dname, "pdf14-accum-", 12) == 0) {
632
25.3M
        return pdf14_accum_dev_spec_op(pdev, dev_spec_op, data, size);
633
25.3M
    }
634
    /* forward to the appropriate super class */
635
199M
    if (cdev->orig_spec_op)
636
199M
        return cdev->orig_spec_op(pdev, dev_spec_op, data, size);
637
5.40k
    if (dev_proc(cdev, open_device) == pattern_clist_open_device)
638
5.40k
        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
5.40k
}
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
7.71k
{
649
7.71k
    gx_device_clist_writer * const cdev =
650
7.71k
        &((gx_device_clist *)dev)->writer;
651
7.71k
    int depth = 1;
652
7.71k
    int code;
653
7.71k
    cmd_rects_enum_t re;
654
7.71k
    gx_color_usage_bits color_usage = cmd_drawing_color_usage(cdev, pdcolor0);
655
656
7.71k
    crop_fill(cdev, rx, ry, rwidth, rheight);
657
7.71k
    if (rwidth <= 0 || rheight <= 0)
658
0
        return 0;
659
7.71k
    if (cdev->permanent_error < 0)
660
0
      return (cdev->permanent_error);
661
    /* If needed, update the trans_bbox */
662
7.71k
    if (cdev->pdf14_needed) {
663
1.01k
        gs_int_rect bbox;
664
665
1.01k
        bbox.p.x = rx;
666
1.01k
        bbox.q.x = rx + rwidth - 1;
667
1.01k
        bbox.p.y = ry;
668
1.01k
        bbox.q.y = ry + rheight - 1;
669
670
1.01k
        clist_update_trans_bbox(cdev, &bbox);
671
1.01k
    }
672
7.71k
    color_usage |= cmd_drawing_color_usage(cdev, pdcolor1);
673
7.71k
    RECT_ENUM_INIT(re, ry, rheight);
674
8.19k
    do {
675
8.19k
        ulong offset_temp;
676
677
8.19k
        RECT_STEP_INIT(re);
678
8.19k
        re.pcls->color_usage.or |= color_usage;
679
8.19k
        code = cmd_disable_lop(cdev, re.pcls);
680
8.19k
        if (code < 0)
681
0
            return code;
682
        /* Change the tile if needed */
683
8.19k
        if (!cls_has_tile_id(cdev, re.pcls, tile->id, offset_temp)) {
684
58
            if (tile->id != gx_no_bitmap_id) {
685
58
                code = clist_change_tile(cdev, re.pcls, tile, depth);
686
58
                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
58
            } else {
700
0
                return_error(gs_error_unregistered);
701
0
            }
702
58
        }
703
8.19k
        code = 0;
704
        /* Write out the devn colors */
705
8.19k
        code = cmd_put_drawing_color(cdev, re.pcls, pdcolor0, &re,
706
8.19k
                                     devn_tile0);
707
8.19k
        code = cmd_put_drawing_color(cdev, re.pcls, pdcolor1, &re,
708
8.19k
                                     devn_tile1);
709
        /* Set the tile phase */
710
8.19k
        if (px != re.pcls->tile_phase.x || py != re.pcls->tile_phase.y) {
711
6.97k
            if (code >= 0)
712
6.97k
                code = cmd_set_tile_phase(cdev, re.pcls, px, py);
713
6.97k
        }
714
        /* Write out the actually command to fill with the devn colors */
715
8.19k
        if (code >= 0) {
716
8.19k
            code = cmd_write_rect_hl_cmd(cdev, re.pcls,
717
8.19k
                                         cmd_opv_ext_tile_rect_hl, rx, re.y,
718
8.19k
                                         rwidth, re.height, true);
719
8.19k
        }
720
8.19k
        if (code < 0)
721
0
            return code;
722
8.19k
loop:
723
8.19k
        re.y += re.height;
724
8.19k
    } while (re.y < re.yend);
725
7.71k
    return 0;
726
7.71k
}
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.92M
{
733
2.92M
    gx_device_clist_writer * const cdev =
734
2.92M
        &((gx_device_clist *)dev)->writer;
735
2.92M
    int depth =
736
2.92M
        (color1 == gx_no_color_index && color0 == gx_no_color_index ?
737
2.92M
         cdev->clist_color_info.depth : 1);
738
2.92M
    gx_color_usage_bits color_usage =
739
2.92M
        (color1 == gx_no_color_index && color0 == gx_no_color_index ?
740
         /* We can't know what colors will be used: assume the worst. */
741
166
         gx_color_usage_all(dev) :
742
2.92M
         (color0 == gx_no_color_index ? 0 : gx_color_index2usage(dev, color0)) |
743
2.92M
         (color1 == gx_no_color_index ? 0 : gx_color_index2usage(dev, color1)));
744
2.92M
    int code;
745
2.92M
    cmd_rects_enum_t re;
746
747
2.92M
    crop_fill(cdev, rx, ry, rwidth, rheight);
748
2.92M
    if (rwidth <= 0 || rheight <= 0)
749
0
        return 0;
750
2.92M
    if (cdev->permanent_error < 0)
751
0
        return (cdev->permanent_error);
752
    /* If needed, update the trans_bbox */
753
2.92M
    if (cdev->pdf14_needed) {
754
4.49k
        gs_int_rect bbox;
755
756
4.49k
        bbox.p.x = rx;
757
4.49k
        bbox.q.x = rx + rwidth - 1;
758
4.49k
        bbox.p.y = ry;
759
4.49k
        bbox.q.y = ry + rheight - 1;
760
761
4.49k
        clist_update_trans_bbox(cdev, &bbox);
762
4.49k
    }
763
2.92M
    RECT_ENUM_INIT(re, ry, rheight);
764
2.93M
    do {
765
2.93M
        ulong offset_temp;
766
767
2.93M
        RECT_STEP_INIT(re);
768
2.93M
        re.pcls->color_usage.or |= color_usage;
769
2.93M
        code = cmd_disable_lop(cdev, re.pcls);
770
2.93M
        if (code < 0)
771
0
            return code;
772
2.93M
        if (!cls_has_tile_id(cdev, re.pcls, tile->id, offset_temp)) {
773
1.20M
            if (tile->id != gx_no_bitmap_id) {
774
1.20M
                code = clist_change_tile(cdev, re.pcls, tile, depth);
775
1.20M
            } else
776
0
                code = -1; /* Force the default implementation. Should never happen. */
777
1.20M
            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
1.20M
        }
789
2.93M
        code = 0;
790
2.93M
        if (color0 != re.pcls->tile_colors[0] || color1 != re.pcls->tile_colors[1])
791
202k
            code = cmd_set_tile_colors(cdev, re.pcls, color0, color1);
792
2.93M
        if (px != re.pcls->tile_phase.x || py != re.pcls->tile_phase.y) {
793
27.7k
            if (code >= 0)
794
27.7k
                code = cmd_set_tile_phase(cdev, re.pcls, px, py);
795
27.7k
        }
796
2.93M
        if (code >= 0)
797
2.93M
            code = cmd_write_rect_cmd(cdev, re.pcls, cmd_op_tile_rect, rx, re.y,
798
2.93M
                                      rwidth, re.height);
799
2.93M
        if (code < 0)
800
0
            return code;
801
2.93M
endr:;
802
2.93M
        re.y += re.height;
803
2.93M
    } while (re.y < re.yend);
804
2.92M
    return 0;
805
2.92M
}
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
1.25M
{
813
1.25M
    gx_device_clist_writer * const cdev =
814
1.25M
        &((gx_device_clist *)dev)->writer;
815
1.25M
    int y0;
816
1.25M
    gx_bitmap_id orig_id = id;
817
1.25M
    gx_color_usage_bits color_usage =
818
1.25M
        (color0 == gx_no_color_index ? 0 : gx_color_index2usage(dev, color0)) |
819
1.25M
        (color1 == gx_no_color_index ? 0 : gx_color_index2usage(dev, color1));
820
1.25M
    cmd_rects_enum_t re;
821
822
1.25M
    fit_copy(dev, data, data_x, raster, id, rx, ry, rwidth, rheight);
823
1.25M
    y0 = ry;
824
1.25M
    if (cdev->permanent_error < 0)
825
0
      return (cdev->permanent_error);
826
    /* If needed, update the trans_bbox */
827
1.25M
    if (cdev->pdf14_needed) {
828
22.8k
        gs_int_rect bbox;
829
830
22.8k
        bbox.p.x = rx;
831
22.8k
        bbox.q.x = rx + rwidth - 1;
832
22.8k
        bbox.p.y = ry;
833
22.8k
        bbox.q.y = ry + rheight - 1;
834
835
22.8k
        clist_update_trans_bbox(cdev, &bbox);
836
22.8k
    }
837
1.25M
    RECT_ENUM_INIT(re, ry, rheight);
838
1.29M
    do {
839
1.29M
        int dx = data_x & 7;
840
1.29M
        int w1 = dx + rwidth;
841
1.29M
        const byte *row = data + (re.y - y0) * raster + (data_x >> 3);
842
1.29M
        int code;
843
844
1.29M
        RECT_STEP_INIT(re);
845
1.29M
        re.pcls->color_usage.or |= color_usage;
846
1.29M
        code = cmd_disable_lop(cdev, re.pcls);
847
1.29M
        if (code >= 0)
848
1.29M
            code = cmd_disable_clip(cdev, re.pcls);
849
1.29M
        if (color0 != re.pcls->colors[0] && code >= 0)
850
4.05k
            code = cmd_set_color0(cdev, re.pcls, color0);
851
1.29M
        if (color1 != re.pcls->colors[1] && code >= 0)
852
92.3k
            code = cmd_set_color1(cdev, re.pcls, color1);
853
1.29M
        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
1.30M
copy:{
858
1.30M
        gx_cmd_rect rect;
859
1.30M
        int rsize;
860
1.30M
        byte op = (byte) cmd_op_copy_mono_planes;
861
1.30M
        byte *dp;
862
1.30M
        uint csize;
863
1.30M
        uint compress;
864
1.30M
        int code;
865
866
1.30M
        rect.x = rx, rect.y = re.y;
867
1.30M
        rect.width = w1, rect.height = re.height;
868
1.30M
        rsize = (dx ? 3 : 1) + cmd_size_rect(&rect) + cmd_sizew(0); /* planar_height 0 */
869
1.30M
        code = cmd_put_bits(cdev, re.pcls, row, w1, re.height, raster,
870
1.30M
                            rsize, (orig_id == gx_no_bitmap_id ?
871
1.30M
                                    1 << cmd_compress_rle :
872
1.30M
                                    cmd_mask_compress_any),
873
1.30M
                            &dp, &csize);
874
1.30M
        if (code < 0 && !(code == gs_error_limitcheck))
875
0
            return code;
876
1.30M
        compress = (uint)code;
877
1.30M
        if (code < 0) {
878
            /* The bitmap was too large; split up the transfer. */
879
8.70k
            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
8.70k
                re.height >>= 1;
885
8.70k
                goto copy;
886
8.70k
            } 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
8.70k
        }
903
1.29M
        op += compress;
904
1.29M
        if (dx) {
905
166k
            if_debug0m('L', dev->memory,
906
166k
                       "[L] fake end_run: really set_misc_data_x[2]\n");
907
166k
            *dp++ = cmd_count_op(cmd_opv_set_misc, 2, dev->memory);
908
166k
            *dp++ = cmd_set_misc_data_x + dx;
909
166k
        }
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
1.29M
        *dp++ = cmd_count_op(op, csize, dev->memory);
921
        /* Store the plane_height */
922
1.29M
        cmd_putw(0, &dp);
923
1.29M
        cmd_put2w(rx, re.y, &dp);
924
1.29M
        cmd_put2w(w1, re.height, &dp);
925
1.29M
        re.pcls->rect = rect;
926
1.29M
        }
927
1.29M
    } while ((re.y += re.height) < re.yend);
928
1.25M
    return 0;
929
1.25M
}
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
16.7k
{
937
16.7k
    gx_device_clist_writer * const cdev =
938
16.7k
        &((gx_device_clist *)dev)->writer;
939
16.7k
    int y0;
940
16.7k
    gx_bitmap_id orig_id = id;
941
16.7k
    cmd_rects_enum_t re;
942
16.7k
    int bpc = dev->color_info.depth / dev->color_info.num_components;
943
16.7k
    int pix_in_byte = bpc <= 8 ? 8/bpc : 1;
944
16.7k
    int byte_in_pix = bpc >= 8 ? bpc/8 : 1;
945
946
16.7k
    if (rwidth <= 0 || rheight <= 0)
947
0
        return 0;
948
949
16.7k
    fit_copy(dev, data, data_x, raster, id, rx, ry, rwidth, rheight);
950
951
16.7k
    y0 = ry;
952
16.7k
    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
16.7k
    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
16.7k
    RECT_ENUM_INIT(re, ry, rheight);
974
16.7k
    do {
975
16.7k
        int code;
976
16.7k
        gx_cmd_rect rect;
977
16.7k
        int rsize;
978
16.7k
        byte *dp, *dp2;
979
16.7k
        uint csize;
980
16.7k
        byte op = (byte) cmd_op_copy_mono_planes;
981
16.7k
        int dx = data_x % pix_in_byte;
982
16.7k
        int w1 = dx + rwidth;
983
16.7k
        const byte *row = data + (re.y - y0) * raster + (data_x * byte_in_pix / pix_in_byte);
984
16.7k
        int bytes_row = ((w1*bpc+7)/8 + 7) & ~7;
985
16.7k
        int maxheight = data_bits_size / bytes_row / cdev->color_info.num_components;
986
16.7k
        int plane;
987
988
16.7k
        RECT_STEP_INIT(re);
989
16.7k
        code = cmd_disable_lop(cdev, re.pcls);
990
16.7k
        if (code >= 0)
991
16.7k
            code = cmd_disable_clip(cdev, re.pcls);
992
16.7k
        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
16.7k
        if (re.height > maxheight)
1000
0
            re.height = maxheight;
1001
1002
16.7k
        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
16.7k
        if ((cdev->cend - cdev->cnext) < 0x100 + ((long)cdev->color_info.num_components * re.height * bytes_row))
1022
3
            cmd_write_buffer(cdev, cmd_opv_end_run); /* Insure that all planes fit in the bufferspace */
1023
1024
16.7k
        rect.x = rx, rect.y = re.y;
1025
16.7k
        rect.width = w1, rect.height = re.height;
1026
16.7k
        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
16.7k
        code = cmd_put_bits(cdev, re.pcls, row, w1*bpc, re.height, raster,
1029
16.7k
                            rsize, (bpc == 1 ? (orig_id == gx_no_bitmap_id ?
1030
11.9k
                                                1 << cmd_compress_rle :
1031
11.9k
                                                cmd_mask_compress_any) : 0),
1032
16.7k
                            &dp, &csize);
1033
16.7k
        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
16.7k
        dp2 = dp;
1038
16.7k
        if (dx) {
1039
3.64k
            if_debug0m('L', cdev->memory,
1040
3.64k
                       "[L] fake end_run: really set_misc_data_x[2]\n");
1041
3.64k
            *dp2++ = cmd_count_op(cmd_opv_set_misc, 2, cdev->memory);
1042
3.64k
            *dp2++ = cmd_set_misc_data_x + dx;
1043
3.64k
        }
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
16.7k
        *dp2++ = cmd_count_op(op + code, csize, cdev->memory);
1055
16.7k
        cmd_putw(plane_height, &dp2);
1056
16.7k
        cmd_put2w(rx, re.y, &dp2);
1057
16.7k
        cmd_put2w(w1, re.height, &dp2);
1058
66.9k
        for (plane = 1; plane < cdev->color_info.num_components && (code >= 0); plane++)
1059
50.2k
        {
1060
50.2k
            byte *dummy_dp;
1061
50.2k
            uint csize2;
1062
            /* Copy subsequent planes - 1 byte header used to send the
1063
             * compression type. */
1064
50.2k
            code = cmd_put_bits(cdev, re.pcls,
1065
50.2k
                                row + plane_height * raster * plane,
1066
50.2k
                                w1*bpc, re.height, raster, 1,
1067
50.2k
                                (bpc == 1 ?
1068
35.7k
                                 (orig_id == gx_no_bitmap_id ?
1069
35.7k
                                  1 << cmd_compress_rle :
1070
35.7k
                                  cmd_mask_compress_any) : 0),
1071
50.2k
                                &dummy_dp, &csize2);
1072
50.2k
            if (code >= 0)
1073
50.2k
                *dummy_dp = code;
1074
1075
50.2k
            csize += csize2;
1076
50.2k
        }
1077
16.7k
        if (code < 0 && !(code == gs_error_limitcheck))
1078
0
            return code;
1079
1080
16.7k
        re.pcls->rect = rect;
1081
16.7k
    } while ((re.y += re.height) < re.yend);
1082
16.7k
    return 0;
1083
16.7k
}
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
5.05M
{
1090
5.05M
    gx_device_clist_writer * const cdev =
1091
5.05M
        &((gx_device_clist *)dev)->writer;
1092
5.05M
    int depth = cdev->clist_color_info.depth; /* Could be different than target
1093
                                                 if 1.4 device */
1094
5.05M
    int y0;
1095
5.05M
    int data_x_bit;
1096
    /* We can't know what colors will be used: assume the worst. */
1097
5.05M
    gx_color_usage_bits all = gx_color_usage_all(cdev);
1098
5.05M
    cmd_rects_enum_t re;
1099
1100
5.05M
    fit_copy(dev, data, data_x, raster, id, rx, ry, rwidth, rheight);
1101
5.02M
    y0 = ry;
1102
5.02M
    data_x_bit = data_x * depth;
1103
5.02M
    if (cdev->permanent_error < 0)
1104
0
      return (cdev->permanent_error);
1105
    /* If needed, update the trans_bbox */
1106
5.02M
    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
5.02M
    RECT_ENUM_INIT(re, ry, rheight);
1117
5.03M
    do {
1118
5.03M
        int dx = (data_x_bit & 7) / depth;
1119
5.03M
        int w1 = dx + rwidth;
1120
5.03M
        const byte *row = data + (re.y - y0) * raster + (data_x_bit >> 3);
1121
5.03M
        int code;
1122
1123
5.03M
        RECT_STEP_INIT(re);
1124
5.03M
        re.pcls->color_usage.or |= all;
1125
1126
5.03M
        code = cmd_disable_lop(cdev, re.pcls);
1127
5.03M
        if (code >= 0)
1128
5.03M
            code = cmd_disable_clip(cdev, re.pcls);
1129
5.03M
        if (code < 0)
1130
0
            return code;
1131
5.03M
        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
5.03M
copy:{
1141
5.03M
            gx_cmd_rect rect;
1142
5.03M
            int rsize;
1143
5.03M
            byte op = (byte) cmd_op_copy_color_alpha;
1144
5.03M
            byte *dp;
1145
5.03M
            uint csize;
1146
5.03M
            uint compress;
1147
1148
5.03M
            rect.x = rx, rect.y = re.y;
1149
5.03M
            rect.width = w1, rect.height = re.height;
1150
5.03M
            rsize = (dx ? 3 : 1) + cmd_size_rect(&rect);
1151
5.03M
            code = cmd_put_bits(cdev, re.pcls, row, w1 * depth,
1152
5.03M
                                re.height, raster, rsize,
1153
5.03M
                                1 << cmd_compress_rle, &dp, &csize);
1154
5.03M
            if (code < 0 && !(code == gs_error_limitcheck))
1155
0
                return code;
1156
5.03M
            compress = (uint)code;
1157
5.03M
            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
5.03M
            op += compress;
1182
5.03M
            if (dx) {
1183
425k
                if_debug0m('L', dev->memory,
1184
425k
                           "[L] fake end_run: really set_misc_data_x[2]\n");
1185
425k
                *dp++ = cmd_count_op(cmd_opv_set_misc, 2, dev->memory);
1186
425k
                *dp++ = cmd_set_misc_data_x + dx;
1187
425k
            }
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
5.03M
            *dp++ = cmd_count_op(op, csize, dev->memory);
1199
5.03M
            cmd_put2w(rx, re.y, &dp);
1200
5.03M
            cmd_put2w(w1, re.height, &dp);
1201
5.03M
            re.pcls->rect = rect;
1202
5.03M
        }
1203
5.03M
    } while ((re.y += re.height) < re.yend);
1204
5.02M
    return 0;
1205
5.02M
}
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
}