Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/base/gxclip2.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
17
/* Mask clipping for patterns */
18
#include "memory_.h"
19
#include "gx.h"
20
#include "gpcheck.h"
21
#include "gserrors.h"
22
#include "gsstruct.h"
23
#include "gxdevice.h"
24
#include "gxdevmem.h"
25
#include "gxclip2.h"
26
#include "gxdcolor.h"
27
#include "gdevmpla.h"
28
29
private_st_device_tile_clip();
30
31
/* Device procedures */
32
static dev_proc_fill_rectangle(tile_clip_fill_rectangle);
33
static dev_proc_fill_rectangle_hl_color(tile_clip_fill_rectangle_hl_color);
34
static dev_proc_copy_mono(tile_clip_copy_mono);
35
static dev_proc_copy_color(tile_clip_copy_color);
36
static dev_proc_copy_planes(tile_clip_copy_planes);
37
static dev_proc_copy_alpha(tile_clip_copy_alpha);
38
static dev_proc_copy_alpha_hl_color(tile_clip_copy_alpha_hl_color);
39
static dev_proc_strip_copy_rop2(tile_clip_strip_copy_rop2);
40
41
/* The device descriptor. */
42
static void
43
tile_clipper_initialize_device_procs(gx_device *dev)
44
42.3k
{
45
42.3k
    set_dev_proc(dev, get_initial_matrix, gx_forward_get_initial_matrix);
46
42.3k
    set_dev_proc(dev, map_rgb_color, gx_forward_map_rgb_color);
47
42.3k
    set_dev_proc(dev, map_color_rgb, gx_forward_map_color_rgb);
48
42.3k
    set_dev_proc(dev, fill_rectangle, tile_clip_fill_rectangle);
49
42.3k
    set_dev_proc(dev, copy_mono, tile_clip_copy_mono);
50
42.3k
    set_dev_proc(dev, copy_color, tile_clip_copy_color);
51
42.3k
    set_dev_proc(dev, get_params, gx_forward_get_params);
52
42.3k
    set_dev_proc(dev, put_params, gx_forward_put_params);
53
42.3k
    set_dev_proc(dev, map_cmyk_color, gx_forward_map_cmyk_color);
54
42.3k
    set_dev_proc(dev, get_page_device, gx_forward_get_page_device);
55
42.3k
    set_dev_proc(dev, get_alpha_bits, gx_forward_get_alpha_bits);
56
42.3k
    set_dev_proc(dev, copy_alpha, tile_clip_copy_alpha);
57
42.3k
    set_dev_proc(dev, get_clipping_box, gx_forward_get_clipping_box);
58
42.3k
    set_dev_proc(dev, get_bits_rectangle, gx_forward_get_bits_rectangle);
59
42.3k
    set_dev_proc(dev, composite, gx_no_composite);
60
42.3k
    set_dev_proc(dev, get_hardware_params, gx_forward_get_hardware_params);
61
42.3k
    set_dev_proc(dev, get_color_mapping_procs, gx_forward_get_color_mapping_procs);
62
42.3k
    set_dev_proc(dev, get_color_comp_index, gx_forward_get_color_comp_index);
63
42.3k
    set_dev_proc(dev, encode_color, gx_forward_encode_color);
64
42.3k
    set_dev_proc(dev, decode_color, gx_forward_decode_color);
65
42.3k
    set_dev_proc(dev, fill_rectangle_hl_color, tile_clip_fill_rectangle_hl_color);
66
42.3k
    set_dev_proc(dev, include_color_space, gx_forward_include_color_space);
67
42.3k
    set_dev_proc(dev, fill_linear_color_scanline, gx_forward_fill_linear_color_scanline);
68
42.3k
    set_dev_proc(dev, fill_linear_color_trapezoid, gx_forward_fill_linear_color_trapezoid);
69
42.3k
    set_dev_proc(dev, fill_linear_color_triangle, gx_forward_fill_linear_color_triangle);
70
42.3k
    set_dev_proc(dev, update_spot_equivalent_colors, gx_forward_update_spot_equivalent_colors);
71
42.3k
    set_dev_proc(dev, ret_devn_params, gx_forward_ret_devn_params);
72
42.3k
    set_dev_proc(dev, fillpage, gx_forward_fillpage);
73
42.3k
    set_dev_proc(dev, dev_spec_op, gx_forward_dev_spec_op);
74
42.3k
    set_dev_proc(dev, copy_planes, tile_clip_copy_planes);
75
42.3k
    set_dev_proc(dev, strip_copy_rop2, tile_clip_strip_copy_rop2);
76
42.3k
    set_dev_proc(dev, copy_alpha_hl_color, tile_clip_copy_alpha_hl_color);
77
78
    /* Ideally the following defaults would be set up for us, but this
79
     * does not currently work. */
80
42.3k
    set_dev_proc(dev, open_device, gx_default_open_device);
81
42.3k
    set_dev_proc(dev, sync_output, gx_default_sync_output);
82
42.3k
    set_dev_proc(dev, output_page, gx_default_output_page);
83
42.3k
    set_dev_proc(dev, close_device, gx_default_close_device);
84
42.3k
    set_dev_proc(dev, fill_path, gx_default_fill_path);
85
42.3k
    set_dev_proc(dev, stroke_path, gx_default_stroke_path);
86
42.3k
    set_dev_proc(dev, fill_mask, gx_default_fill_mask);
87
42.3k
    set_dev_proc(dev, fill_trapezoid, gx_default_fill_trapezoid);
88
42.3k
    set_dev_proc(dev, fill_parallelogram, gx_default_fill_parallelogram);
89
42.3k
    set_dev_proc(dev, fill_triangle, gx_default_fill_triangle);
90
42.3k
    set_dev_proc(dev, draw_thin_line, gx_default_draw_thin_line);
91
42.3k
    set_dev_proc(dev, strip_tile_rectangle, gx_default_strip_tile_rectangle);
92
42.3k
    set_dev_proc(dev, begin_typed_image, gx_default_begin_typed_image);
93
42.3k
    set_dev_proc(dev, text_begin, gx_default_text_begin);
94
42.3k
    set_dev_proc(dev, strip_tile_rect_devn, gx_default_strip_tile_rect_devn);
95
42.3k
}
96
97
static const gx_device_tile_clip gs_tile_clip_device =
98
{std_device_std_body_open(gx_device_tile_clip,
99
                          tile_clipper_initialize_device_procs,
100
                          "tile clipper",
101
                          0, 0, 1, 1)
102
};
103
104
/* Initialize a tile clipping device from a mask. */
105
int
106
tile_clip_initialize(gx_device_tile_clip * cdev, const gx_strip_bitmap * tiles,
107
                     gx_device * tdev, int px, int py)
108
42.3k
{
109
42.3k
    int code =
110
42.3k
    gx_mask_clip_initialize(cdev, &gs_tile_clip_device,
111
42.3k
                            (const gx_bitmap *)tiles,
112
42.3k
                            tdev, 0, 0, NULL);  /* phase will be reset */
113
114
42.3k
    if (code >= 0) {
115
42.3k
        cdev->tiles = *tiles;
116
42.3k
        tile_clip_set_phase(cdev, px, py);
117
42.3k
    }
118
42.3k
    return code;
119
42.3k
}
120
121
void
122
tile_clip_free(gx_device_tile_clip *cdev)
123
42.3k
{
124
    /* release the target reference */
125
42.3k
    if(cdev->finalize)
126
42.3k
        cdev->finalize((gx_device *)cdev);  /* this also sets the target to NULL */
127
42.3k
    gs_free_object(cdev->memory, cdev, "tile_clip_free(cdev)");
128
42.3k
}
129
130
/* Set the phase of the tile. */
131
void
132
tile_clip_set_phase(gx_device_tile_clip * cdev, int px, int py)
133
2.13M
{
134
2.13M
    cdev->phase.x = px;
135
2.13M
    cdev->phase.y = py;
136
2.13M
}
137
138
/* Fill a rectangle with high level devn color by tiling with the mask. */
139
static int
140
tile_clip_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect,
141
                const gs_gstate *pgs, const gx_drawing_color *pdcolor,
142
                const gx_clip_path *pcpath)
143
860
{
144
860
    gx_device_tile_clip *cdev = (gx_device_tile_clip *) dev;
145
860
    gx_device *tdev = cdev->target;
146
860
    int x, y, w, h;
147
860
    gx_device_color dcolor0, dcolor1;
148
860
    int k;
149
150
    /* Have to pack the no color index into the pure device type */
151
860
    dcolor0.type = gx_dc_type_pure;
152
860
    dcolor0.colors.pure = gx_no_color_index;
153
    /* Have to set the dcolor1 to a non mask type */
154
860
    dcolor1.type = gx_dc_type_devn;
155
55.9k
    for (k = 0; k < GS_CLIENT_COLOR_MAX_COMPONENTS; k++) {
156
55.0k
        dcolor1.colors.devn.values[k] = pdcolor->colors.devn.values[k];
157
55.0k
    }
158
860
    x = fixed2int(rect->p.x);
159
860
    y = fixed2int(rect->p.y);
160
860
    w = fixed2int(rect->q.x) - x;
161
860
    h = fixed2int(rect->q.y) - y;
162
860
    return (*dev_proc(tdev, strip_tile_rect_devn))(tdev, &cdev->tiles,
163
860
                                                    x, y, w, h, &dcolor0, &dcolor1,
164
860
                                                    cdev->phase.x, cdev->phase.y);
165
860
}
166
167
/* Fill a rectangle by tiling with the mask. */
168
static int
169
tile_clip_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
170
                         gx_color_index color)
171
8.05k
{
172
8.05k
    gx_device_tile_clip *cdev = (gx_device_tile_clip *) dev;
173
8.05k
    gx_device *tdev = cdev->target;
174
175
8.05k
    return (*dev_proc(tdev, strip_tile_rectangle)) (tdev, &cdev->tiles,
176
8.05k
                                                    x, y, w, h,
177
8.05k
                    gx_no_color_index, color, cdev->phase.x, cdev->phase.y);
178
8.05k
}
179
180
/* Calculate the X offset corresponding to a given Y, taking the phase */
181
/* and shift into account. */
182
#define x_offset(ty, cdev)\
183
1.86M
  ((cdev)->phase.x + (((ty) + (cdev)->phase.y) / (cdev)->tiles.rep_height) *\
184
1.86M
   (cdev)->tiles.rep_shift)
185
186
/* Copy a monochrome bitmap.  We divide it up into maximal chunks */
187
/* that line up with a single tile, and then do the obvious Boolean */
188
/* combination of the tile mask and the source. */
189
static int
190
tile_clip_copy_mono(gx_device * dev,
191
                const byte * data, int sourcex, int raster, gx_bitmap_id id,
192
                    int x, int y, int w, int h,
193
                    gx_color_index color0, gx_color_index color1)
194
0
{
195
0
    gx_device_tile_clip *cdev = (gx_device_tile_clip *) dev;
196
0
    gx_color_index color, mcolor0, mcolor1;
197
0
    int ty, ny;
198
0
    int code;
199
200
0
    setup_mask_copy_mono(cdev, color, mcolor0, mcolor1);
201
0
    for (ty = y; ty < y + h; ty += ny) {
202
0
        int tx, nx;
203
0
        int cy = (ty + cdev->phase.y) % cdev->tiles.rep_height;
204
0
        int xoff = x_offset(ty, cdev);
205
206
0
        ny = min(y + h - ty, cdev->tiles.size.y - cy);
207
0
        if (ny > cdev->mdev.height)
208
0
            ny = cdev->mdev.height;
209
0
        for (tx = x; tx < x + w; tx += nx) {
210
0
            int cx = (tx + xoff) % cdev->tiles.rep_width;
211
212
0
            nx = min(x + w - tx, cdev->tiles.size.x - cx);
213
            /* Copy a tile slice to the memory device buffer. */
214
0
            memcpy(cdev->buffer.bytes,
215
0
                   cdev->tiles.data + cy * cdev->tiles.raster,
216
0
                   (size_t)cdev->tiles.raster * ny);
217
            /* Intersect the tile with the source data. */
218
            /* mcolor0 and mcolor1 invert the data if needed. */
219
            /* This call can't fail. */
220
0
            (*dev_proc(&cdev->mdev, copy_mono)) ((gx_device *) & cdev->mdev,
221
0
                                 data + (ty - y) * raster, sourcex + tx - x,
222
0
                                                 raster, gx_no_bitmap_id,
223
0
                                           cx, 0, nx, ny, mcolor0, mcolor1);
224
            /* Now copy the color through the double mask. */
225
0
            code = (*dev_proc(cdev->target, copy_mono)) (cdev->target,
226
0
                                 cdev->buffer.bytes, cx, cdev->tiles.raster,
227
0
                                                         gx_no_bitmap_id,
228
0
                                  tx, ty, nx, ny, gx_no_color_index, color);
229
0
            if (code < 0)
230
0
                return code;
231
0
        }
232
0
    }
233
0
    return 0;
234
0
}
235
236
/*
237
 * Define the skeleton for the other copying operations.  We can't use the
238
 * BitBlt tricks: we have to scan for runs of 1s.  There are many obvious
239
 * ways to speed this up; we'll implement some if we need to.  The schema
240
 * is:
241
 *      FOR_RUNS(data_row, tx1, tx, ty) {
242
 *        ... process the run ([tx1,tx),ty) ...
243
 *      } END_FOR_RUNS();
244
 * Free variables: cdev, data, sourcex, raster, x, y, w, h.
245
 */
246
#define t_next(tx)\
247
763M
  BEGIN {\
248
763M
    if ( ++cx == cdev->tiles.size.x )\
249
763M
      cx = 0, tp = tile_row, tbit = 0x80;\
250
763M
    else if ( (tbit >>= 1) == 0 )\
251
392M
      tp++, tbit = 0x80;\
252
763M
    tx++;\
253
763M
  } END
254
#define FOR_RUNS(data_row, tx1, tx, ty)\
255
1.52M
        const byte *data_row = data;\
256
1.52M
        int cy = imod(y + cdev->phase.y, cdev->tiles.rep_height);\
257
1.52M
        const byte *tile_row = cdev->tiles.data + cy * cdev->tiles.raster;\
258
1.52M
        int ty;\
259
1.52M
\
260
3.38M
        for ( ty = y; ty < y + h; ty++, data_row += raster ) {\
261
1.86M
          int cx = imod(x + x_offset(ty, cdev), cdev->tiles.rep_width);\
262
1.86M
          const byte *tp = tile_row + (cx >> 3);\
263
1.86M
          byte tbit = 0x80 >> (cx & 7);\
264
1.86M
          int tx;\
265
1.86M
\
266
2.10M
          for ( tx = x; tx < x + w; ) {\
267
2.06M
            int tx1;\
268
2.06M
\
269
2.06M
            /* Skip a run of 0s. */\
270
372M
            while ( tx < x + w && (*tp & tbit) == 0 )\
271
2.06M
              t_next(tx);\
272
2.06M
            if ( tx == x + w )\
273
2.06M
              break;\
274
2.06M
            /* Scan a run of 1s. */\
275
2.06M
            tx1 = tx;\
276
22.4M
            do {\
277
22.4M
              t_next(tx);\
278
22.4M
            } while ( tx < x + w && (*tp & tbit) != 0 );\
279
1.52M
            if_debug3m('T', cdev->memory, "[T]run x=(%d,%d), y=%d\n", tx1, tx, ty);
280
/* (body goes here) */
281
#define END_FOR_RUNS()\
282
246k
          }\
283
3.38M
          if ( ++cy == cdev->tiles.size.y )\
284
1.86M
            cy = 0, tile_row = cdev->tiles.data;\
285
1.86M
          else\
286
1.86M
            tile_row += cdev->tiles.raster;\
287
1.86M
        }
288
289
/* Copy a color rectangle. */
290
static int
291
tile_clip_copy_color(gx_device * dev,
292
                const byte * data, int sourcex, int raster, gx_bitmap_id id,
293
                     int x, int y, int w, int h)
294
2.08M
{
295
2.08M
    gx_device_tile_clip *cdev = (gx_device_tile_clip *) dev;
296
297
2.08M
    fit_copy(dev, data, sourcex, raster, id, x, y, w, h);
298
1.52M
    {
299
4.16M
        FOR_RUNS(data_row, txrun, tx, ty) {
300
            /* Copy the run. */
301
4.16M
            int code = (*dev_proc(cdev->target, copy_color))
302
4.16M
            (cdev->target, data_row, sourcex + txrun - x, raster,
303
4.16M
             gx_no_bitmap_id, txrun, ty, tx - txrun, 1);
304
305
4.16M
            if (code < 0)
306
0
                return code;
307
4.16M
        }
308
4.16M
        END_FOR_RUNS();
309
1.52M
    }
310
0
    return 0;
311
1.52M
}
312
313
/* Copy a color rectangle. */
314
static int
315
tile_clip_copy_planes(gx_device * dev,
316
                const byte * data, int sourcex, int raster, gx_bitmap_id id,
317
                     int x, int y, int w, int h, int plane_height)
318
22
{
319
22
    gx_device_tile_clip *cdev = (gx_device_tile_clip *) dev;
320
321
22
    fit_copy(dev, data, sourcex, raster, id, x, y, w, h);
322
17
    {
323
2.32k
        FOR_RUNS(data_row, txrun, tx, ty) {
324
            /* Copy the run. */
325
2.32k
            int code = (*dev_proc(cdev->target, copy_planes))
326
2.32k
            (cdev->target, data_row, sourcex + txrun - x, raster,
327
2.32k
             gx_no_bitmap_id, txrun, ty, tx - txrun, 1, plane_height);
328
329
2.32k
            if (code < 0)
330
0
                return code;
331
2.32k
        }
332
2.32k
        END_FOR_RUNS();
333
17
    }
334
0
    return 0;
335
17
}
336
337
338
/* Copy an alpha rectangle similarly. */
339
static int
340
tile_clip_copy_alpha(gx_device * dev,
341
                const byte * data, int sourcex, int raster, gx_bitmap_id id,
342
                int x, int y, int w, int h, gx_color_index color, int depth)
343
0
{
344
0
    gx_device_tile_clip *cdev = (gx_device_tile_clip *) dev;
345
346
0
    fit_copy(dev, data, sourcex, raster, id, x, y, w, h);
347
0
    {
348
0
        FOR_RUNS(data_row, txrun, tx, ty) {
349
            /* Copy the run. */
350
0
            int code = (*dev_proc(cdev->target, copy_alpha))
351
0
            (cdev->target, data_row, sourcex + txrun - x, raster,
352
0
             gx_no_bitmap_id, txrun, ty, tx - txrun, 1, color, depth);
353
354
0
            if (code < 0)
355
0
                return code;
356
0
        }
357
0
        END_FOR_RUNS();
358
0
    }
359
0
    return 0;
360
0
}
361
362
static int
363
tile_clip_copy_alpha_hl_color(gx_device * dev,
364
                const byte * data, int sourcex, int raster, gx_bitmap_id id,
365
                int x, int y, int w, int h, const gx_drawing_color *pdcolor,
366
                int depth)
367
0
{
368
0
    gx_device_tile_clip *cdev = (gx_device_tile_clip *) dev;
369
370
0
    fit_copy(dev, data, sourcex, raster, id, x, y, w, h);
371
0
    {
372
0
        FOR_RUNS(data_row, txrun, tx, ty) {
373
            /* Copy the run. */
374
0
            int code = (*dev_proc(cdev->target, copy_alpha_hl_color))
375
0
            (cdev->target, data_row, sourcex + txrun - x, raster,
376
0
             gx_no_bitmap_id, txrun, ty, tx - txrun, 1, pdcolor, depth);
377
378
0
            if (code < 0)
379
0
                return code;
380
0
        }
381
0
        END_FOR_RUNS();
382
0
    }
383
0
    return 0;
384
0
}
385
386
static int
387
tile_clip_strip_copy_rop2(gx_device * dev,
388
               const byte * data, int sourcex, uint raster, gx_bitmap_id id,
389
                         const gx_color_index * scolors,
390
           const gx_strip_bitmap * textures, const gx_color_index * tcolors,
391
                         int x, int y, int w, int h,
392
                       int phase_x, int phase_y, gs_logical_operation_t lop,
393
                       uint planar_height)
394
0
{
395
0
    gx_device_tile_clip *cdev = (gx_device_tile_clip *) dev;
396
397
0
    fit_copy(dev, data, sourcex, raster, id, x, y, w, h);
398
0
    {
399
0
        FOR_RUNS(data_row, txrun, tx, ty) {
400
            /* Copy the run. */
401
0
            int code = (*dev_proc(cdev->target, strip_copy_rop2))
402
0
            (cdev->target, data_row, sourcex + txrun - x, raster,
403
0
             gx_no_bitmap_id, scolors, textures, tcolors,
404
0
             txrun, ty, tx - txrun, 1, phase_x, phase_y, lop,
405
0
             planar_height);
406
407
0
            if (code < 0)
408
0
                return code;
409
0
        }
410
0
        END_FOR_RUNS();
411
0
    }
412
0
    return 0;
413
0
}