Coverage Report

Created: 2022-04-16 11:23

/src/ghostpdl/base/gdevepo.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
/* 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
5.59k
#define DPRINTF(m,f) if_debug0m(gs_debug_flag_epo_details, m,f)
44
5.59k
#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
0
ENUM_PTRS_WITH(epo_enum_ptrs, gx_device *dev);
91
0
return 0; /* default case */
92
0
case 0:ENUM_RETURN(gx_device_enum_ptr(dev->parent));
93
0
case 1:ENUM_RETURN(gx_device_enum_ptr(dev->child));
94
0
ENUM_PTRS_END
95
0
static RELOC_PTRS_WITH(epo_reloc_ptrs, gx_device *dev)
96
0
{
97
0
    dev->parent = gx_device_reloc_ptr(dev->parent, gcst);
98
0
    dev->child = gx_device_reloc_ptr(dev->child, gcst);
99
0
}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
5.59k
{
121
5.59k
    gx_device *next_dev = dev;
122
123
5.59k
    while (next_dev->parent != NULL)
124
0
        next_dev = next_dev->parent;
125
126
11.1k
    while (next_dev) {
127
5.59k
        if (next_dev->procs.fillpage == epo_fillpage) {
128
0
            return next_dev;
129
0
        }
130
5.59k
        next_dev = next_dev->child;
131
5.59k
    }
132
5.59k
    return NULL;
133
5.59k
}
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
5.59k
{
142
5.59k
    gx_device *terminal = dev;
143
144
5.59k
    while(terminal->child != NULL)
145
0
        terminal = terminal->child;
146
147
5.59k
    return (!gs_is_null_device(terminal) && dev_proc(terminal, fillpage) == gx_default_fillpage);
148
5.59k
}
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
0
{
162
0
    set_dev_proc(dev, output_page, epo_output_page);
163
0
    set_dev_proc(dev, fill_rectangle, epo_fill_rectangle);
164
0
    set_dev_proc(dev, copy_mono, epo_copy_mono);
165
0
    set_dev_proc(dev, copy_color, epo_copy_color);
166
0
    set_dev_proc(dev, copy_alpha, epo_copy_alpha);
167
0
    set_dev_proc(dev, get_bits_rectangle, epo_get_bits_rectangle);
168
0
    set_dev_proc(dev, fill_path, epo_fill_path);
169
0
    set_dev_proc(dev, stroke_path, epo_stroke_path);
170
0
    set_dev_proc(dev, fill_mask, epo_fill_mask);
171
0
    set_dev_proc(dev, fill_trapezoid, epo_fill_trapezoid);
172
0
    set_dev_proc(dev, fill_parallelogram, epo_fill_parallelogram);
173
0
    set_dev_proc(dev, fill_triangle, epo_fill_triangle);
174
0
    set_dev_proc(dev, draw_thin_line, epo_draw_thin_line);
175
0
    set_dev_proc(dev, strip_tile_rectangle, epo_strip_tile_rectangle);
176
0
    set_dev_proc(dev, begin_typed_image, epo_begin_typed_image);
177
0
    set_dev_proc(dev, composite, epo_composite);
178
0
    set_dev_proc(dev, text_begin, epo_text_begin);
179
0
    set_dev_proc(dev, fill_rectangle_hl_color, epo_fill_rectangle_hl_color);
180
0
    set_dev_proc(dev, fill_linear_color_scanline, epo_fill_linear_color_scanline);
181
0
    set_dev_proc(dev, fill_linear_color_trapezoid, epo_fill_linear_color_trapezoid);
182
0
    set_dev_proc(dev, fill_linear_color_triangle, epo_fill_linear_color_triangle);
183
0
    set_dev_proc(dev, fillpage, epo_fillpage);
184
0
    set_dev_proc(dev, put_image, epo_put_image);
185
0
    set_dev_proc(dev, copy_planes, epo_copy_planes);
186
0
    set_dev_proc(dev, strip_copy_rop2, epo_strip_copy_rop2);
187
0
    set_dev_proc(dev, copy_alpha_hl_color, epo_copy_alpha_hl_color);
188
0
    set_dev_proc(dev, process_page, epo_process_page);
189
0
    set_dev_proc(dev, transform_pixel_region, epo_transform_pixel_region);
190
0
    set_dev_proc(dev, fill_stroke_path, epo_fill_stroke_path);
191
0
}
192
193
static void
194
enable_self(gx_device *dev)
195
0
{
196
0
    erasepage_subclass_data *data = (erasepage_subclass_data *)dev->subclass_data;
197
198
0
    data->disabled = 0;
199
0
    enable_procs(dev);
200
0
}
201
202
static void
203
disable_self(gx_device *dev)
204
0
{
205
0
    erasepage_subclass_data *data = (erasepage_subclass_data *)dev->subclass_data;
206
207
0
    data->disabled = 1;
208
209
0
    set_dev_proc(dev, output_page, default_subclass_output_page);
210
0
    set_dev_proc(dev, fill_rectangle, default_subclass_fill_rectangle);
211
0
    set_dev_proc(dev, copy_mono, default_subclass_copy_mono);
212
0
    set_dev_proc(dev, copy_color, default_subclass_copy_color);
213
0
    set_dev_proc(dev, copy_alpha, default_subclass_copy_alpha);
214
0
    set_dev_proc(dev, get_bits_rectangle, default_subclass_get_bits_rectangle);
215
0
    set_dev_proc(dev, fill_path, default_subclass_fill_path);
216
0
    set_dev_proc(dev, stroke_path, default_subclass_stroke_path);
217
0
    set_dev_proc(dev, fill_mask, default_subclass_fill_mask);
218
0
    set_dev_proc(dev, fill_trapezoid, default_subclass_fill_trapezoid);
219
0
    set_dev_proc(dev, fill_parallelogram, default_subclass_fill_parallelogram);
220
0
    set_dev_proc(dev, fill_triangle, default_subclass_fill_triangle);
221
0
    set_dev_proc(dev, draw_thin_line, default_subclass_draw_thin_line);
222
0
    set_dev_proc(dev, strip_tile_rectangle, default_subclass_strip_tile_rectangle);
223
0
    set_dev_proc(dev, begin_typed_image, default_subclass_begin_typed_image);
224
0
    set_dev_proc(dev, composite, default_subclass_composite);
225
0
    set_dev_proc(dev, text_begin, default_subclass_text_begin);
226
0
    set_dev_proc(dev, fill_rectangle_hl_color, default_subclass_fill_rectangle_hl_color);
227
0
    set_dev_proc(dev, fill_linear_color_scanline, default_subclass_fill_linear_color_scanline);
228
0
    set_dev_proc(dev, fill_linear_color_trapezoid, default_subclass_fill_linear_color_trapezoid);
229
0
    set_dev_proc(dev, fill_linear_color_triangle, default_subclass_fill_linear_color_triangle);
230
    /* NOT fillpage! */
231
0
    set_dev_proc(dev, put_image, default_subclass_put_image);
232
0
    set_dev_proc(dev, copy_planes, default_subclass_copy_planes);
233
0
    set_dev_proc(dev, strip_copy_rop2, default_subclass_strip_copy_rop2);
234
0
    set_dev_proc(dev, copy_alpha_hl_color, default_subclass_copy_alpha_hl_color);
235
0
    set_dev_proc(dev, process_page, default_subclass_process_page);
236
0
    set_dev_proc(dev, transform_pixel_region, default_subclass_transform_pixel_region);
237
0
    set_dev_proc(dev, fill_stroke_path, default_subclass_fill_stroke_path);
238
0
    set_dev_proc(dev, lock_pattern, default_subclass_lock_pattern);
239
0
}
240
241
int
242
epo_check_and_install(gx_device *dev)
243
5.59k
{
244
5.59k
    int code = 0;
245
5.59k
    gx_device *installed_epo_device = NULL;
246
5.59k
    bool can_optimize = false;
247
248
    /* Debugging mode to totally disable this */
249
5.59k
    if (gs_debug_c(gs_debug_flag_epo_disable)) {
250
0
        return code;
251
0
    }
252
253
5.59k
    DPRINTF1(dev->memory, "current device is %s\n", dev->dname);
254
255
5.59k
    installed_epo_device = find_installed_epo_device(dev);
256
257
5.59k
    if (installed_epo_device != NULL) {
258
0
        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
0
        if (installed_epo_device->child) {
264
0
            can_optimize = device_wants_optimization(installed_epo_device->child);
265
0
        }
266
0
        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
5.59k
    } else {
273
5.59k
        can_optimize = device_wants_optimization(dev);
274
5.59k
    }
275
276
    /* Already installed, nothing to do */
277
5.59k
    if (installed_epo_device != NULL) {
278
0
        enable_self(installed_epo_device);
279
0
        return code;
280
0
    }
281
282
    /* See if we can optimize */
283
5.59k
    if (!can_optimize) {
284
5.59k
        DPRINTF(dev->memory, "device doesn't want optimization, not installing\n");
285
5.59k
        return code;
286
5.59k
    }
287
288
    /* Always install us as low down the chain as possible. */
289
0
    while (dev->child)
290
0
            dev = dev->child;
291
292
    /* Install subclass for optimization */
293
0
    code = gx_device_subclass(dev, (gx_device *)&gs_epo_device, sizeof(erasepage_subclass_data));
294
0
    if (code < 0) {
295
0
        DPRINTF1(dev->memory, "ERROR installing device %s\n", EPO_DEVICENAME);
296
0
        return code;
297
0
    }
298
299
0
    DPRINTF1(dev->memory, "SUCCESS installed device %s\n", dev->dname);
300
0
    return code;
301
0
}
302
303
static int
304
epo_handle_erase_page(gx_device *dev)
305
0
{
306
0
    erasepage_subclass_data *data = (erasepage_subclass_data *)dev->subclass_data;
307
0
    int code = 0;
308
309
0
    if (data->disabled)
310
0
        return 0;
311
312
0
    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
0
    DPRINTF1(dev->memory, "Do fillpage, Uninstall erasepage, device %s\n", dev->dname);
319
320
    /* Just do a fill_rectangle (using saved color) */
321
0
    if (dev->child && dev->child->is_open && data->queued) {
322
0
        code = dev_proc(dev->child, fill_rectangle)(dev->child,
323
0
                                                    0, 0,
324
0
                                                    dev->child->width,
325
0
                                                    dev->child->height,
326
0
                                                    data->last_color);
327
0
    }
328
    /* Disable the epo device */
329
0
    disable_self(dev);
330
331
0
    return code;
332
0
}
333
334
int epo_fillpage(gx_device *dev, gs_gstate * pgs, gx_device_color *pdevc)
335
0
{
336
0
    erasepage_subclass_data *data = (erasepage_subclass_data *)dev->subclass_data;
337
338
0
    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
0
    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
0
    data->last_color = pdevc->colors.pure;
351
0
    data->queued = 1;
352
353
0
    DPRINTF(dev->memory, "Swallowing fillpage\n");
354
0
    return 0;
355
0
}
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
0
{
369
0
    int code = epo_handle_erase_page(dev);
370
371
0
    if (code != 0)
372
0
        return code;
373
0
    dev = dev->child;
374
0
    return dev_proc(dev, fill_rectangle)(dev, x, y, width, height, color);
375
0
}
376
377
int epo_fill_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath,
378
    const gx_fill_params *params,
379
    const gx_drawing_color *pdcolor, const gx_clip_path *pcpath)
380
0
{
381
0
    int code = epo_handle_erase_page(dev);
382
383
0
    if (code != 0)
384
0
        return code;
385
0
    dev = dev->child;
386
0
    return dev_proc(dev, fill_path)(dev, pgs, ppath, params, pdcolor, pcpath);
387
0
}
388
389
int epo_fill_mask(gx_device *dev, const byte *data, int data_x, int raster, gx_bitmap_id id,
390
    int x, int y, int width, int height,
391
    const gx_drawing_color *pdcolor, int depth,
392
    gs_logical_operation_t lop, const gx_clip_path *pcpath)
393
0
{
394
0
    int code = epo_handle_erase_page(dev);
395
396
0
    if (code != 0)
397
0
        return code;
398
0
    dev = dev->child;
399
0
    return dev_proc(dev, fill_mask)(dev, data, data_x, raster, id, x, y, width, height, pdcolor, depth, lop, pcpath);
400
0
}
401
402
int epo_fill_trapezoid(gx_device *dev, const gs_fixed_edge *left, const gs_fixed_edge *right,
403
    fixed ybot, fixed ytop, bool swap_axes,
404
    const gx_drawing_color *pdcolor, gs_logical_operation_t lop)
405
0
{
406
0
    int code = epo_handle_erase_page(dev);
407
408
0
    if (code != 0)
409
0
        return code;
410
0
    dev = dev->child;
411
0
    return dev_proc(dev, fill_trapezoid)(dev, left, right, ybot, ytop, swap_axes, pdcolor, lop);
412
0
}
413
414
int epo_fill_parallelogram(gx_device *dev, fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
415
    const gx_drawing_color *pdcolor, gs_logical_operation_t lop)
416
0
{
417
0
    int code = epo_handle_erase_page(dev);
418
419
0
    if (code != 0)
420
0
        return code;
421
0
    dev = dev->child;
422
0
    return dev_proc(dev, fill_parallelogram)(dev, px, py, ax, ay, bx, by, pdcolor, lop);
423
0
}
424
425
int epo_fill_triangle(gx_device *dev, fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
426
    const gx_drawing_color *pdcolor, gs_logical_operation_t lop)
427
0
{
428
0
    int code = epo_handle_erase_page(dev);
429
430
0
    if (code != 0)
431
0
        return code;
432
0
    dev = dev->child;
433
0
    return dev_proc(dev, fill_triangle)(dev, px, py, ax, ay, bx, by, pdcolor, lop);
434
0
}
435
436
int epo_draw_thin_line(gx_device *dev, fixed fx0, fixed fy0, fixed fx1, fixed fy1,
437
    const gx_drawing_color *pdcolor, gs_logical_operation_t lop,
438
    fixed adjustx, fixed adjusty)
439
0
{
440
0
    int code = epo_handle_erase_page(dev);
441
442
0
    if (code != 0)
443
0
        return code;
444
0
    dev = dev->child;
445
0
    return dev_proc(dev, draw_thin_line)(dev, fx0, fy0, fx1, fy1, pdcolor, lop, adjustx, adjusty);
446
0
}
447
448
int epo_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect,
449
        const gs_gstate *pgs, const gx_drawing_color *pdcolor, const gx_clip_path *pcpath)
450
0
{
451
0
    int code = epo_handle_erase_page(dev);
452
453
0
    if (code != 0)
454
0
        return code;
455
0
    dev = dev->child;
456
0
    return dev_proc(dev, fill_rectangle_hl_color)(dev, rect, pgs, pdcolor, pcpath);
457
0
}
458
459
int epo_fill_linear_color_scanline(gx_device *dev, const gs_fill_attributes *fa,
460
        int i, int j, int w, const frac31 *c0, const int32_t *c0_f, const int32_t *cg_num,
461
        int32_t cg_den)
462
0
{
463
0
    int code = epo_handle_erase_page(dev);
464
465
0
    if (code != 0)
466
0
        return code;
467
0
    dev = dev->child;
468
0
    return dev_proc(dev, fill_linear_color_scanline)(dev, fa, i, j, w, c0, c0_f, cg_num, cg_den);
469
0
}
470
471
int epo_fill_linear_color_trapezoid(gx_device *dev, const gs_fill_attributes *fa,
472
        const gs_fixed_point *p0, const gs_fixed_point *p1,
473
        const gs_fixed_point *p2, const gs_fixed_point *p3,
474
        const frac31 *c0, const frac31 *c1,
475
        const frac31 *c2, const frac31 *c3)
476
0
{
477
0
    int code = epo_handle_erase_page(dev);
478
479
0
    if (code != 0)
480
0
        return code;
481
0
    dev = dev->child;
482
0
    return dev_proc(dev, fill_linear_color_trapezoid)(dev, fa, p0, p1, p2, p3, c0, c1, c2, c3);
483
0
}
484
485
int epo_fill_linear_color_triangle(gx_device *dev, const gs_fill_attributes *fa,
486
        const gs_fixed_point *p0, const gs_fixed_point *p1,
487
        const gs_fixed_point *p2, const frac31 *c0, const frac31 *c1, const frac31 *c2)
488
0
{
489
0
    int code = epo_handle_erase_page(dev);
490
491
0
    if (code != 0)
492
0
        return code;
493
0
    dev = dev->child;
494
0
    return dev_proc(dev, fill_linear_color_triangle)(dev, fa, p0, p1, p2, c0, c1, c2);
495
0
}
496
497
int epo_put_image(gx_device *dev, gx_device *mdev, const byte **buffers, int num_chan, int x, int y,
498
            int width, int height, int row_stride,
499
            int alpha_plane_index, int tag_plane_index)
500
0
{
501
0
    int code = epo_handle_erase_page(dev);
502
503
0
    if (code != 0)
504
0
        return code;
505
0
    dev = dev->child;
506
0
    return dev_proc(dev, put_image)(dev, mdev, buffers, num_chan, x, y, width, height, row_stride, alpha_plane_index, tag_plane_index);
507
0
}
508
509
int epo_composite(gx_device *dev, gx_device **pcdev, const gs_composite_t *pcte,
510
    gs_gstate *pgs, gs_memory_t *memory, gx_device *cdev)
511
0
{
512
0
    int code = epo_handle_erase_page(dev);
513
514
0
    if (code != 0)
515
0
        return code;
516
0
    return default_subclass_composite(dev, pcdev, pcte, pgs, memory, cdev);
517
0
}
518
519
int epo_text_begin(gx_device *dev, gs_gstate *pgs, const gs_text_params_t *text,
520
    gs_font *font, const gx_clip_path *pcpath,
521
    gs_text_enum_t **ppte)
522
0
{
523
0
    int code = epo_handle_erase_page(dev);
524
525
0
    if (code != 0)
526
0
        return code;
527
0
    dev = dev->child;
528
0
    return dev_proc(dev, text_begin)(dev, pgs, text, font, pcpath, ppte);
529
0
}
530
531
static int epo_initialize_device(gx_device *dev)
532
0
{
533
    /* We musn't allow the following pointers to remain shared with the from_dev
534
       because we're about to tell the caller it's only allowed to copy the prototype
535
       and free the attempted copy of a non-prototype. If from_dev is the prototype
536
       these pointers won't be set, anyway.
537
     */
538
0
    dev->child = NULL;
539
0
    dev->parent = NULL;
540
0
    dev->subclass_data = NULL;
541
0
    return 0;
542
0
}
543
544
void epo_initialize_device_procs(gx_device *dev)
545
0
{
546
0
    default_subclass_initialize_device_procs(dev);
547
548
0
    set_dev_proc(dev, initialize_device, epo_initialize_device);
549
0
    enable_procs(dev);
550
0
}
551
552
int epo_begin_typed_image(gx_device *dev, const gs_gstate *pgs, const gs_matrix *pmat,
553
    const gs_image_common_t *pic, const gs_int_rect *prect,
554
    const gx_drawing_color *pdcolor, const gx_clip_path *pcpath,
555
    gs_memory_t *memory, gx_image_enum_common_t **pinfo)
556
0
{
557
0
    int code = epo_handle_erase_page(dev);
558
559
0
    if (code != 0)
560
0
        return code;
561
0
    dev = dev->child;
562
0
    return dev_proc(dev, begin_typed_image)(dev, pgs, pmat, pic, prect, pdcolor, pcpath, memory, pinfo);
563
0
}
564
565
int epo_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath,
566
    const gx_stroke_params *params,
567
    const gx_drawing_color *pdcolor, const gx_clip_path *pcpath)
568
0
{
569
0
    int code = epo_handle_erase_page(dev);
570
571
0
    if (code != 0)
572
0
        return code;
573
0
    dev = dev->child;
574
0
    return dev_proc(dev, stroke_path)(dev, pgs, ppath, params, pdcolor, pcpath);
575
0
}
576
577
int epo_copy_mono(gx_device *dev, const byte *data, int data_x, int raster, gx_bitmap_id id,
578
    int x, int y, int width, int height,
579
    gx_color_index color0, gx_color_index color1)
580
0
{
581
0
    int code = epo_handle_erase_page(dev);
582
583
0
    if (code != 0)
584
0
        return code;
585
0
    dev = dev->child;
586
0
    return dev_proc(dev, copy_mono)(dev, data, data_x, raster, id, x, y, width, height, color0, color1);
587
0
}
588
589
int epo_copy_color(gx_device *dev, const byte *data, int data_x, int raster, gx_bitmap_id id,\
590
    int x, int y, int width, int height)
591
0
{
592
0
    int code = epo_handle_erase_page(dev);
593
594
0
    if (code != 0)
595
0
        return code;
596
0
    dev = dev->child;
597
0
    return dev_proc(dev, copy_color)(dev, data, data_x, raster, id, x, y, width, height);
598
0
}
599
600
int epo_get_bits_rectangle(gx_device *dev, const gs_int_rect *prect,
601
                           gs_get_bits_params_t *params)
602
0
{
603
0
    int code = epo_handle_erase_page(dev);
604
605
0
    if (code != 0)
606
0
        return code;
607
0
    dev = dev->child;
608
0
    return dev_proc(dev, get_bits_rectangle)(dev, prect, params);
609
0
}
610
611
int epo_copy_alpha(gx_device *dev, const byte *data, int data_x,
612
    int raster, gx_bitmap_id id, int x, int y, int width, int height,
613
    gx_color_index color, int depth)
614
0
{
615
0
    int code = epo_handle_erase_page(dev);
616
617
0
    if (code != 0)
618
0
        return code;
619
0
    dev = dev->child;
620
0
    return dev_proc(dev, copy_alpha)(dev, data, data_x, raster, id, x, y, width, height, color, depth);
621
0
}
622
623
int epo_strip_tile_rectangle(gx_device *dev, const gx_strip_bitmap *tiles, int x, int y, int width, int height,
624
    gx_color_index color0, gx_color_index color1,
625
    int phase_x, int phase_y)
626
0
{
627
0
    int code = epo_handle_erase_page(dev);
628
629
0
    if (code != 0)
630
0
        return code;
631
0
    dev = dev->child;
632
0
    return dev_proc(dev, strip_tile_rectangle)(dev, tiles, x, y, width, height, color0, color1, phase_x, phase_y);
633
0
}
634
635
int epo_strip_copy_rop2(gx_device *dev, const byte *sdata, int sourcex, uint sraster, gx_bitmap_id id,
636
    const gx_color_index *scolors, const gx_strip_bitmap *textures, const gx_color_index *tcolors,
637
    int x, int y, int width, int height, int phase_x, int phase_y, gs_logical_operation_t lop, uint planar_height)
638
0
{
639
0
    int code = epo_handle_erase_page(dev);
640
641
0
    if (code != 0)
642
0
        return code;
643
0
    dev = dev->child;
644
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);
645
0
}
646
647
int epo_copy_planes(gx_device *dev, const byte *data, int data_x, int raster, gx_bitmap_id id,
648
    int x, int y, int width, int height, int plane_height)
649
0
{
650
0
    int code = epo_handle_erase_page(dev);
651
652
0
    if (code != 0)
653
0
        return code;
654
0
    dev = dev->child;
655
0
    return dev_proc(dev, copy_planes)(dev, data, data_x, raster, id, x, y, width, height, plane_height);
656
0
}
657
658
int epo_copy_alpha_hl_color(gx_device *dev, const byte *data, int data_x,
659
    int raster, gx_bitmap_id id, int x, int y, int width, int height,
660
    const gx_drawing_color *pdcolor, int depth)
661
0
{
662
0
    int code = epo_handle_erase_page(dev);
663
664
0
    if (code != 0)
665
0
        return code;
666
0
    dev = dev->child;
667
0
    return dev_proc(dev, copy_alpha_hl_color)(dev, data, data_x, raster, id, x, y, width, height, pdcolor, depth);
668
0
}
669
670
int epo_process_page(gx_device *dev, gx_process_page_options_t *options)
671
0
{
672
0
    int code = epo_handle_erase_page(dev);
673
674
0
    if (code != 0)
675
0
        return code;
676
0
    dev = dev->child;
677
0
    return dev_proc(dev, process_page)(dev, options);
678
0
}
679
680
int epo_fill_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath,
681
    const gx_fill_params *fill_params, const gx_drawing_color *pdcolor_fill,
682
    const gx_stroke_params *stroke_params, const gx_drawing_color *pdcolor_stroke,
683
    const gx_clip_path *pcpath)
684
0
{
685
0
    int code = epo_handle_erase_page(dev);
686
687
0
    if (code != 0)
688
0
        return code;
689
0
    dev = dev->child;
690
0
    return dev_proc(dev, fill_stroke_path)(dev, pgs, ppath, fill_params, pdcolor_fill,
691
0
                                           stroke_params, pdcolor_stroke, pcpath);
692
0
}
693
694
int epo_transform_pixel_region(gx_device *dev, transform_pixel_region_reason reason, transform_pixel_region_data *data)
695
0
{
696
0
    int code = epo_handle_erase_page(dev);
697
698
0
    if (code != 0)
699
0
        return code;
700
0
    dev = dev->child;
701
0
    return dev_proc(dev, transform_pixel_region)(dev, reason, data);
702
0
}