1 /* Copyright (C) 2001-2019 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 /* Null and forwarding device implementation */
17 #include "gx.h"
18 #include "gserrors.h"
19 #include "gxdevice.h"
20 #include "gxcmap.h"
21 #include "memory_.h"
22 #include "gxdevsop.h"
23 
24 /* ---------------- Forwarding procedures ---------------- */
25 
26 /* Additional finalization for forwarding devices. */
27 static void
gx_device_forward_finalize(gx_device * dev)28 gx_device_forward_finalize(gx_device *dev)
29 {
30     gx_device *target = ((gx_device_forward *)dev)->target;
31 
32     ((gx_device_forward *)dev)->target = 0;
33     rc_decrement_only(target, "gx_device_forward_finalize");
34 }
35 
36 /* Set the target of a forwarding device. */
37 void
gx_device_set_target(gx_device_forward * fdev,gx_device * target)38 gx_device_set_target(gx_device_forward *fdev, gx_device *target)
39 {
40     /*
41      * ****** HACK: if this device doesn't have special finalization yet,
42      * make it decrement the reference count of the target.
43      */
44     if (target && !fdev->finalize)
45         fdev->finalize = gx_device_forward_finalize;
46     rc_assign(fdev->target, target, "gx_device_set_target");
47     /* try to initialize to same as target, otherwise UNKNOWN */
48     fdev->graphics_type_tag = target != NULL ? target->graphics_type_tag : GS_UNKNOWN_TAG;
49     fdev->interpolate_control = target != NULL ? target->interpolate_control : 1;	/* the default */
50 }
51 
52 /* Fill in NULL procedures in a forwarding device procedure record. */
53 /* We don't fill in: open_device, close_device, or the lowest-level */
54 /* drawing operations. */
55 void
gx_device_forward_fill_in_procs(register gx_device_forward * dev)56 gx_device_forward_fill_in_procs(register gx_device_forward * dev)
57 {
58     gx_device_set_procs((gx_device *) dev);
59     /* NOT open_device */
60     fill_dev_proc(dev, get_initial_matrix, gx_forward_get_initial_matrix);
61     fill_dev_proc(dev, sync_output, gx_forward_sync_output);
62     fill_dev_proc(dev, output_page, gx_forward_output_page);
63     /* NOT close_device */
64     fill_dev_proc(dev, map_rgb_color, gx_forward_map_rgb_color);
65     fill_dev_proc(dev, map_color_rgb, gx_forward_map_color_rgb);
66     /* NOT fill_rectangle */
67     /* NOT tile_rectangle */
68     /* NOT copy_mono */
69     /* NOT copy_color */
70     /* NOT draw_line (OBSOLETE) */
71     fill_dev_proc(dev, get_bits, gx_forward_get_bits);
72     fill_dev_proc(dev, get_params, gx_forward_get_params);
73     fill_dev_proc(dev, put_params, gx_forward_put_params);
74     fill_dev_proc(dev, map_cmyk_color, gx_forward_map_cmyk_color);
75     fill_dev_proc(dev, get_xfont_procs, gx_forward_get_xfont_procs);
76     fill_dev_proc(dev, get_xfont_device, gx_forward_get_xfont_device);
77     fill_dev_proc(dev, map_rgb_alpha_color, gx_forward_map_rgb_alpha_color);
78     fill_dev_proc(dev, get_page_device, gx_forward_get_page_device);
79     /* NOT get_alpha_bits (OBSOLETE) */
80     /* NOT copy_alpha */
81     fill_dev_proc(dev, get_band, gx_forward_get_band);
82     fill_dev_proc(dev, copy_rop, gx_forward_copy_rop);
83     fill_dev_proc(dev, fill_path, gx_forward_fill_path);
84     fill_dev_proc(dev, stroke_path, gx_forward_stroke_path);
85     fill_dev_proc(dev, fill_mask, gx_forward_fill_mask);
86     fill_dev_proc(dev, fill_trapezoid, gx_forward_fill_trapezoid);
87     fill_dev_proc(dev, fill_parallelogram, gx_forward_fill_parallelogram);
88     fill_dev_proc(dev, fill_triangle, gx_forward_fill_triangle);
89     fill_dev_proc(dev, draw_thin_line, gx_forward_draw_thin_line);
90     fill_dev_proc(dev, begin_image, gx_forward_begin_image);
91     /* NOT image_data (OBSOLETE) */
92     /* NOT end_image (OBSOLETE) */
93     /* NOT strip_tile_rectangle */
94     fill_dev_proc(dev, strip_copy_rop, gx_forward_strip_copy_rop);
95     fill_dev_proc(dev, get_clipping_box, gx_forward_get_clipping_box);
96     fill_dev_proc(dev, begin_typed_image, gx_forward_begin_typed_image);
97     fill_dev_proc(dev, get_bits_rectangle, gx_forward_get_bits_rectangle);
98     fill_dev_proc(dev, map_color_rgb_alpha, gx_forward_map_color_rgb_alpha);
99     fill_dev_proc(dev, create_compositor, gx_no_create_compositor);
100     fill_dev_proc(dev, get_hardware_params, gx_forward_get_hardware_params);
101     fill_dev_proc(dev, text_begin, gx_forward_text_begin);
102     fill_dev_proc(dev, get_color_mapping_procs, gx_forward_get_color_mapping_procs);
103     fill_dev_proc(dev, get_color_comp_index, gx_forward_get_color_comp_index);
104     fill_dev_proc(dev, encode_color, gx_forward_encode_color);
105     fill_dev_proc(dev, decode_color, gx_forward_decode_color);
106     fill_dev_proc(dev, dev_spec_op, gx_forward_dev_spec_op);
107     fill_dev_proc(dev, fill_rectangle_hl_color, gx_forward_fill_rectangle_hl_color);
108     fill_dev_proc(dev, include_color_space, gx_forward_include_color_space);
109     fill_dev_proc(dev, fill_linear_color_scanline, gx_forward_fill_linear_color_scanline);
110     fill_dev_proc(dev, fill_linear_color_trapezoid, gx_forward_fill_linear_color_trapezoid);
111     fill_dev_proc(dev, fill_linear_color_triangle, gx_forward_fill_linear_color_triangle);
112     fill_dev_proc(dev, update_spot_equivalent_colors, gx_forward_update_spot_equivalent_colors);
113     fill_dev_proc(dev, ret_devn_params, gx_forward_ret_devn_params);
114     fill_dev_proc(dev, fillpage, gx_forward_fillpage);
115     fill_dev_proc(dev, put_image, gx_forward_put_image);
116     fill_dev_proc(dev, get_profile, gx_forward_get_profile);
117     fill_dev_proc(dev, set_graphics_type_tag, gx_forward_set_graphics_type_tag);
118     fill_dev_proc(dev, strip_copy_rop2, gx_forward_strip_copy_rop2);
119     fill_dev_proc(dev, strip_tile_rect_devn, gx_forward_strip_tile_rect_devn);
120     fill_dev_proc(dev, strip_tile_rect_devn, gx_forward_strip_tile_rect_devn);
121     fill_dev_proc(dev, transform_pixel_region, gx_forward_transform_pixel_region);
122     fill_dev_proc(dev, fill_stroke_path, gx_forward_fill_stroke_path);
123     gx_device_fill_in_procs((gx_device *) dev);
124 }
125 
126 /* Forward the color mapping procedures from a device to its target. */
127 void
gx_device_forward_color_procs(gx_device_forward * dev)128 gx_device_forward_color_procs(gx_device_forward * dev)
129 {
130     set_dev_proc(dev, map_rgb_color, gx_forward_map_rgb_color);
131     set_dev_proc(dev, map_color_rgb, gx_forward_map_color_rgb);
132     set_dev_proc(dev, map_cmyk_color, gx_forward_map_cmyk_color);
133     set_dev_proc(dev, map_rgb_alpha_color, gx_forward_map_rgb_alpha_color);
134     set_dev_proc(dev, get_color_mapping_procs, gx_forward_get_color_mapping_procs);
135     set_dev_proc(dev, get_color_comp_index, gx_forward_get_color_comp_index);
136     set_dev_proc(dev, encode_color, gx_forward_encode_color);
137     set_dev_proc(dev, decode_color, gx_forward_decode_color);
138     set_dev_proc(dev, get_profile, gx_forward_get_profile);
139     /* Not strictly a color proc, but may affect color encoding */
140     fill_dev_proc(dev, set_graphics_type_tag, gx_forward_set_graphics_type_tag);
141     fill_dev_proc(dev, dev_spec_op, gx_forward_dev_spec_op);
142 }
143 
144 int
gx_forward_close_device(gx_device * dev)145 gx_forward_close_device(gx_device * dev)
146 {
147     gx_device_forward * const fdev = (gx_device_forward *)dev;
148     gx_device *tdev = fdev->target;
149     int code = (tdev == 0) ? gx_default_close_device(dev)
150                        : dev_proc(tdev, close_device)(tdev);
151 
152     if (tdev)
153         tdev->is_open = false;          /* flag corresponds to the state */
154     return code;
155 }
156 
157 void
gx_forward_get_initial_matrix(gx_device * dev,gs_matrix * pmat)158 gx_forward_get_initial_matrix(gx_device * dev, gs_matrix * pmat)
159 {
160     gx_device_forward * const fdev = (gx_device_forward *)dev;
161     gx_device *tdev = fdev->target;
162 
163     if (tdev == 0)
164         gx_default_get_initial_matrix(dev, pmat);
165     else
166         dev_proc(tdev, get_initial_matrix)(tdev, pmat);
167 }
168 
169 int
gx_forward_sync_output(gx_device * dev)170 gx_forward_sync_output(gx_device * dev)
171 {
172     gx_device_forward * const fdev = (gx_device_forward *)dev;
173     gx_device *tdev = fdev->target;
174 
175     return (tdev == 0 ? gx_default_sync_output(dev) :
176             dev_proc(tdev, sync_output)(tdev));
177 }
178 
179 int
gx_forward_output_page(gx_device * dev,int num_copies,int flush)180 gx_forward_output_page(gx_device * dev, int num_copies, int flush)
181 {
182     gx_device_forward * const fdev = (gx_device_forward *)dev;
183     gx_device *tdev = fdev->target;
184     int code =
185         (tdev == 0 ? gx_default_output_page(dev, num_copies, flush) :
186          dev_proc(tdev, output_page)(tdev, num_copies, flush));
187 
188     if (code >= 0 && tdev != 0)
189         dev->PageCount = tdev->PageCount;
190     return code;
191 }
192 
193 gx_color_index
gx_forward_map_rgb_color(gx_device * dev,const gx_color_value cv[])194 gx_forward_map_rgb_color(gx_device * dev, const gx_color_value cv[])
195 {
196     gx_device_forward * const fdev = (gx_device_forward *)dev;
197     gx_device *tdev = fdev->target;
198 
199     return (tdev == 0 ? gx_error_encode_color(dev, cv) :
200             dev_proc(tdev, map_rgb_color)(tdev, cv));
201 }
202 
203 int
gx_forward_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])204 gx_forward_map_color_rgb(gx_device * dev, gx_color_index color,
205                          gx_color_value prgb[3])
206 {
207     gx_device_forward * const fdev = (gx_device_forward *)dev;
208     gx_device *tdev = fdev->target;
209 
210     return (tdev == 0 ? gx_default_map_color_rgb(dev, color, prgb) :
211             dev_proc(tdev, map_color_rgb)(tdev, color, prgb));
212 }
213 
214 int
gx_forward_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)215 gx_forward_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
216                           gx_color_index color)
217 {
218     gx_device_forward * const fdev = (gx_device_forward *)dev;
219     gx_device *tdev = fdev->target;
220 
221     if (tdev == 0)
222         return_error(gs_error_Fatal);
223     return dev_proc(tdev, fill_rectangle)(tdev, x, y, w, h, color);
224 }
225 
226 int
gx_forward_tile_rectangle(gx_device * dev,const gx_tile_bitmap * tile,int x,int y,int w,int h,gx_color_index color0,gx_color_index color1,int px,int py)227 gx_forward_tile_rectangle(gx_device * dev, const gx_tile_bitmap * tile,
228                           int x, int y, int w, int h, gx_color_index color0,
229                           gx_color_index color1, int px, int py)
230 {
231     gx_device_forward * const fdev = (gx_device_forward *)dev;
232     gx_device *tdev = fdev->target;
233     dev_proc_tile_rectangle((*proc)) =
234         (tdev == 0 ? (tdev = dev, gx_default_tile_rectangle) :
235          dev_proc(tdev, tile_rectangle));
236 
237     return proc(tdev, tile, x, y, w, h, color0, color1, px, py);
238 }
239 
240 int
gx_forward_copy_mono(gx_device * dev,const byte * data,int dx,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one)241 gx_forward_copy_mono(gx_device * dev, const byte * data,
242                      int dx, int raster, gx_bitmap_id id,
243                      int x, int y, int w, int h,
244                      gx_color_index zero, gx_color_index one)
245 {
246     gx_device_forward * const fdev = (gx_device_forward *)dev;
247     gx_device *tdev = fdev->target;
248 
249     if (tdev == 0)
250         return_error(gs_error_Fatal);
251     return dev_proc(tdev, copy_mono)
252         (tdev, data, dx, raster, id, x, y, w, h, zero, one);
253 }
254 
255 int
gx_forward_copy_alpha(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int width,int height,gx_color_index color,int depth)256 gx_forward_copy_alpha(gx_device * dev, const byte * data, int data_x,
257            int raster, gx_bitmap_id id, int x, int y, int width, int height,
258                       gx_color_index color, int depth)
259 {
260     gx_device_forward * const fdev = (gx_device_forward *)dev;
261     gx_device *tdev = fdev->target;
262 
263     if (tdev == 0)
264         return_error(gs_error_Fatal);
265     return dev_proc(tdev, copy_alpha)
266         (tdev, data, data_x, raster, id, x, y, width, height, color, depth);
267 }
268 
269 int
gx_forward_copy_color(gx_device * dev,const byte * data,int dx,int raster,gx_bitmap_id id,int x,int y,int w,int h)270 gx_forward_copy_color(gx_device * dev, const byte * data,
271                       int dx, int raster, gx_bitmap_id id,
272                       int x, int y, int w, int h)
273 {
274     gx_device_forward * const fdev = (gx_device_forward *)dev;
275     gx_device *tdev = fdev->target;
276 
277     if (tdev == 0)
278         return_error(gs_error_Fatal);
279     return dev_proc(tdev, copy_color)
280         (tdev, data, dx, raster, id, x, y, w, h);
281 }
282 
283 int
gx_forward_copy_planes(gx_device * dev,const byte * data,int dx,int raster,gx_bitmap_id id,int x,int y,int w,int h,int plane_height)284 gx_forward_copy_planes(gx_device * dev, const byte * data,
285                        int dx, int raster, gx_bitmap_id id,
286                        int x, int y, int w, int h, int plane_height)
287 {
288     gx_device_forward * const fdev = (gx_device_forward *)dev;
289     gx_device *tdev = fdev->target;
290 
291     if (tdev == 0)
292         return_error(gs_error_Fatal);
293     return dev_proc(tdev, copy_planes)
294         (tdev, data, dx, raster, id, x, y, w, h, plane_height);
295 }
296 
297 int
gx_forward_get_bits(gx_device * dev,int y,byte * data,byte ** actual_data)298 gx_forward_get_bits(gx_device * dev, int y, byte * data, byte ** actual_data)
299 {
300     gx_device_forward * const fdev = (gx_device_forward *)dev;
301     gx_device *tdev = fdev->target;
302 
303     return (tdev == 0 ? gx_default_get_bits(dev, y, data, actual_data) :
304             dev_proc(tdev, get_bits)(tdev, y, data, actual_data));
305 }
306 
307 int
gx_forward_get_params(gx_device * dev,gs_param_list * plist)308 gx_forward_get_params(gx_device * dev, gs_param_list * plist)
309 {
310     gx_device_forward * const fdev = (gx_device_forward *)dev;
311     gx_device *tdev = fdev->target;
312 
313     return (tdev == 0 ? gx_default_get_params(dev, plist) :
314             dev_proc(tdev, get_params)(tdev, plist));
315 }
316 
317 int
gx_forward_put_params(gx_device * dev,gs_param_list * plist)318 gx_forward_put_params(gx_device * dev, gs_param_list * plist)
319 {
320     gx_device_forward * const fdev = (gx_device_forward *)dev;
321     gx_device *tdev = fdev->target;
322     bool was_open;
323     int code;
324 
325     if (tdev == 0)
326         return gx_default_put_params(dev, plist);
327     was_open = tdev->is_open;
328     code = dev_proc(tdev, put_params)(tdev, plist);
329     if (code == 0 && !tdev->is_open) {
330             code = was_open ? 1 : 0;   /* target device closed */
331     }
332     if (code >= 0)
333         gx_device_decache_colors(dev);
334     return code;
335 }
336 
337 gx_color_index
gx_forward_map_cmyk_color(gx_device * dev,const gx_color_value cv[])338 gx_forward_map_cmyk_color(gx_device * dev, const gx_color_value cv[])
339 {
340     gx_device_forward * const fdev = (gx_device_forward *)dev;
341     gx_device *tdev = fdev->target;
342 
343     return (tdev == 0 ? gx_default_map_cmyk_color(dev, cv) :
344             dev_proc(tdev, map_cmyk_color)(tdev, cv));
345 }
346 
347 const gx_xfont_procs *
gx_forward_get_xfont_procs(gx_device * dev)348 gx_forward_get_xfont_procs(gx_device * dev)
349 {
350     gx_device_forward * const fdev = (gx_device_forward *)dev;
351     gx_device *tdev = fdev->target;
352 
353     return (tdev == 0 ? gx_default_get_xfont_procs(dev) :
354             dev_proc(tdev, get_xfont_procs)(tdev));
355 }
356 
357 gx_device *
gx_forward_get_xfont_device(gx_device * dev)358 gx_forward_get_xfont_device(gx_device * dev)
359 {
360     gx_device_forward * const fdev = (gx_device_forward *)dev;
361     gx_device *tdev = fdev->target;
362 
363     return (tdev == 0 ? gx_default_get_xfont_device(dev) :
364             dev_proc(tdev, get_xfont_device)(tdev));
365 }
366 
367 gx_color_index
gx_forward_map_rgb_alpha_color(gx_device * dev,gx_color_value r,gx_color_value g,gx_color_value b,gx_color_value alpha)368 gx_forward_map_rgb_alpha_color(gx_device * dev, gx_color_value r,
369                                gx_color_value g, gx_color_value b,
370                                gx_color_value alpha)
371 {
372     gx_device_forward * const fdev = (gx_device_forward *)dev;
373     gx_device *tdev = fdev->target;
374 
375     return (tdev == 0 ?
376             gx_default_map_rgb_alpha_color(dev, r, g, b, alpha) :
377             dev_proc(tdev, map_rgb_alpha_color)(tdev, r, g, b, alpha));
378 }
379 
380 gx_device *
gx_forward_get_page_device(gx_device * dev)381 gx_forward_get_page_device(gx_device * dev)
382 {
383     gx_device_forward * const fdev = (gx_device_forward *)dev;
384     gx_device *tdev = fdev->target;
385     gx_device *pdev;
386 
387     if (tdev == 0)
388         return gx_default_get_page_device(dev);
389     pdev = dev_proc(tdev, get_page_device)(tdev);
390     return pdev;
391 }
392 
393 int
gx_forward_get_band(gx_device * dev,int y,int * band_start)394 gx_forward_get_band(gx_device * dev, int y, int *band_start)
395 {
396     gx_device_forward * const fdev = (gx_device_forward *)dev;
397     gx_device *tdev = fdev->target;
398 
399     return (tdev == 0 ?
400             gx_default_get_band(dev, y, band_start) :
401             dev_proc(tdev, get_band)(tdev, y, band_start));
402 }
403 
404 int
gx_forward_copy_rop(gx_device * dev,const byte * sdata,int sourcex,uint sraster,gx_bitmap_id id,const gx_color_index * scolors,const gx_tile_bitmap * texture,const gx_color_index * tcolors,int x,int y,int width,int height,int phase_x,int phase_y,gs_logical_operation_t lop)405 gx_forward_copy_rop(gx_device * dev,
406                     const byte * sdata, int sourcex, uint sraster,
407                     gx_bitmap_id id, const gx_color_index * scolors,
408                     const gx_tile_bitmap * texture,
409                     const gx_color_index * tcolors,
410                     int x, int y, int width, int height,
411                     int phase_x, int phase_y, gs_logical_operation_t lop)
412 {
413     gx_device_forward * const fdev = (gx_device_forward *)dev;
414     gx_device *tdev = fdev->target;
415     dev_proc_copy_rop((*proc)) =
416         (tdev == 0 ? (tdev = dev, gx_default_copy_rop) :
417          dev_proc(tdev, copy_rop));
418 
419     return proc(tdev, sdata, sourcex, sraster, id, scolors,
420                 texture, tcolors, x, y, width, height,
421                 phase_x, phase_y, lop);
422 }
423 
424 int
gx_forward_fill_path(gx_device * dev,const gs_gstate * pgs,gx_path * ppath,const gx_fill_params * params,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath)425 gx_forward_fill_path(gx_device * dev, const gs_gstate * pgs,
426                      gx_path * ppath, const gx_fill_params * params,
427                      const gx_drawing_color * pdcolor,
428                      const gx_clip_path * pcpath)
429 {
430     gx_device_forward * const fdev = (gx_device_forward *)dev;
431     gx_device *tdev = fdev->target;
432     dev_proc_fill_path((*proc)) =
433         (tdev == 0 ? (tdev = dev, gx_default_fill_path) :
434          dev_proc(tdev, fill_path));
435 
436     return proc(tdev, pgs, ppath, params, pdcolor, pcpath);
437 }
438 
439 int
gx_forward_stroke_path(gx_device * dev,const gs_gstate * pgs,gx_path * ppath,const gx_stroke_params * params,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath)440 gx_forward_stroke_path(gx_device * dev, const gs_gstate * pgs,
441                        gx_path * ppath, const gx_stroke_params * params,
442                        const gx_drawing_color * pdcolor,
443                        const gx_clip_path * pcpath)
444 {
445     gx_device_forward * const fdev = (gx_device_forward *)dev;
446     gx_device *tdev = fdev->target;
447     dev_proc_stroke_path((*proc)) =
448         (tdev == 0 ? (tdev = dev, gx_default_stroke_path) :
449          dev_proc(tdev, stroke_path));
450 
451     return proc(tdev, pgs, ppath, params, pdcolor, pcpath);
452 }
453 
454 int
gx_forward_fill_stroke_path(gx_device * dev,const gs_gstate * pgs,gx_path * ppath,const gx_fill_params * params_fill,const gx_drawing_color * pdcolor_fill,const gx_stroke_params * params_stroke,const gx_drawing_color * pdcolor_stroke,const gx_clip_path * pcpath)455 gx_forward_fill_stroke_path(gx_device * dev, const gs_gstate * pgs,
456                             gx_path * ppath,
457                             const gx_fill_params * params_fill,
458                             const gx_drawing_color * pdcolor_fill,
459                             const gx_stroke_params * params_stroke,
460                             const gx_drawing_color * pdcolor_stroke,
461                             const gx_clip_path * pcpath)
462 {
463     gx_device_forward * const fdev = (gx_device_forward *)dev;
464     gx_device *tdev = fdev->target;
465     dev_proc_fill_stroke_path((*proc)) =
466         (tdev == 0 ? (tdev = dev, gx_default_fill_stroke_path) :
467          dev_proc(tdev, fill_stroke_path));
468 
469     return proc(tdev, pgs, ppath, params_fill, pdcolor_fill, params_stroke, pdcolor_stroke, pcpath);
470 }
471 
472 int
gx_forward_fill_mask(gx_device * dev,const byte * data,int dx,int raster,gx_bitmap_id id,int x,int y,int w,int h,const gx_drawing_color * pdcolor,int depth,gs_logical_operation_t lop,const gx_clip_path * pcpath)473 gx_forward_fill_mask(gx_device * dev,
474                      const byte * data, int dx, int raster, gx_bitmap_id id,
475                      int x, int y, int w, int h,
476                      const gx_drawing_color * pdcolor, int depth,
477                      gs_logical_operation_t lop, const gx_clip_path * pcpath)
478 {
479     gx_device_forward * const fdev = (gx_device_forward *)dev;
480     gx_device *tdev = fdev->target;
481     dev_proc_fill_mask((*proc)) =
482         (tdev == 0 ? (tdev = dev, gx_default_fill_mask) :
483          dev_proc(tdev, fill_mask));
484 
485     return proc(tdev, data, dx, raster, id, x, y, w, h, pdcolor, depth,
486                 lop, pcpath);
487 }
488 
489 int
gx_forward_fill_trapezoid(gx_device * dev,const gs_fixed_edge * left,const gs_fixed_edge * right,fixed ybot,fixed ytop,bool swap_axes,const gx_drawing_color * pdcolor,gs_logical_operation_t lop)490 gx_forward_fill_trapezoid(gx_device * dev,
491                           const gs_fixed_edge * left,
492                           const gs_fixed_edge * right,
493                           fixed ybot, fixed ytop, bool swap_axes,
494                           const gx_drawing_color * pdcolor,
495                           gs_logical_operation_t lop)
496 {
497     gx_device_forward * const fdev = (gx_device_forward *)dev;
498     gx_device *tdev = fdev->target;
499     dev_proc_fill_trapezoid((*proc)) =
500         (tdev == 0 ? (tdev = dev, gx_default_fill_trapezoid) :
501          dev_proc(tdev, fill_trapezoid));
502 
503     return proc(tdev, left, right, ybot, ytop, swap_axes, pdcolor, lop);
504 }
505 
506 int
gx_forward_fill_parallelogram(gx_device * dev,fixed px,fixed py,fixed ax,fixed ay,fixed bx,fixed by,const gx_drawing_color * pdcolor,gs_logical_operation_t lop)507 gx_forward_fill_parallelogram(gx_device * dev,
508                  fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
509                const gx_drawing_color * pdcolor, gs_logical_operation_t lop)
510 {
511     gx_device_forward * const fdev = (gx_device_forward *)dev;
512     gx_device *tdev = fdev->target;
513     dev_proc_fill_parallelogram((*proc)) =
514         (tdev == 0 ? (tdev = dev, gx_default_fill_parallelogram) :
515          dev_proc(tdev, fill_parallelogram));
516 
517     return proc(tdev, px, py, ax, ay, bx, by, pdcolor, lop);
518 }
519 
520 int
gx_forward_fill_triangle(gx_device * dev,fixed px,fixed py,fixed ax,fixed ay,fixed bx,fixed by,const gx_drawing_color * pdcolor,gs_logical_operation_t lop)521 gx_forward_fill_triangle(gx_device * dev,
522                  fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
523                const gx_drawing_color * pdcolor, gs_logical_operation_t lop)
524 {
525     gx_device_forward * const fdev = (gx_device_forward *)dev;
526     gx_device *tdev = fdev->target;
527     dev_proc_fill_triangle((*proc)) =
528         (tdev == 0 ? (tdev = dev, gx_default_fill_triangle) :
529          dev_proc(tdev, fill_triangle));
530 
531     return proc(tdev, px, py, ax, ay, bx, by, pdcolor, lop);
532 }
533 
534 int
gx_forward_draw_thin_line(gx_device * dev,fixed fx0,fixed fy0,fixed fx1,fixed fy1,const gx_drawing_color * pdcolor,gs_logical_operation_t lop,fixed adjustx,fixed adjusty)535 gx_forward_draw_thin_line(gx_device * dev,
536                           fixed fx0, fixed fy0, fixed fx1, fixed fy1,
537                const gx_drawing_color * pdcolor, gs_logical_operation_t lop,
538                           fixed adjustx, fixed adjusty)
539 {
540     gx_device_forward * const fdev = (gx_device_forward *)dev;
541     gx_device *tdev = fdev->target;
542     dev_proc_draw_thin_line((*proc)) =
543         (tdev == 0 ? (tdev = dev, gx_default_draw_thin_line) :
544          dev_proc(tdev, draw_thin_line));
545 
546     return proc(tdev, fx0, fy0, fx1, fy1, pdcolor, lop, adjustx, adjusty);
547 }
548 
549 int
gx_forward_begin_image(gx_device * dev,const gs_gstate * pgs,const gs_image_t * pim,gs_image_format_t format,const gs_int_rect * prect,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * memory,gx_image_enum_common_t ** pinfo)550 gx_forward_begin_image(gx_device * dev,
551                        const gs_gstate * pgs, const gs_image_t * pim,
552                        gs_image_format_t format, const gs_int_rect * prect,
553                        const gx_drawing_color * pdcolor,
554                        const gx_clip_path * pcpath,
555                        gs_memory_t * memory, gx_image_enum_common_t ** pinfo)
556 {
557     gx_device_forward * const fdev = (gx_device_forward *)dev;
558     gx_device *tdev = fdev->target;
559     dev_proc_begin_image((*proc)) =
560         (tdev == 0 ? (tdev = dev, gx_default_begin_image) :
561          dev_proc(tdev, begin_image));
562 
563     return proc(tdev, pgs, pim, format, prect, pdcolor, pcpath,
564                 memory, pinfo);
565 }
566 
567 int
gx_forward_strip_tile_rectangle(gx_device * dev,const gx_strip_bitmap * tiles,int x,int y,int w,int h,gx_color_index color0,gx_color_index color1,int px,int py)568 gx_forward_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles,
569    int x, int y, int w, int h, gx_color_index color0, gx_color_index color1,
570                                 int px, int py)
571 {
572     gx_device_forward * const fdev = (gx_device_forward *)dev;
573     gx_device *tdev = fdev->target;
574     dev_proc_strip_tile_rectangle((*proc)) =
575         (tdev == 0 ? (tdev = dev, gx_default_strip_tile_rectangle) :
576          dev_proc(tdev, strip_tile_rectangle));
577 
578     return proc(tdev, tiles, x, y, w, h, color0, color1, px, py);
579 }
580 
581 int
gx_forward_strip_copy_rop(gx_device * dev,const byte * sdata,int sourcex,uint sraster,gx_bitmap_id id,const gx_color_index * scolors,const gx_strip_bitmap * textures,const gx_color_index * tcolors,int x,int y,int width,int height,int phase_x,int phase_y,gs_logical_operation_t lop)582 gx_forward_strip_copy_rop(gx_device * dev, const byte * sdata, int sourcex,
583                           uint sraster, gx_bitmap_id id,
584                           const gx_color_index * scolors,
585                           const gx_strip_bitmap * textures,
586                           const gx_color_index * tcolors,
587                           int x, int y, int width, int height,
588                           int phase_x, int phase_y, gs_logical_operation_t lop)
589 {
590     gx_device_forward * const fdev = (gx_device_forward *)dev;
591     gx_device *tdev = fdev->target;
592     dev_proc_strip_copy_rop((*proc)) =
593         (tdev == 0 ? (tdev = dev, gx_default_strip_copy_rop) :
594          dev_proc(tdev, strip_copy_rop));
595 
596     return proc(tdev, sdata, sourcex, sraster, id, scolors,
597                 textures, tcolors, x, y, width, height,
598                 phase_x, phase_y, lop);
599 }
600 
601 int
gx_forward_strip_copy_rop2(gx_device * dev,const byte * sdata,int sourcex,uint sraster,gx_bitmap_id id,const gx_color_index * scolors,const gx_strip_bitmap * textures,const gx_color_index * tcolors,int x,int y,int width,int height,int phase_x,int phase_y,gs_logical_operation_t lop,uint planar_height)602 gx_forward_strip_copy_rop2(gx_device * dev, const byte * sdata, int sourcex,
603                            uint sraster, gx_bitmap_id id,
604                            const gx_color_index * scolors,
605                            const gx_strip_bitmap * textures,
606                            const gx_color_index * tcolors,
607                            int x, int y, int width, int height,
608                            int phase_x, int phase_y, gs_logical_operation_t lop,
609                            uint planar_height)
610 {
611     gx_device_forward * const fdev = (gx_device_forward *)dev;
612     gx_device *tdev = fdev->target;
613 
614     if (planar_height != 0) {
615         dev_proc_strip_copy_rop2((*proc2)) =
616             (tdev == 0 ? (tdev = dev, gx_default_strip_copy_rop2) :
617              dev_proc(tdev, strip_copy_rop2));
618 
619         return proc2(tdev, sdata, sourcex, sraster, id, scolors,
620                      textures, tcolors, x, y, width, height,
621                      phase_x, phase_y, lop, planar_height);
622     } else {
623         dev_proc_strip_copy_rop((*proc)) =
624             (tdev == 0 ? (tdev = dev, gx_default_strip_copy_rop) :
625              dev_proc(tdev, strip_copy_rop));
626 
627         return proc(tdev, sdata, sourcex, sraster, id, scolors,
628                     textures, tcolors, x, y, width, height,
629                     phase_x, phase_y, lop);
630     }
631 }
632 
633 int
gx_forward_strip_tile_rect_devn(gx_device * dev,const gx_strip_bitmap * tiles,int x,int y,int w,int h,const gx_drawing_color * pdcolor0,const gx_drawing_color * pdcolor1,int px,int py)634 gx_forward_strip_tile_rect_devn(gx_device * dev, const gx_strip_bitmap * tiles,
635    int x, int y, int w, int h, const gx_drawing_color * pdcolor0,
636    const gx_drawing_color * pdcolor1, int px, int py)
637 {
638     gx_device_forward * const fdev = (gx_device_forward *)dev;
639     gx_device *tdev = fdev->target;
640 
641     if (tdev == 0)
642         return gx_default_strip_tile_rect_devn(dev, tiles, x, y, w, h, pdcolor0,
643                                                pdcolor1, px, py);
644     else
645         return dev_proc(tdev, strip_tile_rect_devn)(tdev, tiles, x, y, w, h,
646                                                     pdcolor0, pdcolor1, px, py);
647 }
648 
649 void
gx_forward_get_clipping_box(gx_device * dev,gs_fixed_rect * pbox)650 gx_forward_get_clipping_box(gx_device * dev, gs_fixed_rect * pbox)
651 {
652     gx_device_forward * const fdev = (gx_device_forward *)dev;
653     gx_device *tdev = fdev->target;
654 
655     if (tdev == 0)
656         gx_default_get_clipping_box(dev, pbox);
657     else
658         dev_proc(tdev, get_clipping_box)(tdev, pbox);
659 }
660 
661 int
gx_forward_begin_typed_image(gx_device * dev,const gs_gstate * pgs,const gs_matrix * pmat,const gs_image_common_t * pim,const gs_int_rect * prect,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * memory,gx_image_enum_common_t ** pinfo)662 gx_forward_begin_typed_image(gx_device * dev, const gs_gstate * pgs,
663                              const gs_matrix * pmat,
664                              const gs_image_common_t * pim,
665                              const gs_int_rect * prect,
666                              const gx_drawing_color * pdcolor,
667                              const gx_clip_path * pcpath,
668                              gs_memory_t * memory,
669                              gx_image_enum_common_t ** pinfo)
670 {
671     gx_device_forward * const fdev = (gx_device_forward *)dev;
672     gx_device *tdev = fdev->target;
673     dev_proc_begin_typed_image((*proc)) =
674         (tdev == 0 ? (tdev = dev, gx_default_begin_typed_image) :
675          dev_proc(tdev, begin_typed_image));
676 
677     return proc(tdev, pgs, pmat, pim, prect, pdcolor, pcpath,
678                 memory, pinfo);
679 }
680 
681 int
gx_forward_get_bits_rectangle(gx_device * dev,const gs_int_rect * prect,gs_get_bits_params_t * params,gs_int_rect ** unread)682 gx_forward_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
683                        gs_get_bits_params_t * params, gs_int_rect ** unread)
684 {
685     gx_device_forward * const fdev = (gx_device_forward *)dev;
686     gx_device *tdev = fdev->target;
687     dev_proc_get_bits_rectangle((*proc)) =
688         (tdev == 0 ? (tdev = dev, gx_default_get_bits_rectangle) :
689          dev_proc(tdev, get_bits_rectangle));
690 
691     return proc(tdev, prect, params, unread);
692 }
693 
694 int
gx_forward_map_color_rgb_alpha(gx_device * dev,gx_color_index color,gx_color_value prgba[4])695 gx_forward_map_color_rgb_alpha(gx_device * dev, gx_color_index color,
696                                gx_color_value prgba[4])
697 {
698     gx_device_forward * const fdev = (gx_device_forward *)dev;
699     gx_device *tdev = fdev->target;
700 
701     return (tdev == 0 ? gx_default_map_color_rgb_alpha(dev, color, prgba) :
702             dev_proc(tdev, map_color_rgb_alpha)(tdev, color, prgba));
703 }
704 
705 int
gx_forward_get_hardware_params(gx_device * dev,gs_param_list * plist)706 gx_forward_get_hardware_params(gx_device * dev, gs_param_list * plist)
707 {
708     gx_device_forward * const fdev = (gx_device_forward *)dev;
709     gx_device *tdev = fdev->target;
710 
711     return (tdev == 0 ? gx_default_get_hardware_params(dev, plist) :
712             dev_proc(tdev, get_hardware_params)(tdev, plist));
713 }
714 
715 int
gx_forward_text_begin(gx_device * dev,gs_gstate * pgs,const gs_text_params_t * text,gs_font * font,gx_path * path,const gx_device_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * memory,gs_text_enum_t ** ppenum)716 gx_forward_text_begin(gx_device * dev, gs_gstate * pgs,
717                       const gs_text_params_t * text, gs_font * font,
718                       gx_path * path, const gx_device_color * pdcolor,
719                       const gx_clip_path * pcpath, gs_memory_t * memory,
720                       gs_text_enum_t ** ppenum)
721 {
722     gx_device_forward * const fdev = (gx_device_forward *)dev;
723     gx_device *tdev = fdev->target;
724     dev_proc_text_begin((*proc)) =
725         (tdev == 0 ? (tdev = dev, gx_default_text_begin) :
726          dev_proc(tdev, text_begin));
727 
728     return proc(tdev, pgs, text, font, path, pdcolor, pcpath,
729                 memory, ppenum);
730 }
731 
732 /* Forwarding device color mapping procs. */
733 
734 /*
735  * We need to forward the color mapping to the target device.
736  */
737 static void
fwd_map_gray_cs(gx_device * dev,frac gray,frac out[])738 fwd_map_gray_cs(gx_device * dev, frac gray, frac out[])
739 {
740     gx_device_forward * const fdev = (gx_device_forward *)dev;
741     gx_device * tdev = fdev->target;
742     subclass_color_mappings scm;
743 
744     if (tdev) {
745         scm = get_color_mapping_procs_subclass(tdev);
746         map_gray_subclass(scm, gray, out);
747     }
748     else
749         gray_cs_to_gray_cm(tdev, gray, out);   /* if all else fails */
750 }
751 
752 /*
753  * We need to forward the color mapping to the target device.
754  */
755 static void
fwd_map_rgb_cs(gx_device * dev,const gs_gstate * pgs,frac r,frac g,frac b,frac out[])756 fwd_map_rgb_cs(gx_device * dev, const gs_gstate *pgs,
757                                    frac r, frac g, frac b, frac out[])
758 {
759     gx_device_forward * const fdev = (gx_device_forward *)dev;
760     gx_device * tdev = fdev->target;
761     subclass_color_mappings scm;
762 
763     if (tdev) {
764         scm = get_color_mapping_procs_subclass(tdev);
765         map_rgb_subclass(scm, pgs, r, g, b, out);
766     }
767     else
768         rgb_cs_to_rgb_cm(tdev, pgs, r, g, b, out);   /* if all else fails */
769 }
770 
771 /*
772  * We need to forward the color mapping to the target device.
773  */
774 static void
fwd_map_cmyk_cs(gx_device * dev,frac c,frac m,frac y,frac k,frac out[])775 fwd_map_cmyk_cs(gx_device * dev, frac c, frac m, frac y, frac k, frac out[])
776 {
777     gx_device_forward * const fdev = (gx_device_forward *)dev;
778     gx_device * tdev = fdev->target;
779     subclass_color_mappings scm;
780 
781     if (tdev) {
782         scm = get_color_mapping_procs_subclass(tdev);
783         map_cmyk_subclass(scm, c, m, y, k, out);
784     }
785     else
786         cmyk_cs_to_cmyk_cm(tdev, c, m, y, k, out);   /* if all else fails */
787 }
788 
789 static const gx_cm_color_map_procs FwdDevice_cm_map_procs = {
790     fwd_map_gray_cs, fwd_map_rgb_cs, fwd_map_cmyk_cs
791 };
792 /*
793  * Instead of returning the target device's mapping procs, we need
794  * to return a list of forwarding wrapper procs for the color mapping
795  * procs.  This is required because the target device mapping procs
796  * may also need the target device pointer (instead of the forwarding
797  * device pointer).
798  */
799 const gx_cm_color_map_procs *
gx_forward_get_color_mapping_procs(const gx_device * dev)800 gx_forward_get_color_mapping_procs(const gx_device * dev)
801 {
802     const gx_device_forward * fdev = (const gx_device_forward *)dev;
803     gx_device * tdev = fdev->target;
804 
805     return (tdev == 0 ? gx_default_DevGray_get_color_mapping_procs(dev)
806         : &FwdDevice_cm_map_procs);
807 }
808 
809 int
gx_forward_get_color_comp_index(gx_device * dev,const char * pname,int name_size,int component_type)810 gx_forward_get_color_comp_index(gx_device * dev, const char * pname,
811                                         int name_size, int component_type)
812 {
813     const gx_device_forward * fdev = (const gx_device_forward *)dev;
814     gx_device *tdev = fdev->target;
815 
816     return (tdev == 0
817         ? gx_error_get_color_comp_index(dev, pname,
818                                 name_size, component_type)
819         : dev_proc(tdev, get_color_comp_index)(tdev, pname,
820                                 name_size, component_type));
821 }
822 
823 gx_color_index
gx_forward_encode_color(gx_device * dev,const gx_color_value colors[])824 gx_forward_encode_color(gx_device * dev, const gx_color_value colors[])
825 {
826     gx_device_forward * const fdev = (gx_device_forward *)dev;
827     gx_device *tdev = fdev->target;
828 
829     return (tdev == 0 ? gx_error_encode_color(dev, colors)
830                       : dev_proc(tdev, encode_color)(tdev, colors));
831 }
832 
833 int
gx_forward_decode_color(gx_device * dev,gx_color_index cindex,gx_color_value colors[])834 gx_forward_decode_color(gx_device * dev, gx_color_index cindex, gx_color_value colors[])
835 {
836     gx_device_forward * const fdev = (gx_device_forward *)dev;
837     gx_device *tdev = fdev->target;
838 
839     if (tdev == 0)      /* If no device - just clear the color values */
840         memset(colors, 0, sizeof(gx_color_value[GX_DEVICE_COLOR_MAX_COMPONENTS]));
841     else
842         dev_proc(tdev, decode_color)(tdev, cindex, colors);
843     return 0;
844 }
845 
846 int
gx_forward_dev_spec_op(gx_device * dev,int dev_spec_op,void * data,int size)847 gx_forward_dev_spec_op(gx_device * dev, int dev_spec_op, void *data, int size)
848 {
849     gx_device_forward * const fdev = (gx_device_forward *)dev;
850     gx_device *tdev = fdev->target;
851 
852     /* Note that clist sets fdev->target == fdev,
853        so this function is unapplicable to clist. */
854     if (tdev == 0) {
855         if (dev_spec_op == gxdso_pattern_shfill_doesnt_need_path) {
856             return (dev_proc(dev, fill_path) == gx_default_fill_path);
857         }
858         return_error(gs_error_undefined);
859     } else if (dev_spec_op == gxdso_pattern_handles_clip_path) {
860         if (dev_proc(dev, fill_path) == gx_default_fill_path)
861             return 0;
862     } else if (dev_spec_op == gxdso_device_child) {
863         gxdso_device_child_request *d = (gxdso_device_child_request *)data;
864         if (d->target == dev) {
865             d->target = fdev->target;
866             return 1;
867         }
868     }
869     return dev_proc(tdev, dev_spec_op)(tdev, dev_spec_op, data, size);
870 }
871 
872 int
gx_forward_fill_rectangle_hl_color(gx_device * dev,const gs_fixed_rect * rect,const gs_gstate * pgs,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath)873 gx_forward_fill_rectangle_hl_color(gx_device *dev,
874     const gs_fixed_rect *rect,
875     const gs_gstate *pgs, const gx_drawing_color *pdcolor,
876     const gx_clip_path *pcpath)
877 {
878     gx_device_forward * const fdev = (gx_device_forward *)dev;
879     gx_device *tdev = fdev->target;
880 
881     /* Note that clist sets fdev->target == fdev,
882        so this function is unapplicable to clist. */
883     if (tdev == 0)
884         return_error(gs_error_rangecheck);
885     else
886         return dev_proc(tdev, fill_rectangle_hl_color)(tdev, rect,
887                                                 pgs, pdcolor, pcpath);
888 }
889 
890 int
gx_forward_copy_alpha_hl_color(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int width,int height,const gx_drawing_color * pdcolor,int depth)891 gx_forward_copy_alpha_hl_color(gx_device * dev, const byte * data, int data_x,
892            int raster, gx_bitmap_id id, int x, int y, int width, int height,
893                       const gx_drawing_color *pdcolor, int depth)
894 {
895     gx_device_forward * const fdev = (gx_device_forward *)dev;
896     gx_device *tdev = fdev->target;
897 
898     if (tdev == 0)
899         return_error(gs_error_rangecheck);
900     else
901         return dev_proc(tdev, copy_alpha_hl_color)
902         (tdev, data, data_x, raster, id, x, y, width, height, pdcolor, depth);
903 }
904 
905 int
gx_forward_include_color_space(gx_device * dev,gs_color_space * cspace,const byte * res_name,int name_length)906 gx_forward_include_color_space(gx_device *dev, gs_color_space *cspace,
907             const byte *res_name, int name_length)
908 {
909     gx_device_forward * const fdev = (gx_device_forward *)dev;
910     gx_device *tdev = fdev->target;
911 
912     /* Note that clist sets fdev->target == fdev,
913        so this function is unapplicable to clist. */
914     if (tdev == 0)
915         return 0;
916     else
917         return dev_proc(tdev, include_color_space)(tdev, cspace, res_name, name_length);
918 }
919 
920 int
gx_forward_fill_linear_color_scanline(gx_device * dev,const gs_fill_attributes * fa,int i,int j,int w,const frac31 * c,const int32_t * addx,const int32_t * mulx,int32_t divx)921 gx_forward_fill_linear_color_scanline(gx_device *dev, const gs_fill_attributes *fa,
922         int i, int j, int w,
923         const frac31 *c, const int32_t *addx, const int32_t *mulx, int32_t divx)
924 {
925     gx_device_forward * const fdev = (gx_device_forward *)dev;
926     gx_device *tdev = fdev->target;
927     dev_proc_fill_linear_color_scanline((*proc)) =
928         (tdev == 0 ? (tdev = dev, gx_default_fill_linear_color_scanline) :
929          dev_proc(tdev, fill_linear_color_scanline));
930     return proc(tdev, fa, i, j, w, c, addx, mulx, divx);
931 }
932 
933 int
gx_forward_fill_linear_color_trapezoid(gx_device * dev,const gs_fill_attributes * fa,const gs_fixed_point * p0,const gs_fixed_point * p1,const gs_fixed_point * p2,const gs_fixed_point * p3,const frac31 * c0,const frac31 * c1,const frac31 * c2,const frac31 * c3)934 gx_forward_fill_linear_color_trapezoid(gx_device *dev, const gs_fill_attributes *fa,
935         const gs_fixed_point *p0, const gs_fixed_point *p1,
936         const gs_fixed_point *p2, const gs_fixed_point *p3,
937         const frac31 *c0, const frac31 *c1,
938         const frac31 *c2, const frac31 *c3)
939 {
940     gx_device_forward * const fdev = (gx_device_forward *)dev;
941     gx_device *tdev = fdev->target;
942     dev_proc_fill_linear_color_trapezoid((*proc)) =
943         (tdev == 0 ? (tdev = dev, gx_default_fill_linear_color_trapezoid) :
944          dev_proc(tdev, fill_linear_color_trapezoid));
945     return proc(tdev, fa, p0, p1, p2, p3, c0, c1, c2, c3);
946 }
947 
948 int
gx_forward_fill_linear_color_triangle(gx_device * dev,const gs_fill_attributes * fa,const gs_fixed_point * p0,const gs_fixed_point * p1,const gs_fixed_point * p2,const frac31 * c0,const frac31 * c1,const frac31 * c2)949 gx_forward_fill_linear_color_triangle(gx_device *dev, const gs_fill_attributes *fa,
950         const gs_fixed_point *p0, const gs_fixed_point *p1,
951         const gs_fixed_point *p2,
952         const frac31 *c0, const frac31 *c1, const frac31 *c2)
953 {
954     gx_device_forward * const fdev = (gx_device_forward *)dev;
955     gx_device *tdev = fdev->target;
956     dev_proc_fill_linear_color_triangle((*proc)) =
957         (tdev == 0 ? (tdev = dev, gx_default_fill_linear_color_triangle) :
958          dev_proc(tdev, fill_linear_color_triangle));
959     return proc(tdev, fa, p0, p1, p2, c0, c1, c2);
960 }
961 
962 int
gx_forward_update_spot_equivalent_colors(gx_device * dev,const gs_gstate * pgs)963 gx_forward_update_spot_equivalent_colors(gx_device *dev, const gs_gstate * pgs)
964 {
965     gx_device_forward * const fdev = (gx_device_forward *)dev;
966     gx_device *tdev = fdev->target;
967     int code = 0;
968 
969     if (tdev != NULL)
970         code = dev_proc(tdev, update_spot_equivalent_colors)(tdev, pgs);
971     return code;
972 }
973 
974 gs_devn_params *
gx_forward_ret_devn_params(gx_device * dev)975 gx_forward_ret_devn_params(gx_device *dev)
976 {
977     gx_device_forward * const fdev = (gx_device_forward *)dev;
978     gx_device *tdev = fdev->target;
979 
980     if (tdev != NULL)
981         return dev_proc(tdev, ret_devn_params)(tdev);
982     return NULL;
983 }
984 
985 int
gx_forward_fillpage(gx_device * dev,gs_gstate * pgs,gx_device_color * pdevc)986 gx_forward_fillpage(gx_device *dev, gs_gstate * pgs, gx_device_color *pdevc)
987 {
988     gx_device_forward * const fdev = (gx_device_forward *)dev;
989     gx_device *tdev = fdev->target;
990     dev_proc_fillpage((*proc)) =
991         (tdev == 0 ? (tdev = dev, gx_default_fillpage) :
992          dev_proc(tdev, fillpage));
993     return proc(tdev, pgs, pdevc);
994 }
995 
996 int
gx_forward_create_compositor(gx_device * dev,gx_device ** pcdev,const gs_composite_t * pcte,gs_gstate * pgs,gs_memory_t * memory,gx_device * cdev)997 gx_forward_create_compositor(gx_device * dev, gx_device ** pcdev,
998                         const gs_composite_t * pcte,
999                         gs_gstate * pgs, gs_memory_t * memory,
1000                         gx_device *cdev)
1001 {
1002     gx_device_forward * const fdev = (gx_device_forward *)dev;
1003     gx_device *tdev = fdev->target;
1004     int code;
1005 
1006     if (tdev == 0)
1007         return gx_no_create_compositor(dev, pcdev, pcte, pgs, memory, cdev);
1008     /* else do the compositor action */
1009     code = dev_proc(tdev, create_compositor)(tdev, pcdev, pcte, pgs, memory, cdev);
1010     /* the compositor may have changed color_info. Pick up the new value */
1011     dev->color_info = tdev->color_info;
1012     return code;
1013 }
1014 
1015 int
gx_forward_get_profile(gx_device * dev,cmm_dev_profile_t ** profile)1016 gx_forward_get_profile(gx_device *dev,  cmm_dev_profile_t **profile)
1017 {
1018     gx_device_forward * const fdev = (gx_device_forward *)dev;
1019     gx_device *tdev = fdev->target;
1020     dev_proc_get_profile((*proc)) =
1021         (tdev == 0 ? (tdev = dev, gx_default_get_profile) :
1022          dev_proc(tdev, get_profile));
1023     return proc(tdev, profile);
1024 }
1025 
1026 void
gx_forward_set_graphics_type_tag(gx_device * dev,gs_graphics_type_tag_t graphics_type_tag)1027 gx_forward_set_graphics_type_tag(gx_device *dev, gs_graphics_type_tag_t graphics_type_tag)
1028 {
1029     gx_device_forward * const fdev = (gx_device_forward *)dev;
1030     gx_device *tdev = fdev->target;
1031 
1032     if (tdev != 0)
1033         dev_proc(tdev, set_graphics_type_tag)(tdev, graphics_type_tag);
1034     /* Keep copy in this device current, and preserve GS_DEVICE_ENCODES_TAGS */
1035     dev->graphics_type_tag = (dev->graphics_type_tag & GS_DEVICE_ENCODES_TAGS) | graphics_type_tag;
1036 }
1037 
1038 int
gx_forward_put_image(gx_device * pdev,gx_device * mdev,const byte ** buffers,int num_chan,int xstart,int ystart,int width,int height,int row_stride,int alpha_plane_index,int tag_plane_index)1039 gx_forward_put_image(gx_device *pdev, gx_device *mdev, const byte **buffers, int num_chan, int xstart,
1040               int ystart, int width, int height, int row_stride,
1041               int alpha_plane_index, int tag_plane_index)
1042 {
1043     gx_device_forward * const fdev = (gx_device_forward *)pdev;
1044     gx_device *tdev = fdev->target;
1045 
1046     if (tdev != 0)
1047         return dev_proc(tdev, put_image)(tdev, mdev, buffers, num_chan, xstart, ystart, width, height, row_stride, alpha_plane_index, tag_plane_index);
1048     else
1049         return gx_default_put_image(tdev, mdev, buffers, num_chan, xstart, ystart, width, height, row_stride, alpha_plane_index, tag_plane_index);
1050 }
1051 
1052 int
gx_forward_transform_pixel_region(gx_device * pdev,transform_pixel_region_reason reason,transform_pixel_region_data * data)1053 gx_forward_transform_pixel_region(gx_device *pdev, transform_pixel_region_reason reason, transform_pixel_region_data *data)
1054 {
1055     gx_device_forward * const fdev = (gx_device_forward *)pdev;
1056     gx_device *tdev = fdev->target;
1057 
1058     if (tdev != 0)
1059         return dev_proc(tdev, transform_pixel_region)(tdev, reason, data);
1060     else
1061         return gx_default_transform_pixel_region(pdev, reason, data);
1062 }
1063 
1064 /* ---------------- The null device(s) ---------_plane_index------- */
1065 
1066 static dev_proc_get_initial_matrix(gx_forward_upright_get_initial_matrix);
1067 static dev_proc_fill_rectangle(null_fill_rectangle);
1068 static dev_proc_copy_mono(null_copy_mono);
1069 static dev_proc_copy_color(null_copy_color);
1070 static dev_proc_put_params(null_put_params);
1071 static dev_proc_copy_alpha(null_copy_alpha);
1072 static dev_proc_copy_rop(null_copy_rop);
1073 static dev_proc_fill_path(null_fill_path);
1074 static dev_proc_stroke_path(null_stroke_path);
1075 static dev_proc_fill_trapezoid(null_fill_trapezoid);
1076 static dev_proc_fill_parallelogram(null_fill_parallelogram);
1077 static dev_proc_fill_triangle(null_fill_triangle);
1078 static dev_proc_draw_thin_line(null_draw_thin_line);
1079 static dev_proc_decode_color(null_decode_color);
1080 /* We would like to have null implementations of begin/data/end image, */
1081 /* but we can't do this, because image_data must keep track of the */
1082 /* Y position so it can return 1 when done. */
1083 static dev_proc_strip_copy_rop(null_strip_copy_rop);
1084 static dev_proc_strip_copy_rop2(null_strip_copy_rop2);
1085 static dev_proc_strip_tile_rect_devn(null_strip_tile_rect_devn);
1086 static dev_proc_fill_rectangle_hl_color(null_fill_rectangle_hl_color);
1087 
1088 #define null_procs(get_initial_matrix, get_page_device) {\
1089         gx_default_open_device,\
1090         get_initial_matrix, /* differs */\
1091         gx_default_sync_output,\
1092         gx_default_output_page,\
1093         gx_default_close_device,\
1094         gx_forward_map_rgb_color,\
1095         gx_forward_map_color_rgb,\
1096         null_fill_rectangle,\
1097         gx_default_tile_rectangle,\
1098         null_copy_mono,\
1099         null_copy_color,\
1100         gx_default_draw_line,\
1101         gx_default_get_bits,\
1102         gx_forward_get_params,\
1103         null_put_params,\
1104         gx_forward_map_cmyk_color,\
1105         gx_forward_get_xfont_procs,\
1106         gx_forward_get_xfont_device,\
1107         gx_forward_map_rgb_alpha_color,\
1108         get_page_device,        /* differs */\
1109         gx_default_get_alpha_bits,\
1110         null_copy_alpha,\
1111         gx_forward_get_band,\
1112         null_copy_rop,\
1113         null_fill_path,\
1114         null_stroke_path,\
1115         gx_default_fill_mask,\
1116         null_fill_trapezoid,\
1117         null_fill_parallelogram,\
1118         null_fill_triangle,\
1119         null_draw_thin_line,\
1120         gx_default_begin_image,\
1121         gx_default_image_data,\
1122         gx_default_end_image,\
1123         gx_default_strip_tile_rectangle,\
1124         null_strip_copy_rop,\
1125         gx_default_get_clipping_box,\
1126         gx_default_begin_typed_image,\
1127         gx_default_get_bits_rectangle,\
1128         gx_forward_map_color_rgb_alpha,\
1129         gx_non_imaging_create_compositor,\
1130         gx_forward_get_hardware_params,\
1131         gx_default_text_begin,\
1132         gx_default_finish_copydevice,\
1133         NULL,                           /* begin_transparency_group */\
1134         NULL,                           /* end_transparency_group */\
1135         NULL,                           /* begin_transparency_mask */\
1136         NULL,                           /* end_transparency_mask */\
1137         NULL,                           /* discard_transparency_layer */\
1138         gx_default_DevGray_get_color_mapping_procs,     /* get_color_mapping_procs */\
1139         gx_default_DevGray_get_color_comp_index,/* get_color_comp_index */\
1140         gx_default_gray_fast_encode,            /* encode_color */\
1141         null_decode_color,              /* decode_color */\
1142         NULL, /* pattern_manage */\
1143         null_fill_rectangle_hl_color,\
1144         gx_default_include_color_space,\
1145         NULL, /* fill_line_sl */\
1146         NULL, /* fill_line_tr */\
1147         NULL, /* fill_line_tri */\
1148         NULL, /* up_spot_eq_col */\
1149         gx_default_ret_devn_params, /* ret_devn_params */\
1150         NULL, /* fillpage */\
1151         NULL, /* push_transparency_state */\
1152         NULL, /* pop_transparency_state */\
1153         NULL, /* put_image */\
1154         gx_default_dev_spec_op, /* dev_spec_op */\
1155         NULL, /* copy_planes */\
1156         NULL, /* get_profile */\
1157         NULL, /* set_graphics_type_tag */\
1158         null_strip_copy_rop2,\
1159         null_strip_tile_rect_devn\
1160 }
1161 
1162 #define NULLD_X_RES 72
1163 #define NULLD_Y_RES 72
1164 
1165 const gx_device_null gs_null_device = {
1166     std_device_std_body_type_open(gx_device_null, 0, "null", &st_device_null,
1167                                   0, 0, NULLD_X_RES, NULLD_Y_RES),
1168     null_procs(gx_forward_upright_get_initial_matrix, /* upright matrix */
1169                gx_default_get_page_device     /* not a page device */ ),
1170     0                           /* target */
1171 };
1172 
1173 const gx_device_null gs_nullpage_device = {
1174 std_device_std_body_type_open(gx_device_null, 0, "nullpage", &st_device_null,
1175                               (int)((float)(DEFAULT_WIDTH_10THS * NULLD_X_RES) / 10),
1176                               (int)((float)(DEFAULT_HEIGHT_10THS * NULLD_Y_RES) / 10),
1177                               NULLD_X_RES, NULLD_Y_RES),
1178     null_procs( gx_forward_get_initial_matrix, /* default matrix */
1179                 gx_page_device_get_page_device /* a page device */ ),
1180     0                           /* target */
1181 };
1182 
1183 static void
gx_forward_upright_get_initial_matrix(gx_device * dev,gs_matrix * pmat)1184 gx_forward_upright_get_initial_matrix(gx_device * dev, gs_matrix * pmat)
1185 {
1186     gx_device_forward * const fdev = (gx_device_forward *)dev;
1187     gx_device *tdev = fdev->target;
1188 
1189     if (tdev == 0)
1190         gx_upright_get_initial_matrix(dev, pmat);
1191     else
1192         dev_proc(tdev, get_initial_matrix)(tdev, pmat);
1193 }
1194 
1195 static int
null_decode_color(gx_device * dev,gx_color_index cindex,gx_color_value colors[])1196 null_decode_color(gx_device * dev, gx_color_index cindex, gx_color_value colors[])
1197 {
1198     colors[0] = (cindex & 1) ?  gx_max_color_value : 0;
1199     return 0;
1200 }
1201 
1202 static int
null_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)1203 null_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
1204                     gx_color_index color)
1205 {
1206     return 0;
1207 }
1208 static int
null_copy_mono(gx_device * dev,const byte * data,int dx,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one)1209 null_copy_mono(gx_device * dev, const byte * data, int dx, int raster,
1210                gx_bitmap_id id, int x, int y, int w, int h,
1211                gx_color_index zero, gx_color_index one)
1212 {
1213     return 0;
1214 }
1215 static int
null_copy_color(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int width,int height)1216 null_copy_color(gx_device * dev, const byte * data,
1217                 int data_x, int raster, gx_bitmap_id id,
1218                 int x, int y, int width, int height)
1219 {
1220     return 0;
1221 }
1222 static int
null_put_params(gx_device * dev,gs_param_list * plist)1223 null_put_params(gx_device * dev, gs_param_list * plist)
1224 {
1225     /*
1226      * If this is not a page device, we must defeat attempts to reset
1227      * the size; otherwise this is equivalent to gx_forward_put_params.
1228      */
1229     int code = gx_forward_put_params(dev, plist);
1230 
1231     if (code < 0 || dev_proc(dev, get_page_device)(dev) == dev)
1232         return code;
1233     dev->width = dev->height = 0;
1234     return code;
1235 }
1236 static int
null_copy_alpha(gx_device * dev,const byte * data,int data_x,int raster,gx_bitmap_id id,int x,int y,int width,int height,gx_color_index color,int depth)1237 null_copy_alpha(gx_device * dev, const byte * data, int data_x, int raster,
1238                 gx_bitmap_id id, int x, int y, int width, int height,
1239                 gx_color_index color, int depth)
1240 {
1241     return 0;
1242 }
1243 static int
null_copy_rop(gx_device * dev,const byte * sdata,int sourcex,uint sraster,gx_bitmap_id id,const gx_color_index * scolors,const gx_tile_bitmap * texture,const gx_color_index * tcolors,int x,int y,int width,int height,int phase_x,int phase_y,gs_logical_operation_t lop)1244 null_copy_rop(gx_device * dev,
1245               const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
1246               const gx_color_index * scolors,
1247               const gx_tile_bitmap * texture, const gx_color_index * tcolors,
1248               int x, int y, int width, int height,
1249               int phase_x, int phase_y, gs_logical_operation_t lop)
1250 {
1251     return 0;
1252 }
1253 static int
null_fill_path(gx_device * dev,const gs_gstate * pgs,gx_path * ppath,const gx_fill_params * params,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath)1254 null_fill_path(gx_device * dev, const gs_gstate * pgs,
1255                gx_path * ppath, const gx_fill_params * params,
1256                const gx_drawing_color * pdcolor, const gx_clip_path * pcpath)
1257 {
1258     return 0;
1259 }
1260 static int
null_stroke_path(gx_device * dev,const gs_gstate * pgs,gx_path * ppath,const gx_stroke_params * params,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath)1261 null_stroke_path(gx_device * dev, const gs_gstate * pgs,
1262                  gx_path * ppath, const gx_stroke_params * params,
1263                  const gx_drawing_color * pdcolor, const gx_clip_path * pcpath)
1264 {
1265     return 0;
1266 }
1267 static int
null_fill_trapezoid(gx_device * dev,const gs_fixed_edge * left,const gs_fixed_edge * right,fixed ybot,fixed ytop,bool swap_axes,const gx_drawing_color * pdcolor,gs_logical_operation_t lop)1268 null_fill_trapezoid(gx_device * dev,
1269                     const gs_fixed_edge * left, const gs_fixed_edge * right,
1270                     fixed ybot, fixed ytop, bool swap_axes,
1271                     const gx_drawing_color * pdcolor,
1272                     gs_logical_operation_t lop)
1273 {
1274     return 0;
1275 }
1276 static int
null_fill_parallelogram(gx_device * dev,fixed px,fixed py,fixed ax,fixed ay,fixed bx,fixed by,const gx_drawing_color * pdcolor,gs_logical_operation_t lop)1277 null_fill_parallelogram(gx_device * dev, fixed px, fixed py,
1278                         fixed ax, fixed ay, fixed bx, fixed by,
1279                         const gx_drawing_color * pdcolor,
1280                         gs_logical_operation_t lop)
1281 {
1282     return 0;
1283 }
1284 static int
null_fill_triangle(gx_device * dev,fixed px,fixed py,fixed ax,fixed ay,fixed bx,fixed by,const gx_drawing_color * pdcolor,gs_logical_operation_t lop)1285 null_fill_triangle(gx_device * dev,
1286                    fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
1287                    const gx_drawing_color * pdcolor,
1288                    gs_logical_operation_t lop)
1289 {
1290     return 0;
1291 }
1292 static int
null_draw_thin_line(gx_device * dev,fixed fx0,fixed fy0,fixed fx1,fixed fy1,const gx_drawing_color * pdcolor,gs_logical_operation_t lop,fixed adjustx,fixed adjusty)1293 null_draw_thin_line(gx_device * dev,
1294                     fixed fx0, fixed fy0, fixed fx1, fixed fy1,
1295                     const gx_drawing_color * pdcolor,
1296                     gs_logical_operation_t lop,
1297                     fixed adjustx, fixed adjusty)
1298 {
1299     return 0;
1300 }
1301 static int
null_strip_copy_rop(gx_device * dev,const byte * sdata,int sourcex,uint sraster,gx_bitmap_id id,const gx_color_index * scolors,const gx_strip_bitmap * textures,const gx_color_index * tcolors,int x,int y,int width,int height,int phase_x,int phase_y,gs_logical_operation_t lop)1302 null_strip_copy_rop(gx_device * dev, const byte * sdata, int sourcex,
1303                     uint sraster, gx_bitmap_id id,
1304                     const gx_color_index * scolors,
1305                     const gx_strip_bitmap * textures,
1306                     const gx_color_index * tcolors,
1307                     int x, int y, int width, int height,
1308                     int phase_x, int phase_y, gs_logical_operation_t lop)
1309 {
1310     return 0;
1311 }
1312 static int
null_strip_copy_rop2(gx_device * dev,const byte * sdata,int sourcex,uint sraster,gx_bitmap_id id,const gx_color_index * scolors,const gx_strip_bitmap * textures,const gx_color_index * tcolors,int x,int y,int width,int height,int phase_x,int phase_y,gs_logical_operation_t lop,uint plane_height)1313 null_strip_copy_rop2(gx_device * dev, const byte * sdata, int sourcex,
1314                      uint sraster, gx_bitmap_id id,
1315                      const gx_color_index * scolors,
1316                      const gx_strip_bitmap * textures,
1317                      const gx_color_index * tcolors,
1318                      int x, int y, int width, int height,
1319                      int phase_x, int phase_y, gs_logical_operation_t lop,
1320                      uint plane_height)
1321 {
1322     return 0;
1323 }
1324 
1325 static int
null_strip_tile_rect_devn(gx_device * dev,const gx_strip_bitmap * tiles,int x,int y,int w,int h,const gx_drawing_color * pdcolor0,const gx_drawing_color * pdcolor1,int px,int py)1326 null_strip_tile_rect_devn(gx_device * dev, const gx_strip_bitmap * tiles,
1327    int x, int y, int w, int h, const gx_drawing_color * pdcolor0,
1328    const gx_drawing_color * pdcolor1, int px, int py)
1329 {
1330     return 0;
1331 }
1332 
1333 /* We use this to erase a pattern background, if pdfwrite has pushed
1334  * the NULL device to dispense with text (because its a strinwidth)
1335  * we don't want to throw an error when erasing the pattern which
1336  * fills the text, because pdfwrite manages the pattern itself and
1337  * we don't need to erase hte background. More generally, since the
1338  * null device is a bit bucket, it shouldn't really throw errors
1339  * when asked to render anything at all.
1340  */
null_fill_rectangle_hl_color(gx_device * pdev,const gs_fixed_rect * rect,const gs_gstate * pgs,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath)1341 static int null_fill_rectangle_hl_color(gx_device *pdev,
1342     const gs_fixed_rect *rect,
1343     const gs_gstate *pgs, const gx_drawing_color *pdcolor,
1344     const gx_clip_path *pcpath)
1345 {
1346     return 0;
1347 }
1348 
1349 bool
fwd_uses_fwd_cmap_procs(gx_device * dev)1350 fwd_uses_fwd_cmap_procs(gx_device * dev)
1351 {
1352     const gx_cm_color_map_procs *pprocs;
1353 
1354     pprocs = dev_proc(dev, get_color_mapping_procs)(dev);
1355     if (pprocs == &FwdDevice_cm_map_procs) {
1356         return true;
1357     }
1358     return false;
1359 }
1360 
1361 const gx_cm_color_map_procs*
fwd_get_target_cmap_procs(gx_device * dev)1362 fwd_get_target_cmap_procs(gx_device * dev)
1363 {
1364     const gx_cm_color_map_procs *pprocs;
1365     gx_device_forward * const fdev = (gx_device_forward *)dev;
1366     gx_device * const tdev = fdev->target;
1367 
1368     pprocs = dev_proc(tdev, get_color_mapping_procs(tdev));
1369     while (pprocs == &FwdDevice_cm_map_procs) {
1370         pprocs = fwd_get_target_cmap_procs(tdev);
1371     }
1372     return pprocs;
1373 }
1374 
1375 #ifdef DEBUG
do_device_dump(gx_device * dev,int n)1376 static void do_device_dump(gx_device *dev, int n)
1377 {
1378     int i, ret;
1379     gxdso_device_child_request data;
1380 
1381     /* Dump the details of device dev */
1382     for (i = 0; i < n; i++)
1383         dmlprintf(dev->memory, " ");
1384     if (dev == NULL) {
1385         dmlprintf(dev->memory, "NULL\n");
1386         return;
1387     }
1388     dmlprintf3(dev->memory, "%p(%ld) = '%s'\n", dev, dev->rc.ref_count, dev->dname);
1389 
1390     data.n = 0;
1391     do {
1392         data.target = dev;
1393         ret = dev_proc(dev, dev_spec_op)(dev, gxdso_device_child, &data, sizeof(data));
1394         if (ret > 0)
1395             do_device_dump(data.target, n+1);
1396     } while ((ret > 0) && (data.n != 0));
1397 }
1398 
gx_device_dump(gx_device * dev,const char * text)1399 void gx_device_dump(gx_device *dev, const char *text)
1400 {
1401     dmlprintf1(dev->memory, "%s", text);
1402     do_device_dump(dev, 0);
1403 }
1404 #endif
1405