Coverage Report

Created: 2026-02-14 07:09

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