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