Coverage Report

Created: 2026-04-01 07:17

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