Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/base/gxp1fill.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2022 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
17
/* PatternType 1 filling algorithms */
18
#include "string_.h"
19
#include "math_.h"
20
#include "gx.h"
21
#include "gserrors.h"
22
#include "gsrop.h"
23
#include "gsmatrix.h"
24
#include "gxcspace.h"           /* for gscolor2.h */
25
#include "gxcolor2.h"
26
#include "gxdcolor.h"
27
#include "gxdevcli.h"
28
#include "gxdevmem.h"
29
#include "gxclip2.h"
30
#include "gxpcolor.h"
31
#include "gxp1impl.h"
32
#include "gxcldev.h"
33
#include "gxblend.h"
34
#include "gsicc_cache.h"
35
#include "gxdevsop.h"
36
#include <limits.h>             /* For INT_MAX etc */
37
38
#include "gdevp14.h"
39
40
51.3M
#define fastfloor(x) (((int)(x)) - (((x)<0) && ((x) != (float)(int)(x))))
41
42
/* Define the state for tile filling. */
43
typedef struct tile_fill_state_s {
44
45
    /* Original arguments */
46
47
    const gx_device_color *pdevc;       /* pattern color */
48
    int x0, y0, w0, h0;
49
    gs_logical_operation_t lop;
50
    const gx_rop_source_t *source;
51
52
    /* Variables set at initialization */
53
54
    gx_device_tile_clip *cdev;
55
    gx_device *pcdev;           /* original device or cdev */
56
    const gx_strip_bitmap *tmask;
57
    gs_int_point phase;
58
    int num_planes;    /* negative if not planar */
59
60
61
    /* Following are only for uncolored patterns */
62
63
    dev_color_proc_fill_rectangle((*fill_rectangle));
64
65
    /* Following are only for colored patterns */
66
67
    gx_device *orig_dev;
68
    int xoff, yoff;             /* set dynamically */
69
70
} tile_fill_state_t;
71
72
/* Define the state for tile filling.
73
   This is used for when we have
74
   transparency */
75
typedef struct tile_fill_trans_state_s {
76
77
    /* Original arguments */
78
79
    const gx_device_color *pdevc;       /* pattern color */
80
    int x0, y0, w0, h0;
81
82
    /* Variables set at initialization */
83
84
    gx_device *pcdev;           /* original device or &cdev */
85
    gs_int_point phase;
86
87
    int xoff, yoff;             /* set dynamically */
88
89
} tile_fill_trans_state_t;
90
91
/* we need some means of detecting if a forwarding clipping device was
92
   installed.  If the tile state cdev pointer is non-NULL, then the
93
   target output device must be the clipping device. */
94
142k
#define CLIPDEV_INSTALLED (state.cdev != NULL)
95
96
/* Initialize the filling state. */
97
static int
98
tile_fill_init(tile_fill_state_t * ptfs, const gx_device_color * pdevc,
99
               gx_device * dev, bool set_mask_phase)
100
114k
{
101
114k
    gx_color_tile *m_tile = pdevc->mask.m_tile;
102
114k
    int px, py;
103
114k
    bool is_planar;
104
105
114k
    ptfs->pdevc = pdevc;
106
114k
    is_planar = dev->is_planar;
107
114k
    if (is_planar) {
108
638
        ptfs->num_planes = dev->color_info.num_components;
109
113k
    } else {
110
113k
        ptfs->num_planes = -1;
111
113k
    }
112
114k
    if (m_tile == 0) {          /* no clipping */
113
71.9k
        ptfs->cdev = NULL;
114
71.9k
        ptfs->pcdev = dev;
115
71.9k
        ptfs->phase = pdevc->phase;
116
71.9k
        return 0;
117
71.9k
    }
118
42.3k
    if ((ptfs->cdev = (gx_device_tile_clip *)gs_alloc_struct(dev->memory,
119
42.3k
                                                 gx_device_tile_clip,
120
42.3k
                                                 &st_device_tile_clip,
121
42.3k
                                                 "tile_fill_init(cdev)")) == NULL) {
122
0
        return_error(gs_error_VMerror);
123
0
    }
124
42.3k
    ptfs->cdev->finalize = NULL;
125
42.3k
    ptfs->pcdev = (gx_device *)ptfs->cdev;
126
42.3k
    ptfs->tmask = &m_tile->tmask;
127
42.3k
    ptfs->phase.x = pdevc->mask.m_phase.x;
128
42.3k
    ptfs->phase.y = pdevc->mask.m_phase.y;
129
    /*
130
     * For non-simple tiles, the phase will be reset on each pass of the
131
     * tile_by_steps loop, but for simple tiles, we must set it now.
132
     */
133
42.3k
    if (set_mask_phase && m_tile->is_simple) {
134
0
        px = imod(-(int)fastfloor(m_tile->step_matrix.tx - ptfs->phase.x + 0.5),
135
0
                  m_tile->tmask.rep_width);
136
0
        py = imod(-(int)fastfloor(m_tile->step_matrix.ty - ptfs->phase.y + 0.5),
137
0
                  m_tile->tmask.rep_height);
138
0
    } else
139
42.3k
        px = py = 0;
140
42.3k
    return tile_clip_initialize(ptfs->cdev, ptfs->tmask, dev, px, py);
141
42.3k
}
142
143
/*
144
 * Fill with non-standard X and Y stepping.
145
 * ptile is pdevc->colors.pattern.{m,p}_tile.
146
 * tbits_or_tmask is whichever of tbits and tmask is supplying
147
 * the tile size.
148
 * This implementation could be sped up considerably!
149
 */
150
static int
151
tile_by_steps(tile_fill_state_t * ptfs, int x0, int y0, int w0, int h0,
152
              const gx_color_tile * ptile,
153
              const gx_strip_bitmap * tbits_or_tmask,
154
              int (*fill_proc) (const tile_fill_state_t * ptfs,
155
                                int x, int y, int w, int h))
156
84.2k
{
157
84.2k
    int x1 = x0 + w0, y1 = y0 + h0;
158
84.2k
    int i0, i1, j0, j1, i, j;
159
84.2k
    gs_matrix step_matrix;      /* translated by phase */
160
84.2k
    int code;
161
#ifdef DEBUG
162
    const gs_memory_t *mem = ptfs->pcdev->memory;
163
#endif
164
165
84.2k
    ptfs->x0 = x0, ptfs->w0 = w0;
166
84.2k
    ptfs->y0 = y0, ptfs->h0 = h0;
167
84.2k
    step_matrix = ptile->step_matrix;
168
84.2k
    step_matrix.tx -= ptfs->phase.x;
169
84.2k
    step_matrix.ty -= ptfs->phase.y;
170
84.2k
    {
171
84.2k
        gs_rect bbox;           /* bounding box in device space */
172
84.2k
        gs_rect ibbox;          /* bounding box in stepping space */
173
84.2k
        double bbw = ptile->bbox.q.x - ptile->bbox.p.x;
174
84.2k
        double bbh = ptile->bbox.q.y - ptile->bbox.p.y;
175
84.2k
        double u0, v0, u1, v1;
176
177
84.2k
        bbox.p.x = x0, bbox.p.y = y0;
178
84.2k
        bbox.q.x = x1, bbox.q.y = y1;
179
84.2k
        code = gs_bbox_transform_inverse(&bbox, &step_matrix, &ibbox);
180
84.2k
        if (code < 0)
181
0
            return code;
182
84.2k
        if_debug10m('T', mem,
183
84.2k
          "[T]x,y=(%d,%d) w,h=(%d,%d) => (%g,%g),(%g,%g), offset=(%g,%g)\n",
184
84.2k
                    x0, y0, w0, h0,
185
84.2k
                    ibbox.p.x, ibbox.p.y, ibbox.q.x, ibbox.q.y,
186
84.2k
                    step_matrix.tx, step_matrix.ty);
187
        /*
188
         * If the pattern is partly transparent and XStep/YStep is smaller
189
         * than the device space BBox, we need to ensure that we cover
190
         * each pixel of the rectangle being filled with *every* pattern
191
         * that overlaps it, not just *some* pattern copy.
192
         */
193
84.2k
        u0 = ibbox.p.x - max(ptile->bbox.p.x, 0) - 0.000001;
194
84.2k
        v0 = ibbox.p.y - max(ptile->bbox.p.y, 0) - 0.000001;
195
84.2k
        u1 = ibbox.q.x - min(ptile->bbox.q.x, 0) + 0.000001;
196
84.2k
        v1 = ibbox.q.y - min(ptile->bbox.q.y, 0) + 0.000001;
197
84.2k
        if (!ptile->is_simple)
198
84.2k
            u0 -= bbw, v0 -= bbh, u1 += bbw, v1 += bbh;
199
84.2k
        i0 = (int)fastfloor(u0);
200
84.2k
        j0 = (int)fastfloor(v0);
201
84.2k
        i1 = (int)ceil(u1);
202
84.2k
        j1 = (int)ceil(v1);
203
84.2k
    }
204
84.2k
    if_debug4m('T', mem, "[T]i=(%d,%d) j=(%d,%d)\n", i0, i1, j0, j1);
205
7.40M
    for (i = i0; i < i1; i++)
206
32.8M
        for (j = j0; j < j1; j++) {
207
25.5M
            int x = (int)fastfloor(step_matrix.xx * i +
208
25.5M
                          step_matrix.yx * j + step_matrix.tx);
209
25.5M
            int y = (int)fastfloor(step_matrix.xy * i +
210
25.5M
                          step_matrix.yy * j + step_matrix.ty);
211
25.5M
            int w = tbits_or_tmask->size.x;
212
25.5M
            int h = tbits_or_tmask->size.y;
213
25.5M
            int xoff, yoff;
214
215
25.5M
            if_debug4m('T', mem, "[T]i=%d j=%d x,y=(%d,%d)", i, j, x, y);
216
25.5M
            if (x == INT_MIN || y == INT_MIN) {
217
1.09M
                if_debug0m('T', mem, " underflow!\n");
218
1.09M
                continue;
219
1.09M
            }
220
24.4M
            if (x < x0)
221
11.4M
                xoff = x0 - x, x = x0, w -= xoff;
222
13.0M
            else
223
13.0M
                xoff = 0;
224
24.4M
            if (y < y0)
225
17.5M
                yoff = y0 - y, y = y0, h -= yoff;
226
6.86M
            else
227
6.86M
                yoff = 0;
228
24.4M
            if (x + w > x1)
229
14.7M
                w = x1 - x;
230
24.4M
            if (y + h > y1)
231
15.2M
                h = y1 - y;
232
24.4M
            if_debug6m('T', mem, "=>(%d,%d) w,h=(%d,%d) x/yoff=(%d,%d)\n",
233
24.4M
                       x, y, w, h, xoff, yoff);
234
24.4M
            if (w > 0 && h > 0) {
235
2.09M
                if (ptfs->pcdev == (gx_device *)ptfs->cdev)
236
2.09M
                    tile_clip_set_phase(ptfs->cdev,
237
2.09M
                                imod(xoff - x, ptfs->tmask->rep_width),
238
2.09M
                                imod(yoff - y, ptfs->tmask->rep_height));
239
                /* Set the offsets for colored pattern fills */
240
2.09M
                ptfs->xoff = xoff;
241
2.09M
                ptfs->yoff = yoff;
242
2.09M
                code = (*fill_proc) (ptfs, x, y, w, h);
243
2.09M
                if (code < 0)
244
0
                    return code;
245
2.09M
            }
246
24.4M
        }
247
84.2k
    return 0;
248
84.2k
}
249
250
/* Fill a rectangle with a colored Pattern. */
251
/* Note that we treat this as "texture" for RasterOp. */
252
static int
253
tile_colored_fill(const tile_fill_state_t * ptfs,
254
                  int x, int y, int w, int h)
255
2.08M
{
256
2.08M
    gx_color_tile *ptile = ptfs->pdevc->colors.pattern.p_tile;
257
2.08M
    gs_logical_operation_t lop = ptfs->lop;
258
2.08M
    const gx_rop_source_t *source = ptfs->source;
259
2.08M
    gx_device *dev = ptfs->orig_dev;
260
2.08M
    int xoff = ptfs->xoff, yoff = ptfs->yoff;
261
2.08M
    gx_strip_bitmap *bits = &ptile->tbits;
262
2.08M
    const byte *data = bits->data;
263
2.08M
    bool full_transfer = (w == ptfs->w0 && h == ptfs->h0);
264
2.08M
    int code = 0;
265
266
2.08M
    if (source == NULL && lop_no_S_is_T(lop) && dev_proc(dev, copy_planes) != gx_default_copy_planes &&
267
2.08M
        ptfs->num_planes > 0) {
268
22
            code = (*dev_proc(ptfs->pcdev, copy_planes))
269
22
                    (ptfs->pcdev, data + bits->raster * yoff, xoff,
270
22
                     bits->raster,
271
22
                     (full_transfer ? bits->id : gx_no_bitmap_id),
272
22
                     x, y, w, h, ptile->tbits.rep_height);
273
2.08M
    } else if (source == NULL && lop_no_S_is_T(lop)) {
274
2.08M
            code = (*dev_proc(ptfs->pcdev, copy_color))
275
2.08M
                    (ptfs->pcdev, data + bits->raster * yoff, xoff,
276
2.08M
                     bits->raster,
277
2.08M
                     (full_transfer ? bits->id : gx_no_bitmap_id),
278
2.08M
                     x, y, w, h);
279
2.08M
    } else {
280
0
        gx_strip_bitmap data_tile;
281
0
        gx_bitmap_id source_id;
282
0
        gx_rop_source_t no_source;
283
284
0
        if (source == NULL)
285
0
            set_rop_no_source(source, no_source, dev);
286
0
        source_id = (full_transfer ? source->id : gx_no_bitmap_id);
287
0
        data_tile.data = (byte *) data;         /* actually const */
288
0
        data_tile.raster = bits->raster;
289
0
        data_tile.size.x = data_tile.rep_width = ptile->tbits.size.x;
290
0
        data_tile.size.y = data_tile.rep_height = ptile->tbits.size.y;
291
0
        data_tile.id = bits->id;
292
0
        data_tile.shift = data_tile.rep_shift = 0;
293
0
        data_tile.num_planes = (ptfs->num_planes > 1 ? ptfs->num_planes : 1);
294
0
        code = (*dev_proc(ptfs->pcdev, strip_copy_rop2))
295
0
                           (ptfs->pcdev,
296
0
                            source->sdata + (y - ptfs->y0) * source->sraster,
297
0
                            source->sourcex + (x - ptfs->x0),
298
0
                            source->sraster, source_id,
299
0
                            (source->use_scolors ? source->scolors : NULL),
300
0
                            &data_tile, NULL,
301
0
                            x, y, w, h,
302
0
                            imod(xoff - x, data_tile.rep_width),
303
0
                            imod(yoff - y, data_tile.rep_height),
304
0
                            lop,
305
0
                            source->planar_height);
306
0
    }
307
2.08M
    return code;
308
2.08M
}
309
310
/* Fill a rectangle with a colored Pattern. */
311
/* Note that we treat this as "texture" for RasterOp. */
312
static int
313
tile_pattern_clist(const tile_fill_state_t * ptfs,
314
                  int x, int y, int w, int h)
315
9.05k
{
316
9.05k
    gx_color_tile *ptile = ptfs->pdevc->colors.pattern.p_tile;
317
9.05k
    gx_device_clist *cdev = ptile->cdev;
318
9.05k
    gx_device_clist_reader *crdev = (gx_device_clist_reader *)cdev;
319
9.05k
    gx_device *dev = ptfs->orig_dev;
320
9.05k
    int code;
321
322
9.05k
    crdev->offset_map = NULL;
323
9.05k
    code = crdev->page_info.io_procs->rewind(crdev->page_info.bfile, false, NULL);
324
9.05k
    if (code < 0) return code;
325
9.05k
    code = crdev->page_info.io_procs->rewind(crdev->page_info.cfile, false, NULL);
326
9.05k
    if (code < 0) return code;
327
328
9.05k
    clist_render_init(cdev);
329
     /* Check for and get ICC profile table */
330
9.05k
    if (crdev->icc_table == NULL) {
331
9.05k
        code = clist_read_icctable(crdev);
332
9.05k
        if (code < 0)
333
0
            return code;
334
9.05k
    }
335
    /* Also allocate the icc cache for the clist reader */
336
9.05k
    if ( crdev->icc_cache_cl == NULL )
337
9.05k
        crdev->icc_cache_cl = gsicc_cache_new(crdev->memory->thread_safe_memory);
338
9.05k
    if_debug0m('L', dev->memory, "Pattern clist playback begin\n");
339
9.05k
    code = clist_playback_file_bands(playback_action_render,
340
9.05k
                crdev, &crdev->page_info, dev, 0, 0, ptfs->xoff - x, ptfs->yoff - y);
341
9.05k
    if_debug0m('L', dev->memory, "Pattern clist playback end\n");
342
    /* FIXME: it would be preferable to have this persist, but as
343
     * clist_render_init() sets it to NULL, we currently have to
344
     * cleanup before returning. Set to NULL for safety
345
     */
346
9.05k
    rc_decrement(crdev->icc_cache_cl, "tile_pattern_clist");
347
9.05k
    crdev->icc_cache_cl = NULL;
348
9.05k
    return code;
349
9.05k
}
350
351
int
352
gx_dc_pattern_fill_rectangle(const gx_device_color * pdevc, int x, int y,
353
                             int w, int h, gx_device * dev,
354
                             gs_logical_operation_t lop,
355
                             const gx_rop_source_t * source)
356
278k
{
357
278k
    gx_color_tile *ptile = pdevc->colors.pattern.p_tile;
358
278k
    const gx_rop_source_t *rop_source = source;
359
278k
    gx_rop_source_t no_source;
360
278k
    gx_strip_bitmap *bits;
361
278k
    tile_fill_state_t state;
362
278k
    int code;
363
364
278k
    if (ptile == 0)             /* null pattern */
365
166k
        return 0;
366
111k
    if (rop_source == NULL)
367
111k
        set_rop_no_source(rop_source, no_source, dev);
368
111k
    bits = &ptile->tbits;
369
370
111k
    code = tile_fill_init(&state, pdevc, dev, false);  /* This _may_ allocate state.cdev */
371
111k
    if (code < 0) {
372
0
        goto exit;
373
0
    }
374
111k
    if (ptile->is_simple && ptile->cdev == NULL) {
375
30.0k
        int px =
376
30.0k
            imod(-(int)fastfloor(ptile->step_matrix.tx - state.phase.x + 0.5),
377
30.0k
                 bits->rep_width);
378
30.0k
        int py =
379
30.0k
            imod(-(int)fastfloor(ptile->step_matrix.ty - state.phase.y + 0.5),
380
30.0k
                 bits->rep_height);
381
382
30.0k
        if (CLIPDEV_INSTALLED)
383
669
            tile_clip_set_phase(state.cdev, px, py);
384
30.0k
        if (source == NULL && lop_no_S_is_T(lop))
385
30.0k
            code = (*dev_proc(state.pcdev, strip_tile_rectangle))
386
30.0k
                (state.pcdev, bits, x, y, w, h,
387
30.0k
                 gx_no_color_index, gx_no_color_index, px, py);
388
0
        else
389
0
            code = (*dev_proc(state.pcdev, strip_copy_rop2))
390
0
                        (state.pcdev,
391
0
                         rop_source->sdata, rop_source->sourcex,
392
0
                         rop_source->sraster, rop_source->id,
393
0
                         (rop_source->use_scolors ? rop_source->scolors : NULL),
394
0
                         bits, NULL, x, y, w, h, px, py, lop,
395
0
                         rop_source->planar_height);
396
81.4k
    } else {
397
81.4k
        state.lop = lop;
398
81.4k
        state.source = source;
399
81.4k
        state.orig_dev = dev;
400
81.4k
        if (ptile->cdev == NULL) {
401
40.3k
            code = tile_by_steps(&state, x, y, w, h, ptile,
402
40.3k
                                 &ptile->tbits, tile_colored_fill);
403
41.0k
        } else {
404
41.0k
            gx_device_clist *cdev = ptile->cdev;
405
41.0k
            gx_device_clist_reader *crdev = (gx_device_clist_reader *)cdev;
406
41.0k
            gx_strip_bitmap tbits;
407
408
41.0k
            crdev->yplane.depth = 0; /* Don't know what to set here. */
409
41.0k
            crdev->yplane.shift = 0;
410
41.0k
            crdev->yplane.index = -1;
411
41.0k
            crdev->pages = NULL;
412
41.0k
            crdev->num_pages = 1;
413
41.0k
            state.orig_dev = dev;
414
41.0k
            tbits = ptile->tbits;
415
41.0k
            tbits.size.x = crdev->width;
416
41.0k
            tbits.size.y = crdev->height;
417
41.0k
            code = tile_by_steps(&state, x, y, w, h, ptile,
418
41.0k
                                 &tbits, tile_pattern_clist);
419
41.0k
        }
420
81.4k
    }
421
111k
exit:
422
111k
    if (CLIPDEV_INSTALLED) {
423
41.0k
        tile_clip_free((gx_device_tile_clip *)state.cdev);
424
41.0k
        state.cdev = NULL;
425
41.0k
    }
426
111k
    return code;
427
111k
}
428
429
/* Fill a rectangle with an uncolored Pattern. */
430
/* Note that we treat this as "texture" for RasterOp. */
431
static int
432
tile_masked_fill(const tile_fill_state_t * ptfs,
433
                 int x, int y, int w, int h)
434
8.91k
{
435
8.91k
    if (ptfs->source == NULL)
436
8.91k
        return (*ptfs->fill_rectangle)
437
8.91k
            (ptfs->pdevc, x, y, w, h, ptfs->pcdev, ptfs->lop, NULL);
438
0
    else {
439
0
        const gx_rop_source_t *source = ptfs->source;
440
0
        gx_rop_source_t step_source;
441
442
0
        step_source.sdata = source->sdata + (y - ptfs->y0) * source->sraster;
443
0
        step_source.sourcex = source->sourcex + (x - ptfs->x0);
444
0
        step_source.sraster = source->sraster;
445
0
        step_source.id = (w == ptfs->w0 && h == ptfs->h0 ?
446
0
                          source->id : gx_no_bitmap_id);
447
0
        step_source.scolors[0] = source->scolors[0];
448
0
        step_source.scolors[1] = source->scolors[1];
449
0
        step_source.planar_height = source->planar_height;
450
0
        step_source.use_scolors = source->use_scolors;
451
0
        return (*ptfs->fill_rectangle)
452
0
            (ptfs->pdevc, x, y, w, h, ptfs->pcdev, ptfs->lop, &step_source);
453
0
    }
454
8.91k
}
455
int
456
gx_dc_pure_masked_fill_rect(const gx_device_color * pdevc,
457
                            int x, int y, int w, int h, gx_device * dev,
458
                            gs_logical_operation_t lop,
459
                            const gx_rop_source_t * source)
460
1.25k
{
461
1.25k
    gx_color_tile *ptile = pdevc->mask.m_tile;
462
1.25k
    tile_fill_state_t state;
463
1.25k
    int code;
464
465
    /*
466
     * This routine should never be called if there is no masking,
467
     * but we leave the checks below just in case.
468
     */
469
1.25k
    code = tile_fill_init(&state, pdevc, dev, true);
470
1.25k
    if (code < 0)
471
0
        return code;
472
1.25k
    if (state.pcdev == dev || ptile->is_simple)
473
0
        code = (*gx_dc_type_data_pure.fill_rectangle)
474
0
            (pdevc, x, y, w, h, state.pcdev, lop, source);
475
1.25k
    else {
476
1.25k
        state.lop = lop;
477
1.25k
        state.source = source;
478
1.25k
        state.fill_rectangle = gx_dc_type_data_pure.fill_rectangle;
479
1.25k
        code = tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask,
480
1.25k
                             tile_masked_fill);
481
1.25k
    }
482
1.25k
    if (CLIPDEV_INSTALLED) {
483
1.25k
        tile_clip_free((gx_device_tile_clip *)state.cdev);
484
1.25k
        state.cdev = NULL;
485
1.25k
    }
486
1.25k
    return code;
487
1.25k
}
488
489
int
490
gx_dc_devn_masked_fill_rect(const gx_device_color * pdevc,
491
                            int x, int y, int w, int h, gx_device * dev,
492
                            gs_logical_operation_t lop,
493
                            const gx_rop_source_t * source)
494
24
{
495
24
    gx_color_tile *ptile = pdevc->mask.m_tile;
496
24
    tile_fill_state_t state;
497
24
    int code;
498
499
    /*
500
     * This routine should never be called if there is no masking,
501
     * but we leave the checks below just in case.
502
     */
503
24
    code = tile_fill_init(&state, pdevc, dev, true);
504
24
    if (code < 0)
505
0
        return code;
506
24
    if (state.pcdev == dev || ptile->is_simple) {
507
0
        gx_device_color dcolor = *pdevc;
508
509
0
        if (ptile == NULL) {
510
0
        int k;
511
512
            /* Have to set the pdevc to a non mask type since the pattern was stored as non-masking */
513
0
            dcolor.type = gx_dc_type_devn;
514
0
            for (k = 0; k < GS_CLIENT_COLOR_MAX_COMPONENTS; k++) {
515
0
                dcolor.colors.devn.values[k] = pdevc->colors.devn.values[k];
516
0
            }
517
0
        }
518
0
        code = (*gx_dc_type_data_devn.fill_rectangle)
519
0
            (&dcolor, x, y, w, h, state.pcdev, lop, source);
520
24
    } else {
521
24
        state.lop = lop;
522
24
        state.source = source;
523
24
        state.fill_rectangle = gx_dc_type_data_devn.fill_rectangle;
524
24
        code = tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask,
525
24
                             tile_masked_fill);
526
24
    }
527
24
    if (CLIPDEV_INSTALLED) {
528
24
        tile_clip_free((gx_device_tile_clip *)state.cdev);
529
24
        state.cdev = NULL;
530
24
    }
531
24
    return code;
532
24
}
533
534
int
535
gx_dc_binary_masked_fill_rect(const gx_device_color * pdevc,
536
                              int x, int y, int w, int h, gx_device * dev,
537
                              gs_logical_operation_t lop,
538
                              const gx_rop_source_t * source)
539
0
{
540
0
    gx_color_tile *ptile = pdevc->mask.m_tile;
541
0
    tile_fill_state_t state;
542
0
    int code;
543
544
0
    code = tile_fill_init(&state, pdevc, dev, true);
545
0
    if (code < 0)
546
0
        return code;
547
0
    if (state.pcdev == dev || ptile->is_simple)
548
0
        code = (*gx_dc_type_data_ht_binary.fill_rectangle)
549
0
            (pdevc, x, y, w, h, state.pcdev, lop, source);
550
0
    else {
551
0
        state.lop = lop;
552
0
        state.source = source;
553
0
        state.fill_rectangle = gx_dc_type_data_ht_binary.fill_rectangle;
554
0
        code = tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask,
555
0
                             tile_masked_fill);
556
0
    }
557
0
    if (CLIPDEV_INSTALLED) {
558
0
        tile_clip_free((gx_device_tile_clip *)state.cdev);
559
0
        state.cdev = NULL;
560
0
    }
561
0
    return code;
562
0
}
563
564
int
565
gx_dc_colored_masked_fill_rect(const gx_device_color * pdevc,
566
                               int x, int y, int w, int h, gx_device * dev,
567
                               gs_logical_operation_t lop,
568
                               const gx_rop_source_t * source)
569
0
{
570
0
    gx_color_tile *ptile = pdevc->mask.m_tile;
571
0
    tile_fill_state_t state;
572
0
    int code;
573
574
0
    code = tile_fill_init(&state, pdevc, dev, true);
575
0
    if (code < 0)
576
0
        return code;
577
0
    if (state.pcdev == dev || ptile->is_simple)
578
0
        code = (*gx_dc_type_data_ht_colored.fill_rectangle)
579
0
            (pdevc, x, y, w, h, state.pcdev, lop, source);
580
0
    else {
581
0
        state.lop = lop;
582
0
        state.source = source;
583
0
        state.fill_rectangle = gx_dc_type_data_ht_colored.fill_rectangle;
584
0
        code = tile_by_steps(&state, x, y, w, h, ptile, &ptile->tmask,
585
0
                             tile_masked_fill);
586
0
    }
587
0
    if (CLIPDEV_INSTALLED) {
588
0
        tile_clip_free((gx_device_tile_clip *)state.cdev);
589
0
        state.cdev = NULL;
590
0
    }
591
0
    return code;
592
0
}
593
594
/*
595
 * This is somewhat a clone of the tile_by_steps function but one
596
 * that performs filling from and to pdf14dev (transparency) buffers.
597
 * At some point it may be desirable to do some optimization here.
598
 */
599
static int
600
tile_by_steps_trans(tile_fill_trans_state_t * ptfs, int x0, int y0, int w0, int h0,
601
              gx_pattern_trans_t *fill_trans_buffer, const gx_color_tile * ptile,
602
              int native16)
603
825
{
604
825
    int x1 = x0 + w0, y1 = y0 + h0;
605
825
    int i0, i1, j0, j1, i, j;
606
825
    gs_matrix step_matrix;      /* translated by phase */
607
825
    gx_pattern_trans_t *ptrans_pat = ptile->ttrans;
608
#ifdef DEBUG
609
    const gs_memory_t *mem = ptile->ttrans->mem;
610
#endif
611
825
    int code;
612
613
825
    ptfs->x0 = x0, ptfs->w0 = w0;
614
825
    ptfs->y0 = y0, ptfs->h0 = h0;
615
825
    step_matrix = ptile->step_matrix;
616
825
    step_matrix.tx -= ptfs->phase.x;
617
825
    step_matrix.ty -= ptfs->phase.y;
618
825
    {
619
825
        gs_rect bbox;           /* bounding box in device space */
620
825
        gs_rect ibbox;          /* bounding box in stepping space */
621
825
        double bbw = ptile->bbox.q.x - ptile->bbox.p.x;
622
825
        double bbh = ptile->bbox.q.y - ptile->bbox.p.y;
623
825
        double u0, v0, u1, v1;
624
625
825
        bbox.p.x = x0, bbox.p.y = y0;
626
825
        bbox.q.x = x1, bbox.q.y = y1;
627
825
        code = gs_bbox_transform_inverse(&bbox, &step_matrix, &ibbox);
628
825
        if (code < 0)
629
0
            return code;
630
825
        if_debug10m('T', mem,
631
825
          "[T]x,y=(%d,%d) w,h=(%d,%d) => (%g,%g),(%g,%g), offset=(%g,%g)\n",
632
825
                    x0, y0, w0, h0,
633
825
                    ibbox.p.x, ibbox.p.y, ibbox.q.x, ibbox.q.y,
634
825
                    step_matrix.tx, step_matrix.ty);
635
        /*
636
         * If the pattern is partly transparent and XStep/YStep is smaller
637
         * than the device space BBox, we need to ensure that we cover
638
         * each pixel of the rectangle being filled with *every* pattern
639
         * that overlaps it, not just *some* pattern copy.
640
         */
641
825
        u0 = ibbox.p.x - max(ptile->bbox.p.x, 0) - 0.000001;
642
825
        v0 = ibbox.p.y - max(ptile->bbox.p.y, 0) - 0.000001;
643
825
        u1 = ibbox.q.x - min(ptile->bbox.q.x, 0) + 0.000001;
644
825
        v1 = ibbox.q.y - min(ptile->bbox.q.y, 0) + 0.000001;
645
825
        if (!ptile->is_simple)
646
825
            u0 -= bbw, v0 -= bbh, u1 += bbw, v1 += bbh;
647
825
        i0 = (int)fastfloor(u0);
648
825
        j0 = (int)fastfloor(v0);
649
825
        i1 = (int)ceil(u1);
650
825
        j1 = (int)ceil(v1);
651
825
    }
652
825
    if_debug4m('T', mem, "[T]i=(%d,%d) j=(%d,%d)\n", i0, i1, j0, j1);
653
3.40k
    for (i = i0; i < i1; i++)
654
10.4k
        for (j = j0; j < j1; j++) {
655
7.82k
            int x = (int)fastfloor(step_matrix.xx * i +
656
7.82k
                          step_matrix.yx * j + step_matrix.tx);
657
7.82k
            int y = (int)fastfloor(step_matrix.xy * i +
658
7.82k
                          step_matrix.yy * j + step_matrix.ty);
659
7.82k
            int w = ptrans_pat->width;
660
7.82k
            int h = ptrans_pat->height;
661
7.82k
            int xoff, yoff;
662
7.82k
            int px, py;
663
664
7.82k
            if_debug4m('T', mem, "[T]i=%d j=%d x,y=(%d,%d)", i, j, x, y);
665
7.82k
            if (x < x0)
666
2.66k
                xoff = x0 - x, x = x0, w -= xoff;
667
5.16k
            else
668
5.16k
                xoff = 0;
669
7.82k
            if (y < y0)
670
5.11k
                yoff = y0 - y, y = y0, h -= yoff;
671
2.71k
            else
672
2.71k
                yoff = 0;
673
7.82k
            if (x + w > x1)
674
5.27k
                w = x1 - x;
675
7.82k
            if (y + h > y1)
676
5.11k
                h = y1 - y;
677
7.82k
            if_debug6m('T', mem, "=>(%d,%d) w,h=(%d,%d) x/yoff=(%d,%d)\n",
678
7.82k
                       x, y, w, h, xoff, yoff);
679
7.82k
            if (w > 0 && h > 0) {
680
681
892
                px = imod(xoff - x, ptile->ttrans->width);
682
892
                py = imod(yoff - y, ptile->ttrans->height);
683
684
                /* Set the offsets for colored pattern fills */
685
892
                ptfs->xoff = xoff;
686
892
                ptfs->yoff = yoff;
687
688
                /* We only go through blending during tiling, if there was overlap
689
                   as defined by the step matrix and the bounding box.
690
                   Ignore if the area is outside the fill_trans_buffer.rect (bug 700719) */
691
892
                if (x > fill_trans_buffer->rect.q.x || x+w < 0 ||
692
892
                    y > fill_trans_buffer->rect.q.y || y+h < 0)
693
0
                    continue; /* skip the fill (can breakpoint here) */
694
892
                ptile->ttrans->pat_trans_fill(x, y, x+w, y+h, px, py, ptile,
695
892
                    fill_trans_buffer, native16);
696
892
            }
697
7.82k
        }
698
825
    return 0;
699
825
}
700
701
static void
702
be_rev_cpy(uint16_t *dst,const uint16_t *src,int n)
703
0
{
704
0
    for (; n != 0; n--) {
705
0
        uint16_t in = *src++;
706
0
        ((byte *)dst)[0] = in>>8;
707
0
        ((byte *)dst)[1] = in;
708
0
        dst++;
709
0
    }
710
0
}
711
712
/* This does the case of tiling with simple tiles.  Since it is not commented
713
 * anywhere note that simple means that the tile size is the same as the step
714
 * matrix size and the cross terms in the step matrix are 0.  Hence a simple
715
 * case of tile replication. This needs to be optimized.  */
716
/* Our source tile runs (conceptually) from (0,0) to
717
 * (ptile->ttrans->width, ptile->ttrans->height). In practise, only a limited
718
 * section of this (ptile->rect) may actually be used. */
719
void
720
tile_rect_trans_simple(int xmin, int ymin, int xmax, int ymax,
721
                       int px, int py, const gx_color_tile *ptile,
722
                       gx_pattern_trans_t *fill_trans_buffer,
723
                       int native16)
724
11.5k
{
725
11.5k
    int kk, jj, ii, h, w;
726
11.5k
    int buff_out_y_offset, buff_out_x_offset;
727
11.5k
    unsigned char *ptr_out, *ptr_in, *buff_out, *buff_in, *ptr_out_temp;
728
11.5k
    unsigned char *row_ptr;
729
11.5k
    int in_row_offset;
730
11.5k
    int dx, dy;
731
11.5k
    int left_rem_end, left_width, num_full_tiles, right_tile_width;
732
11.5k
    int left_copy_rem_end, left_copy_width, left_copy_offset, left_copy_start;
733
11.5k
    int mid_copy_width, right_copy_width;
734
11.5k
    int tile_width  = ptile->ttrans->width;
735
11.5k
    int tile_height = ptile->ttrans->height;
736
11.5k
    int src_planes = fill_trans_buffer->n_chan + (fill_trans_buffer->has_tags ? 1 : 0);
737
11.5k
    pdf14_buf *buf = fill_trans_buffer->buf;
738
11.5k
    bool deep = fill_trans_buffer->deep;
739
740
    /* Update the bbox in the topmost stack entry to reflect the fact that we
741
     * have drawn into it. FIXME: This makes the groups too large! */
742
11.5k
    if (buf->dirty.p.x > xmin)
743
10.6k
        buf->dirty.p.x = xmin;
744
11.5k
    if (buf->dirty.p.y > ymin)
745
9.99k
        buf->dirty.p.y = ymin;
746
11.5k
    if (buf->dirty.q.x < xmax)
747
10.6k
        buf->dirty.q.x = xmax;
748
11.5k
    if (buf->dirty.q.y < ymax)
749
9.99k
        buf->dirty.q.y = ymax;
750
11.5k
    buff_out_y_offset = ymin - fill_trans_buffer->rect.p.y;
751
11.5k
    buff_out_x_offset = xmin - fill_trans_buffer->rect.p.x;
752
753
11.5k
    buff_out = fill_trans_buffer->transbytes +
754
11.5k
        buff_out_y_offset * fill_trans_buffer->rowstride +
755
11.5k
        (buff_out_x_offset<<deep);
756
757
11.5k
    buff_in = ptile->ttrans->transbytes;
758
759
11.5k
    h = ymax - ymin;
760
11.5k
    w = xmax - xmin;
761
762
11.5k
    if (h <= 0 || w <= 0) return;
763
764
    /* Calc dx, dy within the entire (conceptual) input tile. */
765
9.99k
    dx = (xmin + px) % tile_width;
766
9.99k
    dy = (ymin + py) % tile_height;
767
768
    /* To speed this up, the inner loop on the width is implemented with
769
     * memcpys where we have a left remainder, full tiles and a right
770
     * remainder. Depending upon the rect that we are filling we may have
771
     * only one of these three portions, or two or all three.  We compute
772
     * the parts now outside the loops. */
773
774
    /* Left remainder part */
775
9.99k
    left_rem_end = min(dx+w,tile_width);
776
9.99k
    left_width = left_rem_end - dx;
777
9.99k
    left_copy_start = max(dx,ptile->ttrans->rect.p.x);
778
9.99k
    left_copy_rem_end = min(dx+w,ptile->ttrans->rect.q.x);
779
9.99k
    left_copy_width = left_copy_rem_end - left_copy_start;
780
9.99k
    if (left_copy_width < 0)
781
0
        left_copy_width = 0;
782
9.99k
    left_copy_offset = (left_copy_start-ptile->ttrans->rect.p.x)<<deep;
783
784
    /* Now the middle part */
785
9.99k
    num_full_tiles = (int)fastfloor((float) (w - left_width)/ (float) tile_width);
786
9.99k
    mid_copy_width = ptile->ttrans->rect.q.x - ptile->ttrans->rect.p.x;
787
788
    /* Now the right part */
789
9.99k
    right_tile_width = w - num_full_tiles*tile_width - left_width;
790
9.99k
    right_copy_width = right_tile_width - ptile->ttrans->rect.p.x;
791
9.99k
    if (right_copy_width > ptile->ttrans->rect.q.x)
792
0
        right_copy_width = ptile->ttrans->rect.q.x;
793
9.99k
    right_copy_width -= ptile->ttrans->rect.p.x;
794
9.99k
    if (right_copy_width < 0)
795
0
        right_copy_width = 0;
796
797
9.99k
    if (deep && native16) {
798
        /* fill_trans_buffer is in native endian. ptile is in big endian. */
799
        /* Convert as we copy. */
800
0
        for (kk = 0; kk < src_planes; kk++) {
801
802
0
            ptr_out = buff_out + kk * fill_trans_buffer->planestride;
803
0
            ptr_in  = buff_in  + kk * ptile->ttrans->planestride;
804
0
            if (fill_trans_buffer->has_shape && kk == fill_trans_buffer->n_chan)
805
0
                ptr_out += fill_trans_buffer->planestride; /* tag plane follows shape plane */
806
807
0
            for (jj = 0; jj < h; jj++, ptr_out += fill_trans_buffer->rowstride) {
808
809
0
                in_row_offset = ((jj + dy) % ptile->ttrans->height);
810
0
                if (in_row_offset >= ptile->ttrans->rect.q.y)
811
0
                    continue;
812
0
                in_row_offset -= ptile->ttrans->rect.p.y;
813
0
                if (in_row_offset < 0)
814
0
                    continue;
815
0
                row_ptr = ptr_in + in_row_offset * ptile->ttrans->rowstride;
816
817
                 /* This is the case when we have no blending. */
818
0
                ptr_out_temp = ptr_out;
819
820
                /* Left part */
821
0
                be_rev_cpy((uint16_t *)ptr_out_temp, (uint16_t *)(row_ptr + left_copy_offset), left_copy_width);
822
0
                ptr_out_temp += left_width<<deep;
823
824
                /* Now the full tiles */
825
826
0
                for ( ii = 0; ii < num_full_tiles; ii++){
827
0
                    be_rev_cpy((uint16_t *)ptr_out_temp, (uint16_t *)row_ptr, mid_copy_width);
828
0
                    ptr_out_temp += tile_width<<deep;
829
0
                }
830
831
                /* Now the remainder */
832
0
                be_rev_cpy((uint16_t *)ptr_out_temp, (uint16_t *)row_ptr, right_copy_width);
833
0
            }
834
0
        }
835
9.99k
    } else {
836
49.5k
        for (kk = 0; kk < src_planes; kk++) {
837
838
39.5k
            ptr_out = buff_out + kk * fill_trans_buffer->planestride;
839
39.5k
            ptr_in  = buff_in  + kk * ptile->ttrans->planestride;
840
39.5k
            if (fill_trans_buffer->has_shape && kk == fill_trans_buffer->n_chan)
841
0
                ptr_out += fill_trans_buffer->planestride; /* tag plane follows shape plane */
842
843
324k
            for (jj = 0; jj < h; jj++, ptr_out += fill_trans_buffer->rowstride) {
844
845
285k
                in_row_offset = ((jj + dy) % ptile->ttrans->height);
846
285k
                if (in_row_offset >= ptile->ttrans->rect.q.y)
847
0
                    continue;
848
285k
                in_row_offset -= ptile->ttrans->rect.p.y;
849
285k
                if (in_row_offset < 0)
850
0
                    continue;
851
285k
                row_ptr = ptr_in + in_row_offset * ptile->ttrans->rowstride;
852
853
                 /* This is the case when we have no blending. */
854
285k
                ptr_out_temp = ptr_out;
855
856
                /* Left part */
857
285k
                memcpy( ptr_out_temp, row_ptr + left_copy_offset, left_copy_width<<deep);
858
285k
                ptr_out_temp += left_width<<deep;
859
860
                /* Now the full tiles */
861
862
494k
                for ( ii = 0; ii < num_full_tiles; ii++){
863
208k
                    memcpy( ptr_out_temp, row_ptr, mid_copy_width<<deep);
864
208k
                    ptr_out_temp += tile_width<<deep;
865
208k
                }
866
867
                /* Now the remainder */
868
285k
                memcpy( ptr_out_temp, row_ptr, right_copy_width<<deep);
869
285k
            }
870
39.5k
        }
871
9.99k
    }
872
873
    /* If the group we are filling has a shape plane fill that now */
874
    /* Note:  Since this was a virgin group push we can just blast it with
875
     * 255 */
876
9.99k
    if (fill_trans_buffer->has_shape) {
877
0
        ptr_out = buff_out + fill_trans_buffer->n_chan * fill_trans_buffer->planestride;
878
0
        for (jj = 0; jj < h; jj++,ptr_out += fill_trans_buffer->rowstride) {
879
0
            memset(ptr_out, 255, w<<deep);
880
0
        }
881
0
    }
882
9.99k
}
883
884
/* This does the case of tiling with non simple tiles.  In this case, the
885
 * tiles may overlap and so we really need to do blending within the existing
886
 * buffer.  This needs some serious optimization. */
887
static void
888
do_tile_rect_trans_blend(int xmin, int ymin, int xmax, int ymax,
889
                         int px, int py, const gx_color_tile *ptile,
890
                         gx_pattern_trans_t *fill_trans_buffer)
891
70
{
892
70
    int kk, jj, ii, h, w;
893
70
    int buff_out_y_offset, buff_out_x_offset;
894
70
    unsigned char *buff_out, *buff_in;
895
70
    unsigned char *buff_ptr, *row_ptr_in, *row_ptr_out;
896
70
    unsigned char *tile_ptr;
897
70
    int in_row_offset;
898
70
    int dx, dy;
899
70
    byte src[PDF14_MAX_PLANES];
900
70
    byte dst[PDF14_MAX_PLANES];
901
70
    int tile_width  = ptile->ttrans->width;
902
70
    int tile_height = ptile->ttrans->height;
903
70
    int num_chan    = ptile->ttrans->n_chan;  /* Includes alpha */
904
70
    int tag_offset = fill_trans_buffer->n_chan + (fill_trans_buffer->has_shape ? 1 : 0);
905
70
    pdf14_device *p14dev = (pdf14_device *) fill_trans_buffer->pdev14;
906
907
70
    if (fill_trans_buffer->has_tags == 0)
908
70
        tag_offset = 0;
909
910
70
    buff_out_y_offset = ymin - fill_trans_buffer->rect.p.y;
911
70
    buff_out_x_offset = xmin - fill_trans_buffer->rect.p.x;
912
913
70
    h = ymax - ymin;
914
70
    w = xmax - xmin;
915
916
70
    if (h <= 0 || w <= 0) return;
917
918
    /* Calc dx, dy within the entire (conceptual) input tile. */
919
70
    dx = (xmin + px) % tile_width;
920
70
    dy = (ymin + py) % tile_height;
921
922
70
    buff_out = fill_trans_buffer->transbytes +
923
70
        buff_out_y_offset * fill_trans_buffer->rowstride +
924
70
        buff_out_x_offset;
925
926
70
    buff_in = ptile->ttrans->transbytes;
927
928
440
    for (jj = 0; jj < h; jj++){
929
930
370
        in_row_offset = (jj + dy) % ptile->ttrans->height;
931
370
        if (in_row_offset >= ptile->ttrans->rect.q.y)
932
0
            continue;
933
370
        in_row_offset -= ptile->ttrans->rect.p.y;
934
370
        if (in_row_offset < 0)
935
0
            continue;
936
370
        row_ptr_in = buff_in + in_row_offset * ptile->ttrans->rowstride;
937
938
370
        row_ptr_out = buff_out + jj * fill_trans_buffer->rowstride;
939
940
1.33k
        for (ii = 0; ii < w; ii++) {
941
962
            int x_in_offset = (dx + ii) % ptile->ttrans->width;
942
943
962
            if (x_in_offset >= ptile->ttrans->rect.q.x)
944
0
                continue;
945
962
            x_in_offset -= ptile->ttrans->rect.p.x;
946
962
            if (x_in_offset < 0)
947
0
                continue;
948
962
            tile_ptr = row_ptr_in + x_in_offset;
949
962
            buff_ptr = row_ptr_out + ii;
950
951
            /* We need to blend here.  The blending mode from the current
952
               imager state is used.
953
            */
954
955
            /* The color values. This needs to be optimized */
956
4.81k
            for (kk = 0; kk < num_chan; kk++) {
957
3.84k
                dst[kk] = *(buff_ptr + kk * fill_trans_buffer->planestride);
958
3.84k
                src[kk] = *(tile_ptr + kk * ptile->ttrans->planestride);
959
3.84k
            }
960
961
            /* Blend */
962
962
            art_pdf_composite_pixel_alpha_8(dst, src, ptile->ttrans->n_chan-1,
963
962
                                            ptile->blending_mode, ptile->ttrans->n_chan-1,
964
962
                                            ptile->ttrans->blending_procs, p14dev);
965
966
            /* Store the color values */
967
4.81k
            for (kk = 0; kk < num_chan; kk++) {
968
3.84k
                *(buff_ptr + kk * fill_trans_buffer->planestride) = dst[kk];
969
3.84k
            }
970
            /* Now handle the blending of the tag. NB: dst tag_offset follows shape */
971
962
            if (tag_offset > 0) {
972
0
                int src_tag = *(tile_ptr + num_chan * ptile->ttrans->planestride);
973
0
                int dst_tag = *(buff_ptr + tag_offset * fill_trans_buffer->planestride);
974
975
0
                dst_tag |= src_tag; /* simple blend combines tags */
976
0
                *(buff_ptr + tag_offset * fill_trans_buffer->planestride) = dst_tag;
977
0
            }
978
962
        }
979
370
    }
980
981
    /* If the group we are filling has a shape plane fill that now */
982
    /* Note:  Since this was a virgin group push we can just blast it with
983
     * 255 */
984
70
    if (fill_trans_buffer->has_shape) {
985
0
        buff_ptr = buff_out + fill_trans_buffer->n_chan * fill_trans_buffer->planestride;
986
987
0
        for (jj = 0; jj < h; jj++) {
988
0
            memset(buff_ptr, 255, w);
989
0
            buff_ptr += fill_trans_buffer->rowstride;
990
0
        }
991
0
    }
992
70
}
993
994
/* In this version, source data is big endian, dest is native endian */
995
static void
996
do_tile_rect_trans_blend_16(int xmin, int ymin, int xmax, int ymax,
997
                            int px, int py, const gx_color_tile *ptile,
998
                            gx_pattern_trans_t *fill_trans_buffer)
999
0
{
1000
0
    int kk, jj, ii, h, w;
1001
0
    int buff_out_y_offset, buff_out_x_offset;
1002
0
    uint16_t *buff_out, *buff_in;
1003
0
    uint16_t *buff_ptr, *row_ptr_in, *row_ptr_out;
1004
0
    uint16_t *tile_ptr;
1005
0
    int in_row_offset;
1006
0
    int dx, dy;
1007
0
    uint16_t src[PDF14_MAX_PLANES];
1008
0
    uint16_t dst[PDF14_MAX_PLANES];
1009
0
    int tile_width  = ptile->ttrans->width;
1010
0
    int tile_height = ptile->ttrans->height;
1011
0
    int num_chan    = ptile->ttrans->n_chan;  /* Includes alpha */
1012
0
    int tag_offset = fill_trans_buffer->n_chan + (fill_trans_buffer->has_shape ? 1 : 0);
1013
0
    pdf14_device *p14dev = (pdf14_device *) fill_trans_buffer->pdev14;
1014
1015
0
    if (fill_trans_buffer->has_tags == 0)
1016
0
        tag_offset = 0;
1017
1018
0
    buff_out_y_offset = ymin - fill_trans_buffer->rect.p.y;
1019
0
    buff_out_x_offset = xmin - fill_trans_buffer->rect.p.x;
1020
1021
0
    h = ymax - ymin;
1022
0
    w = xmax - xmin;
1023
1024
0
    if (h <= 0 || w <= 0) return;
1025
1026
    /* Calc dx, dy within the entire (conceptual) input tile. */
1027
0
    dx = (xmin + px) % tile_width;
1028
0
    dy = (ymin + py) % tile_height;
1029
1030
0
    buff_out = (uint16_t *)(void *)(fill_trans_buffer->transbytes +
1031
0
                                    buff_out_y_offset * fill_trans_buffer->rowstride +
1032
0
                                    buff_out_x_offset*2);
1033
1034
0
    buff_in = (uint16_t *)(void *)ptile->ttrans->transbytes;
1035
1036
0
    for (jj = 0; jj < h; jj++){
1037
1038
0
        in_row_offset = (jj + dy) % ptile->ttrans->height;
1039
0
        if (in_row_offset >= ptile->ttrans->rect.q.y)
1040
0
            continue;
1041
0
        in_row_offset -= ptile->ttrans->rect.p.y;
1042
0
        if (in_row_offset < 0)
1043
0
            continue;
1044
0
        row_ptr_in = buff_in + in_row_offset * (ptile->ttrans->rowstride>>1);
1045
1046
0
        row_ptr_out = buff_out + jj * (fill_trans_buffer->rowstride>>1);
1047
1048
0
        for (ii = 0; ii < w; ii++) {
1049
0
            int x_in_offset = (dx + ii) % ptile->ttrans->width;
1050
1051
0
            if (x_in_offset >= ptile->ttrans->rect.q.x)
1052
0
                continue;
1053
0
            x_in_offset -= ptile->ttrans->rect.p.x;
1054
0
            if (x_in_offset < 0)
1055
0
                continue;
1056
0
            tile_ptr = row_ptr_in + x_in_offset;
1057
0
            buff_ptr = row_ptr_out + ii;
1058
1059
            /* We need to blend here.  The blending mode from the current
1060
               imager state is used.
1061
            */
1062
1063
            /* Data is stored in big endian, but must be processed in native */
1064
0
#define GET16_BE2NATIVE(v) \
1065
0
    ((((byte *)(v))[0]<<8) | (((byte *)(v))[1]))
1066
1067
            /* The color values. This needs to be optimized */
1068
0
            for (kk = 0; kk < num_chan; kk++) {
1069
0
                dst[kk] = *(buff_ptr + kk * (fill_trans_buffer->planestride>>1));
1070
0
                src[kk] = GET16_BE2NATIVE(tile_ptr + kk * (ptile->ttrans->planestride>>1));
1071
0
            }
1072
1073
            /* Blend */
1074
0
            art_pdf_composite_pixel_alpha_16(dst, src, ptile->ttrans->n_chan-1,
1075
0
                                             ptile->blending_mode, ptile->ttrans->n_chan-1,
1076
0
                                             ptile->ttrans->blending_procs, p14dev);
1077
1078
            /* Store the color values */
1079
0
            for (kk = 0; kk < num_chan; kk++) {
1080
0
                *(buff_ptr + kk * (fill_trans_buffer->planestride>>1)) = dst[kk];
1081
0
            }
1082
            /* Now handle the blending of the tag. NB: dst tag_offset follows shape */
1083
0
            if (tag_offset > 0) {
1084
0
                int src_tag = GET16_BE2NATIVE(tile_ptr + (num_chan * ptile->ttrans->planestride>>1));
1085
0
                int dst_tag = *(buff_ptr + (tag_offset * fill_trans_buffer->planestride>>1));
1086
1087
0
                dst_tag |= src_tag; /* simple blend combines tags */
1088
0
                *(buff_ptr + (tag_offset * fill_trans_buffer->planestride>>1)) = dst_tag;
1089
0
            }
1090
0
        }
1091
0
    }
1092
0
#undef GET16_BE2NATIVE
1093
1094
    /* If the group we are filling has a shape plane fill that now */
1095
    /* Note:  Since this was a virgin group push we can just blast it with
1096
     * 255 */
1097
0
    if (fill_trans_buffer->has_shape) {
1098
0
        buff_ptr = buff_out + fill_trans_buffer->n_chan * (fill_trans_buffer->planestride>>1);
1099
1100
0
        for (jj = 0; jj < h; jj++) {
1101
0
            memset(buff_ptr, 255, w*2);
1102
0
            buff_ptr += fill_trans_buffer->rowstride>>1;
1103
0
        }
1104
0
    }
1105
0
}
1106
1107
/* In this version, both source and dest data is big endian */
1108
static void
1109
do_tile_rect_trans_blend_16be(int xmin, int ymin, int xmax, int ymax,
1110
                              int px, int py, const gx_color_tile *ptile,
1111
                              gx_pattern_trans_t *fill_trans_buffer)
1112
0
{
1113
0
    int kk, jj, ii, h, w;
1114
0
    int buff_out_y_offset, buff_out_x_offset;
1115
0
    uint16_t *buff_out, *buff_in;
1116
0
    uint16_t *buff_ptr, *row_ptr_in, *row_ptr_out;
1117
0
    uint16_t *tile_ptr;
1118
0
    int in_row_offset;
1119
0
    int dx, dy;
1120
0
    uint16_t src[PDF14_MAX_PLANES];
1121
0
    uint16_t dst[PDF14_MAX_PLANES];
1122
0
    int tile_width  = ptile->ttrans->width;
1123
0
    int tile_height = ptile->ttrans->height;
1124
0
    int num_chan    = ptile->ttrans->n_chan;  /* Includes alpha */
1125
0
    int tag_offset = fill_trans_buffer->n_chan + (fill_trans_buffer->has_shape ? 1 : 0);
1126
0
    pdf14_device *p14dev = (pdf14_device *) fill_trans_buffer->pdev14;
1127
1128
0
    if (fill_trans_buffer->has_tags == 0)
1129
0
        tag_offset = 0;
1130
1131
0
    buff_out_y_offset = ymin - fill_trans_buffer->rect.p.y;
1132
0
    buff_out_x_offset = xmin - fill_trans_buffer->rect.p.x;
1133
1134
0
    h = ymax - ymin;
1135
0
    w = xmax - xmin;
1136
1137
0
    if (h <= 0 || w <= 0) return;
1138
1139
    /* Calc dx, dy within the entire (conceptual) input tile. */
1140
0
    dx = (xmin + px) % tile_width;
1141
0
    dy = (ymin + py) % tile_height;
1142
1143
0
    buff_out = (uint16_t *)(void *)(fill_trans_buffer->transbytes +
1144
0
                                    buff_out_y_offset * fill_trans_buffer->rowstride +
1145
0
                                    buff_out_x_offset*2);
1146
1147
0
    buff_in = (uint16_t *)(void *)ptile->ttrans->transbytes;
1148
1149
0
    for (jj = 0; jj < h; jj++){
1150
1151
0
        in_row_offset = (jj + dy) % ptile->ttrans->height;
1152
0
        if (in_row_offset >= ptile->ttrans->rect.q.y)
1153
0
            continue;
1154
0
        in_row_offset -= ptile->ttrans->rect.p.y;
1155
0
        if (in_row_offset < 0)
1156
0
            continue;
1157
0
        row_ptr_in = buff_in + in_row_offset * (ptile->ttrans->rowstride>>1);
1158
1159
0
        row_ptr_out = buff_out + jj * (fill_trans_buffer->rowstride>>1);
1160
1161
0
        for (ii = 0; ii < w; ii++) {
1162
0
            int x_in_offset = (dx + ii) % ptile->ttrans->width;
1163
1164
0
            if (x_in_offset >= ptile->ttrans->rect.q.x)
1165
0
                continue;
1166
0
            x_in_offset -= ptile->ttrans->rect.p.x;
1167
0
            if (x_in_offset < 0)
1168
0
                continue;
1169
0
            tile_ptr = row_ptr_in + x_in_offset;
1170
0
            buff_ptr = row_ptr_out + ii;
1171
1172
            /* We need to blend here.  The blending mode from the current
1173
               imager state is used.
1174
            */
1175
1176
            /* Data is stored in big endian, but must be processed in native */
1177
0
#define GET16_BE2NATIVE(v) \
1178
0
    ((((byte *)(v))[0]<<8) | (((byte *)(v))[1]))
1179
0
#define PUT16_NATIVE2BE(p,v) \
1180
0
    ((((byte *)(p))[0] = v>>8), (((byte *)(p))[1] = v))
1181
1182
            /* The color values. This needs to be optimized */
1183
0
            for (kk = 0; kk < num_chan; kk++) {
1184
0
                dst[kk] = GET16_BE2NATIVE(buff_ptr + kk * (fill_trans_buffer->planestride>>1));
1185
0
                src[kk] = GET16_BE2NATIVE(tile_ptr + kk * (ptile->ttrans->planestride>>1));
1186
0
            }
1187
1188
            /* Blend */
1189
0
            art_pdf_composite_pixel_alpha_16(dst, src, ptile->ttrans->n_chan-1,
1190
0
                                             ptile->blending_mode, ptile->ttrans->n_chan-1,
1191
0
                                             ptile->ttrans->blending_procs, p14dev);
1192
1193
            /* Store the color values */
1194
0
            for (kk = 0; kk < num_chan; kk++) {
1195
0
                PUT16_NATIVE2BE(buff_ptr + kk * (fill_trans_buffer->planestride>>1), dst[kk]);
1196
0
            }
1197
            /* Now handle the blending of the tag. NB: dst tag_offset follows shape */
1198
0
            if (tag_offset > 0) {
1199
0
                int src_tag = GET16_BE2NATIVE(tile_ptr + (num_chan * ptile->ttrans->planestride>>1));
1200
0
                int dst_tag = GET16_BE2NATIVE(buff_ptr + (tag_offset * fill_trans_buffer->planestride>>1));
1201
1202
0
                dst_tag |= src_tag; /* simple blend combines tags */
1203
0
                PUT16_NATIVE2BE(buff_ptr + (tag_offset * fill_trans_buffer->planestride>>1), dst_tag);
1204
0
            }
1205
0
        }
1206
0
    }
1207
1208
    /* If the group we are filling has a shape plane fill that now */
1209
    /* Note:  Since this was a virgin group push we can just blast it with
1210
     * 255 */
1211
0
    if (fill_trans_buffer->has_shape) {
1212
0
        buff_ptr = buff_out + fill_trans_buffer->n_chan * (fill_trans_buffer->planestride>>1);
1213
1214
0
        for (jj = 0; jj < h; jj++) {
1215
0
            memset(buff_ptr, 255, w*2);
1216
0
            buff_ptr += fill_trans_buffer->rowstride>>1;
1217
0
        }
1218
0
    }
1219
0
}
1220
1221
void
1222
tile_rect_trans_blend(int xmin, int ymin, int xmax, int ymax,
1223
                      int px, int py, const gx_color_tile *ptile,
1224
                      gx_pattern_trans_t *fill_trans_buffer,
1225
                      int native16)
1226
70
{
1227
70
    pdf14_buf *buf = fill_trans_buffer->buf;
1228
1229
    /* Update the bbox in the topmost stack entry to reflect the fact that we
1230
     * have drawn into it. FIXME: This makes the groups too large! */
1231
70
    if (buf->dirty.p.x > xmin)
1232
6
        buf->dirty.p.x = xmin;
1233
70
    if (buf->dirty.p.y > ymin)
1234
6
        buf->dirty.p.y = ymin;
1235
70
    if (buf->dirty.q.x < xmax)
1236
12
        buf->dirty.q.x = xmax;
1237
70
    if (buf->dirty.q.y < ymax)
1238
7
        buf->dirty.q.y = ymax;
1239
1240
70
    if (!ptile->ttrans->deep)
1241
70
        do_tile_rect_trans_blend(xmin, ymin, xmax, ymax,
1242
70
                                 px, py, ptile, fill_trans_buffer);
1243
0
    else if (native16)
1244
0
        do_tile_rect_trans_blend_16(xmin, ymin, xmax, ymax,
1245
0
                                    px, py, ptile, fill_trans_buffer);
1246
0
    else
1247
0
        do_tile_rect_trans_blend_16be(xmin, ymin, xmax, ymax,
1248
0
                                      px, py, ptile, fill_trans_buffer);
1249
70
}
1250
1251
/* This version does a rect fill with the transparency object */
1252
int
1253
gx_dc_pat_trans_fill_rectangle(const gx_device_color * pdevc, int x, int y,
1254
                               int w, int h, gx_device * dev,
1255
                               gs_logical_operation_t lop,
1256
                               const gx_rop_source_t * source)
1257
0
{
1258
0
    gx_color_tile *ptile = pdevc->colors.pattern.p_tile;
1259
0
    int code;
1260
0
    gs_int_point phase;
1261
0
    const gx_rop_source_t *rop_source = source;
1262
0
    gx_rop_source_t no_source;
1263
1264
0
    if (ptile == 0)             /* null pattern */
1265
0
        return 0;
1266
0
    if (rop_source == NULL)
1267
0
        set_rop_no_source(rop_source, no_source, dev);
1268
1269
0
    phase.x = pdevc->phase.x;
1270
0
    phase.y = pdevc->phase.y;
1271
1272
#if 0
1273
    if_debug8m('v', ptile->ttrans->mem,
1274
            "[v]gx_dc_pat_trans_fill_rectangle, Fill: (%d, %d), %d x %d To Buffer: (%d, %d), %d x %d \n",
1275
            x, y, w, h,  ptile->ttrans->fill_trans_buffer->rect.p.x,
1276
            ptile->ttrans->fill_trans_buffer->rect.p.y,
1277
            ptile->ttrans->fill_trans_buffer->rect.q.x -
1278
            ptile->ttrans->fill_trans_buffer->rect.p.x,
1279
            ptile->ttrans->fill_trans_buffer->rect.q.y -
1280
            ptile->ttrans->fill_trans_buffer->rect.p.y);
1281
#endif
1282
0
    code = gx_trans_pattern_fill_rect(x, y, x+w, y+h, ptile,
1283
0
                                      ptile->ttrans->fill_trans_buffer, phase,
1284
0
                                      dev, pdevc, 0);
1285
0
    return code;
1286
0
}
1287
1288
/* This fills the transparency buffer rectangles with a pattern buffer
1289
   that includes transparency */
1290
int
1291
gx_trans_pattern_fill_rect(int xmin, int ymin, int xmax, int ymax,
1292
                           gx_color_tile *ptile,
1293
                           gx_pattern_trans_t *fill_trans_buffer,
1294
                           gs_int_point phase, gx_device *dev,
1295
                           const gx_device_color * pdevc,
1296
                           int native16)
1297
13.0k
{
1298
13.0k
    tile_fill_trans_state_t state_trans;
1299
13.0k
    tile_fill_state_t state_clist_trans;
1300
13.0k
    int code = 0;
1301
13.0k
    int w = xmax - xmin;
1302
13.0k
    int h = ymax - ymin;
1303
1304
13.0k
    if (ptile == 0)             /* null pattern */
1305
0
        return 0;
1306
1307
13.0k
    fit_fill_xywh(dev, xmin, ymin, w, h);
1308
13.0k
    if (w < 0 || h < 0)
1309
1
        return 0;
1310
13.0k
    xmax = w + xmin;
1311
13.0k
    ymax = h + ymin;
1312
1313
    /* Initialize the fill state */
1314
13.0k
    state_trans.phase.x = phase.x;
1315
13.0k
    state_trans.phase.y = phase.y;
1316
1317
13.0k
    if (ptile->is_simple && ptile->cdev == NULL) {
1318
        /* A simple case.  Tile is not clist and simple. */
1319
10.6k
        int px =
1320
10.6k
            imod(-(int)fastfloor(ptile->step_matrix.tx - phase.x + 0.5),
1321
10.6k
                  ptile->ttrans->width);
1322
10.6k
        int py =
1323
10.6k
            imod(-(int)fastfloor(ptile->step_matrix.ty - phase.y + 0.5),
1324
10.6k
                 ptile->ttrans->height);
1325
1326
10.6k
        tile_rect_trans_simple(xmin, ymin, xmax, ymax, px, py, ptile,
1327
10.6k
            fill_trans_buffer, native16);
1328
10.6k
    } else {
1329
2.33k
        if (ptile->cdev == NULL) {
1330
            /* No clist for the pattern, but a complex case
1331
               This portion transforms the bounding box by the step matrix
1332
               and does partial rect fills with tiles that fall into this
1333
               transformed bbox */
1334
825
            code = tile_by_steps_trans(&state_trans, xmin, ymin, xmax-xmin,
1335
825
                                        ymax-ymin, fill_trans_buffer, ptile,
1336
825
                                        native16);
1337
1338
1.51k
        } else {
1339
            /* clist for the trans tile.  This uses the pdf14 device as a target
1340
               and should blend directly into the buffer.  Note that the
1341
               pattern can not have a push pdf14 device or a pop pdf14 device
1342
               compositor action.  Those are removed during the compositor
1343
               clist writing operation where we check for the case of a pattern
1344
               with a transparency */
1345
1.51k
            gx_device_clist *cdev = ptile->cdev;
1346
1.51k
            gx_device_clist_reader *crdev = (gx_device_clist_reader *)cdev;
1347
1.51k
            gx_strip_bitmap tbits;
1348
1349
1.51k
            code = tile_fill_init(&state_clist_trans, pdevc, dev, false);
1350
1351
1.51k
            state_clist_trans.phase.x = phase.x;
1352
1.51k
            state_clist_trans.phase.y = phase.y;
1353
1.51k
            crdev->yplane.depth = 0;
1354
1.51k
            crdev->yplane.shift = 0;
1355
1.51k
            crdev->yplane.index = -1;
1356
1.51k
            crdev->pages = NULL;
1357
1.51k
            crdev->num_pages = 1;
1358
1.51k
            state_clist_trans.orig_dev = dev;
1359
1.51k
            state_clist_trans.pdevc = pdevc;
1360
1.51k
            tbits = ptile->tbits;
1361
1.51k
            tbits.size.x = crdev->width;
1362
1.51k
            tbits.size.y = crdev->height;
1363
1.51k
            if (code >= 0)
1364
1.51k
                code = tile_by_steps(&state_clist_trans, xmin, ymin, xmax-xmin,
1365
1.51k
                                     ymax-ymin, ptile, &tbits, tile_pattern_clist);
1366
1367
1.51k
            if (code >= 0 && (state_clist_trans.cdev != NULL)) {
1368
0
                tile_clip_free((gx_device_tile_clip *)state_clist_trans.cdev);
1369
0
                state_clist_trans.cdev = NULL;
1370
0
            }
1371
1372
1.51k
        }
1373
2.33k
    }
1374
13.0k
    return code;
1375
13.0k
}