Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/gdevepo.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2023 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
/* Device for erasepage optimization subclass device */
17
18
#include "math_.h"
19
#include "memory_.h"
20
#include "gx.h"
21
#include "gserrors.h"
22
#include "gsparam.h"
23
#include "gxdevice.h"
24
#include "gsdevice.h"   /* requires gsmatrix.h */
25
#include "gxdcolor.h"   /* for gx_device_black/white */
26
#include "gxiparam.h"   /* for image source size */
27
#include "gxgstate.h"
28
#include "gxpaint.h"
29
#include "gxpath.h"
30
#include "gxcpath.h"
31
#include "gxcmap.h"         /* color mapping procs */
32
#include "gsstype.h"
33
#include "gdevprn.h"
34
#include "gdevp14.h"        /* Needed to patch up the procs after compositor creation */
35
#include "gximage.h"        /* For gx_image_enum */
36
#include "gdevsclass.h"
37
#include "gsstate.h"
38
#include "gxdevsop.h"
39
#include "gdevepo.h"
40
#include <stdlib.h>
41
42
/* Shorter macros for sanity's sake */
43
1.16M
#define DPRINTF(m,f) if_debug0m(gs_debug_flag_epo_details, m,f)
44
1.42M
#define DPRINTF1(m,f,a1) if_debug1m(gs_debug_flag_epo_details, m,f, a1)
45
46
/* This is only called for debugging */
47
extern void epo_disable(int flag);
48
49
/* Device procedures, we need quite a lot of them */
50
static dev_proc_output_page(epo_output_page);
51
static dev_proc_fill_rectangle(epo_fill_rectangle);
52
static dev_proc_fill_path(epo_fill_path);
53
static dev_proc_fill_mask(epo_fill_mask);
54
static dev_proc_fill_trapezoid(epo_fill_trapezoid);
55
static dev_proc_fill_parallelogram(epo_fill_parallelogram);
56
static dev_proc_fill_triangle(epo_fill_triangle);
57
static dev_proc_draw_thin_line(epo_draw_thin_line);
58
static dev_proc_fill_rectangle_hl_color(epo_fill_rectangle_hl_color);
59
static dev_proc_fill_linear_color_scanline(epo_fill_linear_color_scanline);
60
static dev_proc_fill_linear_color_trapezoid(epo_fill_linear_color_trapezoid);
61
static dev_proc_fill_linear_color_triangle(epo_fill_linear_color_triangle);
62
static dev_proc_put_image(epo_put_image);
63
static dev_proc_fillpage(epo_fillpage);
64
static dev_proc_composite(epo_composite);
65
static dev_proc_text_begin(epo_text_begin);
66
static dev_proc_initialize_device_procs(epo_initialize_device_procs);
67
static dev_proc_begin_typed_image(epo_begin_typed_image);
68
static dev_proc_stroke_path(epo_stroke_path);
69
static dev_proc_copy_mono(epo_copy_mono);
70
static dev_proc_copy_color(epo_copy_color);
71
static dev_proc_copy_alpha(epo_copy_alpha);
72
static dev_proc_get_bits_rectangle(epo_get_bits_rectangle);
73
static dev_proc_strip_tile_rectangle(epo_strip_tile_rectangle);
74
static dev_proc_strip_copy_rop2(epo_strip_copy_rop2);
75
static dev_proc_copy_planes(epo_copy_planes);
76
static dev_proc_copy_alpha_hl_color(epo_copy_alpha_hl_color);
77
static dev_proc_process_page(epo_process_page);
78
static dev_proc_transform_pixel_region(epo_transform_pixel_region);
79
static dev_proc_fill_stroke_path(epo_fill_stroke_path);
80
81
/* The device prototype */
82
#define MAX_COORD (max_int_in_fixed - 1000)
83
#define MAX_RESOLUTION 4000
84
85
#define public_st_epo_device()  /* in gsdevice.c */\
86
  gs_public_st_complex_only(st_epo_device, gx_device, EPO_DEVICENAME,\
87
    0, epo_enum_ptrs, epo_reloc_ptrs, default_subclass_finalize)
88
89
static
90
198k
ENUM_PTRS_WITH(epo_enum_ptrs, gx_device *dev);
91
66.3k
return 0; /* default case */
92
66.3k
case 0:ENUM_RETURN(gx_device_enum_ptr(dev->parent));
93
66.3k
case 1:ENUM_RETURN(gx_device_enum_ptr(dev->child));
94
198k
ENUM_PTRS_END
95
66.3k
static RELOC_PTRS_WITH(epo_reloc_ptrs, gx_device *dev)
96
66.3k
{
97
66.3k
    dev->parent = gx_device_reloc_ptr(dev->parent, gcst);
98
66.3k
    dev->child = gx_device_reloc_ptr(dev->child, gcst);
99
66.3k
}RELOC_PTRS_END
100
101
public_st_epo_device();
102
103
const
104
gx_device_epo gs_epo_device =
105
{
106
    std_device_dci_type_body_sc(gx_device_epo, epo_initialize_device_procs,
107
                        EPO_DEVICENAME, &st_epo_device,
108
                        MAX_COORD, MAX_COORD,
109
                        MAX_RESOLUTION, MAX_RESOLUTION,
110
                        1, 8, 255, 0, 256, 1, NULL, NULL, NULL)
111
};
112
113
#undef MAX_COORD
114
#undef MAX_RESOLUTION
115
116
/* Starting at the top of the device chain (top parent) find  */
117
/* and return the epo device, or NULL if not found.   */
118
static gx_device *
119
find_installed_epo_device(gx_device *dev)
120
1.16M
{
121
1.16M
    gx_device *next_dev = dev;
122
123
1.16M
    while (next_dev->parent != NULL)
124
0
        next_dev = next_dev->parent;
125
126
2.14M
    while (next_dev) {
127
1.16M
        if (next_dev->procs.fillpage == epo_fillpage) {
128
194k
            return next_dev;
129
194k
        }
130
974k
        next_dev = next_dev->child;
131
974k
    }
132
974k
    return NULL;
133
1.16M
}
134
135
/* See if this is a device we can optimize
136
 * (currently only the ones that use gx_default_fillpage, which
137
 * automatically excludes clist and pdfwrite, etc)
138
 */
139
static bool
140
device_wants_optimization(gx_device *dev)
141
1.16M
{
142
1.16M
    gx_device *terminal = dev;
143
144
1.16M
    while(terminal->child != NULL)
145
0
        terminal = terminal->child;
146
147
1.16M
    return (!gs_is_null_device(terminal) && dev_proc(terminal, fillpage) == gx_default_fillpage);
148
1.16M
}
149
150
/* Use this when debugging to enable/disable epo
151
 * (1 - disable, 0 - enable)
152
 */
153
void
154
epo_disable(int flag)
155
0
{
156
0
    gs_debug[gs_debug_flag_epo_disable] = flag;
157
0
}
158
159
static void
160
enable_procs(gx_device *dev)
161
225k
{
162
225k
    set_dev_proc(dev, output_page, epo_output_page);
163
225k
    set_dev_proc(dev, fill_rectangle, epo_fill_rectangle);
164
225k
    set_dev_proc(dev, copy_mono, epo_copy_mono);
165
225k
    set_dev_proc(dev, copy_color, epo_copy_color);
166
225k
    set_dev_proc(dev, copy_alpha, epo_copy_alpha);
167
225k
    set_dev_proc(dev, get_bits_rectangle, epo_get_bits_rectangle);
168
225k
    set_dev_proc(dev, fill_path, epo_fill_path);
169
225k
    set_dev_proc(dev, stroke_path, epo_stroke_path);
170
225k
    set_dev_proc(dev, fill_mask, epo_fill_mask);
171
225k
    set_dev_proc(dev, fill_trapezoid, epo_fill_trapezoid);
172
225k
    set_dev_proc(dev, fill_parallelogram, epo_fill_parallelogram);
173
225k
    set_dev_proc(dev, fill_triangle, epo_fill_triangle);
174
225k
    set_dev_proc(dev, draw_thin_line, epo_draw_thin_line);
175
225k
    set_dev_proc(dev, strip_tile_rectangle, epo_strip_tile_rectangle);
176
225k
    set_dev_proc(dev, begin_typed_image, epo_begin_typed_image);
177
225k
    set_dev_proc(dev, composite, epo_composite);
178
225k
    set_dev_proc(dev, text_begin, epo_text_begin);
179
225k
    set_dev_proc(dev, fill_rectangle_hl_color, epo_fill_rectangle_hl_color);
180
225k
    set_dev_proc(dev, fill_linear_color_scanline, epo_fill_linear_color_scanline);
181
225k
    set_dev_proc(dev, fill_linear_color_trapezoid, epo_fill_linear_color_trapezoid);
182
225k
    set_dev_proc(dev, fill_linear_color_triangle, epo_fill_linear_color_triangle);
183
225k
    set_dev_proc(dev, fillpage, epo_fillpage);
184
225k
    set_dev_proc(dev, put_image, epo_put_image);
185
225k
    set_dev_proc(dev, copy_planes, epo_copy_planes);
186
225k
    set_dev_proc(dev, strip_copy_rop2, epo_strip_copy_rop2);
187
225k
    set_dev_proc(dev, copy_alpha_hl_color, epo_copy_alpha_hl_color);
188
225k
    set_dev_proc(dev, process_page, epo_process_page);
189
225k
    set_dev_proc(dev, transform_pixel_region, epo_transform_pixel_region);
190
225k
    set_dev_proc(dev, fill_stroke_path, epo_fill_stroke_path);
191
225k
}
192
193
static void
194
enable_self(gx_device *dev)
195
194k
{
196
194k
    erasepage_subclass_data *data = (erasepage_subclass_data *)dev->subclass_data;
197
198
194k
    data->disabled = 0;
199
194k
    enable_procs(dev);
200
194k
}
201
202
static void
203
disable_self(gx_device *dev)
204
27.7k
{
205
27.7k
    erasepage_subclass_data *data = (erasepage_subclass_data *)dev->subclass_data;
206
207
27.7k
    data->disabled = 1;
208
209
27.7k
    set_dev_proc(dev, output_page, default_subclass_output_page);
210
27.7k
    set_dev_proc(dev, fill_rectangle, default_subclass_fill_rectangle);
211
27.7k
    set_dev_proc(dev, copy_mono, default_subclass_copy_mono);
212
27.7k
    set_dev_proc(dev, copy_color, default_subclass_copy_color);
213
27.7k
    set_dev_proc(dev, copy_alpha, default_subclass_copy_alpha);
214
27.7k
    set_dev_proc(dev, get_bits_rectangle, default_subclass_get_bits_rectangle);
215
27.7k
    set_dev_proc(dev, fill_path, default_subclass_fill_path);
216
27.7k
    set_dev_proc(dev, stroke_path, default_subclass_stroke_path);
217
27.7k
    set_dev_proc(dev, fill_mask, default_subclass_fill_mask);
218
27.7k
    set_dev_proc(dev, fill_trapezoid, default_subclass_fill_trapezoid);
219
27.7k
    set_dev_proc(dev, fill_parallelogram, default_subclass_fill_parallelogram);
220
27.7k
    set_dev_proc(dev, fill_triangle, default_subclass_fill_triangle);
221
27.7k
    set_dev_proc(dev, draw_thin_line, default_subclass_draw_thin_line);
222
27.7k
    set_dev_proc(dev, strip_tile_rectangle, default_subclass_strip_tile_rectangle);
223
27.7k
    set_dev_proc(dev, begin_typed_image, default_subclass_begin_typed_image);
224
27.7k
    set_dev_proc(dev, composite, default_subclass_composite);
225
27.7k
    set_dev_proc(dev, text_begin, default_subclass_text_begin);
226
27.7k
    set_dev_proc(dev, fill_rectangle_hl_color, default_subclass_fill_rectangle_hl_color);
227
27.7k
    set_dev_proc(dev, fill_linear_color_scanline, default_subclass_fill_linear_color_scanline);
228
27.7k
    set_dev_proc(dev, fill_linear_color_trapezoid, default_subclass_fill_linear_color_trapezoid);
229
27.7k
    set_dev_proc(dev, fill_linear_color_triangle, default_subclass_fill_linear_color_triangle);
230
    /* NOT fillpage! */
231
27.7k
    set_dev_proc(dev, put_image, default_subclass_put_image);
232
27.7k
    set_dev_proc(dev, copy_planes, default_subclass_copy_planes);
233
27.7k
    set_dev_proc(dev, strip_copy_rop2, default_subclass_strip_copy_rop2);
234
27.7k
    set_dev_proc(dev, copy_alpha_hl_color, default_subclass_copy_alpha_hl_color);
235
27.7k
    set_dev_proc(dev, process_page, default_subclass_process_page);
236
27.7k
    set_dev_proc(dev, transform_pixel_region, default_subclass_transform_pixel_region);
237
27.7k
    set_dev_proc(dev, fill_stroke_path, default_subclass_fill_stroke_path);
238
27.7k
    set_dev_proc(dev, lock_pattern, default_subclass_lock_pattern);
239
27.7k
}
240
241
int
242
epo_check_and_install(gx_device *dev)
243
1.16M
{
244
1.16M
    int code = 0;
245
1.16M
    gx_device *installed_epo_device = NULL;
246
1.16M
    bool can_optimize = false;
247
248
    /* Debugging mode to totally disable this */
249
1.16M
    if (gs_debug_c(gs_debug_flag_epo_disable)) {
250
0
        return code;
251
0
    }
252
253
1.16M
    DPRINTF1(dev->memory, "current device is %s\n", dev->dname);
254
255
1.16M
    installed_epo_device = find_installed_epo_device(dev);
256
257
1.16M
    if (installed_epo_device != NULL) {
258
194k
        DPRINTF1(dev->memory, "device %s already installed\n", EPO_DEVICENAME);
259
        /* This is looking for the case where the device
260
         * changed into something we can't optimize, after it was already installed
261
         * (could be clist or some other weird thing)
262
         */
263
194k
        if (installed_epo_device->child) {
264
194k
            can_optimize = device_wants_optimization(installed_epo_device->child);
265
194k
        }
266
194k
        if (!can_optimize) {
267
0
            DPRINTF1(dev->memory, "child %s can't be optimized, uninstalling\n", installed_epo_device->child->dname);
268
            /* Not doing any pending fillpages because we are about to do a fillpage anyway */
269
0
            disable_self(installed_epo_device);
270
0
            return code;
271
0
        }
272
974k
    } else {
273
974k
        can_optimize = device_wants_optimization(dev);
274
974k
    }
275
276
    /* Already installed, nothing to do */
277
1.16M
    if (installed_epo_device != NULL) {
278
194k
        enable_self(installed_epo_device);
279
194k
        return code;
280
194k
    }
281
282
    /* See if we can optimize */
283
974k
    if (!can_optimize) {
284
942k
        DPRINTF(dev->memory, "device doesn't want optimization, not installing\n");
285
942k
        return code;
286
942k
    }
287
288
    /* Always install us as low down the chain as possible. */
289
31.6k
    while (dev->child)
290
0
            dev = dev->child;
291
292
    /* Install subclass for optimization */
293
31.6k
    code = gx_device_subclass(dev, (gx_device *)&gs_epo_device, sizeof(erasepage_subclass_data));
294
31.6k
    if (code < 0) {
295
6
        DPRINTF1(dev->memory, "ERROR installing device %s\n", EPO_DEVICENAME);
296
6
        return code;
297
6
    }
298
299
31.6k
    DPRINTF1(dev->memory, "SUCCESS installed device %s\n", dev->dname);
300
31.6k
    return code;
301
31.6k
}
302
303
static int
304
epo_handle_erase_page(gx_device *dev)
305
27.7k
{
306
27.7k
    erasepage_subclass_data *data = (erasepage_subclass_data *)dev->subclass_data;
307
27.7k
    int code = 0;
308
309
27.7k
    if (data->disabled)
310
0
        return 0;
311
312
27.7k
    if (gs_debug_c(gs_debug_flag_epo_install_only)) {
313
0
        disable_self(dev);
314
0
        DPRINTF1(dev->memory, "Uninstall erasepage, device=%s\n", dev->dname);
315
0
        return code;
316
0
    }
317
318
27.7k
    DPRINTF1(dev->memory, "Do fillpage, Uninstall erasepage, device %s\n", dev->dname);
319
320
    /* Just do a fill_rectangle (using saved color) */
321
27.7k
    if (dev->child && dev->child->is_open && data->queued && dev_proc(dev->child, fill_rectangle) != NULL) {
322
27.7k
        code = dev_proc(dev->child, fill_rectangle)(dev->child,
323
27.7k
                                                    0, 0,
324
27.7k
                                                    dev->child->width,
325
27.7k
                                                    dev->child->height,
326
27.7k
                                                    data->last_color);
327
27.7k
    }
328
    /* Disable the epo device */
329
27.7k
    disable_self(dev);
330
331
27.7k
    return code;
332
27.7k
}
333
334
int epo_fillpage(gx_device *dev, gs_gstate * pgs, gx_device_color *pdevc)
335
225k
{
336
225k
    erasepage_subclass_data *data = (erasepage_subclass_data *)dev->subclass_data;
337
338
225k
    if (data->disabled || gs_debug_c(gs_debug_flag_epo_install_only)) {
339
0
        return default_subclass_fillpage(dev, pgs, pdevc);
340
0
    }
341
342
    /* If color is not pure, don't defer this, uninstall and do it now */
343
225k
    if (!color_is_pure(pdevc)) {
344
0
        DPRINTF(dev->memory, "epo_fillpage(), color is not pure, uninstalling\n");
345
0
        disable_self(dev);
346
0
        return dev_proc(dev->child, fillpage)(dev->child, pgs, pdevc);
347
0
    }
348
349
    /* Save the color being requested, and swallow the fillpage */
350
225k
    data->last_color = pdevc->colors.pure;
351
225k
    data->queued = 1;
352
353
225k
    DPRINTF(dev->memory, "Swallowing fillpage\n");
354
225k
    return 0;
355
225k
}
356
357
int epo_output_page(gx_device *dev, int num_copies, int flush)
358
0
{
359
0
    int code = epo_handle_erase_page(dev);
360
361
0
    if (code != 0)
362
0
        return code;
363
0
    dev = dev->child;
364
0
    return dev_proc(dev, output_page)(dev, num_copies, flush);
365
0
}
366
367
int epo_fill_rectangle(gx_device *dev, int x, int y, int width, int height, gx_color_index color)
368
375
{
369
375
    int code = epo_handle_erase_page(dev);
370
371
375
    if (code != 0)
372
0
        return code;
373
375
    dev = dev->child;
374
375
    if (dev_proc(dev, fill_rectangle) != NULL)
375
375
        return dev_proc(dev, fill_rectangle)(dev, x, y, width, height, color);
376
0
    else
377
0
        return 0;
378
375
}
379
380
int epo_fill_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath,
381
    const gx_fill_params *params,
382
    const gx_drawing_color *pdcolor, const gx_clip_path *pcpath)
383
11.2k
{
384
11.2k
    int code = epo_handle_erase_page(dev);
385
386
11.2k
    if (code != 0)
387
0
        return code;
388
11.2k
    dev = dev->child;
389
11.2k
    return dev_proc(dev, fill_path)(dev, pgs, ppath, params, pdcolor, pcpath);
390
11.2k
}
391
392
int epo_fill_mask(gx_device *dev, const byte *data, int data_x, int raster, gx_bitmap_id id,
393
    int x, int y, int width, int height,
394
    const gx_drawing_color *pdcolor, int depth,
395
    gs_logical_operation_t lop, const gx_clip_path *pcpath)
396
0
{
397
0
    int code = epo_handle_erase_page(dev);
398
399
0
    if (code != 0)
400
0
        return code;
401
0
    dev = dev->child;
402
0
    return dev_proc(dev, fill_mask)(dev, data, data_x, raster, id, x, y, width, height, pdcolor, depth, lop, pcpath);
403
0
}
404
405
int epo_fill_trapezoid(gx_device *dev, const gs_fixed_edge *left, const gs_fixed_edge *right,
406
    fixed ybot, fixed ytop, bool swap_axes,
407
    const gx_drawing_color *pdcolor, gs_logical_operation_t lop)
408
0
{
409
0
    int code = epo_handle_erase_page(dev);
410
411
0
    if (code != 0)
412
0
        return code;
413
0
    dev = dev->child;
414
0
    return dev_proc(dev, fill_trapezoid)(dev, left, right, ybot, ytop, swap_axes, pdcolor, lop);
415
0
}
416
417
int epo_fill_parallelogram(gx_device *dev, fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
418
    const gx_drawing_color *pdcolor, gs_logical_operation_t lop)
419
0
{
420
0
    int code = epo_handle_erase_page(dev);
421
422
0
    if (code != 0)
423
0
        return code;
424
0
    dev = dev->child;
425
0
    return dev_proc(dev, fill_parallelogram)(dev, px, py, ax, ay, bx, by, pdcolor, lop);
426
0
}
427
428
int epo_fill_triangle(gx_device *dev, fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
429
    const gx_drawing_color *pdcolor, gs_logical_operation_t lop)
430
0
{
431
0
    int code = epo_handle_erase_page(dev);
432
433
0
    if (code != 0)
434
0
        return code;
435
0
    dev = dev->child;
436
0
    return dev_proc(dev, fill_triangle)(dev, px, py, ax, ay, bx, by, pdcolor, lop);
437
0
}
438
439
int epo_draw_thin_line(gx_device *dev, fixed fx0, fixed fy0, fixed fx1, fixed fy1,
440
    const gx_drawing_color *pdcolor, gs_logical_operation_t lop,
441
    fixed adjustx, fixed adjusty)
442
0
{
443
0
    int code = epo_handle_erase_page(dev);
444
445
0
    if (code != 0)
446
0
        return code;
447
0
    dev = dev->child;
448
0
    return dev_proc(dev, draw_thin_line)(dev, fx0, fy0, fx1, fy1, pdcolor, lop, adjustx, adjusty);
449
0
}
450
451
int epo_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect,
452
        const gs_gstate *pgs, const gx_drawing_color *pdcolor, const gx_clip_path *pcpath)
453
0
{
454
0
    int code = epo_handle_erase_page(dev);
455
456
0
    if (code != 0)
457
0
        return code;
458
0
    dev = dev->child;
459
0
    return dev_proc(dev, fill_rectangle_hl_color)(dev, rect, pgs, pdcolor, pcpath);
460
0
}
461
462
int epo_fill_linear_color_scanline(gx_device *dev, const gs_fill_attributes *fa,
463
        int i, int j, int w, const frac31 *c0, const int32_t *c0_f, const int32_t *cg_num,
464
        int32_t cg_den)
465
0
{
466
0
    int code = epo_handle_erase_page(dev);
467
468
0
    if (code != 0)
469
0
        return code;
470
0
    dev = dev->child;
471
0
    return dev_proc(dev, fill_linear_color_scanline)(dev, fa, i, j, w, c0, c0_f, cg_num, cg_den);
472
0
}
473
474
int epo_fill_linear_color_trapezoid(gx_device *dev, const gs_fill_attributes *fa,
475
        const gs_fixed_point *p0, const gs_fixed_point *p1,
476
        const gs_fixed_point *p2, const gs_fixed_point *p3,
477
        const frac31 *c0, const frac31 *c1,
478
        const frac31 *c2, const frac31 *c3)
479
0
{
480
0
    int code = epo_handle_erase_page(dev);
481
482
0
    if (code != 0)
483
0
        return code;
484
0
    dev = dev->child;
485
0
    return dev_proc(dev, fill_linear_color_trapezoid)(dev, fa, p0, p1, p2, p3, c0, c1, c2, c3);
486
0
}
487
488
int epo_fill_linear_color_triangle(gx_device *dev, const gs_fill_attributes *fa,
489
        const gs_fixed_point *p0, const gs_fixed_point *p1,
490
        const gs_fixed_point *p2, const frac31 *c0, const frac31 *c1, const frac31 *c2)
491
0
{
492
0
    int code = epo_handle_erase_page(dev);
493
494
0
    if (code != 0)
495
0
        return code;
496
0
    dev = dev->child;
497
0
    return dev_proc(dev, fill_linear_color_triangle)(dev, fa, p0, p1, p2, c0, c1, c2);
498
0
}
499
500
int epo_put_image(gx_device *dev, gx_device *mdev, const byte **buffers, int num_chan, int x, int y,
501
            int width, int height, int row_stride,
502
            int alpha_plane_index, int tag_plane_index)
503
0
{
504
0
    int code = epo_handle_erase_page(dev);
505
506
0
    if (code != 0)
507
0
        return code;
508
0
    dev = dev->child;
509
0
    return dev_proc(dev, put_image)(dev, mdev, buffers, num_chan, x, y, width, height, row_stride, alpha_plane_index, tag_plane_index);
510
0
}
511
512
int epo_composite(gx_device *dev, gx_device **pcdev, const gs_composite_t *pcte,
513
    gs_gstate *pgs, gs_memory_t *memory, gx_device *cdev)
514
3.48k
{
515
3.48k
    int code = epo_handle_erase_page(dev);
516
517
3.48k
    if (code != 0)
518
0
        return code;
519
3.48k
    return default_subclass_composite(dev, pcdev, pcte, pgs, memory, cdev);
520
3.48k
}
521
522
int epo_text_begin(gx_device *dev, gs_gstate *pgs, const gs_text_params_t *text,
523
    gs_font *font, const gx_clip_path *pcpath,
524
    gs_text_enum_t **ppte)
525
8.90k
{
526
8.90k
    int code = epo_handle_erase_page(dev);
527
528
8.90k
    if (code != 0)
529
0
        return code;
530
8.90k
    dev = dev->child;
531
8.90k
    return dev_proc(dev, text_begin)(dev, pgs, text, font, pcpath, ppte);
532
8.90k
}
533
534
static int epo_initialize_device(gx_device *dev)
535
0
{
536
    /* We musn't allow the following pointers to remain shared with the from_dev
537
       because we're about to tell the caller it's only allowed to copy the prototype
538
       and free the attempted copy of a non-prototype. If from_dev is the prototype
539
       these pointers won't be set, anyway.
540
     */
541
0
    dev->child = NULL;
542
0
    dev->parent = NULL;
543
0
    dev->subclass_data = NULL;
544
0
    return 0;
545
0
}
546
547
void epo_initialize_device_procs(gx_device *dev)
548
31.6k
{
549
31.6k
    default_subclass_initialize_device_procs(dev);
550
551
31.6k
    set_dev_proc(dev, initialize_device, epo_initialize_device);
552
31.6k
    enable_procs(dev);
553
31.6k
}
554
555
int epo_begin_typed_image(gx_device *dev, const gs_gstate *pgs, const gs_matrix *pmat,
556
    const gs_image_common_t *pic, const gs_int_rect *prect,
557
    const gx_drawing_color *pdcolor, const gx_clip_path *pcpath,
558
    gs_memory_t *memory, gx_image_enum_common_t **pinfo)
559
2.79k
{
560
2.79k
    int code = epo_handle_erase_page(dev);
561
562
2.79k
    if (code != 0)
563
0
        return code;
564
2.79k
    dev = dev->child;
565
2.79k
    return dev_proc(dev, begin_typed_image)(dev, pgs, pmat, pic, prect, pdcolor, pcpath, memory, pinfo);
566
2.79k
}
567
568
int epo_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath,
569
    const gx_stroke_params *params,
570
    const gx_drawing_color *pdcolor, const gx_clip_path *pcpath)
571
789
{
572
789
    int code = epo_handle_erase_page(dev);
573
574
789
    if (code != 0)
575
0
        return code;
576
789
    dev = dev->child;
577
789
    return dev_proc(dev, stroke_path)(dev, pgs, ppath, params, pdcolor, pcpath);
578
789
}
579
580
int epo_copy_mono(gx_device *dev, const byte *data, int data_x, int raster, gx_bitmap_id id,
581
    int x, int y, int width, int height,
582
    gx_color_index color0, gx_color_index color1)
583
0
{
584
0
    int code = epo_handle_erase_page(dev);
585
586
0
    if (code != 0)
587
0
        return code;
588
0
    dev = dev->child;
589
0
    return dev_proc(dev, copy_mono)(dev, data, data_x, raster, id, x, y, width, height, color0, color1);
590
0
}
591
592
int epo_copy_color(gx_device *dev, const byte *data, int data_x, int raster, gx_bitmap_id id,\
593
    int x, int y, int width, int height)
594
0
{
595
0
    int code = epo_handle_erase_page(dev);
596
597
0
    if (code != 0)
598
0
        return code;
599
0
    dev = dev->child;
600
0
    return dev_proc(dev, copy_color)(dev, data, data_x, raster, id, x, y, width, height);
601
0
}
602
603
int epo_get_bits_rectangle(gx_device *dev, const gs_int_rect *prect,
604
                           gs_get_bits_params_t *params)
605
0
{
606
0
    int code = epo_handle_erase_page(dev);
607
608
0
    if (code != 0)
609
0
        return code;
610
0
    dev = dev->child;
611
0
    return dev_proc(dev, get_bits_rectangle)(dev, prect, params);
612
0
}
613
614
int epo_copy_alpha(gx_device *dev, const byte *data, int data_x,
615
    int raster, gx_bitmap_id id, int x, int y, int width, int height,
616
    gx_color_index color, int depth)
617
0
{
618
0
    int code = epo_handle_erase_page(dev);
619
620
0
    if (code != 0)
621
0
        return code;
622
0
    dev = dev->child;
623
0
    return dev_proc(dev, copy_alpha)(dev, data, data_x, raster, id, x, y, width, height, color, depth);
624
0
}
625
626
int epo_strip_tile_rectangle(gx_device *dev, const gx_strip_bitmap *tiles, int x, int y, int width, int height,
627
    gx_color_index color0, gx_color_index color1,
628
    int phase_x, int phase_y)
629
0
{
630
0
    int code = epo_handle_erase_page(dev);
631
632
0
    if (code != 0)
633
0
        return code;
634
0
    dev = dev->child;
635
0
    return dev_proc(dev, strip_tile_rectangle)(dev, tiles, x, y, width, height, color0, color1, phase_x, phase_y);
636
0
}
637
638
int epo_strip_copy_rop2(gx_device *dev, const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id,
639
    const gx_color_index *scolors, const gx_strip_bitmap *textures, const gx_color_index *tcolors,
640
    int x, int y, int width, int height, int phase_x, int phase_y, gs_logical_operation_t lop, uint planar_height)
641
0
{
642
0
    int code = epo_handle_erase_page(dev);
643
644
0
    if (code != 0)
645
0
        return code;
646
0
    dev = dev->child;
647
0
    return dev_proc(dev, strip_copy_rop2)(dev, sdata, sourcex, sraster, id, scolors, textures, tcolors, x, y, width, height, phase_x, phase_y, lop, planar_height);
648
0
}
649
650
int epo_copy_planes(gx_device *dev, const byte *data, int data_x, int raster, gx_bitmap_id id,
651
    int x, int y, int width, int height, int plane_height)
652
0
{
653
0
    int code = epo_handle_erase_page(dev);
654
655
0
    if (code != 0)
656
0
        return code;
657
0
    dev = dev->child;
658
0
    return dev_proc(dev, copy_planes)(dev, data, data_x, raster, id, x, y, width, height, plane_height);
659
0
}
660
661
int epo_copy_alpha_hl_color(gx_device *dev, const byte *data, int data_x,
662
    int raster, gx_bitmap_id id, int x, int y, int width, int height,
663
    const gx_drawing_color *pdcolor, int depth)
664
0
{
665
0
    int code = epo_handle_erase_page(dev);
666
667
0
    if (code != 0)
668
0
        return code;
669
0
    dev = dev->child;
670
0
    return dev_proc(dev, copy_alpha_hl_color)(dev, data, data_x, raster, id, x, y, width, height, pdcolor, depth);
671
0
}
672
673
int epo_process_page(gx_device *dev, gx_process_page_options_t *options)
674
0
{
675
0
    int code = epo_handle_erase_page(dev);
676
677
0
    if (code != 0)
678
0
        return code;
679
0
    dev = dev->child;
680
0
    return dev_proc(dev, process_page)(dev, options);
681
0
}
682
683
int epo_fill_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath,
684
    const gx_fill_params *fill_params, const gx_drawing_color *pdcolor_fill,
685
    const gx_stroke_params *stroke_params, const gx_drawing_color *pdcolor_stroke,
686
    const gx_clip_path *pcpath)
687
189
{
688
189
    int code = epo_handle_erase_page(dev);
689
690
189
    if (code != 0)
691
0
        return code;
692
189
    dev = dev->child;
693
189
    return dev_proc(dev, fill_stroke_path)(dev, pgs, ppath, fill_params, pdcolor_fill,
694
189
                                           stroke_params, pdcolor_stroke, pcpath);
695
189
}
696
697
int epo_transform_pixel_region(gx_device *dev, transform_pixel_region_reason reason, transform_pixel_region_data *data)
698
0
{
699
0
    int code = epo_handle_erase_page(dev);
700
701
0
    if (code != 0)
702
0
        return code;
703
0
    dev = dev->child;
704
0
    return dev_proc(dev, transform_pixel_region)(dev, reason, data);
705
0
}