Coverage Report

Created: 2025-12-31 07:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/base/gdevsclass.c
Line
Count
Source
1
/* Copyright (C) 2001-2025 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
/* 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
1.87M
{
116
1.87M
    if (dev->child)
117
1.87M
        dev_proc(dev->child, get_initial_matrix)(dev->child, pmat);
118
0
    else
119
0
        gx_default_get_initial_matrix(dev, pmat);
120
1.87M
    return;
121
1.87M
}
122
123
int default_subclass_sync_output(gx_device *dev)
124
347k
{
125
347k
    if (dev->child)
126
347k
        return dev_proc(dev->child, sync_output)(dev->child);
127
    /* else */
128
0
    return gx_default_sync_output(dev);
129
347k
}
130
131
int default_subclass_output_page(gx_device *dev, int num_copies, int flush)
132
37.3k
{
133
37.3k
    int code = 0;
134
135
37.3k
    if (dev->child) {
136
37.3k
        code = dev_proc(dev->child, output_page)(dev->child, num_copies, flush);
137
37.3k
        dev->PageCount = dev->child->PageCount;
138
37.3k
        return code;
139
37.3k
    }
140
0
    dev->PageCount += num_copies; /* a minor lie */
141
0
    return 0;
142
37.3k
}
143
144
int default_subclass_close_device(gx_device *dev)
145
43.1k
{
146
43.1k
    int code;
147
148
43.1k
    if (dev->child) {
149
43.1k
        code = dev_proc(dev->child, close_device)(dev->child);
150
43.1k
        dev->is_open = dev->child->is_open = false;
151
43.1k
        return code;
152
43.1k
    }
153
0
    dev->is_open = false;
154
0
    return 0;
155
43.1k
}
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
2.89M
{
176
2.89M
    if (dev->child)
177
2.89M
        return dev_proc(dev->child, fill_rectangle)(dev->child, x, y, width, height, color);
178
0
    return 0;
179
2.89M
}
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
617k
{
200
617k
    if (dev->child)
201
617k
        return dev_proc(dev->child, get_params)(dev->child, plist);
202
    /* else */
203
0
    return gx_default_get_params(dev, plist);
204
617k
}
205
206
int default_subclass_put_params(gx_device *dev, gs_param_list *plist)
207
241k
{
208
241k
    int code;
209
210
241k
    if (dev->child) {
211
241k
        code = dev_proc(dev->child, put_params)(dev->child, plist);
212
        /* The child device might have closed itself (yes seriously, this can happen!) */
213
241k
        dev->is_open = dev->child->is_open;
214
241k
        gx_update_from_subclass(dev);
215
241k
        return code;
216
241k
    }
217
    /* else */
218
0
    return gx_default_put_params(dev, plist);
219
241k
}
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
8.64M
{
231
8.64M
    if (dev->child)
232
8.64M
        return dev_proc(dev->child, get_page_device)(dev->child);
233
    /* else */
234
0
    return gx_default_get_page_device(dev);
235
8.64M
}
236
237
int default_subclass_get_alpha_bits(gx_device *dev, graphics_object_type type)
238
29.2M
{
239
29.2M
    if (dev->child)
240
29.2M
        return dev_proc(dev->child, get_alpha_bits)(dev->child, type);
241
0
    return 0;
242
29.2M
}
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
7.87M
{
257
7.87M
    if (dev->child)
258
7.87M
        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
7.87M
}
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
1.09M
{
267
1.09M
    if (dev->child)
268
1.09M
        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
1.09M
}
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
1.37k
{
334
1.37k
    if (dev->child) {
335
1.37k
        dev_proc(dev->child, get_clipping_box)(dev->child, pbox);
336
1.37k
    } else
337
0
        gx_default_get_clipping_box(dev, pbox);
338
339
1.37k
    return;
340
1.37k
}
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
370k
{
347
370k
    if (dev->child)
348
370k
        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
370k
}
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
static void subclass_composite_front_finalize(gx_device *dev)
363
0
{
364
0
    generic_subclass_data *psubclass_data = (generic_subclass_data *)dev->parent->subclass_data;
365
366
0
    dev->parent->child = psubclass_data->pre_composite_device;
367
0
    psubclass_data->saved_finalize_method(dev);
368
0
}
369
370
int default_subclass_composite_front(gx_device *dev, gx_device **pcdev, const gs_composite_t *pcte,
371
    gs_gstate *pgs, gs_memory_t *memory, gx_device *cdev)
372
0
{
373
0
    int code = 0;
374
0
    gs_pdf14trans_t *pct = (gs_pdf14trans_t *)pcte;
375
0
    generic_subclass_data *psubclass_data = (generic_subclass_data *)dev->subclass_data;
376
0
    gx_device *thisdev = dev;
377
378
0
    if (dev->child) {
379
0
        code = dev_proc(dev->child, composite)(dev->child, pcdev, pcte, pgs, memory, cdev);
380
0
        if (code < 0)
381
0
            return code;
382
383
0
        if (gs_is_overprint_compositor(pcte))
384
0
        {
385
            /* *pcdev is always returned containing a device capable of doing
386
             * compositing. This may mean it is a new device. If this wants
387
             * to be the new 'device' in the graphics state, then code will
388
             * return as 1. */
389
0
            if (code == 1) {
390
                /* We want this device to stay ahead of the compositor; the newly created compositor has
391
                 * inserted itself in front of our child device, so basically we want to replace
392
                 * our current child with the newly created compositor. I hope !
393
                 */
394
0
                psubclass_data = (generic_subclass_data *)dev->subclass_data;
395
0
                if (psubclass_data == NULL)
396
0
                    return_error(gs_error_undefined);
397
0
                psubclass_data->pre_composite_device = dev->child;
398
0
                psubclass_data->saved_finalize_method = (*pcdev)->finalize;
399
0
                (*pcdev)->finalize = subclass_composite_front_finalize;
400
401
0
                (*pcdev)->child = dev->child;
402
0
                dev->child = *pcdev;
403
0
                (*pcdev)->parent = dev;
404
0
                while (dev) {
405
0
                    memcpy(&dev->color_info, &(*pcdev)->color_info, sizeof(gx_device_color_info));
406
0
                    dev->num_planar_planes = dev->child->num_planar_planes;
407
0
                    dev = dev->parent;
408
0
                }
409
0
            }
410
0
        }
411
0
        else if (gs_is_pdf14trans_compositor(pcte)) {
412
0
            switch(pct->params.pdf14_op)
413
0
            {
414
0
                case PDF14_POP_DEVICE:
415
0
                    if (psubclass_data->pre_composite_device != NULL) {
416
0
                        if (dev->child) {
417
0
                            dev->child->parent = NULL;
418
0
                            dev->child->child = NULL;
419
0
                            dev->child->finalize = psubclass_data->saved_finalize_method;
420
0
                            rc_decrement(dev->child, "default_subclass_composite_front");
421
0
                        }
422
0
                        dev->child = psubclass_data->pre_composite_device;
423
0
                        psubclass_data->pre_composite_device = NULL;
424
0
                        psubclass_data->saved_finalize_method = NULL;
425
0
                        while (dev) {
426
0
                            memcpy(&(dev->color_info), &(dev->child->color_info), sizeof(gx_device_color_info));
427
0
                            dev->num_planar_planes = dev->child->num_planar_planes;
428
0
                            dev = dev->parent;
429
0
                        }
430
0
                    }
431
0
                    break;
432
0
                case PDF14_PUSH_DEVICE:
433
                    /* *pcdev is always returned containing a device capable of doing
434
                     * compositing. This may mean it is a new device. If this wants
435
                     * to be the new 'device' in the graphics state, then code will
436
                     * return as 1. */
437
0
                    if (code == 1) {
438
                        /* We want this device to stay ahead of the compositor; the newly created compositor has
439
                         * inserted itself in front of our child device, so basically we want to replace
440
                         * our current child with the newly created compositor. I hope !
441
                         */
442
0
                        psubclass_data = (generic_subclass_data *)dev->subclass_data;
443
0
                        if (psubclass_data == NULL)
444
0
                            return_error(gs_error_undefined);
445
0
                        psubclass_data->pre_composite_device = dev->child;
446
0
                        psubclass_data->saved_finalize_method = (*pcdev)->finalize;
447
0
                        (*pcdev)->finalize = subclass_composite_front_finalize;
448
449
0
                        (*pcdev)->child = dev->child;
450
0
                        dev->child = *pcdev;
451
0
                        (*pcdev)->parent = dev;
452
0
                        while (dev) {
453
0
                            memcpy(&dev->color_info, &(*pcdev)->color_info, sizeof(gx_device_color_info));
454
0
                            dev->num_planar_planes = dev->child->num_planar_planes;
455
0
                            dev = dev->parent;
456
0
                        }
457
0
                    }
458
0
                    break;
459
0
                default:
460
                    /* It seems like many operations can result in the pdf14 device altering its color
461
                     * info, presumably as we push different blending spaces. Ick. In order to stay in sync
462
                     * any time we have inserted a compositor after this class, we must update the color info
463
                     * of this device after every operation, in case it changes....
464
                     */
465
0
                    if (psubclass_data->pre_composite_device != NULL) {
466
0
                        while (dev) {
467
0
                            memcpy(&(dev->color_info), &(dev->child->color_info), sizeof(gx_device_color_info));
468
0
                            dev->num_planar_planes = dev->child->num_planar_planes;
469
0
                            dev = dev->parent;
470
0
                        }
471
0
                    }
472
0
                    break;
473
0
            }
474
0
        }
475
        /* We are inserting the compositor code after this device, or the compositor
476
         * did not create a new compositor. Either way we don't want the compositor code
477
         * to think we want to push a new device, so just return this device to the caller.
478
         */
479
0
        *pcdev = thisdev;
480
0
        return 0;
481
0
    }
482
0
    return 0;
483
0
}
484
485
int default_subclass_composite(gx_device *dev, gx_device **pcdev, const gs_composite_t *pcte,
486
    gs_gstate *pgs, gs_memory_t *memory, gx_device *cdev)
487
153k
{
488
153k
    int code;
489
490
153k
    if (dev->child) {
491
        /* Some more unpleasantness here. If the child device is a clist, then it will use the first argument
492
         * that we pass to access its own data (not unreasonably), so we need to make sure we pass in the
493
         * child device. This has some follow on implications detailed below.
494
         */
495
153k
        code = dev_proc(dev->child, composite)(dev->child, pcdev, pcte, pgs, memory, cdev);
496
153k
        if (code < 0)
497
4
            return code;
498
499
        /* *pcdev is always returned containing a device capable of doing
500
         * compositing. This may mean it is a new device. If this wants
501
         * to be the new 'device' in the graphics state, then code will
502
         * return as 1. */
503
153k
        if (code == 1) {
504
            /* The device chain on entry to this function was:
505
             *   dev(the subclassing device) -> child.
506
             * But now we also have:
507
             *   *pcdev -> child.
508
             * Or in some cases:
509
             *   *pcdev (-> other device)* -> child
510
             * Most callers would be happy to make dev->child = *pcdev,
511
             * thus giving us:
512
             *   dev -> *pcdev (-> other device)* ->child
513
             * Unfortunately, we are not happy with that. We need to
514
             * remain tightly bound to the child. i.e. we are aiming for:
515
             *   *pcdev (-> other device)* -> dev -> child
516
             * Accordingly, we need to move ourselves within the device
517
             * chain.
518
             */
519
5.20k
            gx_device *penult = *pcdev;
520
521
5.20k
            if (penult == NULL) {
522
                /* This should never happen. */
523
0
                return gs_error_unknownerror;
524
0
            }
525
526
            /* Find the penultimate device. */
527
14.7k
            while (1) {
528
14.7k
                gxdso_device_child_request req;
529
14.7k
                req.target = penult;
530
14.7k
                req.n = 0;
531
14.7k
                code = dev_proc(penult, dev_spec_op)(penult, gxdso_device_child, &req, sizeof(req));
532
14.7k
                if (code < 0)
533
0
                    return code;
534
14.7k
                if (req.target == NULL) {
535
                    /* Wooah! Where was dev->child? */
536
0
                    return gs_error_unknownerror;
537
0
                }
538
14.7k
                if (req.target == dev->child)
539
5.20k
                    break; /* penult is the parent. */
540
9.51k
                penult = req.target;
541
9.51k
            }
542
543
5.20k
            if (penult == NULL) {
544
                /* This should never happen. We know that we've just
545
                 * had a compositor inserted before dev->child, so there
546
                 * really ought to be one! */
547
0
                return gs_error_unknownerror;
548
0
            }
549
550
            /* We already point to dev->child, and hence own a reference
551
             * to it. */
552
553
            /* Now insert ourselves as the child of the penultimate one. */
554
5.20k
            code = dev_proc(penult, dev_spec_op)(penult, gxdso_device_insert_child, dev, 0);
555
5.20k
            if (code < 0)
556
0
                return code;
557
558
            /* Now we want our caller to update itself to recognise that
559
             * *pcdev should be its child, not dev. So we return 1. */
560
5.20k
            return 1;
561
5.20k
        }
562
148k
        else {
563
            /* See the 2 comments above. Now, if the child did not create a new compositor (eg its a clist)
564
             * then it returns pcdev pointing to the passed in device (the child in our case). Now this is a
565
             * problem, if we return with pcdev == child->dev, and the current device is 'dev' then the
566
             * compositor code will think we wanted to push a new device and will select the child device.
567
             * so here if pcdev == dev->child we change it to be our own device, so that the calling code
568
             * won't redirect the device in the graphics state.
569
             */
570
148k
            *pcdev = dev;
571
148k
            return code;
572
148k
        }
573
153k
    }
574
0
    return 0;
575
153k
}
576
577
int default_subclass_get_hardware_params(gx_device *dev, gs_param_list *plist)
578
0
{
579
0
    if (dev->child)
580
0
        return dev_proc(dev->child, get_hardware_params)(dev->child, plist);
581
    /* else */
582
0
    return gx_default_get_hardware_params(dev, plist);
583
0
}
584
585
int default_subclass_text_begin(gx_device *dev, gs_gstate *pgs, const gs_text_params_t *text,
586
    gs_font *font, const gx_clip_path *pcpath,
587
    gs_text_enum_t **ppte)
588
3.91M
{
589
3.91M
    if (dev->child)
590
3.91M
        return dev_proc(dev->child, text_begin)(dev->child, pgs, text, font, pcpath, ppte);
591
    /* else */
592
0
    return gx_default_text_begin(dev, pgs, text, font, pcpath, ppte);
593
3.91M
}
594
595
int default_subclass_begin_transparency_group(gx_device *dev, const gs_transparency_group_params_t *ptgp,
596
    const gs_rect *pbbox, gs_gstate *pgs, gs_memory_t *mem)
597
0
{
598
0
    if (dev->child)
599
0
        return dev_proc(dev->child, begin_transparency_group)(dev->child, ptgp, pbbox, pgs, mem);
600
601
0
    return 0;
602
0
}
603
604
int default_subclass_end_transparency_group(gx_device *dev, gs_gstate *pgs)
605
0
{
606
0
    if (dev->child)
607
0
        return dev_proc(dev->child, end_transparency_group)(dev->child, pgs);
608
609
0
    return 0;
610
0
}
611
612
int default_subclass_begin_transparency_mask(gx_device *dev, const gx_transparency_mask_params_t *ptmp,
613
    const gs_rect *pbbox, gs_gstate *pgs, gs_memory_t *mem)
614
0
{
615
0
    if (dev->child)
616
0
        return dev_proc(dev->child, begin_transparency_mask)(dev->child, ptmp, pbbox, pgs, mem);
617
618
0
    return 0;
619
0
}
620
621
int default_subclass_end_transparency_mask(gx_device *dev, gs_gstate *pgs)
622
0
{
623
0
    if (dev->child)
624
0
        return dev_proc(dev->child, end_transparency_mask)(dev->child, pgs);
625
626
0
    return 0;
627
0
}
628
629
int default_subclass_discard_transparency_layer(gx_device *dev, gs_gstate *pgs)
630
0
{
631
0
    if (dev->child)
632
0
        return dev_proc(dev->child, discard_transparency_layer)(dev->child, pgs);
633
634
0
    return 0;
635
0
}
636
637
const gx_cm_color_map_procs *default_subclass_get_color_mapping_procs(const gx_device *dev,
638
                                                                      const gx_device **tdev)
639
4.32M
{
640
4.32M
    if (dev->child)
641
4.32M
        return dev_proc(dev->child, get_color_mapping_procs)(dev->child, tdev);
642
    /* else */
643
0
    return gx_default_DevGray_get_color_mapping_procs(dev, tdev);
644
4.32M
}
645
646
int  default_subclass_get_color_comp_index(gx_device *dev, const char * pname, int name_size, int component_type)
647
19.9k
{
648
19.9k
    if (dev->child)
649
19.9k
        return dev_proc(dev->child, get_color_comp_index)(dev->child, pname, name_size, component_type);
650
    /* else */
651
0
    return gx_error_get_color_comp_index(dev, pname, name_size, component_type);
652
19.9k
}
653
654
gx_color_index default_subclass_encode_color(gx_device *dev, const gx_color_value colors[])
655
4.41M
{
656
4.41M
    if (dev->child)
657
4.41M
        return dev_proc(dev->child, encode_color)(dev->child, colors);
658
    /* else */
659
0
    return gx_error_encode_color(dev, colors);
660
4.41M
}
661
662
int default_subclass_decode_color(gx_device *dev, gx_color_index cindex, gx_color_value colors[])
663
0
{
664
0
    if (dev->child)
665
0
        return dev_proc(dev->child, decode_color)(dev->child, cindex, colors);
666
0
    else {
667
0
        memset(colors, 0, sizeof(gx_color_value[GX_DEVICE_COLOR_MAX_COMPONENTS]));
668
0
    }
669
670
0
    return 0;
671
0
}
672
673
int default_subclass_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect,
674
        const gs_gstate *pgs, const gx_drawing_color *pdcolor, const gx_clip_path *pcpath)
675
0
{
676
0
    if (dev->child)
677
0
        return dev_proc(dev->child, fill_rectangle_hl_color)(dev->child, rect, pgs, pdcolor, pcpath);
678
    /* else */
679
0
    return_error(gs_error_rangecheck);
680
0
}
681
682
int default_subclass_include_color_space(gx_device *dev, gs_color_space *cspace, const byte *res_name, int name_length)
683
0
{
684
0
    if (dev->child)
685
0
        return dev_proc(dev->child, include_color_space)(dev->child, cspace, res_name, name_length);
686
687
0
    return 0;
688
0
}
689
690
int default_subclass_fill_linear_color_scanline(gx_device *dev, const gs_fill_attributes *fa,
691
        int i, int j, int w, const frac31 *c0, const int32_t *c0_f, const int32_t *cg_num,
692
        int32_t cg_den)
693
0
{
694
0
    if (dev->child)
695
0
        return dev_proc(dev->child, fill_linear_color_scanline)(dev->child, fa, i, j, w, c0, c0_f, cg_num, cg_den);
696
    /* else */
697
0
    return gx_default_fill_linear_color_scanline(dev, fa, i, j, w, c0, c0_f, cg_num, cg_den);
698
0
}
699
700
int default_subclass_fill_linear_color_trapezoid(gx_device *dev, const gs_fill_attributes *fa,
701
        const gs_fixed_point *p0, const gs_fixed_point *p1,
702
        const gs_fixed_point *p2, const gs_fixed_point *p3,
703
        const frac31 *c0, const frac31 *c1,
704
        const frac31 *c2, const frac31 *c3)
705
0
{
706
0
    if (dev->child)
707
0
        return dev_proc(dev->child, fill_linear_color_trapezoid)(dev->child, fa, p0, p1, p2, p3, c0, c1, c2, c3);
708
    /* else */
709
0
    return gx_default_fill_linear_color_trapezoid(dev, fa, p0, p1, p2, p3, c0, c1, c2, c3);
710
0
}
711
712
int default_subclass_fill_linear_color_triangle(gx_device *dev, const gs_fill_attributes *fa,
713
        const gs_fixed_point *p0, const gs_fixed_point *p1,
714
        const gs_fixed_point *p2, const frac31 *c0, const frac31 *c1, const frac31 *c2)
715
0
{
716
0
    if (dev->child)
717
0
        return dev_proc(dev->child, fill_linear_color_triangle)(dev->child, fa, p0, p1, p2, c0, c1, c2);
718
    /* else */
719
0
    return gx_default_fill_linear_color_triangle(dev, fa, p0, p1, p2, c0, c1, c2);
720
0
}
721
722
int default_subclass_update_spot_equivalent_colors(gx_device *dev, const gs_gstate * pgs, const gs_color_space *pcs)
723
221
{
724
221
    if (dev->child)
725
221
        return dev_proc(dev->child, update_spot_equivalent_colors)(dev->child, pgs, pcs);
726
727
0
    return 0;
728
221
}
729
730
gs_devn_params *default_subclass_ret_devn_params(gx_device *dev)
731
9.96k
{
732
9.96k
    if (dev->child)
733
9.96k
        return dev_proc(dev->child, ret_devn_params)(dev->child);
734
735
0
    return 0;
736
9.96k
}
737
738
int default_subclass_fillpage(gx_device *dev, gs_gstate * pgs, gx_device_color *pdevc)
739
0
{
740
0
    if (dev->child)
741
0
        return dev_proc(dev->child, fillpage)(dev->child, pgs, pdevc);
742
    /* else */
743
0
    return gx_default_fillpage(dev, pgs, pdevc);
744
0
}
745
746
int default_subclass_push_transparency_state(gx_device *dev, gs_gstate *pgs)
747
0
{
748
0
    if (dev->child)
749
0
        return dev_proc(dev->child, push_transparency_state)(dev->child, pgs);
750
751
0
    return 0;
752
0
}
753
754
int default_subclass_pop_transparency_state(gx_device *dev, gs_gstate *pgs)
755
0
{
756
0
    if (dev->child)
757
0
        return dev_proc(dev->child, pop_transparency_state)(dev->child, pgs);
758
759
0
    return 0;
760
0
}
761
762
int default_subclass_put_image(gx_device *dev, gx_device *mdev, const byte **buffers, int num_chan, int x, int y,
763
            int width, int height, int row_stride,
764
            int alpha_plane_index, int tag_plane_index)
765
0
{
766
0
    if (dev->child) {
767
0
        if (dev == mdev) {
768
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);
769
0
        }
770
0
        else {
771
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);
772
0
        }
773
0
    }
774
0
    return 0;
775
0
}
776
777
int default_subclass_dev_spec_op(gx_device *dev, int op, void *data, int datasize)
778
47.3M
{
779
47.3M
    if (op == gxdso_is_clist_device)
780
0
        return 0;
781
47.3M
    if (op == gxdso_device_child) {
782
0
        gxdso_device_child_request *d = (gxdso_device_child_request *)data;
783
0
        if (d->target == dev) {
784
0
            d->target = dev->child;
785
0
            return 1;
786
0
        }
787
0
    }
788
47.3M
    if (dev->child)
789
47.3M
        return dev_proc(dev->child, dev_spec_op)(dev->child, op, data, datasize);
790
791
0
    return 0;
792
47.3M
}
793
794
int default_subclass_copy_planes(gx_device *dev, const byte *data, int data_x, int raster, gx_bitmap_id id,
795
    int x, int y, int width, int height, int plane_height)
796
0
{
797
0
    if (dev->child)
798
0
        return dev_proc(dev->child, copy_planes)(dev->child, data, data_x, raster, id, x, y, width, height, plane_height);
799
800
0
    return 0;
801
0
}
802
803
int default_subclass_get_profile(const gx_device *dev, cmm_dev_profile_t **dev_profile)
804
21.3M
{
805
21.3M
    if (dev->child) {
806
21.3M
        return dev_proc(dev->child, get_profile)(dev->child, dev_profile);
807
21.3M
    }
808
    /* else */
809
0
    return gx_default_get_profile(dev, dev_profile);
810
21.3M
}
811
812
/* In a delightful asymmetry, we have a set_graphics_type_tag, but no get_graphics_type_tag. Instead
813
 * (shudder) the code pulls the currently encoded colour and tag *directly* from the current device.
814
 * This means we have to copy the ENCODE_TAGS from the device we are subclassing, into the device which
815
 * is newly created at installation time. We also have to have our default set_graphics_type_tag method
816
 * update its graphics_type_tag, even though this device has no interest in it, just in case we happen
817
 * to be the top device in the chain......
818
 */
819
820
void default_subclass_set_graphics_type_tag(gx_device *dev, gs_graphics_type_tag_t tag)
821
1.19M
{
822
    /*
823
     * AIUI we should not be calling this method *unless* the ENCODE_TAGS bit is set, so we don't need
824
     * to do any checking. Just set the supplied tag in the current device, and pass it on to the underlying
825
     * device(s). This line is a direct copy from gx_default_set_graphics_type_tag.
826
     */
827
1.19M
    dev->graphics_type_tag = (dev->graphics_type_tag & GS_DEVICE_ENCODES_TAGS) | tag;
828
829
1.19M
    if (dev->child)
830
1.19M
        dev_proc(dev->child, set_graphics_type_tag)(dev->child, tag);
831
832
1.19M
    return;
833
1.19M
}
834
835
int default_subclass_strip_copy_rop2(gx_device *dev, const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id,
836
    const gx_color_index *scolors, const gx_strip_bitmap *textures, const gx_color_index *tcolors,
837
    int x, int y, int width, int height, int phase_x, int phase_y, gs_logical_operation_t lop, uint planar_height)
838
0
{
839
0
    if (!dev->child)
840
0
        return 0;
841
842
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);
843
0
}
844
845
int default_subclass_strip_tile_rect_devn(gx_device *dev, const gx_strip_bitmap *tiles, int x, int y, int width, int height,
846
    const gx_drawing_color *pdcolor0, const gx_drawing_color *pdcolor1, int phase_x, int phase_y)
847
0
{
848
0
    if (dev->child)
849
0
        return dev_proc(dev->child, strip_tile_rect_devn)(dev->child, tiles, x, y, width, height, pdcolor0, pdcolor1, phase_x, phase_y);
850
    /* else */
851
0
    return gx_default_strip_tile_rect_devn(dev, tiles, x, y, width, height, pdcolor0, pdcolor1, phase_x, phase_y);
852
0
}
853
854
int default_subclass_copy_alpha_hl_color(gx_device *dev, const byte *data, int data_x,
855
    int raster, gx_bitmap_id id, int x, int y, int width, int height,
856
    const gx_drawing_color *pdcolor, int depth)
857
0
{
858
0
    if (dev->child)
859
0
        return dev_proc(dev->child, copy_alpha_hl_color)(dev->child, data, data_x, raster, id, x, y, width, height, pdcolor, depth);
860
    /* else */
861
0
    return_error(gs_error_rangecheck);
862
0
}
863
864
int default_subclass_process_page(gx_device *dev, gx_process_page_options_t *options)
865
0
{
866
0
    if (dev->child)
867
0
        return dev_proc(dev->child, process_page)(dev->child, options);
868
869
0
    return 0;
870
0
}
871
872
int default_subclass_fill_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath,
873
        const gx_fill_params *fill_params, const gx_drawing_color *pdcolor_fill,
874
        const gx_stroke_params *stroke_params, const gx_drawing_color *pdcolor_stroke,
875
        const gx_clip_path *pcpath)
876
18.5k
{
877
18.5k
    if (dev->child)
878
18.5k
        return dev_proc(dev->child, fill_stroke_path)(dev->child, pgs, ppath, fill_params, pdcolor_fill,
879
18.5k
                                                      stroke_params, pdcolor_stroke, pcpath);
880
0
    return 0;
881
18.5k
}
882
883
int default_subclass_lock_pattern(gx_device *dev, gs_gstate *pgs, gs_id pattern_id, int lock)
884
303
{
885
303
    if (dev->child)
886
303
        return dev_proc(dev->child, lock_pattern)(dev->child, pgs, pattern_id, lock);
887
0
    return 0;
888
303
}
889
890
int default_subclass_transform_pixel_region(gx_device *dev, transform_pixel_region_reason reason, transform_pixel_region_data *data)
891
0
{
892
0
    if (dev->child)
893
0
        return dev_proc(dev->child, transform_pixel_region)(dev->child, reason, data);
894
895
0
    return gs_error_unknownerror;
896
0
}
897
898
void default_subclass_finalize(const gs_memory_t *cmem, void *vptr)
899
43.1k
{
900
43.1k
    gx_device * const dev = (gx_device *)vptr;
901
43.1k
    generic_subclass_data *psubclass_data = (generic_subclass_data *)dev->subclass_data;
902
43.1k
    (void)cmem; /* unused */
903
904
43.1k
    discard(gs_closedevice(dev));
905
906
43.1k
    if (dev->finalize)
907
0
        dev->finalize(dev);
908
909
    /* The only way we should get here is when the original device
910
     * should be freed (because the subclassing device is pretending
911
     * to be the original device). That being the case, all the child
912
     * devices should have a reference count of 1 (referenced only by
913
     * their parent). Anything else is an error.
914
     */
915
43.1k
    if (dev->child != NULL) {
916
43.1k
        if (dev->child->rc.ref_count != 1) {
917
0
            dmprintf(dev->memory, "Error: finalizing subclassing device while child refcount > 1\n");
918
0
            while (dev->child->rc.ref_count != 1)
919
0
                rc_decrement_only(dev->child, "de-reference child device");
920
0
        }
921
43.1k
        rc_decrement(dev->child, "de-reference child device");
922
43.1k
    }
923
924
43.1k
    if (psubclass_data) {
925
43.1k
        gs_free_object(dev->memory->non_gc_memory, psubclass_data, "gx_epo_finalize(suclass data)");
926
43.1k
        dev->subclass_data = NULL;
927
43.1k
    }
928
43.1k
    if (dev->stype_is_dynamic)
929
43.1k
        gs_free_const_object(dev->memory->non_gc_memory, dev->stype,
930
43.1k
                             "default_subclass_finalize");
931
43.1k
    if (dev->icc_struct)
932
43.1k
        rc_decrement(dev->icc_struct, "finalize subclass device");
933
43.1k
    if (dev->PageList)
934
43.1k
        rc_decrement(dev->PageList, "finalize subclass device");
935
43.1k
    if (dev->NupControl)
936
43.1k
        rc_decrement(dev->NupControl, "finalize subclass device");
937
43.1k
}
938
939
void default_subclass_initialize_device_procs(gx_device *dev)
940
43.1k
{
941
43.1k
    set_dev_proc(dev, open_device, default_subclass_open_device);
942
43.1k
    set_dev_proc(dev, get_initial_matrix, default_subclass_get_initial_matrix);
943
43.1k
    set_dev_proc(dev, sync_output, default_subclass_sync_output);
944
43.1k
    set_dev_proc(dev, output_page, default_subclass_output_page);
945
43.1k
    set_dev_proc(dev, close_device, default_subclass_close_device);
946
43.1k
    set_dev_proc(dev, map_rgb_color, default_subclass_map_rgb_color);
947
43.1k
    set_dev_proc(dev, map_color_rgb, default_subclass_map_color_rgb);
948
43.1k
    set_dev_proc(dev, fill_rectangle, default_subclass_fill_rectangle);
949
43.1k
    set_dev_proc(dev, copy_mono, default_subclass_copy_mono);
950
43.1k
    set_dev_proc(dev, copy_color, default_subclass_copy_color);
951
43.1k
    set_dev_proc(dev, get_params, default_subclass_get_params);
952
43.1k
    set_dev_proc(dev, put_params, default_subclass_put_params);
953
43.1k
    set_dev_proc(dev, map_cmyk_color, default_subclass_map_cmyk_color);
954
43.1k
    set_dev_proc(dev, get_page_device, default_subclass_get_page_device);
955
43.1k
    set_dev_proc(dev, get_alpha_bits, default_subclass_get_alpha_bits);
956
43.1k
    set_dev_proc(dev, copy_alpha, default_subclass_copy_alpha);
957
43.1k
    set_dev_proc(dev, fill_path, default_subclass_fill_path);
958
43.1k
    set_dev_proc(dev, stroke_path, default_subclass_stroke_path);
959
43.1k
    set_dev_proc(dev, fill_mask, default_subclass_fill_mask);
960
43.1k
    set_dev_proc(dev, fill_trapezoid, default_subclass_fill_trapezoid);
961
43.1k
    set_dev_proc(dev, fill_parallelogram, default_subclass_fill_parallelogram);
962
43.1k
    set_dev_proc(dev, fill_triangle, default_subclass_fill_triangle);
963
43.1k
    set_dev_proc(dev, draw_thin_line, default_subclass_draw_thin_line);
964
43.1k
    set_dev_proc(dev, strip_tile_rectangle, default_subclass_strip_tile_rectangle);
965
43.1k
    set_dev_proc(dev, get_clipping_box, default_subclass_get_clipping_box);
966
43.1k
    set_dev_proc(dev, begin_typed_image, default_subclass_begin_typed_image);
967
43.1k
    set_dev_proc(dev, get_bits_rectangle, default_subclass_get_bits_rectangle);
968
43.1k
    set_dev_proc(dev, composite, default_subclass_composite);
969
43.1k
    set_dev_proc(dev, get_hardware_params, default_subclass_get_hardware_params);
970
43.1k
    set_dev_proc(dev, text_begin, default_subclass_text_begin);
971
43.1k
    set_dev_proc(dev, begin_transparency_group, default_subclass_begin_transparency_group);
972
43.1k
    set_dev_proc(dev, end_transparency_group, default_subclass_end_transparency_group);
973
43.1k
    set_dev_proc(dev, begin_transparency_mask, default_subclass_begin_transparency_mask);
974
43.1k
    set_dev_proc(dev, end_transparency_mask, default_subclass_end_transparency_mask);
975
43.1k
    set_dev_proc(dev, discard_transparency_layer, default_subclass_discard_transparency_layer);
976
43.1k
    set_dev_proc(dev, get_color_mapping_procs, default_subclass_get_color_mapping_procs);
977
43.1k
    set_dev_proc(dev, get_color_comp_index, default_subclass_get_color_comp_index);
978
43.1k
    set_dev_proc(dev, encode_color, default_subclass_encode_color);
979
43.1k
    set_dev_proc(dev, decode_color, default_subclass_decode_color);
980
43.1k
    set_dev_proc(dev, fill_rectangle_hl_color, default_subclass_fill_rectangle_hl_color);
981
43.1k
    set_dev_proc(dev, include_color_space, default_subclass_include_color_space);
982
43.1k
    set_dev_proc(dev, fill_linear_color_scanline, default_subclass_fill_linear_color_scanline);
983
43.1k
    set_dev_proc(dev, fill_linear_color_trapezoid, default_subclass_fill_linear_color_trapezoid);
984
43.1k
    set_dev_proc(dev, fill_linear_color_triangle, default_subclass_fill_linear_color_triangle);
985
43.1k
    set_dev_proc(dev, update_spot_equivalent_colors, default_subclass_update_spot_equivalent_colors);
986
43.1k
    set_dev_proc(dev, ret_devn_params, default_subclass_ret_devn_params);
987
43.1k
    set_dev_proc(dev, fillpage, default_subclass_fillpage);
988
43.1k
    set_dev_proc(dev, push_transparency_state, default_subclass_push_transparency_state);
989
43.1k
    set_dev_proc(dev, pop_transparency_state, default_subclass_pop_transparency_state);
990
43.1k
    set_dev_proc(dev, put_image, default_subclass_put_image);
991
43.1k
    set_dev_proc(dev, dev_spec_op, default_subclass_dev_spec_op);
992
43.1k
    set_dev_proc(dev, copy_planes, default_subclass_copy_planes);
993
43.1k
    set_dev_proc(dev, get_profile, default_subclass_get_profile);
994
43.1k
    set_dev_proc(dev, set_graphics_type_tag, default_subclass_set_graphics_type_tag);
995
43.1k
    set_dev_proc(dev, strip_copy_rop2, default_subclass_strip_copy_rop2);
996
43.1k
    set_dev_proc(dev, strip_tile_rect_devn, default_subclass_strip_tile_rect_devn);
997
43.1k
    set_dev_proc(dev, copy_alpha_hl_color, default_subclass_copy_alpha_hl_color);
998
43.1k
    set_dev_proc(dev, process_page, default_subclass_process_page);
999
43.1k
    set_dev_proc(dev, transform_pixel_region, default_subclass_transform_pixel_region);
1000
43.1k
    set_dev_proc(dev, fill_stroke_path, default_subclass_fill_stroke_path);
1001
43.1k
    set_dev_proc(dev, lock_pattern, default_subclass_lock_pattern);
1002
43.1k
}
1003
1004
int
1005
default_subclass_install(gx_device *dev, gs_gstate *pgs)
1006
0
{
1007
0
    dev = dev->child;
1008
0
    return dev->page_procs.install(dev, pgs);
1009
0
}
1010
1011
int
1012
default_subclass_begin_page(gx_device *dev, gs_gstate *pgs)
1013
0
{
1014
0
    dev = dev->child;
1015
0
    return dev->page_procs.begin_page(dev, pgs);
1016
0
}
1017
1018
int
1019
default_subclass_end_page(gx_device *dev, int reason, gs_gstate *pgs)
1020
0
{
1021
0
    dev = dev->child;
1022
0
    return dev->page_procs.end_page(dev, reason, pgs);
1023
0
}
1024
1025
void gx_subclass_fill_in_page_procs(gx_device *dev)
1026
43.1k
{
1027
43.1k
    if (dev->page_procs.install == NULL)
1028
43.1k
        dev->page_procs.install = default_subclass_install;
1029
43.1k
    if (dev->page_procs.begin_page == NULL)
1030
43.1k
        dev->page_procs.begin_page = default_subclass_begin_page;
1031
43.1k
    if (dev->page_procs.end_page == NULL)
1032
43.1k
        dev->page_procs.end_page = default_subclass_end_page;
1033
43.1k
}