Coverage Report

Created: 2022-04-16 11:23

/src/ghostpdl/base/gdevsclass.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
/* Common code for subclassing devices */
17
#include "math_.h"
18
#include "memory_.h"
19
#include "gx.h"
20
#include "gserrors.h"
21
#include "gsparam.h"
22
#include "gxdevice.h"
23
#include "gsdevice.h"   /* requires gsmatrix.h */
24
#include "gxdcolor.h"   /* for gx_device_black/white */
25
#include "gxiparam.h"   /* for image source size */
26
#include "gxgstate.h"
27
#include "gxpaint.h"
28
#include "gxpath.h"
29
#include "gxcpath.h"
30
#include "gxcmap.h"         /* color mapping procs */
31
#include "gsstype.h"
32
#include "gdevprn.h"
33
#include "gdevp14.h"        /* Needed to patch up the procs after compositor creation */
34
#include "gdevsclass.h"
35
#include "gxdevsop.h"
36
37
/*
38
 * It would be nice if we could rewrite the clist handling to use this kind of device class chain
39
 * instead of the nasty hackery it currently utilises (stores the device procs for the existing
40
 * device in 'orig_procs' which is in the device structure) and overwrites the procs with its
41
 * own ones. The bbox forwarding device could also be rewritten this way and would probably then
42
 * be usable as a real forwarding device (last time I tried to do this for eps2write I was unable
43
 * to solve the problems with text enumerators).
44
 */
45
46
/* At first sight we should never have a method in a device structure which is NULL
47
 * because gx_device_fill_in_procs() should replace all the NULLs with default routines.
48
 * However, obselete routines, and a number of newer routines (especially those involving
49
 * transparency) don't get filled in. Its not obvious to me if this is deliberate or not,
50
 * but we'll be careful and check the subclassed device's method before trying to execute
51
 * it. Same for all the methods. NB the fill_rectangle method is deliberately not filled in
52
 * because that gets set up by gdev_prn_allocate_memory(). Isn't it great the way we do our
53
 * initialisation in lots of places?
54
 */
55
56
/* TODO make gx_device_fill_in_procs fill in *all* the procs, currently it doesn't.
57
 * this will mean declaring gx_default_ methods for the transparency methods, possibly
58
 * some others. Like a number of other default methods, these can simply return an error
59
 * which hopefuly will avoid us having to check for NULL device methods.
60
 * We also agreed to set the fill_rectangle method to a default as well (currently it explicitly
61
 * does not do this) and have gdev_prn_alloc_buffer check to see if the method is the default
62
 * before overwriting it, rather than the current check for NULL.
63
 */
64
65
/* More observations; method naems, we have text_begin, but begin_typed_image.
66
 * The enumerator initialiser for images gx_image_enum_common_init doesn't initialise
67
 * the 'memory' member variable. The text enumerator initialiser gs_text_enum_init does.
68
 * The default text enum init routine increments the reference count of the device, but the image enumerator
69
 * doesn't.
70
 */
71
72
/* We have a device method for 'get_profile' but we don't have one for 'set_profile' which causes some
73
 * problems, the 'set' simply sets the profile in the top device. This is modified in gsicc_set_device_profile
74
 * for now but really should have a method to itself.
75
 *
76
 * And in a delightful asymmetry, we have a set_graphics_type_tag, but no get_graphics_type_tag. Instead
77
 * (shudder) the code pulls the currently encoded colour and tag *directly* from the current device.
78
 * This means we have to copy the ENCODE_TAGS from the device we are subclassing, into the device which
79
 * is newly created at installation time. We also have to have our default set_graphics_type_tag method
80
 * update its graphics_type_tag, even though this device has no interest in it, just in case we happen
81
 * to be the top device in the chain......
82
 */
83
84
/*
85
 * gsdparam.c line 272 checks for method being NULL, this is bad, we should check for a return error
86
 * or default method and do initialisation based on that.
87
 */
88
89
90
/* For printing devices the 'open' routine in gdevprn calls gdevprn_allocate_memory
91
 * which is responsible for creating the page buffer. This *also* fills in some of
92
 * the device procs, in particular fill_rectangle() so its vitally important that
93
 * we pass this on.
94
 */
95
int default_subclass_open_device(gx_device *dev)
96
0
{
97
0
    int code = 0;
98
99
    /* observed with Bug 699794, don't set is_open = true if the open_device failed */
100
    /* and make sure to propagate the return code from the child device to caller.  */
101
    /* Only open the child if it was closed  and if child open is OK, return 1.     */
102
    /* (see gs_opendevice) */
103
0
    if (dev->child && dev->child->is_open == 0) {
104
0
        code = dev_proc(dev->child, open_device)(dev->child);
105
0
        if (code >= 0) {
106
0
            dev->child->is_open = true;
107
0
            code = 1; /* device had been closed, but now is open */
108
0
        }
109
0
        gx_update_from_subclass(dev); /* this is probably safe to do even if the open failed */
110
0
    }
111
0
    return code;
112
0
}
113
114
void default_subclass_get_initial_matrix(gx_device *dev, gs_matrix *pmat)
115
0
{
116
0
    if (dev->child)
117
0
        dev_proc(dev->child, get_initial_matrix)(dev->child, pmat);
118
0
    else
119
0
        gx_default_get_initial_matrix(dev, pmat);
120
0
    return;
121
0
}
122
123
int default_subclass_sync_output(gx_device *dev)
124
0
{
125
0
    if (dev->child)
126
0
        return dev_proc(dev->child, sync_output)(dev->child);
127
    /* else */
128
0
    return gx_default_sync_output(dev);
129
0
}
130
131
int default_subclass_output_page(gx_device *dev, int num_copies, int flush)
132
0
{
133
0
    int code = 0;
134
135
0
    if (dev->child) {
136
0
        code = dev_proc(dev->child, output_page)(dev->child, num_copies, flush);
137
0
        dev->PageCount = dev->child->PageCount;
138
0
        return code;
139
0
    }
140
0
    dev->PageCount += num_copies; /* a minor lie */
141
0
    return 0;
142
0
}
143
144
int default_subclass_close_device(gx_device *dev)
145
0
{
146
0
    int code;
147
148
0
    if (dev->child) {
149
0
        code = dev_proc(dev->child, close_device)(dev->child);
150
0
        dev->is_open = dev->child->is_open = false;
151
0
        return code;
152
0
    }
153
0
    dev->is_open = false;
154
0
    return 0;
155
0
}
156
157
gx_color_index default_subclass_map_rgb_color(gx_device *dev, const gx_color_value cv[])
158
0
{
159
0
    if (dev->child)
160
0
        return dev_proc(dev->child, map_rgb_color)(dev->child, cv);
161
0
    else
162
0
        gx_error_encode_color(dev, cv);
163
0
    return 0;
164
0
}
165
166
int default_subclass_map_color_rgb(gx_device *dev, gx_color_index color, gx_color_value rgb[3])
167
0
{
168
0
    if (dev->child)
169
0
        return dev_proc(dev->child, map_color_rgb)(dev->child, color, rgb);
170
    /* else */
171
0
    return gx_default_map_color_rgb(dev, color, rgb);
172
0
}
173
174
int default_subclass_fill_rectangle(gx_device *dev, int x, int y, int width, int height, gx_color_index color)
175
0
{
176
0
    if (dev->child)
177
0
        return dev_proc(dev->child, fill_rectangle)(dev->child, x, y, width, height, color);
178
0
    return 0;
179
0
}
180
181
int default_subclass_copy_mono(gx_device *dev, const byte *data, int data_x, int raster, gx_bitmap_id id,
182
    int x, int y, int width, int height,
183
    gx_color_index color0, gx_color_index color1)
184
0
{
185
0
    if (dev->child)
186
0
        return dev_proc(dev->child, copy_mono)(dev->child, data, data_x, raster, id, x, y, width, height, color0, color1);
187
0
    return 0;
188
0
}
189
190
int default_subclass_copy_color(gx_device *dev, const byte *data, int data_x, int raster, gx_bitmap_id id,\
191
    int x, int y, int width, int height)
192
0
{
193
0
    if (dev->child)
194
0
        return dev_proc(dev->child, copy_color)(dev->child, data, data_x, raster, id, x, y, width, height);
195
0
    return 0;
196
0
}
197
198
int default_subclass_get_params(gx_device *dev, gs_param_list *plist)
199
0
{
200
0
    if (dev->child)
201
0
        return dev_proc(dev->child, get_params)(dev->child, plist);
202
    /* else */
203
0
    return gx_default_get_params(dev, plist);
204
0
}
205
206
int default_subclass_put_params(gx_device *dev, gs_param_list *plist)
207
0
{
208
0
    int code;
209
210
0
    if (dev->child) {
211
0
        code = dev_proc(dev->child, put_params)(dev->child, plist);
212
        /* The child device might have closed itself (yes seriously, this can happen!) */
213
0
        dev->is_open = dev->child->is_open;
214
0
        gx_update_from_subclass(dev);
215
0
        return code;
216
0
    }
217
    /* else */
218
0
    return gx_default_put_params(dev, plist);
219
0
}
220
221
gx_color_index default_subclass_map_cmyk_color(gx_device *dev, const gx_color_value cv[])
222
0
{
223
0
    if (dev->child)
224
0
        return dev_proc(dev->child, map_cmyk_color)(dev->child, cv);
225
    /* else */
226
0
    return gx_default_map_cmyk_color(dev, cv);
227
0
}
228
229
gx_device *default_subclass_get_page_device(gx_device *dev)
230
0
{
231
0
    if (dev->child)
232
0
        return dev_proc(dev->child, get_page_device)(dev->child);
233
    /* else */
234
0
    return gx_default_get_page_device(dev);
235
0
}
236
237
int default_subclass_get_alpha_bits(gx_device *dev, graphics_object_type type)
238
0
{
239
0
    if (dev->child)
240
0
        return dev_proc(dev->child, get_alpha_bits)(dev->child, type);
241
0
    return 0;
242
0
}
243
244
int default_subclass_copy_alpha(gx_device *dev, const byte *data, int data_x,
245
    int raster, gx_bitmap_id id, int x, int y, int width, int height,
246
    gx_color_index color, int depth)
247
0
{
248
0
    if (dev->child)
249
0
        return dev_proc(dev->child, copy_alpha)(dev->child, data, data_x, raster, id, x, y, width, height, color, depth);
250
0
    return 0;
251
0
}
252
253
int default_subclass_fill_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath,
254
    const gx_fill_params *params,
255
    const gx_drawing_color *pdcolor, const gx_clip_path *pcpath)
256
0
{
257
0
    if (dev->child)
258
0
        return dev_proc(dev->child, fill_path)(dev->child, pgs, ppath, params, pdcolor, pcpath);
259
    /* else */
260
0
    return gx_default_fill_path(dev, pgs, ppath, params, pdcolor, pcpath);
261
0
}
262
263
int default_subclass_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath,
264
    const gx_stroke_params *params,
265
    const gx_drawing_color *pdcolor, const gx_clip_path *pcpath)
266
0
{
267
0
    if (dev->child)
268
0
        return dev_proc(dev->child, stroke_path)(dev->child, pgs, ppath, params, pdcolor, pcpath);
269
    /* else */
270
0
    return gx_default_stroke_path(dev, pgs, ppath, params, pdcolor, pcpath);
271
0
}
272
273
int default_subclass_fill_mask(gx_device *dev, const byte *data, int data_x, int raster, gx_bitmap_id id,
274
    int x, int y, int width, int height,
275
    const gx_drawing_color *pdcolor, int depth,
276
    gs_logical_operation_t lop, const gx_clip_path *pcpath)
277
0
{
278
0
    if (dev->child)
279
0
        return dev_proc(dev->child, fill_mask)(dev->child, data, data_x, raster, id, x, y, width, height, pdcolor, depth, lop, pcpath);
280
    /* else */
281
0
    return gx_default_fill_mask(dev, data, data_x, raster, id, x, y, width, height, pdcolor, depth, lop, pcpath);
282
0
}
283
284
int default_subclass_fill_trapezoid(gx_device *dev, const gs_fixed_edge *left, const gs_fixed_edge *right,
285
    fixed ybot, fixed ytop, bool swap_axes,
286
    const gx_drawing_color *pdcolor, gs_logical_operation_t lop)
287
0
{
288
0
    if (dev->child)
289
0
        return dev_proc(dev->child, fill_trapezoid)(dev->child, left, right, ybot, ytop, swap_axes, pdcolor, lop);
290
    /* else */
291
0
    return gx_default_fill_trapezoid(dev, left, right, ybot, ytop, swap_axes, pdcolor, lop);
292
0
}
293
294
int default_subclass_fill_parallelogram(gx_device *dev, fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
295
    const gx_drawing_color *pdcolor, gs_logical_operation_t lop)
296
0
{
297
0
    if (dev->child)
298
0
        return dev_proc(dev->child, fill_parallelogram)(dev->child, px, py, ax, ay, bx, by, pdcolor, lop);
299
    /* else */
300
0
    return gx_default_fill_parallelogram(dev, px, py, ax, ay, bx, by, pdcolor, lop);
301
0
}
302
303
int default_subclass_fill_triangle(gx_device *dev, fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
304
    const gx_drawing_color *pdcolor, gs_logical_operation_t lop)
305
0
{
306
0
    if (dev->child)
307
0
        return dev_proc(dev->child, fill_triangle)(dev->child, px, py, ax, ay, bx, by, pdcolor, lop);
308
    /* else */
309
0
    return gx_default_fill_triangle(dev, px, py, ax, ay, bx, by, pdcolor, lop);
310
0
}
311
312
int default_subclass_draw_thin_line(gx_device *dev, fixed fx0, fixed fy0, fixed fx1, fixed fy1,
313
    const gx_drawing_color *pdcolor, gs_logical_operation_t lop,
314
    fixed adjustx, fixed adjusty)
315
0
{
316
0
    if (dev->child)
317
0
        return dev_proc(dev->child, draw_thin_line)(dev->child, fx0, fy0, fx1, fy1, pdcolor, lop, adjustx, adjusty);
318
    /* else */
319
0
    return gx_default_draw_thin_line(dev, fx0, fy0, fx1, fy1, pdcolor, lop, adjustx, adjusty);
320
0
}
321
322
int default_subclass_strip_tile_rectangle(gx_device *dev, const gx_strip_bitmap *tiles, int x, int y, int width, int height,
323
    gx_color_index color0, gx_color_index color1,
324
    int phase_x, int phase_y)
325
0
{
326
0
    if (dev->child)
327
0
        return dev_proc(dev->child, strip_tile_rectangle)(dev->child, tiles, x, y, width, height, color0, color1, phase_x, phase_y);
328
    /* else */
329
0
    return gx_default_strip_tile_rectangle(dev, tiles, x, y, width, height, color0, color1, phase_x, phase_y);
330
0
}
331
332
void default_subclass_get_clipping_box(gx_device *dev, gs_fixed_rect *pbox)
333
0
{
334
0
    if (dev->child) {
335
0
        dev_proc(dev->child, get_clipping_box)(dev->child, pbox);
336
0
    } else
337
0
        gx_default_get_clipping_box(dev, pbox);
338
339
0
    return;
340
0
}
341
342
int default_subclass_begin_typed_image(gx_device *dev, const gs_gstate *pgs, const gs_matrix *pmat,
343
    const gs_image_common_t *pic, const gs_int_rect *prect,
344
    const gx_drawing_color *pdcolor, const gx_clip_path *pcpath,
345
    gs_memory_t *memory, gx_image_enum_common_t **pinfo)
346
0
{
347
0
    if (dev->child)
348
0
        return dev_proc(dev->child, begin_typed_image)(dev->child, pgs, pmat, pic, prect, pdcolor, pcpath, memory, pinfo);
349
    /* else */
350
0
    return gx_default_begin_typed_image(dev, pgs, pmat, pic, prect, pdcolor, pcpath, memory, pinfo);
351
0
}
352
353
int default_subclass_get_bits_rectangle(gx_device *dev, const gs_int_rect *prect,
354
    gs_get_bits_params_t *params)
355
0
{
356
0
    if (dev->child)
357
0
        return dev_proc(dev->child, get_bits_rectangle)(dev->child, prect, params);
358
    /* else */
359
0
    return gx_default_get_bits_rectangle(dev, prect, params);
360
0
}
361
362
int default_subclass_composite(gx_device *dev, gx_device **pcdev, const gs_composite_t *pcte,
363
    gs_gstate *pgs, gs_memory_t *memory, gx_device *cdev)
364
0
{
365
0
    int code;
366
367
0
    if (dev->child) {
368
        /* Some more unpleasantness here. If the child device is a clist, then it will use the first argument
369
         * that we pass to access its own data (not unreasonably), so we need to make sure we pass in the
370
         * child device. This has some follow on implications detailed below.
371
         */
372
0
        code = dev_proc(dev->child, composite)(dev->child, pcdev, pcte, pgs, memory, cdev);
373
0
        if (code < 0)
374
0
            return code;
375
376
        /* *pcdev is always returned containing a device capable of doing
377
         * compositing. This may mean it is a new device. If this wants
378
         * to be the new 'device' in the graphics state, then code will
379
         * return as 1. */
380
0
        if (code == 1) {
381
            /* The device chain on entry to this function was:
382
             *   dev(the subclassing device) -> child.
383
             * But now we also have:
384
             *   *pcdev -> child.
385
             * Or in some cases:
386
             *   *pcdev (-> other device)* -> child
387
             * Most callers would be happy to make dev->child = *pcdev,
388
             * thus giving us:
389
             *   dev -> *pcdev (-> other device)* ->child
390
             * Unfortunately, we are not happy with that. We need to
391
             * remain tightly bound to the child. i.e. we are aiming for:
392
             *   *pcdev (-> other device)* -> dev -> child
393
             * Accordingly, we need to move ourselves within the device
394
             * chain.
395
             */
396
0
            gx_device *penult = *pcdev;
397
398
0
            if (penult == NULL) {
399
                /* This should never happen. */
400
0
                return gs_error_unknownerror;
401
0
            }
402
403
            /* Find the penultimate device. */
404
0
            while (1) {
405
0
                gxdso_device_child_request req;
406
0
                req.target = penult;
407
0
                req.n = 0;
408
0
                code = dev_proc(penult, dev_spec_op)(penult, gxdso_device_child, &req, sizeof(req));
409
0
                if (code < 0)
410
0
                    return code;
411
0
                if (req.target == NULL) {
412
                    /* Wooah! Where was dev->child? */
413
0
                    return gs_error_unknownerror;
414
0
                }
415
0
                if (req.target == dev->child)
416
0
                    break; /* penult is the parent. */
417
0
                penult = req.target;
418
0
            }
419
420
0
            if (penult == NULL) {
421
                /* This should never happen. We know that we've just
422
                 * had a compositor inserted before dev->child, so there
423
                 * really ought to be one! */
424
0
                return gs_error_unknownerror;
425
0
            }
426
427
            /* We already point to dev->child, and hence own a reference
428
             * to it. */
429
430
            /* Now insert ourselves as the child of the penultimate one. */
431
0
            code = dev_proc(penult, dev_spec_op)(penult, gxdso_device_insert_child, dev, 0);
432
0
            if (code < 0)
433
0
                return code;
434
435
            /* Now we want our caller to update itself to recognise that
436
             * *pcdev should be its child, not dev. So we return 1. */
437
0
            return 1;
438
0
        }
439
0
        else {
440
            /* See the 2 comments above. Now, if the child did not create a new compositor (eg its a clist)
441
             * then it returns pcdev pointing to the passed in device (the child in our case). Now this is a
442
             * problem, if we return with pcdev == child->dev, and teh current device is 'dev' then the
443
             * compositor code will think we wanted to push a new device and will select the child device.
444
             * so here if pcdev == dev->child we change it to be our own device, so that the calling code
445
             * won't redirect the device in the graphics state.
446
             */
447
0
            *pcdev = dev;
448
0
            return code;
449
0
        }
450
0
    }
451
0
    return 0;
452
0
}
453
454
int default_subclass_get_hardware_params(gx_device *dev, gs_param_list *plist)
455
0
{
456
0
    if (dev->child)
457
0
        return dev_proc(dev->child, get_hardware_params)(dev->child, plist);
458
    /* else */
459
0
    return gx_default_get_hardware_params(dev, plist);
460
0
}
461
462
int default_subclass_text_begin(gx_device *dev, gs_gstate *pgs, const gs_text_params_t *text,
463
    gs_font *font, const gx_clip_path *pcpath,
464
    gs_text_enum_t **ppte)
465
0
{
466
0
    if (dev->child)
467
0
        return dev_proc(dev->child, text_begin)(dev->child, pgs, text, font, pcpath, ppte);
468
    /* else */
469
0
    return gx_default_text_begin(dev, pgs, text, font, pcpath, ppte);
470
0
}
471
472
int default_subclass_begin_transparency_group(gx_device *dev, const gs_transparency_group_params_t *ptgp,
473
    const gs_rect *pbbox, gs_gstate *pgs, gs_memory_t *mem)
474
0
{
475
0
    if (dev->child)
476
0
        return dev_proc(dev->child, begin_transparency_group)(dev->child, ptgp, pbbox, pgs, mem);
477
478
0
    return 0;
479
0
}
480
481
int default_subclass_end_transparency_group(gx_device *dev, gs_gstate *pgs)
482
0
{
483
0
    if (dev->child)
484
0
        return dev_proc(dev->child, end_transparency_group)(dev->child, pgs);
485
486
0
    return 0;
487
0
}
488
489
int default_subclass_begin_transparency_mask(gx_device *dev, const gx_transparency_mask_params_t *ptmp,
490
    const gs_rect *pbbox, gs_gstate *pgs, gs_memory_t *mem)
491
0
{
492
0
    if (dev->child)
493
0
        return dev_proc(dev->child, begin_transparency_mask)(dev->child, ptmp, pbbox, pgs, mem);
494
495
0
    return 0;
496
0
}
497
498
int default_subclass_end_transparency_mask(gx_device *dev, gs_gstate *pgs)
499
0
{
500
0
    if (dev->child)
501
0
        return dev_proc(dev->child, end_transparency_mask)(dev->child, pgs);
502
503
0
    return 0;
504
0
}
505
506
int default_subclass_discard_transparency_layer(gx_device *dev, gs_gstate *pgs)
507
0
{
508
0
    if (dev->child)
509
0
        return dev_proc(dev->child, discard_transparency_layer)(dev->child, pgs);
510
511
0
    return 0;
512
0
}
513
514
const gx_cm_color_map_procs *default_subclass_get_color_mapping_procs(const gx_device *dev,
515
                                                                      const gx_device **tdev)
516
0
{
517
0
    if (dev->child)
518
0
        return dev_proc(dev->child, get_color_mapping_procs)(dev->child, tdev);
519
    /* else */
520
0
    return gx_default_DevGray_get_color_mapping_procs(dev, tdev);
521
0
}
522
523
int  default_subclass_get_color_comp_index(gx_device *dev, const char * pname, int name_size, int component_type)
524
0
{
525
0
    if (dev->child)
526
0
        return dev_proc(dev->child, get_color_comp_index)(dev->child, pname, name_size, component_type);
527
    /* else */
528
0
    return gx_error_get_color_comp_index(dev, pname, name_size, component_type);
529
0
}
530
531
gx_color_index default_subclass_encode_color(gx_device *dev, const gx_color_value colors[])
532
0
{
533
0
    if (dev->child)
534
0
        return dev_proc(dev->child, encode_color)(dev->child, colors);
535
    /* else */
536
0
    return gx_error_encode_color(dev, colors);
537
0
}
538
539
int default_subclass_decode_color(gx_device *dev, gx_color_index cindex, gx_color_value colors[])
540
0
{
541
0
    if (dev->child)
542
0
        return dev_proc(dev->child, decode_color)(dev->child, cindex, colors);
543
0
    else {
544
0
        memset(colors, 0, sizeof(gx_color_value[GX_DEVICE_COLOR_MAX_COMPONENTS]));
545
0
    }
546
547
0
    return 0;
548
0
}
549
550
int default_subclass_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect,
551
        const gs_gstate *pgs, const gx_drawing_color *pdcolor, const gx_clip_path *pcpath)
552
0
{
553
0
    if (dev->child)
554
0
        return dev_proc(dev->child, fill_rectangle_hl_color)(dev->child, rect, pgs, pdcolor, pcpath);
555
    /* else */
556
0
    return_error(gs_error_rangecheck);
557
0
}
558
559
int default_subclass_include_color_space(gx_device *dev, gs_color_space *cspace, const byte *res_name, int name_length)
560
0
{
561
0
    if (dev->child)
562
0
        return dev_proc(dev->child, include_color_space)(dev->child, cspace, res_name, name_length);
563
564
0
    return 0;
565
0
}
566
567
int default_subclass_fill_linear_color_scanline(gx_device *dev, const gs_fill_attributes *fa,
568
        int i, int j, int w, const frac31 *c0, const int32_t *c0_f, const int32_t *cg_num,
569
        int32_t cg_den)
570
0
{
571
0
    if (dev->child)
572
0
        return dev_proc(dev->child, fill_linear_color_scanline)(dev->child, fa, i, j, w, c0, c0_f, cg_num, cg_den);
573
    /* else */
574
0
    return gx_default_fill_linear_color_scanline(dev, fa, i, j, w, c0, c0_f, cg_num, cg_den);
575
0
}
576
577
int default_subclass_fill_linear_color_trapezoid(gx_device *dev, const gs_fill_attributes *fa,
578
        const gs_fixed_point *p0, const gs_fixed_point *p1,
579
        const gs_fixed_point *p2, const gs_fixed_point *p3,
580
        const frac31 *c0, const frac31 *c1,
581
        const frac31 *c2, const frac31 *c3)
582
0
{
583
0
    if (dev->child)
584
0
        return dev_proc(dev->child, fill_linear_color_trapezoid)(dev->child, fa, p0, p1, p2, p3, c0, c1, c2, c3);
585
    /* else */
586
0
    return gx_default_fill_linear_color_trapezoid(dev, fa, p0, p1, p2, p3, c0, c1, c2, c3);
587
0
}
588
589
int default_subclass_fill_linear_color_triangle(gx_device *dev, const gs_fill_attributes *fa,
590
        const gs_fixed_point *p0, const gs_fixed_point *p1,
591
        const gs_fixed_point *p2, const frac31 *c0, const frac31 *c1, const frac31 *c2)
592
0
{
593
0
    if (dev->child)
594
0
        return dev_proc(dev->child, fill_linear_color_triangle)(dev->child, fa, p0, p1, p2, c0, c1, c2);
595
    /* else */
596
0
    return gx_default_fill_linear_color_triangle(dev, fa, p0, p1, p2, c0, c1, c2);
597
0
}
598
599
int default_subclass_update_spot_equivalent_colors(gx_device *dev, const gs_gstate * pgs, const gs_color_space *pcs)
600
0
{
601
0
    if (dev->child)
602
0
        return dev_proc(dev->child, update_spot_equivalent_colors)(dev->child, pgs, pcs);
603
604
0
    return 0;
605
0
}
606
607
gs_devn_params *default_subclass_ret_devn_params(gx_device *dev)
608
0
{
609
0
    if (dev->child)
610
0
        return dev_proc(dev->child, ret_devn_params)(dev->child);
611
612
0
    return 0;
613
0
}
614
615
int default_subclass_fillpage(gx_device *dev, gs_gstate * pgs, gx_device_color *pdevc)
616
0
{
617
0
    if (dev->child)
618
0
        return dev_proc(dev->child, fillpage)(dev->child, pgs, pdevc);
619
    /* else */
620
0
    return gx_default_fillpage(dev, pgs, pdevc);
621
0
}
622
623
int default_subclass_push_transparency_state(gx_device *dev, gs_gstate *pgs)
624
0
{
625
0
    if (dev->child)
626
0
        return dev_proc(dev->child, push_transparency_state)(dev->child, pgs);
627
628
0
    return 0;
629
0
}
630
631
int default_subclass_pop_transparency_state(gx_device *dev, gs_gstate *pgs)
632
0
{
633
0
    if (dev->child)
634
0
        return dev_proc(dev->child, pop_transparency_state)(dev->child, pgs);
635
636
0
    return 0;
637
0
}
638
639
int default_subclass_put_image(gx_device *dev, gx_device *mdev, const byte **buffers, int num_chan, int x, int y,
640
            int width, int height, int row_stride,
641
            int alpha_plane_index, int tag_plane_index)
642
0
{
643
0
    if (dev->child) {
644
0
        if (dev == mdev) {
645
0
            return dev_proc(dev->child, put_image)(dev->child, dev->child, buffers, num_chan, x, y, width, height, row_stride, alpha_plane_index, tag_plane_index);
646
0
        }
647
0
        else {
648
0
            return dev_proc(dev->child, put_image)(dev->child, mdev, buffers, num_chan, x, y, width, height, row_stride, alpha_plane_index, tag_plane_index);
649
0
        }
650
0
    }
651
0
    return 0;
652
0
}
653
654
int default_subclass_dev_spec_op(gx_device *dev, int op, void *data, int datasize)
655
0
{
656
0
    if (op == gxdso_is_clist_device)
657
0
        return 0;
658
0
    if (op == gxdso_device_child) {
659
0
        gxdso_device_child_request *d = (gxdso_device_child_request *)data;
660
0
        if (d->target == dev) {
661
0
            d->target = dev->child;
662
0
            return 1;
663
0
        }
664
0
    }
665
0
    if (dev->child)
666
0
        return dev_proc(dev->child, dev_spec_op)(dev->child, op, data, datasize);
667
668
0
    return 0;
669
0
}
670
671
int default_subclass_copy_planes(gx_device *dev, const byte *data, int data_x, int raster, gx_bitmap_id id,
672
    int x, int y, int width, int height, int plane_height)
673
0
{
674
0
    if (dev->child)
675
0
        return dev_proc(dev->child, copy_planes)(dev->child, data, data_x, raster, id, x, y, width, height, plane_height);
676
677
0
    return 0;
678
0
}
679
680
int default_subclass_get_profile(const gx_device *dev, cmm_dev_profile_t **dev_profile)
681
0
{
682
0
    if (dev->child) {
683
0
        return dev_proc(dev->child, get_profile)(dev->child, dev_profile);
684
0
    }
685
    /* else */
686
0
    return gx_default_get_profile(dev, dev_profile);
687
0
}
688
689
/* In a delightful asymmetry, we have a set_graphics_type_tag, but no get_graphics_type_tag. Instead
690
 * (shudder) the code pulls the currently encoded colour and tag *directly* from the current device.
691
 * This means we have to copy the ENCODE_TAGS from the device we are subclassing, into the device which
692
 * is newly created at installation time. We also have to have our default set_graphics_type_tag method
693
 * update its graphics_type_tag, even though this device has no interest in it, just in case we happen
694
 * to be the top device in the chain......
695
 */
696
697
void default_subclass_set_graphics_type_tag(gx_device *dev, gs_graphics_type_tag_t tag)
698
0
{
699
    /*
700
     * AIUI we should not be calling this method *unless* the ENCODE_TAGS bit is set, so we don't need
701
     * to do any checking. Just set the supplied tag in the current device, and pass it on to the underlying
702
     * device(s). This line is a direct copy from gx_default_set_graphics_type_tag.
703
     */
704
0
    dev->graphics_type_tag = (dev->graphics_type_tag & GS_DEVICE_ENCODES_TAGS) | tag;
705
706
0
    if (dev->child)
707
0
        dev_proc(dev->child, set_graphics_type_tag)(dev->child, tag);
708
709
0
    return;
710
0
}
711
712
int default_subclass_strip_copy_rop2(gx_device *dev, const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id,
713
    const gx_color_index *scolors, const gx_strip_bitmap *textures, const gx_color_index *tcolors,
714
    int x, int y, int width, int height, int phase_x, int phase_y, gs_logical_operation_t lop, uint planar_height)
715
0
{
716
0
    if (!dev->child)
717
0
        return 0;
718
719
0
    return dev_proc(dev->child, strip_copy_rop2)(dev->child, sdata, sourcex, sraster, id, scolors, textures, tcolors, x, y, width, height, phase_x, phase_y, lop, planar_height);
720
0
}
721
722
int default_subclass_strip_tile_rect_devn(gx_device *dev, const gx_strip_bitmap *tiles, int x, int y, int width, int height,
723
    const gx_drawing_color *pdcolor0, const gx_drawing_color *pdcolor1, int phase_x, int phase_y)
724
0
{
725
0
    if (dev->child)
726
0
        return dev_proc(dev->child, strip_tile_rect_devn)(dev->child, tiles, x, y, width, height, pdcolor0, pdcolor1, phase_x, phase_y);
727
    /* else */
728
0
    return gx_default_strip_tile_rect_devn(dev->child, tiles, x, y, width, height, pdcolor0, pdcolor1, phase_x, phase_y);
729
0
}
730
731
int default_subclass_copy_alpha_hl_color(gx_device *dev, const byte *data, int data_x,
732
    int raster, gx_bitmap_id id, int x, int y, int width, int height,
733
    const gx_drawing_color *pdcolor, int depth)
734
0
{
735
0
    if (dev->child)
736
0
        return dev_proc(dev->child, copy_alpha_hl_color)(dev->child, data, data_x, raster, id, x, y, width, height, pdcolor, depth);
737
    /* else */
738
0
    return_error(gs_error_rangecheck);
739
0
}
740
741
int default_subclass_process_page(gx_device *dev, gx_process_page_options_t *options)
742
0
{
743
0
    if (dev->child)
744
0
        return dev_proc(dev->child, process_page)(dev->child, options);
745
746
0
    return 0;
747
0
}
748
749
int default_subclass_fill_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath,
750
        const gx_fill_params *fill_params, const gx_drawing_color *pdcolor_fill,
751
        const gx_stroke_params *stroke_params, const gx_drawing_color *pdcolor_stroke,
752
        const gx_clip_path *pcpath)
753
0
{
754
0
    if (dev->child)
755
0
        return dev_proc(dev->child, fill_stroke_path)(dev->child, pgs, ppath, fill_params, pdcolor_fill,
756
0
                                                      stroke_params, pdcolor_stroke, pcpath);
757
0
    return 0;
758
0
}
759
760
int default_subclass_lock_pattern(gx_device *dev, gs_gstate *pgs, gs_id pattern_id, int lock)
761
0
{
762
0
    if (dev->child)
763
0
        return dev_proc(dev->child, lock_pattern)(dev->child, pgs, pattern_id, lock);
764
0
    return 0;
765
0
}
766
767
int default_subclass_transform_pixel_region(gx_device *dev, transform_pixel_region_reason reason, transform_pixel_region_data *data)
768
0
{
769
0
    if (dev->child)
770
0
        return dev_proc(dev->child, transform_pixel_region)(dev->child, reason, data);
771
772
0
    return gs_error_unknownerror;
773
0
}
774
775
void default_subclass_finalize(const gs_memory_t *cmem, void *vptr)
776
0
{
777
0
    gx_device * const dev = (gx_device *)vptr;
778
0
    generic_subclass_data *psubclass_data = (generic_subclass_data *)dev->subclass_data;
779
0
    (void)cmem; /* unused */
780
781
0
    discard(gs_closedevice(dev));
782
783
0
    if (dev->finalize)
784
0
        dev->finalize(dev);
785
786
0
    if (psubclass_data) {
787
0
        gs_free_object(dev->memory->non_gc_memory, psubclass_data, "gx_epo_finalize(suclass data)");
788
0
        dev->subclass_data = NULL;
789
0
    }
790
0
    if (dev->child) {
791
0
        gs_free_object(dev->memory->stable_memory, dev->child, "free child device memory for subclassing device");
792
0
    }
793
0
    if (dev->stype_is_dynamic)
794
0
        gs_free_const_object(dev->memory->non_gc_memory, dev->stype,
795
0
                             "default_subclass_finalize");
796
0
    if (dev->parent)
797
0
        dev->parent->child = dev->child;
798
0
    if (dev->child)
799
0
        dev->child->parent = dev->parent;
800
0
    if (dev->icc_struct)
801
0
        rc_decrement(dev->icc_struct, "finalize subclass device");
802
0
    if (dev->PageList)
803
0
        rc_decrement(dev->PageList, "finalize subclass device");
804
0
    if (dev->NupControl)
805
0
        rc_decrement(dev->NupControl, "finalize subclass device");
806
0
}
807
808
void default_subclass_initialize_device_procs(gx_device *dev)
809
0
{
810
0
    set_dev_proc(dev, open_device, default_subclass_open_device);
811
0
    set_dev_proc(dev, get_initial_matrix, default_subclass_get_initial_matrix);
812
0
    set_dev_proc(dev, sync_output, default_subclass_sync_output);
813
0
    set_dev_proc(dev, output_page, default_subclass_output_page);
814
0
    set_dev_proc(dev, close_device, default_subclass_close_device);
815
0
    set_dev_proc(dev, map_rgb_color, default_subclass_map_rgb_color);
816
0
    set_dev_proc(dev, map_color_rgb, default_subclass_map_color_rgb);
817
0
    set_dev_proc(dev, fill_rectangle, default_subclass_fill_rectangle);
818
0
    set_dev_proc(dev, copy_mono, default_subclass_copy_mono);
819
0
    set_dev_proc(dev, copy_color, default_subclass_copy_color);
820
0
    set_dev_proc(dev, get_params, default_subclass_get_params);
821
0
    set_dev_proc(dev, put_params, default_subclass_put_params);
822
0
    set_dev_proc(dev, map_cmyk_color, default_subclass_map_cmyk_color);
823
0
    set_dev_proc(dev, get_page_device, default_subclass_get_page_device);
824
0
    set_dev_proc(dev, get_alpha_bits, default_subclass_get_alpha_bits);
825
0
    set_dev_proc(dev, copy_alpha, default_subclass_copy_alpha);
826
0
    set_dev_proc(dev, fill_path, default_subclass_fill_path);
827
0
    set_dev_proc(dev, stroke_path, default_subclass_stroke_path);
828
0
    set_dev_proc(dev, fill_mask, default_subclass_fill_mask);
829
0
    set_dev_proc(dev, fill_trapezoid, default_subclass_fill_trapezoid);
830
0
    set_dev_proc(dev, fill_parallelogram, default_subclass_fill_parallelogram);
831
0
    set_dev_proc(dev, fill_triangle, default_subclass_fill_triangle);
832
0
    set_dev_proc(dev, draw_thin_line, default_subclass_draw_thin_line);
833
0
    set_dev_proc(dev, strip_tile_rectangle, default_subclass_strip_tile_rectangle);
834
0
    set_dev_proc(dev, get_clipping_box, default_subclass_get_clipping_box);
835
0
    set_dev_proc(dev, begin_typed_image, default_subclass_begin_typed_image);
836
0
    set_dev_proc(dev, get_bits_rectangle, default_subclass_get_bits_rectangle);
837
0
    set_dev_proc(dev, composite, default_subclass_composite);
838
0
    set_dev_proc(dev, get_hardware_params, default_subclass_get_hardware_params);
839
0
    set_dev_proc(dev, text_begin, default_subclass_text_begin);
840
0
    set_dev_proc(dev, begin_transparency_group, default_subclass_begin_transparency_group);
841
0
    set_dev_proc(dev, end_transparency_group, default_subclass_end_transparency_group);
842
0
    set_dev_proc(dev, begin_transparency_mask, default_subclass_begin_transparency_mask);
843
0
    set_dev_proc(dev, end_transparency_mask, default_subclass_end_transparency_mask);
844
0
    set_dev_proc(dev, discard_transparency_layer, default_subclass_discard_transparency_layer);
845
0
    set_dev_proc(dev, get_color_mapping_procs, default_subclass_get_color_mapping_procs);
846
0
    set_dev_proc(dev, get_color_comp_index, default_subclass_get_color_comp_index);
847
0
    set_dev_proc(dev, encode_color, default_subclass_encode_color);
848
0
    set_dev_proc(dev, decode_color, default_subclass_decode_color);
849
0
    set_dev_proc(dev, fill_rectangle_hl_color, default_subclass_fill_rectangle_hl_color);
850
0
    set_dev_proc(dev, include_color_space, default_subclass_include_color_space);
851
0
    set_dev_proc(dev, fill_linear_color_scanline, default_subclass_fill_linear_color_scanline);
852
0
    set_dev_proc(dev, fill_linear_color_trapezoid, default_subclass_fill_linear_color_trapezoid);
853
0
    set_dev_proc(dev, fill_linear_color_triangle, default_subclass_fill_linear_color_triangle);
854
0
    set_dev_proc(dev, update_spot_equivalent_colors, default_subclass_update_spot_equivalent_colors);
855
0
    set_dev_proc(dev, ret_devn_params, default_subclass_ret_devn_params);
856
0
    set_dev_proc(dev, fillpage, default_subclass_fillpage);
857
0
    set_dev_proc(dev, push_transparency_state, default_subclass_push_transparency_state);
858
0
    set_dev_proc(dev, pop_transparency_state, default_subclass_pop_transparency_state);
859
0
    set_dev_proc(dev, put_image, default_subclass_put_image);
860
0
    set_dev_proc(dev, dev_spec_op, default_subclass_dev_spec_op);
861
0
    set_dev_proc(dev, copy_planes, default_subclass_copy_planes);
862
0
    set_dev_proc(dev, get_profile, default_subclass_get_profile);
863
0
    set_dev_proc(dev, set_graphics_type_tag, default_subclass_set_graphics_type_tag);
864
0
    set_dev_proc(dev, strip_copy_rop2, default_subclass_strip_copy_rop2);
865
0
    set_dev_proc(dev, strip_tile_rect_devn, default_subclass_strip_tile_rect_devn);
866
0
    set_dev_proc(dev, copy_alpha_hl_color, default_subclass_copy_alpha_hl_color);
867
0
    set_dev_proc(dev, process_page, default_subclass_process_page);
868
0
    set_dev_proc(dev, transform_pixel_region, default_subclass_transform_pixel_region);
869
0
    set_dev_proc(dev, fill_stroke_path, default_subclass_fill_stroke_path);
870
0
    set_dev_proc(dev, lock_pattern, default_subclass_lock_pattern);
871
0
}
872
873
int
874
default_subclass_install(gx_device *dev, gs_gstate *pgs)
875
0
{
876
0
    dev = dev->child;
877
0
    return dev->page_procs.install(dev, pgs);
878
0
}
879
880
int
881
default_subclass_begin_page(gx_device *dev, gs_gstate *pgs)
882
0
{
883
0
    dev = dev->child;
884
0
    return dev->page_procs.begin_page(dev, pgs);
885
0
}
886
887
int
888
default_subclass_end_page(gx_device *dev, int reason, gs_gstate *pgs)
889
0
{
890
0
    dev = dev->child;
891
0
    return dev->page_procs.end_page(dev, reason, pgs);
892
0
}
893
894
void gx_subclass_fill_in_page_procs(gx_device *dev)
895
0
{
896
0
    if (dev->page_procs.install == NULL)
897
0
        dev->page_procs.install = default_subclass_install;
898
0
    if (dev->page_procs.begin_page == NULL)
899
0
        dev->page_procs.begin_page = default_subclass_begin_page;
900
0
    if (dev->page_procs.end_page == NULL)
901
0
        dev->page_procs.end_page = default_subclass_end_page;
902
0
}