Coverage Report

Created: 2022-10-31 07:00

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