Coverage Report

Created: 2025-11-16 07:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/base/gdevdbit.c
Line
Count
Source
1
/* Copyright (C) 2001-2025 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
/* Default device bitmap copying implementation */
17
#include "gx.h"
18
#include "gpcheck.h"
19
#include "gserrors.h"
20
#include "gsbittab.h"
21
#include "gsrect.h"
22
#include "gsropt.h"
23
#include "gxdcolor.h"
24
#include "gxdevice.h"
25
#include "gxdevmem.h"
26
#include "gdevmem.h"
27
#include "gxgetbit.h"
28
#undef mdev
29
#include "gxcpath.h"
30
31
/* Implement copy_mono by filling lots of small rectangles. */
32
/* This is very inefficient, but it works as a default. */
33
int
34
gx_default_copy_mono(gx_device * dev, const byte * data,
35
            int dx, int raster, gx_bitmap_id id, int x, int y, int w, int h,
36
                     gx_color_index zero, gx_color_index one)
37
3.86M
{
38
3.86M
    bool invert;
39
3.86M
    gx_color_index color;
40
3.86M
    gx_device_color devc;
41
42
3.86M
    if (!data)
43
0
        return gs_throw_code(gs_error_unknownerror);
44
3.86M
    fit_copy(dev, data, dx, raster, id, x, y, w, h);
45
2.63M
    if (!data)
46
0
        return gs_throw_code(gs_error_unknownerror);
47
2.63M
    if (one != gx_no_color_index) {
48
2.59M
        invert = false;
49
2.59M
        color = one;
50
2.59M
        if (zero != gx_no_color_index) {
51
55.9k
            int code = (*dev_proc(dev, fill_rectangle))
52
55.9k
            (dev, x, y, w, h, zero);
53
54
55.9k
            if (code < 0)
55
0
                return code;
56
55.9k
        }
57
2.59M
    } else {
58
39.6k
        invert = true;
59
39.6k
        color = zero;
60
39.6k
    }
61
2.63M
    if (!data)
62
0
        return gs_throw_code(gs_error_unknownerror);
63
2.63M
    set_nonclient_dev_color(&devc, color);
64
2.63M
    if (!data)
65
0
        return gs_throw_code(gs_error_unknownerror);
66
2.63M
    return gx_dc_default_fill_masked
67
2.63M
        (&devc, data, dx, raster, id, x, y, w, h, dev, rop3_T, invert);
68
2.63M
}
69
70
/* Implement copy_color by filling lots of small rectangles. */
71
/* This is very inefficient, but it works as a default. */
72
int
73
gx_default_copy_color(gx_device * dev, const byte * data,
74
                      int dx, int raster, gx_bitmap_id id,
75
                      int x, int y, int w, int h)
76
2.29M
{
77
2.29M
    int depth = dev->color_info.depth;
78
2.29M
    byte mask;
79
80
2.29M
    dev_proc_fill_rectangle((*fill));
81
2.29M
    const byte *row;
82
2.29M
    int iy;
83
84
2.29M
    if (depth == 1)
85
793k
        return (*dev_proc(dev, copy_mono)) (dev, data, dx, raster, id,
86
793k
                                            x, y, w, h,
87
793k
                                    (gx_color_index) 0, (gx_color_index) 1);
88
2.29M
    fit_copy(dev, data, dx, raster, id, x, y, w, h);
89
1.49M
    fill = dev_proc(dev, fill_rectangle);
90
1.49M
    mask = (byte) ((1 << depth) - 1);
91
3.00M
    for (row = data, iy = 0; iy < h; row += raster, ++iy) {
92
1.50M
        int ix;
93
1.50M
        gx_color_index c0 = gx_no_color_index;
94
1.50M
        const byte *ptr = row + ((dx * depth) >> 3);
95
1.50M
        int i0;
96
97
42.6M
        for (i0 = ix = 0; ix < w; ++ix) {
98
41.1M
            gx_color_index color;
99
100
41.1M
            if (depth >= 8) {
101
40.3M
                color = *ptr++;
102
40.3M
                switch (depth) {
103
0
                    case 64:
104
0
                        color = (color << 8) + *ptr++;
105
0
                    case 56:
106
0
                        color = (color << 8) + *ptr++;
107
0
                    case 48:
108
0
                        color = (color << 8) + *ptr++;
109
0
                    case 40:
110
0
                        color = (color << 8) + *ptr++;
111
0
                    case 32:
112
0
                        color = (color << 8) + *ptr++;
113
30.3M
                    case 24:
114
30.3M
                        color = (color << 8) + *ptr++;
115
30.3M
                    case 16:
116
30.3M
                        color = (color << 8) + *ptr++;
117
40.3M
                }
118
40.3M
            } else {
119
808k
                uint dbit = (-(ix + dx + 1) * depth) & 7;
120
121
808k
                color = (*ptr >> dbit) & mask;
122
808k
                if (dbit == 0)
123
387k
                    ptr++;
124
808k
            }
125
41.1M
            if (color != c0) {
126
2.88M
                if (ix > i0) {
127
1.37M
                    int code = (*fill)
128
1.37M
                    (dev, i0 + x, iy + y, ix - i0, 1, c0);
129
130
1.37M
                    if (code < 0)
131
0
                        return code;
132
1.37M
                }
133
2.88M
                c0 = color;
134
2.88M
                i0 = ix;
135
2.88M
            }
136
41.1M
        }
137
1.50M
        if (ix > i0) {
138
1.50M
            int code = (*fill) (dev, i0 + x, iy + y, ix - i0, 1, c0);
139
140
1.50M
            if (code < 0)
141
0
                return code;
142
1.50M
        }
143
1.50M
    }
144
1.49M
    return 0;
145
1.49M
}
146
147
int
148
gx_no_copy_alpha(gx_device * dev, const byte * data, int data_x,
149
           int raster, gx_bitmap_id id, int x, int y, int width, int height,
150
                 gx_color_index color, int depth)
151
0
{
152
0
    return_error(gs_error_unknownerror);
153
0
}
154
155
/* Currently we really should only be here if the target device is planar
156
   AND it supports devn colors AND is 8 or 16 bit.  For example tiffsep
157
   and psdcmyk may make use of this if AA is enabled.  It is basically
158
   designed for devices that need more than 64 bits for color support
159
160
   So that I can follow things and  make it readable for future generations,
161
   I am not using the macro nightmare that default_copy_alpha uses. */
162
int
163
gx_default_copy_alpha_hl_color(gx_device * dev, const byte * data, int data_x,
164
           int raster, gx_bitmap_id id, int x, int y, int width, int height,
165
                      const gx_drawing_color *pdcolor, int depth)
166
0
{
167
0
    const byte *row_alpha;
168
0
    gs_memory_t *mem = dev->memory;
169
0
    int bpp = dev->color_info.depth;
170
0
    uchar ncomps = dev->color_info.num_components;
171
0
    uint64_t out_raster, product = 0;
172
0
    int code = 0;
173
0
    gx_color_value src_cv[GS_CLIENT_COLOR_MAX_COMPONENTS];
174
0
    gx_color_value curr_cv[GS_CLIENT_COLOR_MAX_COMPONENTS];
175
0
    gx_color_value blend_cv[GS_CLIENT_COLOR_MAX_COMPONENTS];
176
0
    int ry;
177
0
    uchar k, j;
178
0
    gs_get_bits_params_t gb_params;
179
0
    byte *src_planes[GS_CLIENT_COLOR_MAX_COMPONENTS];
180
0
    gs_int_rect gb_rect;
181
0
    int byte_depth;
182
0
    int shift, word_width;
183
0
    gx_color_value *composite;
184
0
    byte *gb_buff;
185
0
    int x_curr, w_curr, gb_buff_start;
186
187
0
    byte_depth = bpp / ncomps;
188
0
    shift = 16 - byte_depth;
189
0
    word_width = byte_depth >> 3;
190
191
0
    fit_copy(dev, data, data_x, raster, id, x, y, width, height);
192
0
    row_alpha = data;
193
0
    out_raster = bitmap_raster(width * (size_t)byte_depth);
194
0
    if (check_64bit_multiply(out_raster, ncomps, (int64_t *) &product) != 0)
195
0
        return gs_note_error(gs_error_undefinedresult);
196
0
    gb_buff = gs_alloc_bytes(mem, product, "copy_alpha_hl_color(gb_buff)");
197
0
    if (gb_buff == 0) {
198
0
        code = gs_note_error(gs_error_VMerror);
199
0
        return code;
200
0
    }
201
0
    for (k = 0; k < ncomps; k++) {
202
0
        src_cv[k] = pdcolor->colors.devn.values[k];
203
0
    }
204
    /* Initialize the get_bits parameters. Here we just get a plane at a  time. */
205
0
    gb_params.options =  GB_COLORS_NATIVE
206
0
                       | GB_ALPHA_NONE
207
0
                       | GB_DEPTH_ALL
208
0
                       | GB_PACKING_PLANAR
209
0
                       | GB_RETURN_COPY
210
0
                       | GB_ALIGN_STANDARD
211
0
                       | GB_OFFSET_0
212
0
                       | GB_RASTER_STANDARD
213
0
                       | GB_SELECT_PLANES;
214
0
    gb_rect.p.x = x;
215
0
    gb_rect.q.x = x + width;
216
0
    for (ry = y; ry < y + height; row_alpha += raster, ++ry) {
217
0
        int sx, rx;
218
219
0
        gb_rect.p.y = ry;
220
0
        gb_rect.q.y = ry+1;
221
0
        for (k = 0; k < ncomps; k++) {
222
            /* First set the params to zero for all planes except the one we want */
223
            /* I am not sure why get_bits_rectangle for the planar device can
224
               not hand back the data in a proper planar form.  To get the
225
               individual planes seems that I need to jump through some hoops
226
               here */
227
0
            for (j = 0; j < ncomps; j++)
228
0
                gb_params.data[j] = 0;
229
0
            gb_params.data[k] = gb_buff + k * out_raster;
230
0
            code = dev_proc(dev, get_bits_rectangle) (dev, &gb_rect,
231
0
                                                      &gb_params);
232
0
            src_planes[k] = gb_params.data[k];
233
0
            if (code < 0) {
234
0
                gs_free_object(mem, gb_buff, "copy_alpha_hl_color");
235
0
                return code;
236
0
            }
237
0
        }
238
        /* At this point we have to carry around some additional variables
239
           so that we can handle any buffer flushes due to alpha == 0 values.
240
           See below why this is needed */
241
0
        x_curr = x;
242
0
        w_curr = 0;
243
0
        gb_buff_start = 0;
244
0
        for (sx = data_x, rx = x; sx < data_x + width; ++sx, ++rx) {
245
0
            int alpha2, alpha;
246
247
0
            w_curr += 1;
248
0
            switch (depth)
249
0
            {
250
0
            case 2:
251
0
                alpha = ((row_alpha[sx >> 2] >> ((3 - (sx & 3)) << 1)) & 3) * 85;
252
0
                break;
253
0
            case 4:
254
0
                alpha2 = row_alpha[sx >> 1];
255
0
                alpha = (sx & 1 ? alpha2 & 0xf : alpha2 >> 4) * 17;
256
0
                break;
257
0
            case 8:
258
0
                alpha = row_alpha[sx];
259
0
                break;
260
0
            default:
261
0
                return_error(gs_error_rangecheck);
262
0
            }
263
264
0
            if (alpha == 0) {
265
                /* With alpha 0 we want to avoid writing out this value.
266
                 * While it is true that writting it out leaves the color
267
                 * unchanged,  any device that's watching what pixels are
268
                 * written (such as the pattern tile devices) may have problems.
269
                 * As in gx_default_copy_alpha the right thing to do is to write
270
                 * out what we have so far and then continue to collect when we
271
                 * get back to non zero alpha.  */
272
0
                code = dev_proc(dev, copy_planes)(dev, &(gb_buff[gb_buff_start]),
273
0
                                                  0, out_raster, gs_no_bitmap_id,
274
0
                                                  x_curr, ry, w_curr-1, 1, 1);
275
0
                if (code < 0) {
276
0
                    gs_free_object(mem, gb_buff, "copy_alpha_hl_color");
277
0
                    return code;
278
0
                }
279
                /* reset ourselves */
280
0
                gb_buff_start = gb_buff_start + w_curr * word_width;
281
0
                w_curr = 0;
282
0
                x_curr = rx + 1;
283
0
            } else {
284
0
                if (alpha == 255) {
285
                    /* Just use the new color. */
286
0
                    composite = &(src_cv[0]);
287
0
                } else {
288
                    /* We need to do the weighting by the alpha value */
289
0
                    alpha += (alpha>>7); /* Expand from 0..255->0..256 */
290
                    /* First get the old color */
291
0
                    for (k = 0; k < ncomps; k++) {
292
                        /* We only have 8 and 16 bit depth to worry about.
293
                           However, this stuff should really be done with
294
                           the device encode/decode procedure. */
295
0
                        byte *ptr = ((src_planes[k]) + (sx - data_x) * word_width);
296
0
                        curr_cv[k] = 0;
297
0
                        switch (word_width) {
298
0
                            case 2:
299
0
                                curr_cv[k] += (*ptr++ << 8);
300
0
                                curr_cv[k] += *ptr;
301
0
                                break;
302
0
                            case 1:
303
0
                                curr_cv[k] += *ptr;
304
0
                                curr_cv[k] += curr_cv[k] << 8;
305
0
                        }
306
                        /* Now compute the new color which is a blend of
307
                           the old and the new */
308
0
                        blend_cv[k] =  ((curr_cv[k]<<8) +
309
0
                                        (((long) src_cv[k] - (long) curr_cv[k]) * alpha))>>8;
310
0
                        composite = &(blend_cv[0]);
311
0
                    }
312
0
                }
313
                /* Update our plane data buffers.  Just reuse the current one */
314
0
                for (k = 0; k < ncomps; k++) {
315
0
                    byte *ptr = ((src_planes[k]) + (sx - data_x) * word_width);
316
0
                    switch (word_width) {
317
0
                        case 2:
318
0
                            *ptr++ = composite[k] >> 8;
319
0
                        case 1:
320
0
                            *ptr++ = composite[k] >> shift;
321
0
                    }
322
0
                }
323
0
            } /* else on alpha != 0 */
324
0
        } /* loop on x */
325
        /* Flush what ever we have left.  We may only have a partial due to
326
           the presence of alpha = 0 values */
327
0
        code = dev_proc(dev, copy_planes)(dev, &(gb_buff[gb_buff_start]),
328
0
                                          0, out_raster, gs_no_bitmap_id,
329
0
                                          x_curr, ry, w_curr, 1, 1);
330
0
    } /* loop on y */
331
0
    gs_free_object(mem, gb_buff, "copy_alpha_hl_color");
332
0
    return code;
333
0
}
334
335
int
336
gx_default_copy_alpha(gx_device * dev, const byte * data, int data_x,
337
           int raster, gx_bitmap_id id, int x, int y, int width, int height,
338
                      gx_color_index color, int depth)
339
0
{       /* This might be called with depth = 1.... */
340
0
    if (depth == 1)
341
0
        return (*dev_proc(dev, copy_mono)) (dev, data, data_x, raster, id,
342
0
                                            x, y, width, height,
343
0
                                            gx_no_color_index, color);
344
    /*
345
     * Simulate alpha by weighted averaging of RGB values.
346
     * This is very slow, but functionally correct.
347
     */
348
0
    {
349
0
        const byte *row;
350
0
        gs_memory_t *mem = dev->memory;
351
0
        int bpp = dev->color_info.depth;
352
0
        uchar ncomps = dev->color_info.num_components;
353
0
        uint in_size = gx_device_raster_chunky(dev, false);
354
0
        byte *lin;
355
0
        uint out_size;
356
0
        byte *lout;
357
0
        int code = 0;
358
0
        gx_color_value color_cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
359
0
        int ry, lx;
360
0
        gs_int_rect rect;
361
362
0
        fit_copy(dev, data, data_x, raster, id, x, y, width, height);
363
0
        row = data;
364
0
        out_size = bitmap_raster(width * bpp);
365
0
        lin = gs_alloc_bytes(mem, in_size, "copy_alpha(lin)");
366
0
        lout = gs_alloc_bytes(mem, out_size, "copy_alpha(lout)");
367
0
        if (lin == 0 || lout == 0) {
368
0
            code = gs_note_error(gs_error_VMerror);
369
0
            goto out;
370
0
        }
371
0
        (*dev_proc(dev, decode_color)) (dev, color, color_cv);
372
0
        rect.p.x = 0;
373
0
        rect.q.x = dev->width;
374
0
        for (ry = y; ry < y + height; row += raster, ++ry) {
375
0
            byte *line;
376
0
            int sx, rx;
377
378
0
            byte *l_dptr = lout;
379
0
            int l_dbit = 0;
380
0
            byte l_dbyte = ((l_dbit) ? (byte)(*(l_dptr) & (0xff00 >> (l_dbit))) : 0);
381
0
            int l_xprev = x;
382
0
            gs_get_bits_params_t params;
383
384
0
            params.options = (GB_ALIGN_STANDARD |
385
0
                              (GB_RETURN_COPY | GB_RETURN_POINTER) |
386
0
                              GB_OFFSET_0 |
387
0
                              GB_RASTER_STANDARD | GB_PACKING_CHUNKY |
388
0
                              GB_COLORS_NATIVE | GB_ALPHA_NONE);
389
0
            params.x_offset = 0;
390
0
            params.raster = bitmap_raster(dev->width * (size_t)dev->color_info.depth);
391
0
            params.data[0] = lin;
392
0
            rect.p.y = ry;
393
0
            rect.q.y = ry+1;
394
0
            code = (*dev_proc(dev, get_bits_rectangle))(dev, &rect,
395
0
                                                        &params);
396
0
            if (code < 0)
397
0
                break;
398
0
            line = params.data[0];
399
0
            lx = x;
400
0
            for (sx = data_x, rx = x; sx < data_x + width; ++sx, ++rx) {
401
0
                gx_color_index previous = gx_no_color_index;
402
0
                gx_color_index composite;
403
0
                int alpha2, alpha;
404
405
0
                switch(depth)
406
0
                {
407
0
                case 2:
408
                    /* map 0 - 3 to 0 - 15 */
409
0
                    alpha = ((row[sx >> 2] >> ((3 - (sx & 3)) << 1)) & 3) * 85;
410
0
                    break;
411
0
                case 4:
412
0
                    alpha2 = row[sx >> 1],
413
0
                        alpha = (sx & 1 ? alpha2 & 0xf : alpha2 >> 4) * 17;
414
0
                    break;
415
0
                case 8:
416
0
                    alpha = row[sx];
417
0
                    break;
418
0
                default:
419
0
                    return_error(gs_error_rangecheck);
420
0
                }
421
0
              blend:
422
0
                if (alpha == 0) {
423
                    /* Previously the code used to just write out the previous
424
                     * colour when the alpha was 0, but that's wrong. It leaves
425
                     * the underlying colour unchanged, but has the effect of
426
                     * making this pixel appear solid in any device that's
427
                     * watching what pixels are written (such as the pattern
428
                     * tile devices). The right thing to do is to write out
429
                     * the buffered accumulator, and skip over any pixels that
430
                     * are completely clear. */
431
0
                    if (rx > l_xprev ) {
432
0
                        sample_store_flush(l_dptr, l_dbit, l_dbyte);
433
0
                        code = (*dev_proc(dev, copy_color))
434
0
                          (dev, lout, l_xprev - (lx), out_size,
435
0
                           gx_no_bitmap_id, l_xprev, ry, (rx) - l_xprev, 1);
436
0
                        if ( code < 0 )
437
0
                          return code;
438
0
                    }
439
0
                    l_dptr = lout;
440
0
                    l_dbit = 0;
441
0
                    l_dbyte = (l_dbit ? (byte)(*l_dptr & (0xff00 >> l_dbit)) : 0);
442
0
                    l_xprev = rx+1;
443
0
                    lx = rx+1;
444
0
                } else {
445
0
                    if (alpha == 255) { /* Just write the new color. */
446
0
                        composite = color;
447
0
                    } else {
448
0
                        gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
449
0
                        uchar i;
450
0
                        int alpha2 = alpha + (alpha>>7);
451
452
0
                        if (previous == gx_no_color_index) { /* Extract the old color. */
453
0
                            if (bpp < 8) {
454
0
                                const uint bit = rx * bpp;
455
0
                                const byte *src = line + (bit >> 3);
456
457
0
                                previous =
458
0
                                    (*src >> (8 - ((bit & 7) + bpp))) &
459
0
                                    ((1 << bpp) - 1);
460
0
                            } else {
461
0
                                const byte *src = line + (rx * (bpp >> 3));
462
463
0
                                previous = 0;
464
0
                                switch (bpp >> 3) {
465
0
                                    case 8:
466
0
                                        previous += (gx_color_index) * src++
467
0
                                            << SAMPLE_BOUND_SHIFT(previous, 56);
468
0
                                    case 7:
469
0
                                        previous += (gx_color_index) * src++
470
0
                                            << SAMPLE_BOUND_SHIFT(previous, 48);
471
0
                                    case 6:
472
0
                                        previous += (gx_color_index) * src++
473
0
                                            << SAMPLE_BOUND_SHIFT(previous, 40);
474
0
                                    case 5:
475
0
                                        previous += (gx_color_index) * src++
476
0
                                            << SAMPLE_BOUND_SHIFT(previous, 32);
477
0
                                    case 4:
478
0
                                        previous += (gx_color_index) * src++ << 24;
479
0
                                    case 3:
480
0
                                        previous += (gx_color_index) * src++ << 16;
481
0
                                    case 2:
482
0
                                        previous += (gx_color_index) * src++ << 8;
483
0
                                    case 1:
484
0
                                        previous += *src++;
485
0
                                }
486
0
                            }
487
0
                        }
488
0
                        (*dev_proc(dev, decode_color)) (dev, previous, cv);
489
#if ARCH_INTS_ARE_SHORT
490
#  define b_int long
491
#else
492
0
#  define b_int int
493
0
#endif
494
0
#define make_shade(old, clr, alpha) \
495
0
  (((((b_int)(old))<<8) + (((b_int)(clr) - (b_int)(old)) * (alpha)))>>8)
496
0
                        for (i=0; i<ncomps; i++)
497
0
                            cv[i] = make_shade(cv[i], color_cv[i], alpha2);
498
0
#undef b_int
499
0
#undef make_shade
500
0
                        composite =
501
0
                            (*dev_proc(dev, encode_color)) (dev, cv);
502
0
                        if (composite == gx_no_color_index) { /* The device can't represent this color. */
503
                            /* Move the alpha value towards 0 or 1. */
504
0
                            if (alpha == 127) /* move 1/2 towards 1 */
505
0
                                ++alpha;
506
0
                            alpha = (alpha & 128) | (alpha >> 1);
507
0
                            goto blend;
508
0
                        }
509
0
                    }
510
0
                    if (sizeof(composite) > 4) {
511
0
                        if (sample_store_next64(composite, &l_dptr, &l_dbit, bpp, &l_dbyte) < 0)
512
0
                            return_error(gs_error_rangecheck);
513
0
                    }
514
0
                    else {
515
0
                        if (sample_store_next32(composite, &l_dptr, &l_dbit, bpp, &l_dbyte) < 0)
516
0
                            return_error(gs_error_rangecheck);
517
0
                    }
518
0
                }
519
0
            }
520
0
            if ( rx > l_xprev ) {
521
0
                sample_store_flush(l_dptr, l_dbit, l_dbyte);
522
0
                code = (*dev_proc(dev, copy_color))
523
0
                  (dev, lout, l_xprev - lx, out_size,
524
0
                   gx_no_bitmap_id, l_xprev, ry, rx - l_xprev, 1);
525
0
                if (code < 0)
526
0
                    return code;
527
0
            }
528
0
        }
529
0
      out:gs_free_object(mem, lout, "copy_alpha(lout)");
530
0
        gs_free_object(mem, lin, "copy_alpha(lin)");
531
0
        return code;
532
0
    }
533
0
}
534
535
int
536
gx_default_fill_mask(gx_device * orig_dev,
537
                     const byte * data, int dx, int raster, gx_bitmap_id id,
538
                     int x, int y, int w, int h,
539
                     const gx_drawing_color * pdcolor, int depth,
540
                     gs_logical_operation_t lop, const gx_clip_path * pcpath)
541
20.8M
{
542
20.8M
    gx_device *dev = orig_dev;
543
20.8M
    gx_device_clip cdev;
544
20.8M
    int code = 0;
545
546
20.8M
    if (w == 0 || h == 0)
547
5.27k
        return 0;
548
549
20.7M
    if (pcpath != 0)
550
1.52M
    {
551
1.52M
        gs_fixed_rect rect;
552
1.52M
        int tmp;
553
554
1.52M
        rect.p.x = int2fixed(x);
555
1.52M
        rect.p.y = int2fixed(y);
556
1.52M
        rect.q.x = int2fixed(x+w);
557
1.52M
        rect.q.y = int2fixed(y+h);
558
1.52M
        dev = gx_make_clip_device_on_stack_if_needed(&cdev, pcpath, dev, &rect);
559
1.52M
        if (dev == NULL)
560
30.6k
            return 0;
561
        /* Clip region if possible */
562
1.49M
        tmp = fixed2int(rect.p.x);
563
1.49M
        if (tmp > x)
564
2.13k
        {
565
2.13k
            dx += tmp-x;
566
2.13k
            x = tmp;
567
2.13k
        }
568
1.49M
        tmp = fixed2int(rect.q.x);
569
1.49M
        if (tmp < x+w)
570
4.88k
            w = tmp-x;
571
1.49M
        tmp = fixed2int(rect.p.y);
572
1.49M
        if (tmp > y)
573
47.9k
        {
574
47.9k
            data += (tmp-y) * raster;
575
47.9k
            y = tmp;
576
47.9k
        }
577
1.49M
        tmp = fixed2int(rect.q.y);
578
1.49M
        if (tmp < y+h)
579
96.6k
            h = tmp-y;
580
1.49M
    }
581
20.7M
    if (depth > 1) {
582
        /****** CAN'T DO ROP OR HALFTONE WITH ALPHA ******/
583
0
        code = (*dev_proc(dev, copy_alpha))
584
0
            (dev, data, dx, raster, id, x, y, w, h,
585
0
             gx_dc_pure_color(pdcolor), depth);
586
0
    } else
587
20.7M
        code = pdcolor->type->fill_masked(pdcolor, data, dx, raster, id,
588
20.7M
                                          x, y, w, h, dev, lop, false);
589
20.7M
    if (dev != orig_dev)
590
10.6k
        gx_destroy_clip_device_on_stack(&cdev);
591
20.7M
    return code;
592
20.7M
}
593
594
/* Default implementation of strip_tile_rect_devn.  With the current design
595
   only devices that support devn color will be making use of this
596
   procedure and those are planar devices.  So we have an implemenation
597
   for planar devices and not a default implemenetation at this time. */
598
int
599
gx_default_strip_tile_rect_devn(gx_device * dev, const gx_strip_bitmap * tiles,
600
   int x, int y, int w, int h, const gx_drawing_color * pdcolor0,
601
   const gx_drawing_color * pdcolor1, int px, int py)
602
0
{
603
0
    int width = tiles->size.x;
604
0
    int height = tiles->size.y;
605
0
    int raster = tiles->raster;
606
0
    int rwidth = tiles->rep_width;
607
0
    int rheight = tiles->rep_height;
608
0
    int shift = tiles->shift;
609
0
    int code;
610
611
0
    if (rwidth == 0 || rheight == 0)
612
0
        return_error(gs_error_unregistered); /* Must not happen. */
613
0
    fit_fill_xy(dev, x, y, w, h);
614
0
    if (w == 0 || h == 0)
615
0
        return 0;
616
617
    /* Loop over as many tiles as we need vertically */
618
0
    while (1) {
619
0
        int xoff = (shift == 0 ? px :
620
0
                                 px + (y + py) / rheight * tiles->rep_shift);
621
        /* irx = x offset within the tile to start copying from */
622
0
        int irx = ((rwidth & (rwidth - 1)) == 0 ?  /* power of 2 */
623
0
                   (x + xoff) & (rwidth - 1) :
624
0
                   (x + xoff) % rwidth);
625
        /* ry = y offset within the tile to start copying from */
626
0
        int ry = ((rheight & (rheight - 1)) == 0 ?  /* power of 2 */
627
0
                  (y + py) & (rheight - 1) :
628
0
                  (y + py) % rheight);
629
        /* icw = how many bits we can copy before we run out of tile and need to loop */
630
0
        int icw = width - irx;
631
        /* ch = how many rows we can copy before we run out of tile and need to loop */
632
0
        int ch = height - ry;
633
0
        byte *row0 = tiles->data + ry * raster;
634
635
        /* Loop per line */
636
0
        do {
637
0
            byte *row = row0;
638
0
            int w2 = w;
639
0
            int left_in_tile = icw;
640
0
            int runlen = 0;
641
0
            int bit = 1<<((7-irx) & 7);
642
0
            int x2 = x;
643
0
            if (left_in_tile > w2)
644
0
                left_in_tile = w2;
645
646
            /* Loop per row */
647
0
            while (w2) {
648
0
                while (left_in_tile && ((bit & *row) == 0)) {
649
0
                    bit >>= 1;
650
0
                    if (bit == 0)
651
0
                        bit = 128, row++;
652
0
                    left_in_tile--;
653
0
                    runlen++;
654
0
                }
655
0
                if (runlen) {
656
0
                    gs_fixed_rect rect;
657
0
                    rect.p.x = int2fixed(x2);
658
0
                    rect.p.y = int2fixed(y);
659
0
                    rect.q.x = rect.p.x + int2fixed(runlen);
660
0
                    rect.q.y = rect.p.y + int2fixed(1);
661
                    /* Pure colours are only used to signal transparency */
662
0
                    if (pdcolor0->type != gx_dc_type_pure) {
663
0
                        code = dev_proc(dev, fill_rectangle_hl_color)(dev, &rect, NULL, pdcolor0, NULL);
664
0
                        if (code < 0)
665
0
                            return code;
666
0
                    }
667
0
                    x2 += runlen;
668
0
                    w2 -= runlen;
669
0
                    runlen = 0;
670
0
                }
671
0
                while (left_in_tile && ((bit & *row) != 0)) {
672
0
                    bit >>= 1;
673
0
                    if (bit == 0)
674
0
                        bit = 128, row++;
675
0
                    left_in_tile--;
676
0
                    runlen++;
677
0
                }
678
0
                if (runlen) {
679
0
                    gs_fixed_rect rect;
680
0
                    rect.p.x = int2fixed(x2);
681
0
                    rect.p.y = int2fixed(y);
682
0
                    rect.q.x = rect.p.x + int2fixed(runlen);
683
0
                    rect.q.y = rect.p.y + int2fixed(1);
684
                    /* Pure colours are only used to signal transparency */
685
0
                    if (pdcolor1->type != gx_dc_type_pure) {
686
0
                        code = dev_proc(dev, fill_rectangle_hl_color)(dev, &rect, NULL, pdcolor1, NULL);
687
0
                        if (code < 0)
688
0
                            return code;
689
0
                    }
690
0
                    x2 += runlen;
691
0
                    w2 -= runlen;
692
0
                    runlen = 0;
693
0
                }
694
0
                if (left_in_tile == 0) {
695
0
                    left_in_tile = rwidth;
696
0
                    if (left_in_tile > w2)
697
0
                        left_in_tile = w2;
698
0
                }
699
0
            }
700
701
            /* That's a line complete. */
702
0
            y++;
703
0
            if (--h == 0)
704
0
                return 0;
705
0
            row0 += raster;
706
0
        } while (--ch != 0); /* Until we finish a tile vertically */
707
0
    }
708
0
}
709
710
/* Default implementation of strip_tile_rectangle */
711
int
712
gx_default_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles,
713
   int x, int y, int w, int h, gx_color_index color0, gx_color_index color1,
714
                                int px, int py)
715
65.4M
{       /* Fill the rectangle in chunks. */
716
65.4M
    int width = tiles->size.x;
717
65.4M
    int height = tiles->size.y;
718
65.4M
    int raster = tiles->raster;
719
65.4M
    int rwidth = tiles->rep_width;
720
65.4M
    int rheight = tiles->rep_height;
721
65.4M
    int shift = tiles->shift;
722
65.4M
    gs_id tile_id = tiles->id;
723
724
65.4M
    if (rwidth == 0 || rheight == 0)
725
1
        return_error(gs_error_unregistered); /* Must not happen. */
726
65.4M
    fit_fill_xy(dev, x, y, w, h);
727
728
#ifdef DEBUG
729
    if (gs_debug_c('t')) {
730
        int ptx, pty;
731
        const byte *ptp = tiles->data;
732
733
        dmlprintf4(dev->memory, "[t]tile %dx%d raster=%d id=%lu;",
734
                   tiles->size.x, tiles->size.y, tiles->raster, tiles->id);
735
        dmlprintf6(dev->memory, " x,y=%d,%d w,h=%d,%d p=%d,%d\n",
736
                   x, y, w, h, px, py);
737
        dmlputs(dev->memory, "");
738
        for (pty = 0; pty < tiles->size.y; pty++) {
739
            dmprintf(dev->memory, "   ");
740
            for (ptx = 0; ptx < tiles->raster; ptx++)
741
                dmprintf1(dev->memory, "%3x", *ptp++);
742
        }
743
        dmputc(dev->memory, '\n');
744
    }
745
#endif
746
747
65.4M
    {       /*
748
                                 * Note: we can't do the following computations until after
749
                                 * the fit_fill_xy.
750
                                 */
751
65.4M
        int xoff =
752
65.4M
        (shift == 0 ? px :
753
65.4M
         px + (y + py) / rheight * tiles->rep_shift);
754
65.4M
        int irx = ((rwidth & (rwidth - 1)) == 0 ?  /* power of 2 */
755
24.8M
                   (x + xoff) & (rwidth - 1) :
756
65.4M
                   (x + xoff) % rwidth);
757
65.4M
        int ry = ((rheight & (rheight - 1)) == 0 ?  /* power of 2 */
758
24.8M
                  (y + py) & (rheight - 1) :
759
65.4M
                  (y + py) % rheight);
760
65.4M
        int icw = width - irx;
761
65.4M
        int ch = height - ry;
762
65.4M
        byte *row = tiles->data + ry * raster;
763
764
65.4M
        dev_proc_copy_mono((*proc_mono));
765
65.4M
        dev_proc_copy_color((*proc_color));
766
65.4M
        dev_proc_copy_planes((*proc_planes));
767
65.4M
        int code = 0;
768
769
65.4M
        if (color0 == gx_no_color_index && color1 == gx_no_color_index) {
770
10.1M
            if (tiles->num_planes > 1) {
771
24.4k
                proc_mono = 0;
772
24.4k
                proc_color = 0;
773
24.4k
                proc_planes = dev_proc(dev, copy_planes);
774
10.1M
            } else {
775
10.1M
                proc_planes = 0;
776
10.1M
                proc_color = dev_proc(dev, copy_color);
777
10.1M
                proc_mono = 0;
778
10.1M
            }
779
55.2M
        } else {
780
55.2M
            proc_planes = 0;
781
55.2M
            proc_color = 0;
782
55.2M
            proc_mono = dev_proc(dev, copy_mono);
783
55.2M
        }
784
785
149M
#define GX_DEFAULT_COPY_TILE(dev, srcx, tx, ty, tw, th, tid) do {\
786
149M
                if_debug6m('t', (dev)->memory, "   copy id=%lu sx=%d => x=%d y=%d w=%d h=%d\n", tid, srcx, tx, ty, tw, th);\
787
149M
                if (tiles->num_planes > 1) {\
788
91.8k
                    if (proc_planes)\
789
91.8k
                        code = (*proc_planes)(dev, row, srcx, raster, tid, tx, ty, tw, th, height);\
790
149M
                } else {\
791
149M
                    if (proc_color != 0) {\
792
90.6M
                        code = (*proc_color)(dev, row, srcx, raster, tid, tx, ty, tw, th);\
793
90.6M
                    } else {\
794
58.8M
                        if (proc_mono)\
795
166M
                            code = (*proc_mono)(dev, row, srcx, raster, tid, tx, ty, tw, th, color0, color1);\
796
58.8M
                         else code = 0;\
797
58.8M
                    }\
798
149M
                }\
799
149M
                if (code < 0) return_error(code);\
800
149M
                } while (0);
801
802
803
65.4M
        if (ch >= h) {   /* Shallow operation */
804
64.2M
            if (icw >= w) { /* Just one (partial) tile to transfer. */
805
54.2M
                GX_DEFAULT_COPY_TILE(dev, irx, x, y, w, h, (w == width && h == height ? tile_id : gs_no_bitmap_id));
806
54.2M
            } else {
807
10.0M
                int ex = x + w;
808
10.0M
                int fex = ex - width;
809
10.0M
                int cx = x + icw;
810
10.0M
                ulong id = (h == height ? tile_id : gs_no_bitmap_id);
811
812
10.0M
                GX_DEFAULT_COPY_TILE(dev, irx, x, y, icw, h, gs_no_bitmap_id);
813
75.9M
                while (cx <= fex) {
814
65.9M
                    GX_DEFAULT_COPY_TILE(dev, 0, cx, y, width, h, id);
815
65.9M
                    cx += width;
816
65.9M
                }
817
10.0M
                if (cx < ex) {
818
8.07M
                    GX_DEFAULT_COPY_TILE(dev, 0, cx, y, ex - cx, h, gs_no_bitmap_id);
819
8.07M
                }
820
10.0M
            }
821
64.2M
        } else if (icw >= w && shift == 0) {
822
            /* Narrow operation, no shift */
823
1.00M
            int ey = y + h;
824
1.00M
            int fey = ey - height;
825
1.00M
            int cy = y + ch;
826
1.00M
            ulong id = (w == width ? tile_id : gs_no_bitmap_id);
827
828
1.00M
            GX_DEFAULT_COPY_TILE(dev, irx, x, y, w, ch, (ch == height ? id : gs_no_bitmap_id));
829
1.00M
            row = tiles->data;
830
1.55M
            do {
831
1.55M
                ch = (cy > fey ? ey - cy : height);
832
1.55M
                GX_DEFAULT_COPY_TILE(dev, irx, x, cy, w, ch,
833
1.55M
                          (ch == height ? id : gs_no_bitmap_id));
834
1.55M
            }
835
1.55M
            while ((cy += ch) < ey);
836
1.00M
        } else {
837
            /* Full operation.  If shift != 0, some scan lines */
838
            /* may be narrow.  We could test shift == 0 in advance */
839
            /* and use a slightly faster loop, but right now */
840
            /* we don't bother. */
841
222k
            int ex = x + w, ey = y + h;
842
222k
            int fex = ex - width, fey = ey - height;
843
222k
            int cx, cy;
844
845
790k
            for (cy = y;;) {
846
790k
                ulong id = (ch == height ? tile_id : gs_no_bitmap_id);
847
848
790k
                if (icw >= w) {
849
0
                    GX_DEFAULT_COPY_TILE(dev, irx, x, cy, w, ch,
850
0
                              (w == width ? id : gs_no_bitmap_id));
851
790k
                } else {
852
790k
                    GX_DEFAULT_COPY_TILE(dev, irx, x, cy, icw, ch, gs_no_bitmap_id);
853
790k
                    cx = x + icw;
854
8.14M
                    while (cx <= fex) {
855
7.35M
                        GX_DEFAULT_COPY_TILE(dev, 0, cx, cy, width, ch, id);
856
7.35M
                        cx += width;
857
7.35M
                    }
858
790k
                    if (cx < ex) {
859
659k
                        GX_DEFAULT_COPY_TILE(dev, 0, cx, cy, ex - cx, ch, gs_no_bitmap_id);
860
659k
                    }
861
790k
                }
862
790k
                if ((cy += ch) >= ey)
863
222k
                    break;
864
568k
                ch = (cy > fey ? ey - cy : height);
865
568k
                if ((irx += shift) >= rwidth)
866
0
                    irx -= rwidth;
867
568k
                icw = width - irx;
868
568k
                row = tiles->data;
869
568k
            }
870
222k
        }
871
65.4M
#undef GX_DEFAULT_COPY_TILE
872
65.4M
    }
873
65.4M
    return 0;
874
65.4M
}
875
876
int
877
gx_no_strip_copy_rop2(gx_device * dev,
878
             const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
879
                     const gx_color_index * scolors,
880
           const gx_strip_bitmap * textures, const gx_color_index * tcolors,
881
                     int x, int y, int width, int height,
882
                     int phase_x, int phase_y, gs_logical_operation_t lop,
883
                     uint planar_height)
884
0
{
885
0
    return_error(gs_error_unknownerror);  /* not implemented */
886
0
}
887
888
/* ---------------- Unaligned copy operations ---------------- */
889
890
/*
891
 * Implementing unaligned operations in terms of the standard aligned
892
 * operations requires adjusting the bitmap origin and/or the raster to be
893
 * aligned.  Adjusting the origin is simple; adjusting the raster requires
894
 * doing the operation one scan line at a time.
895
 */
896
int
897
gx_copy_mono_unaligned(gx_device * dev, const byte * data,
898
            int dx, int raster, gx_bitmap_id id, int x, int y, int w, int h,
899
                       gx_color_index zero, gx_color_index one)
900
0
{
901
0
    dev_proc_copy_mono((*copy_mono)) = dev_proc(dev, copy_mono);
902
0
    uint offset = ALIGNMENT_MOD(data, align_bitmap_mod);
903
0
    int step = raster & (align_bitmap_mod - 1);
904
905
    /* Adjust the origin. */
906
0
    data -= offset;
907
0
    dx += offset << 3;
908
909
    /* Adjust the raster. */
910
0
    if (!step) {   /* No adjustment needed. */
911
0
        return (*copy_mono) (dev, data, dx, raster, id,
912
0
                             x, y, w, h, zero, one);
913
0
    }
914
    /* Do the transfer one scan line at a time. */
915
0
    {
916
0
        const byte *p = data;
917
0
        int d = dx;
918
0
        int code = 0;
919
0
        int i;
920
921
0
        for (i = 0; i < h && code >= 0;
922
0
             ++i, p += raster - step, d += step << 3
923
0
            )
924
0
            code = (*copy_mono) (dev, p, d, raster, gx_no_bitmap_id,
925
0
                                 x, y + i, w, 1, zero, one);
926
0
        return code;
927
0
    }
928
0
}
929
930
int
931
gx_copy_color_unaligned(gx_device * dev, const byte * data,
932
                        int data_x, int raster, gx_bitmap_id id,
933
                        int x, int y, int width, int height)
934
0
{
935
0
    dev_proc_copy_color((*copy_color)) = dev_proc(dev, copy_color);
936
0
    int depth = dev->color_info.depth;
937
0
    uint offset = (uint) (data - (const byte *)0) & (align_bitmap_mod - 1);
938
0
    int step = raster & (align_bitmap_mod - 1);
939
940
    /*
941
     * Adjust the origin.
942
     * We have to do something very special for 24-bit data,
943
     * because that is the only depth that doesn't divide
944
     * align_bitmap_mod exactly.  In particular, we need to find
945
     * M*B + R == 0 mod 3, where M is align_bitmap_mod, R is the
946
     * offset value just calculated, and B is an integer unknown;
947
     * the new value of offset will be M*B + R.
948
     */
949
0
    if (depth == 24)
950
0
        offset += (offset % 3) *
951
0
            (align_bitmap_mod * (3 - (align_bitmap_mod % 3)));
952
0
    data -= offset;
953
0
    data_x += (offset << 3) / depth;
954
955
    /* Adjust the raster. */
956
0
    if (!step) {   /* No adjustment needed. */
957
0
        return (*copy_color) (dev, data, data_x, raster, id,
958
0
                              x, y, width, height);
959
0
    }
960
    /* Do the transfer one scan line at a time. */
961
0
    {
962
0
        const byte *p = data;
963
0
        int d = data_x;
964
0
        int dstep = (step << 3) / depth;
965
0
        int code = 0;
966
0
        int i;
967
968
0
        for (i = 0; i < height && code >= 0;
969
0
             ++i, p += raster - step, d += dstep
970
0
            )
971
0
            code = (*copy_color) (dev, p, d, raster, gx_no_bitmap_id,
972
0
                                  x, y + i, width, 1);
973
0
        return code;
974
0
    }
975
0
}
976
977
int
978
gx_copy_alpha_unaligned(gx_device * dev, const byte * data, int data_x,
979
           int raster, gx_bitmap_id id, int x, int y, int width, int height,
980
                        gx_color_index color, int depth)
981
0
{
982
0
    dev_proc_copy_alpha((*copy_alpha)) = dev_proc(dev, copy_alpha);
983
0
    uint offset = (uint) (data - (const byte *)0) & (align_bitmap_mod - 1);
984
0
    int step = raster & (align_bitmap_mod - 1);
985
986
    /* Adjust the origin. */
987
0
    data -= offset;
988
0
    data_x += (offset << 3) / depth;
989
990
    /* Adjust the raster. */
991
0
    if (!step) {   /* No adjustment needed. */
992
0
        return (*copy_alpha) (dev, data, data_x, raster, id,
993
0
                              x, y, width, height, color, depth);
994
0
    }
995
    /* Do the transfer one scan line at a time. */
996
0
    {
997
0
        const byte *p = data;
998
0
        int d = data_x;
999
0
        int dstep = (step << 3) / depth;
1000
0
        int code = 0;
1001
0
        int i;
1002
1003
0
        for (i = 0; i < height && code >= 0;
1004
0
             ++i, p += raster - step, d += dstep
1005
0
            )
1006
0
            code = (*copy_alpha) (dev, p, d, raster, gx_no_bitmap_id,
1007
0
                                  x, y + i, width, 1, color, depth);
1008
0
        return code;
1009
0
    }
1010
0
}