Coverage Report

Created: 2025-06-24 07:01

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