Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/base/gdevsclass.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2022 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
/* Common code for subclassing devices */
17
#include "math_.h"
18
#include "memory_.h"
19
#include "gx.h"
20
#include "gserrors.h"
21
#include "gsparam.h"
22
#include "gxdevice.h"
23
#include "gsdevice.h"   /* requires gsmatrix.h */
24
#include "gxdcolor.h"   /* for gx_device_black/white */
25
#include "gxiparam.h"   /* for image source size */
26
#include "gxgstate.h"
27
#include "gxpaint.h"
28
#include "gxpath.h"
29
#include "gxcpath.h"
30
#include "gxcmap.h"         /* color mapping procs */
31
#include "gsstype.h"
32
#include "gdevprn.h"
33
#include "gdevp14.h"        /* Needed to patch up the procs after compositor creation */
34
#include "gdevsclass.h"
35
#include "gxdevsop.h"
36
37
/*
38
 * It would be nice if we could rewrite the clist handling to use this kind of device class chain
39
 * instead of the nasty hackery it currently utilises (stores the device procs for the existing
40
 * device in 'orig_procs' which is in the device structure) and overwrites the procs with its
41
 * own ones. The bbox forwarding device could also be rewritten this way and would probably then
42
 * be usable as a real forwarding device (last time I tried to do this for eps2write I was unable
43
 * to solve the problems with text enumerators).
44
 */
45
46
/* At first sight we should never have a method in a device structure which is NULL
47
 * because gx_device_fill_in_procs() should replace all the NULLs with default routines.
48
 * However, obselete routines, and a number of newer routines (especially those involving
49
 * transparency) don't get filled in. Its not obvious to me if this is deliberate or not,
50
 * but we'll be careful and check the subclassed device's method before trying to execute
51
 * it. Same for all the methods. NB the fill_rectangle method is deliberately not filled in
52
 * because that gets set up by gdev_prn_allocate_memory(). Isn't it great the way we do our
53
 * initialisation in lots of places?
54
 */
55
56
/* TODO make gx_device_fill_in_procs fill in *all* the procs, currently it doesn't.
57
 * this will mean declaring gx_default_ methods for the transparency methods, possibly
58
 * some others. Like a number of other default methods, these can simply return an error
59
 * which hopefuly will avoid us having to check for NULL device methods.
60
 * We also agreed to set the fill_rectangle method to a default as well (currently it explicitly
61
 * does not do this) and have gdev_prn_alloc_buffer check to see if the method is the default
62
 * before overwriting it, rather than the current check for NULL.
63
 */
64
65
/* More observations; method naems, we have text_begin, but begin_typed_image.
66
 * The enumerator initialiser for images gx_image_enum_common_init doesn't initialise
67
 * the 'memory' member variable. The text enumerator initialiser gs_text_enum_init does.
68
 * The default text enum init routine increments the reference count of the device, but the image enumerator
69
 * doesn't.
70
 */
71
72
/* We have a device method for 'get_profile' but we don't have one for 'set_profile' which causes some
73
 * problems, the 'set' simply sets the profile in the top device. This is modified in gsicc_set_device_profile
74
 * for now but really should have a method to itself.
75
 *
76
 * And in a delightful asymmetry, we have a set_graphics_type_tag, but no get_graphics_type_tag. Instead
77
 * (shudder) the code pulls the currently encoded colour and tag *directly* from the current device.
78
 * This means we have to copy the ENCODE_TAGS from the device we are subclassing, into the device which
79
 * is newly created at installation time. We also have to have our default set_graphics_type_tag method
80
 * update its graphics_type_tag, even though this device has no interest in it, just in case we happen
81
 * to be the top device in the chain......
82
 */
83
84
/*
85
 * gsdparam.c line 272 checks for method being NULL, this is bad, we should check for a return error
86
 * or default method and do initialisation based on that.
87
 */
88
89
90
/* For printing devices the 'open' routine in gdevprn calls gdevprn_allocate_memory
91
 * which is responsible for creating the page buffer. This *also* fills in some of
92
 * the device procs, in particular fill_rectangle() so its vitally important that
93
 * we pass this on.
94
 */
95
int default_subclass_open_device(gx_device *dev)
96
0
{
97
0
    int code = 0;
98
99
    /* observed with Bug 699794, don't set is_open = true if the open_device failed */
100
    /* and make sure to propagate the return code from the child device to caller.  */
101
    /* Only open the child if it was closed  and if child open is OK, return 1.     */
102
    /* (see gs_opendevice) */
103
0
    if (dev->child && dev->child->is_open == 0) {
104
0
        code = dev_proc(dev->child, open_device)(dev->child);
105
0
        if (code >= 0) {
106
0
            dev->child->is_open = true;
107
0
            code = 1; /* device had been closed, but now is open */
108
0
        }
109
0
        gx_update_from_subclass(dev); /* this is probably safe to do even if the open failed */
110
0
    }
111
0
    return code;
112
0
}
113
114
void default_subclass_get_initial_matrix(gx_device *dev, gs_matrix *pmat)
115
680k
{
116
680k
    if (dev->child)
117
680k
        dev_proc(dev->child, get_initial_matrix)(dev->child, pmat);
118
0
    else
119
0
        gx_default_get_initial_matrix(dev, pmat);
120
680k
    return;
121
680k
}
122
123
int default_subclass_sync_output(gx_device *dev)
124
131k
{
125
131k
    if (dev->child)
126
131k
        return dev_proc(dev->child, sync_output)(dev->child);
127
    /* else */
128
0
    return gx_default_sync_output(dev);
129
131k
}
130
131
int default_subclass_output_page(gx_device *dev, int num_copies, int flush)
132
13.3k
{
133
13.3k
    int code = 0;
134
135
13.3k
    if (dev->child) {
136
13.3k
        code = dev_proc(dev->child, output_page)(dev->child, num_copies, flush);
137
13.3k
        dev->PageCount = dev->child->PageCount;
138
13.3k
        return code;
139
13.3k
    }
140
0
    dev->PageCount += num_copies; /* a minor lie */
141
0
    return 0;
142
13.3k
}
143
144
int default_subclass_close_device(gx_device *dev)
145
20.7k
{
146
20.7k
    int code;
147
148
20.7k
    if (dev->child) {
149
20.7k
        code = dev_proc(dev->child, close_device)(dev->child);
150
20.7k
        dev->is_open = dev->child->is_open = false;
151
20.7k
        return code;
152
20.7k
    }
153
0
    dev->is_open = false;
154
0
    return 0;
155
20.7k
}
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
812k
{
176
812k
    if (dev->child)
177
812k
        return dev_proc(dev->child, fill_rectangle)(dev->child, x, y, width, height, color);
178
0
    return 0;
179
812k
}
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
237k
{
200
237k
    if (dev->child)
201
237k
        return dev_proc(dev->child, get_params)(dev->child, plist);
202
    /* else */
203
0
    return gx_default_get_params(dev, plist);
204
237k
}
205
206
int default_subclass_put_params(gx_device *dev, gs_param_list *plist)
207
84.4k
{
208
84.4k
    int code;
209
210
84.4k
    if (dev->child) {
211
84.4k
        code = dev_proc(dev->child, put_params)(dev->child, plist);
212
        /* The child device might have closed itself (yes seriously, this can happen!) */
213
84.4k
        dev->is_open = dev->child->is_open;
214
84.4k
        gx_update_from_subclass(dev);
215
84.4k
        return code;
216
84.4k
    }
217
    /* else */
218
0
    return gx_default_put_params(dev, plist);
219
84.4k
}
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
1.41M
{
231
1.41M
    if (dev->child)
232
1.41M
        return dev_proc(dev->child, get_page_device)(dev->child);
233
    /* else */
234
0
    return gx_default_get_page_device(dev);
235
1.41M
}
236
237
int default_subclass_get_alpha_bits(gx_device *dev, graphics_object_type type)
238
11.1M
{
239
11.1M
    if (dev->child)
240
11.1M
        return dev_proc(dev->child, get_alpha_bits)(dev->child, type);
241
0
    return 0;
242
11.1M
}
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
692k
{
257
692k
    if (dev->child)
258
692k
        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
692k
}
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
132k
{
267
132k
    if (dev->child)
268
132k
        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
132k
}
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
68
{
334
68
    if (dev->child) {
335
68
        dev_proc(dev->child, get_clipping_box)(dev->child, pbox);
336
68
    } else
337
0
        gx_default_get_clipping_box(dev, pbox);
338
339
68
    return;
340
68
}
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
3.64k
{
347
3.64k
    if (dev->child)
348
3.64k
        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
3.64k
}
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 = dev->parent;
400
0
                        }
401
0
                    }
402
0
                    break;
403
0
                case PDF14_PUSH_DEVICE:
404
                    /* *pcdev is always returned containing a device capable of doing
405
                     * compositing. This may mean it is a new device. If this wants
406
                     * to be the new 'device' in the graphics state, then code will
407
                     * return as 1. */
408
0
                    if (code == 1) {
409
                        /* We want this device to stay ahead of the compositor; the newly created compositor has
410
                         * inserted itself in front of our child device, so basically we want to replace
411
                         * our current child with the newly created compositor. I hope !
412
                         */
413
0
                        psubclass_data = (generic_subclass_data *)dev->subclass_data;
414
0
                        if (psubclass_data == NULL)
415
0
                            return_error(gs_error_undefined);
416
0
                        psubclass_data->pre_composite_device = dev->child;
417
0
                        psubclass_data->saved_finalize_method = (*pcdev)->finalize;
418
0
                        (*pcdev)->finalize = subclass_composite_front_finalize;
419
420
0
                        (*pcdev)->child = dev->child;
421
0
                        dev->child = *pcdev;
422
0
                        (*pcdev)->parent = dev;
423
0
                        while (dev) {
424
0
                            memcpy(&dev->color_info, &(*pcdev)->color_info, sizeof(gx_device_color_info));
425
0
                            dev = dev->parent;
426
0
                        }
427
0
                    }
428
0
                    break;
429
0
                default:
430
                    /* It seems like many operations can result in the pdf14 device altering its color
431
                     * info, presumably as we push different blending spaces. Ick. In order to stay in sync
432
                     * any time we have inserted a compositor after this class, we must update the color info
433
                     * of this device after every operation, in case it changes....
434
                     */
435
0
                    if (psubclass_data->pre_composite_device != NULL) {
436
0
                        while (dev) {
437
0
                            memcpy(&(dev->color_info), &(dev->child->color_info), sizeof(gx_device_color_info));
438
0
                            dev = dev->parent;
439
0
                        }
440
0
                    }
441
0
                    break;
442
0
            }
443
444
0
        }
445
        /* We are inserting the compositor code after this device, or the compositor
446
         * did not create a new compositor. Either way we don't want the compositor code
447
         * to think we want to push a new device, so just return this device to the caller.
448
         */
449
0
        *pcdev = thisdev;
450
0
        return 0;
451
0
    }
452
0
    return 0;
453
0
}
454
455
int default_subclass_composite(gx_device *dev, gx_device **pcdev, const gs_composite_t *pcte,
456
    gs_gstate *pgs, gs_memory_t *memory, gx_device *cdev)
457
5.68k
{
458
5.68k
    int code;
459
460
5.68k
    if (dev->child) {
461
        /* Some more unpleasantness here. If the child device is a clist, then it will use the first argument
462
         * that we pass to access its own data (not unreasonably), so we need to make sure we pass in the
463
         * child device. This has some follow on implications detailed below.
464
         */
465
5.68k
        code = dev_proc(dev->child, composite)(dev->child, pcdev, pcte, pgs, memory, cdev);
466
5.68k
        if (code < 0)
467
3
            return code;
468
469
        /* *pcdev is always returned containing a device capable of doing
470
         * compositing. This may mean it is a new device. If this wants
471
         * to be the new 'device' in the graphics state, then code will
472
         * return as 1. */
473
5.67k
        if (code == 1) {
474
            /* The device chain on entry to this function was:
475
             *   dev(the subclassing device) -> child.
476
             * But now we also have:
477
             *   *pcdev -> child.
478
             * Or in some cases:
479
             *   *pcdev (-> other device)* -> child
480
             * Most callers would be happy to make dev->child = *pcdev,
481
             * thus giving us:
482
             *   dev -> *pcdev (-> other device)* ->child
483
             * Unfortunately, we are not happy with that. We need to
484
             * remain tightly bound to the child. i.e. we are aiming for:
485
             *   *pcdev (-> other device)* -> dev -> child
486
             * Accordingly, we need to move ourselves within the device
487
             * chain.
488
             */
489
836
            gx_device *penult = *pcdev;
490
491
836
            if (penult == NULL) {
492
                /* This should never happen. */
493
0
                return gs_error_unknownerror;
494
0
            }
495
496
            /* Find the penultimate device. */
497
2.43k
            while (1) {
498
2.43k
                gxdso_device_child_request req;
499
2.43k
                req.target = penult;
500
2.43k
                req.n = 0;
501
2.43k
                code = dev_proc(penult, dev_spec_op)(penult, gxdso_device_child, &req, sizeof(req));
502
2.43k
                if (code < 0)
503
0
                    return code;
504
2.43k
                if (req.target == NULL) {
505
                    /* Wooah! Where was dev->child? */
506
0
                    return gs_error_unknownerror;
507
0
                }
508
2.43k
                if (req.target == dev->child)
509
836
                    break; /* penult is the parent. */
510
1.59k
                penult = req.target;
511
1.59k
            }
512
513
836
            if (penult == NULL) {
514
                /* This should never happen. We know that we've just
515
                 * had a compositor inserted before dev->child, so there
516
                 * really ought to be one! */
517
0
                return gs_error_unknownerror;
518
0
            }
519
520
            /* We already point to dev->child, and hence own a reference
521
             * to it. */
522
523
            /* Now insert ourselves as the child of the penultimate one. */
524
836
            code = dev_proc(penult, dev_spec_op)(penult, gxdso_device_insert_child, dev, 0);
525
836
            if (code < 0)
526
0
                return code;
527
528
            /* Now we want our caller to update itself to recognise that
529
             * *pcdev should be its child, not dev. So we return 1. */
530
836
            return 1;
531
836
        }
532
4.84k
        else {
533
            /* See the 2 comments above. Now, if the child did not create a new compositor (eg its a clist)
534
             * then it returns pcdev pointing to the passed in device (the child in our case). Now this is a
535
             * problem, if we return with pcdev == child->dev, and the current device is 'dev' then the
536
             * compositor code will think we wanted to push a new device and will select the child device.
537
             * so here if pcdev == dev->child we change it to be our own device, so that the calling code
538
             * won't redirect the device in the graphics state.
539
             */
540
4.84k
            *pcdev = dev;
541
4.84k
            return code;
542
4.84k
        }
543
5.67k
    }
544
0
    return 0;
545
5.68k
}
546
547
int default_subclass_get_hardware_params(gx_device *dev, gs_param_list *plist)
548
0
{
549
0
    if (dev->child)
550
0
        return dev_proc(dev->child, get_hardware_params)(dev->child, plist);
551
    /* else */
552
0
    return gx_default_get_hardware_params(dev, plist);
553
0
}
554
555
int default_subclass_text_begin(gx_device *dev, gs_gstate *pgs, const gs_text_params_t *text,
556
    gs_font *font, const gx_clip_path *pcpath,
557
    gs_text_enum_t **ppte)
558
1.59M
{
559
1.59M
    if (dev->child)
560
1.59M
        return dev_proc(dev->child, text_begin)(dev->child, pgs, text, font, pcpath, ppte);
561
    /* else */
562
0
    return gx_default_text_begin(dev, pgs, text, font, pcpath, ppte);
563
1.59M
}
564
565
int default_subclass_begin_transparency_group(gx_device *dev, const gs_transparency_group_params_t *ptgp,
566
    const gs_rect *pbbox, gs_gstate *pgs, gs_memory_t *mem)
567
0
{
568
0
    if (dev->child)
569
0
        return dev_proc(dev->child, begin_transparency_group)(dev->child, ptgp, pbbox, pgs, mem);
570
571
0
    return 0;
572
0
}
573
574
int default_subclass_end_transparency_group(gx_device *dev, gs_gstate *pgs)
575
0
{
576
0
    if (dev->child)
577
0
        return dev_proc(dev->child, end_transparency_group)(dev->child, pgs);
578
579
0
    return 0;
580
0
}
581
582
int default_subclass_begin_transparency_mask(gx_device *dev, const gx_transparency_mask_params_t *ptmp,
583
    const gs_rect *pbbox, gs_gstate *pgs, gs_memory_t *mem)
584
0
{
585
0
    if (dev->child)
586
0
        return dev_proc(dev->child, begin_transparency_mask)(dev->child, ptmp, pbbox, pgs, mem);
587
588
0
    return 0;
589
0
}
590
591
int default_subclass_end_transparency_mask(gx_device *dev, gs_gstate *pgs)
592
0
{
593
0
    if (dev->child)
594
0
        return dev_proc(dev->child, end_transparency_mask)(dev->child, pgs);
595
596
0
    return 0;
597
0
}
598
599
int default_subclass_discard_transparency_layer(gx_device *dev, gs_gstate *pgs)
600
0
{
601
0
    if (dev->child)
602
0
        return dev_proc(dev->child, discard_transparency_layer)(dev->child, pgs);
603
604
0
    return 0;
605
0
}
606
607
const gx_cm_color_map_procs *default_subclass_get_color_mapping_procs(const gx_device *dev,
608
                                                                      const gx_device **tdev)
609
1.06M
{
610
1.06M
    if (dev->child)
611
1.06M
        return dev_proc(dev->child, get_color_mapping_procs)(dev->child, tdev);
612
    /* else */
613
0
    return gx_default_DevGray_get_color_mapping_procs(dev, tdev);
614
1.06M
}
615
616
int  default_subclass_get_color_comp_index(gx_device *dev, const char * pname, int name_size, int component_type)
617
19.1k
{
618
19.1k
    if (dev->child)
619
19.1k
        return dev_proc(dev->child, get_color_comp_index)(dev->child, pname, name_size, component_type);
620
    /* else */
621
0
    return gx_error_get_color_comp_index(dev, pname, name_size, component_type);
622
19.1k
}
623
624
gx_color_index default_subclass_encode_color(gx_device *dev, const gx_color_value colors[])
625
1.15M
{
626
1.15M
    if (dev->child)
627
1.15M
        return dev_proc(dev->child, encode_color)(dev->child, colors);
628
    /* else */
629
0
    return gx_error_encode_color(dev, colors);
630
1.15M
}
631
632
int default_subclass_decode_color(gx_device *dev, gx_color_index cindex, gx_color_value colors[])
633
0
{
634
0
    if (dev->child)
635
0
        return dev_proc(dev->child, decode_color)(dev->child, cindex, colors);
636
0
    else {
637
0
        memset(colors, 0, sizeof(gx_color_value[GX_DEVICE_COLOR_MAX_COMPONENTS]));
638
0
    }
639
640
0
    return 0;
641
0
}
642
643
int default_subclass_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect,
644
        const gs_gstate *pgs, const gx_drawing_color *pdcolor, const gx_clip_path *pcpath)
645
0
{
646
0
    if (dev->child)
647
0
        return dev_proc(dev->child, fill_rectangle_hl_color)(dev->child, rect, pgs, pdcolor, pcpath);
648
    /* else */
649
0
    return_error(gs_error_rangecheck);
650
0
}
651
652
int default_subclass_include_color_space(gx_device *dev, gs_color_space *cspace, const byte *res_name, int name_length)
653
0
{
654
0
    if (dev->child)
655
0
        return dev_proc(dev->child, include_color_space)(dev->child, cspace, res_name, name_length);
656
657
0
    return 0;
658
0
}
659
660
int default_subclass_fill_linear_color_scanline(gx_device *dev, const gs_fill_attributes *fa,
661
        int i, int j, int w, const frac31 *c0, const int32_t *c0_f, const int32_t *cg_num,
662
        int32_t cg_den)
663
0
{
664
0
    if (dev->child)
665
0
        return dev_proc(dev->child, fill_linear_color_scanline)(dev->child, fa, i, j, w, c0, c0_f, cg_num, cg_den);
666
    /* else */
667
0
    return gx_default_fill_linear_color_scanline(dev, fa, i, j, w, c0, c0_f, cg_num, cg_den);
668
0
}
669
670
int default_subclass_fill_linear_color_trapezoid(gx_device *dev, const gs_fill_attributes *fa,
671
        const gs_fixed_point *p0, const gs_fixed_point *p1,
672
        const gs_fixed_point *p2, const gs_fixed_point *p3,
673
        const frac31 *c0, const frac31 *c1,
674
        const frac31 *c2, const frac31 *c3)
675
0
{
676
0
    if (dev->child)
677
0
        return dev_proc(dev->child, fill_linear_color_trapezoid)(dev->child, fa, p0, p1, p2, p3, c0, c1, c2, c3);
678
    /* else */
679
0
    return gx_default_fill_linear_color_trapezoid(dev, fa, p0, p1, p2, p3, c0, c1, c2, c3);
680
0
}
681
682
int default_subclass_fill_linear_color_triangle(gx_device *dev, const gs_fill_attributes *fa,
683
        const gs_fixed_point *p0, const gs_fixed_point *p1,
684
        const gs_fixed_point *p2, const frac31 *c0, const frac31 *c1, const frac31 *c2)
685
0
{
686
0
    if (dev->child)
687
0
        return dev_proc(dev->child, fill_linear_color_triangle)(dev->child, fa, p0, p1, p2, c0, c1, c2);
688
    /* else */
689
0
    return gx_default_fill_linear_color_triangle(dev, fa, p0, p1, p2, c0, c1, c2);
690
0
}
691
692
int default_subclass_update_spot_equivalent_colors(gx_device *dev, const gs_gstate * pgs, const gs_color_space *pcs)
693
25
{
694
25
    if (dev->child)
695
25
        return dev_proc(dev->child, update_spot_equivalent_colors)(dev->child, pgs, pcs);
696
697
0
    return 0;
698
25
}
699
700
gs_devn_params *default_subclass_ret_devn_params(gx_device *dev)
701
1.63k
{
702
1.63k
    if (dev->child)
703
1.63k
        return dev_proc(dev->child, ret_devn_params)(dev->child);
704
705
0
    return 0;
706
1.63k
}
707
708
int default_subclass_fillpage(gx_device *dev, gs_gstate * pgs, gx_device_color *pdevc)
709
0
{
710
0
    if (dev->child)
711
0
        return dev_proc(dev->child, fillpage)(dev->child, pgs, pdevc);
712
    /* else */
713
0
    return gx_default_fillpage(dev, pgs, pdevc);
714
0
}
715
716
int default_subclass_push_transparency_state(gx_device *dev, gs_gstate *pgs)
717
0
{
718
0
    if (dev->child)
719
0
        return dev_proc(dev->child, push_transparency_state)(dev->child, pgs);
720
721
0
    return 0;
722
0
}
723
724
int default_subclass_pop_transparency_state(gx_device *dev, gs_gstate *pgs)
725
0
{
726
0
    if (dev->child)
727
0
        return dev_proc(dev->child, pop_transparency_state)(dev->child, pgs);
728
729
0
    return 0;
730
0
}
731
732
int default_subclass_put_image(gx_device *dev, gx_device *mdev, const byte **buffers, int num_chan, int x, int y,
733
            int width, int height, int row_stride,
734
            int alpha_plane_index, int tag_plane_index)
735
0
{
736
0
    if (dev->child) {
737
0
        if (dev == mdev) {
738
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);
739
0
        }
740
0
        else {
741
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);
742
0
        }
743
0
    }
744
0
    return 0;
745
0
}
746
747
int default_subclass_dev_spec_op(gx_device *dev, int op, void *data, int datasize)
748
7.26M
{
749
7.26M
    if (op == gxdso_is_clist_device)
750
0
        return 0;
751
7.26M
    if (op == gxdso_device_child) {
752
0
        gxdso_device_child_request *d = (gxdso_device_child_request *)data;
753
0
        if (d->target == dev) {
754
0
            d->target = dev->child;
755
0
            return 1;
756
0
        }
757
0
    }
758
7.26M
    if (dev->child)
759
7.26M
        return dev_proc(dev->child, dev_spec_op)(dev->child, op, data, datasize);
760
761
0
    return 0;
762
7.26M
}
763
764
int default_subclass_copy_planes(gx_device *dev, const byte *data, int data_x, int raster, gx_bitmap_id id,
765
    int x, int y, int width, int height, int plane_height)
766
0
{
767
0
    if (dev->child)
768
0
        return dev_proc(dev->child, copy_planes)(dev->child, data, data_x, raster, id, x, y, width, height, plane_height);
769
770
0
    return 0;
771
0
}
772
773
int default_subclass_get_profile(const gx_device *dev, cmm_dev_profile_t **dev_profile)
774
7.09M
{
775
7.09M
    if (dev->child) {
776
7.09M
        return dev_proc(dev->child, get_profile)(dev->child, dev_profile);
777
7.09M
    }
778
    /* else */
779
0
    return gx_default_get_profile(dev, dev_profile);
780
7.09M
}
781
782
/* In a delightful asymmetry, we have a set_graphics_type_tag, but no get_graphics_type_tag. Instead
783
 * (shudder) the code pulls the currently encoded colour and tag *directly* from the current device.
784
 * This means we have to copy the ENCODE_TAGS from the device we are subclassing, into the device which
785
 * is newly created at installation time. We also have to have our default set_graphics_type_tag method
786
 * update its graphics_type_tag, even though this device has no interest in it, just in case we happen
787
 * to be the top device in the chain......
788
 */
789
790
void default_subclass_set_graphics_type_tag(gx_device *dev, gs_graphics_type_tag_t tag)
791
255k
{
792
    /*
793
     * AIUI we should not be calling this method *unless* the ENCODE_TAGS bit is set, so we don't need
794
     * to do any checking. Just set the supplied tag in the current device, and pass it on to the underlying
795
     * device(s). This line is a direct copy from gx_default_set_graphics_type_tag.
796
     */
797
255k
    dev->graphics_type_tag = (dev->graphics_type_tag & GS_DEVICE_ENCODES_TAGS) | tag;
798
799
255k
    if (dev->child)
800
255k
        dev_proc(dev->child, set_graphics_type_tag)(dev->child, tag);
801
802
255k
    return;
803
255k
}
804
805
int default_subclass_strip_copy_rop2(gx_device *dev, const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id,
806
    const gx_color_index *scolors, const gx_strip_bitmap *textures, const gx_color_index *tcolors,
807
    int x, int y, int width, int height, int phase_x, int phase_y, gs_logical_operation_t lop, uint planar_height)
808
0
{
809
0
    if (!dev->child)
810
0
        return 0;
811
812
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);
813
0
}
814
815
int default_subclass_strip_tile_rect_devn(gx_device *dev, const gx_strip_bitmap *tiles, int x, int y, int width, int height,
816
    const gx_drawing_color *pdcolor0, const gx_drawing_color *pdcolor1, int phase_x, int phase_y)
817
0
{
818
0
    if (dev->child)
819
0
        return dev_proc(dev->child, strip_tile_rect_devn)(dev->child, tiles, x, y, width, height, pdcolor0, pdcolor1, phase_x, phase_y);
820
    /* else */
821
0
    return gx_default_strip_tile_rect_devn(dev->child, tiles, x, y, width, height, pdcolor0, pdcolor1, phase_x, phase_y);
822
0
}
823
824
int default_subclass_copy_alpha_hl_color(gx_device *dev, const byte *data, int data_x,
825
    int raster, gx_bitmap_id id, int x, int y, int width, int height,
826
    const gx_drawing_color *pdcolor, int depth)
827
0
{
828
0
    if (dev->child)
829
0
        return dev_proc(dev->child, copy_alpha_hl_color)(dev->child, data, data_x, raster, id, x, y, width, height, pdcolor, depth);
830
    /* else */
831
0
    return_error(gs_error_rangecheck);
832
0
}
833
834
int default_subclass_process_page(gx_device *dev, gx_process_page_options_t *options)
835
0
{
836
0
    if (dev->child)
837
0
        return dev_proc(dev->child, process_page)(dev->child, options);
838
839
0
    return 0;
840
0
}
841
842
int default_subclass_fill_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath,
843
        const gx_fill_params *fill_params, const gx_drawing_color *pdcolor_fill,
844
        const gx_stroke_params *stroke_params, const gx_drawing_color *pdcolor_stroke,
845
        const gx_clip_path *pcpath)
846
7.95k
{
847
7.95k
    if (dev->child)
848
7.95k
        return dev_proc(dev->child, fill_stroke_path)(dev->child, pgs, ppath, fill_params, pdcolor_fill,
849
7.95k
                                                      stroke_params, pdcolor_stroke, pcpath);
850
0
    return 0;
851
7.95k
}
852
853
int default_subclass_lock_pattern(gx_device *dev, gs_gstate *pgs, gs_id pattern_id, int lock)
854
40
{
855
40
    if (dev->child)
856
40
        return dev_proc(dev->child, lock_pattern)(dev->child, pgs, pattern_id, lock);
857
0
    return 0;
858
40
}
859
860
int default_subclass_transform_pixel_region(gx_device *dev, transform_pixel_region_reason reason, transform_pixel_region_data *data)
861
0
{
862
0
    if (dev->child)
863
0
        return dev_proc(dev->child, transform_pixel_region)(dev->child, reason, data);
864
865
0
    return gs_error_unknownerror;
866
0
}
867
868
void default_subclass_finalize(const gs_memory_t *cmem, void *vptr)
869
20.7k
{
870
20.7k
    gx_device * const dev = (gx_device *)vptr;
871
20.7k
    generic_subclass_data *psubclass_data = (generic_subclass_data *)dev->subclass_data;
872
20.7k
    (void)cmem; /* unused */
873
874
20.7k
    discard(gs_closedevice(dev));
875
876
20.7k
    if (dev->finalize)
877
0
        dev->finalize(dev);
878
879
    /* Use rc_decrement_only here not rc_decrement because rc_decrement zeroes the
880
     * pointer if the count reaches 0. That would be disastrous for us because we
881
     * rely on recursively calling finalize in order to fix up the chain of devices.
882
     */
883
20.7k
    rc_decrement_only(dev->child, "de-reference child device");
884
885
20.7k
    if (psubclass_data) {
886
20.7k
        gs_free_object(dev->memory->non_gc_memory, psubclass_data, "gx_epo_finalize(suclass data)");
887
20.7k
        dev->subclass_data = NULL;
888
20.7k
    }
889
20.7k
    if (dev->stype_is_dynamic)
890
20.7k
        gs_free_const_object(dev->memory->non_gc_memory, dev->stype,
891
20.7k
                             "default_subclass_finalize");
892
20.7k
    if (dev->parent)
893
0
        dev->parent->child = dev->child;
894
20.7k
    if (dev->child)
895
4
        dev->child->parent = dev->parent;
896
20.7k
    if (dev->icc_struct)
897
20.7k
        rc_decrement(dev->icc_struct, "finalize subclass device");
898
20.7k
    if (dev->PageList)
899
20.7k
        rc_decrement(dev->PageList, "finalize subclass device");
900
20.7k
    if (dev->NupControl)
901
20.7k
        rc_decrement(dev->NupControl, "finalize subclass device");
902
20.7k
}
903
904
void default_subclass_initialize_device_procs(gx_device *dev)
905
20.7k
{
906
20.7k
    set_dev_proc(dev, open_device, default_subclass_open_device);
907
20.7k
    set_dev_proc(dev, get_initial_matrix, default_subclass_get_initial_matrix);
908
20.7k
    set_dev_proc(dev, sync_output, default_subclass_sync_output);
909
20.7k
    set_dev_proc(dev, output_page, default_subclass_output_page);
910
20.7k
    set_dev_proc(dev, close_device, default_subclass_close_device);
911
20.7k
    set_dev_proc(dev, map_rgb_color, default_subclass_map_rgb_color);
912
20.7k
    set_dev_proc(dev, map_color_rgb, default_subclass_map_color_rgb);
913
20.7k
    set_dev_proc(dev, fill_rectangle, default_subclass_fill_rectangle);
914
20.7k
    set_dev_proc(dev, copy_mono, default_subclass_copy_mono);
915
20.7k
    set_dev_proc(dev, copy_color, default_subclass_copy_color);
916
20.7k
    set_dev_proc(dev, get_params, default_subclass_get_params);
917
20.7k
    set_dev_proc(dev, put_params, default_subclass_put_params);
918
20.7k
    set_dev_proc(dev, map_cmyk_color, default_subclass_map_cmyk_color);
919
20.7k
    set_dev_proc(dev, get_page_device, default_subclass_get_page_device);
920
20.7k
    set_dev_proc(dev, get_alpha_bits, default_subclass_get_alpha_bits);
921
20.7k
    set_dev_proc(dev, copy_alpha, default_subclass_copy_alpha);
922
20.7k
    set_dev_proc(dev, fill_path, default_subclass_fill_path);
923
20.7k
    set_dev_proc(dev, stroke_path, default_subclass_stroke_path);
924
20.7k
    set_dev_proc(dev, fill_mask, default_subclass_fill_mask);
925
20.7k
    set_dev_proc(dev, fill_trapezoid, default_subclass_fill_trapezoid);
926
20.7k
    set_dev_proc(dev, fill_parallelogram, default_subclass_fill_parallelogram);
927
20.7k
    set_dev_proc(dev, fill_triangle, default_subclass_fill_triangle);
928
20.7k
    set_dev_proc(dev, draw_thin_line, default_subclass_draw_thin_line);
929
20.7k
    set_dev_proc(dev, strip_tile_rectangle, default_subclass_strip_tile_rectangle);
930
20.7k
    set_dev_proc(dev, get_clipping_box, default_subclass_get_clipping_box);
931
20.7k
    set_dev_proc(dev, begin_typed_image, default_subclass_begin_typed_image);
932
20.7k
    set_dev_proc(dev, get_bits_rectangle, default_subclass_get_bits_rectangle);
933
20.7k
    set_dev_proc(dev, composite, default_subclass_composite);
934
20.7k
    set_dev_proc(dev, get_hardware_params, default_subclass_get_hardware_params);
935
20.7k
    set_dev_proc(dev, text_begin, default_subclass_text_begin);
936
20.7k
    set_dev_proc(dev, begin_transparency_group, default_subclass_begin_transparency_group);
937
20.7k
    set_dev_proc(dev, end_transparency_group, default_subclass_end_transparency_group);
938
20.7k
    set_dev_proc(dev, begin_transparency_mask, default_subclass_begin_transparency_mask);
939
20.7k
    set_dev_proc(dev, end_transparency_mask, default_subclass_end_transparency_mask);
940
20.7k
    set_dev_proc(dev, discard_transparency_layer, default_subclass_discard_transparency_layer);
941
20.7k
    set_dev_proc(dev, get_color_mapping_procs, default_subclass_get_color_mapping_procs);
942
20.7k
    set_dev_proc(dev, get_color_comp_index, default_subclass_get_color_comp_index);
943
20.7k
    set_dev_proc(dev, encode_color, default_subclass_encode_color);
944
20.7k
    set_dev_proc(dev, decode_color, default_subclass_decode_color);
945
20.7k
    set_dev_proc(dev, fill_rectangle_hl_color, default_subclass_fill_rectangle_hl_color);
946
20.7k
    set_dev_proc(dev, include_color_space, default_subclass_include_color_space);
947
20.7k
    set_dev_proc(dev, fill_linear_color_scanline, default_subclass_fill_linear_color_scanline);
948
20.7k
    set_dev_proc(dev, fill_linear_color_trapezoid, default_subclass_fill_linear_color_trapezoid);
949
20.7k
    set_dev_proc(dev, fill_linear_color_triangle, default_subclass_fill_linear_color_triangle);
950
20.7k
    set_dev_proc(dev, update_spot_equivalent_colors, default_subclass_update_spot_equivalent_colors);
951
20.7k
    set_dev_proc(dev, ret_devn_params, default_subclass_ret_devn_params);
952
20.7k
    set_dev_proc(dev, fillpage, default_subclass_fillpage);
953
20.7k
    set_dev_proc(dev, push_transparency_state, default_subclass_push_transparency_state);
954
20.7k
    set_dev_proc(dev, pop_transparency_state, default_subclass_pop_transparency_state);
955
20.7k
    set_dev_proc(dev, put_image, default_subclass_put_image);
956
20.7k
    set_dev_proc(dev, dev_spec_op, default_subclass_dev_spec_op);
957
20.7k
    set_dev_proc(dev, copy_planes, default_subclass_copy_planes);
958
20.7k
    set_dev_proc(dev, get_profile, default_subclass_get_profile);
959
20.7k
    set_dev_proc(dev, set_graphics_type_tag, default_subclass_set_graphics_type_tag);
960
20.7k
    set_dev_proc(dev, strip_copy_rop2, default_subclass_strip_copy_rop2);
961
20.7k
    set_dev_proc(dev, strip_tile_rect_devn, default_subclass_strip_tile_rect_devn);
962
20.7k
    set_dev_proc(dev, copy_alpha_hl_color, default_subclass_copy_alpha_hl_color);
963
20.7k
    set_dev_proc(dev, process_page, default_subclass_process_page);
964
20.7k
    set_dev_proc(dev, transform_pixel_region, default_subclass_transform_pixel_region);
965
20.7k
    set_dev_proc(dev, fill_stroke_path, default_subclass_fill_stroke_path);
966
20.7k
    set_dev_proc(dev, lock_pattern, default_subclass_lock_pattern);
967
20.7k
}
968
969
int
970
default_subclass_install(gx_device *dev, gs_gstate *pgs)
971
0
{
972
0
    dev = dev->child;
973
0
    return dev->page_procs.install(dev, pgs);
974
0
}
975
976
int
977
default_subclass_begin_page(gx_device *dev, gs_gstate *pgs)
978
0
{
979
0
    dev = dev->child;
980
0
    return dev->page_procs.begin_page(dev, pgs);
981
0
}
982
983
int
984
default_subclass_end_page(gx_device *dev, int reason, gs_gstate *pgs)
985
0
{
986
0
    dev = dev->child;
987
0
    return dev->page_procs.end_page(dev, reason, pgs);
988
0
}
989
990
void gx_subclass_fill_in_page_procs(gx_device *dev)
991
20.7k
{
992
20.7k
    if (dev->page_procs.install == NULL)
993
20.7k
        dev->page_procs.install = default_subclass_install;
994
20.7k
    if (dev->page_procs.begin_page == NULL)
995
20.7k
        dev->page_procs.begin_page = default_subclass_begin_page;
996
20.7k
    if (dev->page_procs.end_page == NULL)
997
20.7k
        dev->page_procs.end_page = default_subclass_end_page;
998
20.7k
}