xref: /plan9/sys/src/cmd/gs/src/gdevnfwd.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1996, 2000 Aladdin Enterprises.  All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /* $Id: gdevnfwd.c,v 1.28 2005/03/14 18:08:36 dan Exp $ */
18 /* Null and forwarding device implementation */
19 #include "gx.h"
20 #include "gserrors.h"
21 #include "gxdevice.h"
22 #include "gxcmap.h"
23 #include "memory_.h"
24 
25 /* ---------------- Forwarding procedures ---------------- */
26 
27 /* Additional finalization for forwarding devices. */
28 private void
gx_device_forward_finalize(gx_device * dev)29 gx_device_forward_finalize(gx_device *dev)
30 {
31     gx_device *target = ((gx_device_forward *)dev)->target;
32 
33     ((gx_device_forward *)dev)->target = 0;
34     rc_decrement_only(target, "gx_device_forward_finalize");
35 }
36 
37 /* Set the target of a forwarding device. */
38 void
gx_device_set_target(gx_device_forward * fdev,gx_device * target)39 gx_device_set_target(gx_device_forward *fdev, gx_device *target)
40 {
41     /*
42      * ****** HACK: if this device doesn't have special finalization yet,
43      * make it decrement the reference count of the target.
44      */
45     if (target && !fdev->finalize)
46 	fdev->finalize = gx_device_forward_finalize;
47     rc_assign(fdev->target, target, "gx_device_set_target");
48 }
49 
50 /* Fill in NULL procedures in a forwarding device procedure record. */
51 /* We don't fill in: open_device, close_device, or the lowest-level */
52 /* drawing operations. */
53 void
gx_device_forward_fill_in_procs(register gx_device_forward * dev)54 gx_device_forward_fill_in_procs(register gx_device_forward * dev)
55 {
56     gx_device_set_procs((gx_device *) dev);
57     /* NOT open_device */
58     fill_dev_proc(dev, get_initial_matrix, gx_forward_get_initial_matrix);
59     fill_dev_proc(dev, sync_output, gx_forward_sync_output);
60     fill_dev_proc(dev, output_page, gx_forward_output_page);
61     /* NOT close_device */
62     fill_dev_proc(dev, map_rgb_color, gx_forward_map_rgb_color);
63     fill_dev_proc(dev, map_color_rgb, gx_forward_map_color_rgb);
64     /* NOT fill_rectangle */
65     /* NOT tile_rectangle */
66     /* NOT copy_mono */
67     /* NOT copy_color */
68     /* NOT draw_line (OBSOLETE) */
69     fill_dev_proc(dev, get_bits, gx_forward_get_bits);
70     fill_dev_proc(dev, get_params, gx_forward_get_params);
71     fill_dev_proc(dev, put_params, gx_forward_put_params);
72     fill_dev_proc(dev, map_cmyk_color, gx_forward_map_cmyk_color);
73     fill_dev_proc(dev, get_xfont_procs, gx_forward_get_xfont_procs);
74     fill_dev_proc(dev, get_xfont_device, gx_forward_get_xfont_device);
75     fill_dev_proc(dev, map_rgb_alpha_color, gx_forward_map_rgb_alpha_color);
76     fill_dev_proc(dev, get_page_device, gx_forward_get_page_device);
77     /* NOT get_alpha_bits (OBSOLETE) */
78     /* NOT copy_alpha */
79     fill_dev_proc(dev, get_band, gx_forward_get_band);
80     fill_dev_proc(dev, copy_rop, gx_forward_copy_rop);
81     fill_dev_proc(dev, fill_path, gx_forward_fill_path);
82     fill_dev_proc(dev, stroke_path, gx_forward_stroke_path);
83     fill_dev_proc(dev, fill_mask, gx_forward_fill_mask);
84     fill_dev_proc(dev, fill_trapezoid, gx_forward_fill_trapezoid);
85     fill_dev_proc(dev, fill_parallelogram, gx_forward_fill_parallelogram);
86     fill_dev_proc(dev, fill_triangle, gx_forward_fill_triangle);
87     fill_dev_proc(dev, draw_thin_line, gx_forward_draw_thin_line);
88     fill_dev_proc(dev, begin_image, gx_forward_begin_image);
89     /* NOT image_data (OBSOLETE) */
90     /* NOT end_image (OBSOLETE) */
91     /* NOT strip_tile_rectangle */
92     fill_dev_proc(dev, strip_copy_rop, gx_forward_strip_copy_rop);
93     fill_dev_proc(dev, get_clipping_box, gx_forward_get_clipping_box);
94     fill_dev_proc(dev, begin_typed_image, gx_forward_begin_typed_image);
95     fill_dev_proc(dev, get_bits_rectangle, gx_forward_get_bits_rectangle);
96     fill_dev_proc(dev, map_color_rgb_alpha, gx_forward_map_color_rgb_alpha);
97     fill_dev_proc(dev, create_compositor, gx_no_create_compositor);
98     fill_dev_proc(dev, get_hardware_params, gx_forward_get_hardware_params);
99     fill_dev_proc(dev, text_begin, gx_forward_text_begin);
100     fill_dev_proc(dev, get_color_mapping_procs, gx_forward_get_color_mapping_procs);
101     fill_dev_proc(dev, get_color_comp_index, gx_forward_get_color_comp_index);
102     fill_dev_proc(dev, encode_color, gx_forward_encode_color);
103     fill_dev_proc(dev, decode_color, gx_forward_decode_color);
104     fill_dev_proc(dev, pattern_manage, gx_forward_pattern_manage);
105     fill_dev_proc(dev, fill_rectangle_hl_color, gx_forward_fill_rectangle_hl_color);
106     fill_dev_proc(dev, include_color_space, gx_forward_include_color_space);
107     fill_dev_proc(dev, fill_linear_color_scanline, gx_forward_fill_linear_color_scanline);
108     fill_dev_proc(dev, fill_linear_color_trapezoid, gx_forward_fill_linear_color_trapezoid);
109     fill_dev_proc(dev, fill_linear_color_triangle, gx_forward_fill_linear_color_triangle);
110     fill_dev_proc(dev, update_spot_equivalent_colors, gx_forward_update_spot_equivalent_colors);
111     gx_device_fill_in_procs((gx_device *) dev);
112 }
113 
114 /* Forward the color mapping procedures from a device to its target. */
115 void
gx_device_forward_color_procs(gx_device_forward * dev)116 gx_device_forward_color_procs(gx_device_forward * dev)
117 {
118     set_dev_proc(dev, map_rgb_color, gx_forward_map_rgb_color);
119     set_dev_proc(dev, map_color_rgb, gx_forward_map_color_rgb);
120     set_dev_proc(dev, map_cmyk_color, gx_forward_map_cmyk_color);
121     set_dev_proc(dev, map_rgb_alpha_color, gx_forward_map_rgb_alpha_color);
122     set_dev_proc(dev, get_color_mapping_procs, gx_forward_get_color_mapping_procs);
123     set_dev_proc(dev, get_color_comp_index, gx_forward_get_color_comp_index);
124     set_dev_proc(dev, encode_color, gx_forward_encode_color);
125     set_dev_proc(dev, decode_color, gx_forward_decode_color);
126 }
127 
128 int
gx_forward_close_device(gx_device * dev)129 gx_forward_close_device(gx_device * dev)
130 {
131     gx_device_forward * const fdev = (gx_device_forward *)dev;
132     gx_device *tdev = fdev->target;
133 
134     return (tdev == 0) ? gx_default_close_device(dev)
135 		       : dev_proc(tdev, close_device)(tdev);
136 }
137 
138 void
gx_forward_get_initial_matrix(gx_device * dev,gs_matrix * pmat)139 gx_forward_get_initial_matrix(gx_device * dev, gs_matrix * pmat)
140 {
141     gx_device_forward * const fdev = (gx_device_forward *)dev;
142     gx_device *tdev = fdev->target;
143 
144     if (tdev == 0)
145 	gx_default_get_initial_matrix(dev, pmat);
146     else
147 	dev_proc(tdev, get_initial_matrix)(tdev, pmat);
148 }
149 
150 int
gx_forward_sync_output(gx_device * dev)151 gx_forward_sync_output(gx_device * dev)
152 {
153     gx_device_forward * const fdev = (gx_device_forward *)dev;
154     gx_device *tdev = fdev->target;
155 
156     return (tdev == 0 ? gx_default_sync_output(dev) :
157 	    dev_proc(tdev, sync_output)(tdev));
158 }
159 
160 int
gx_forward_output_page(gx_device * dev,int num_copies,int flush)161 gx_forward_output_page(gx_device * dev, int num_copies, int flush)
162 {
163     gx_device_forward * const fdev = (gx_device_forward *)dev;
164     gx_device *tdev = fdev->target;
165     int code =
166 	(tdev == 0 ? gx_default_output_page(dev, num_copies, flush) :
167 	 dev_proc(tdev, output_page)(tdev, num_copies, flush));
168 
169     if (code >= 0 && tdev != 0)
170 	dev->PageCount = tdev->PageCount;
171     return code;
172 }
173 
174 gx_color_index
gx_forward_map_rgb_color(gx_device * dev,const gx_color_value cv[])175 gx_forward_map_rgb_color(gx_device * dev, const gx_color_value cv[])
176 {
177     gx_device_forward * const fdev = (gx_device_forward *)dev;
178     gx_device *tdev = fdev->target;
179 
180     return (tdev == 0 ? gx_error_encode_color(dev, cv) :
181 	    dev_proc(tdev, map_rgb_color)(tdev, cv));
182 }
183 
184 int
gx_forward_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])185 gx_forward_map_color_rgb(gx_device * dev, gx_color_index color,
186 			 gx_color_value prgb[3])
187 {
188     gx_device_forward * const fdev = (gx_device_forward *)dev;
189     gx_device *tdev = fdev->target;
190 
191     return (tdev == 0 ? gx_default_map_color_rgb(dev, color, prgb) :
192 	    dev_proc(tdev, map_color_rgb)(tdev, color, prgb));
193 }
194 
195 int
gx_forward_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)196 gx_forward_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
197 			  gx_color_index color)
198 {
199     gx_device_forward * const fdev = (gx_device_forward *)dev;
200     gx_device *tdev = fdev->target;
201 
202     if (tdev == 0)
203 	return_error(gs_error_Fatal);
204     return dev_proc(tdev, fill_rectangle)(tdev, x, y, w, h, color);
205 }
206 
207 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)208 gx_forward_tile_rectangle(gx_device * dev, const gx_tile_bitmap * tile,
209 			  int x, int y, int w, int h, gx_color_index color0,
210 			  gx_color_index color1, int px, int py)
211 {
212     gx_device_forward * const fdev = (gx_device_forward *)dev;
213     gx_device *tdev = fdev->target;
214     dev_proc_tile_rectangle((*proc)) =
215 	(tdev == 0 ? (tdev = dev, gx_default_tile_rectangle) :
216 	 dev_proc(tdev, tile_rectangle));
217 
218     return proc(tdev, tile, x, y, w, h, color0, color1, px, py);
219 }
220 
221 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)222 gx_forward_copy_mono(gx_device * dev, const byte * data,
223 		     int dx, int raster, gx_bitmap_id id,
224 		     int x, int y, int w, int h,
225 		     gx_color_index zero, gx_color_index one)
226 {
227     gx_device_forward * const fdev = (gx_device_forward *)dev;
228     gx_device *tdev = fdev->target;
229 
230     if (tdev == 0)
231 	return_error(gs_error_Fatal);
232     return dev_proc(tdev, copy_mono)
233 	(tdev, data, dx, raster, id, x, y, w, h, zero, one);
234 }
235 
236 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)237 gx_forward_copy_alpha(gx_device * dev, const byte * data, int data_x,
238 	   int raster, gx_bitmap_id id, int x, int y, int width, int height,
239 		      gx_color_index color, int depth)
240 {
241     gx_device_forward * const fdev = (gx_device_forward *)dev;
242     gx_device *tdev = fdev->target;
243 
244     if (tdev == 0)
245 	return_error(gs_error_Fatal);
246     return dev_proc(tdev, copy_mono)
247 	(tdev, data, data_x, raster, id, x, y, width, height, color, depth);
248 }
249 
250 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)251 gx_forward_copy_color(gx_device * dev, const byte * data,
252 		      int dx, int raster, gx_bitmap_id id,
253 		      int x, int y, int w, int h)
254 {
255     gx_device_forward * const fdev = (gx_device_forward *)dev;
256     gx_device *tdev = fdev->target;
257 
258     if (tdev == 0)
259 	return_error(gs_error_Fatal);
260     return dev_proc(tdev, copy_color)
261 	(tdev, data, dx, raster, id, x, y, w, h);
262 }
263 
264 int
gx_forward_get_bits(gx_device * dev,int y,byte * data,byte ** actual_data)265 gx_forward_get_bits(gx_device * dev, int y, byte * data, byte ** actual_data)
266 {
267     gx_device_forward * const fdev = (gx_device_forward *)dev;
268     gx_device *tdev = fdev->target;
269 
270     return (tdev == 0 ? gx_default_get_bits(dev, y, data, actual_data) :
271 	    dev_proc(tdev, get_bits)(tdev, y, data, actual_data));
272 }
273 
274 int
gx_forward_get_params(gx_device * dev,gs_param_list * plist)275 gx_forward_get_params(gx_device * dev, gs_param_list * plist)
276 {
277     gx_device_forward * const fdev = (gx_device_forward *)dev;
278     gx_device *tdev = fdev->target;
279 
280     return (tdev == 0 ? gx_default_get_params(dev, plist) :
281 	    dev_proc(tdev, get_params)(tdev, plist));
282 }
283 
284 int
gx_forward_put_params(gx_device * dev,gs_param_list * plist)285 gx_forward_put_params(gx_device * dev, gs_param_list * plist)
286 {
287     gx_device_forward * const fdev = (gx_device_forward *)dev;
288     gx_device *tdev = fdev->target;
289     int code;
290 
291     if (tdev == 0)
292 	return gx_default_put_params(dev, plist);
293     code = dev_proc(tdev, put_params)(tdev, plist);
294     if (code >= 0)
295 	gx_device_decache_colors(dev);
296     return code;
297 }
298 
299 gx_color_index
gx_forward_map_cmyk_color(gx_device * dev,const gx_color_value cv[])300 gx_forward_map_cmyk_color(gx_device * dev, const gx_color_value cv[])
301 {
302     gx_device_forward * const fdev = (gx_device_forward *)dev;
303     gx_device *tdev = fdev->target;
304 
305     return (tdev == 0 ? gx_default_map_cmyk_color(dev, cv) :
306 	    dev_proc(tdev, map_cmyk_color)(tdev, cv));
307 }
308 
309 const gx_xfont_procs *
gx_forward_get_xfont_procs(gx_device * dev)310 gx_forward_get_xfont_procs(gx_device * dev)
311 {
312     gx_device_forward * const fdev = (gx_device_forward *)dev;
313     gx_device *tdev = fdev->target;
314 
315     return (tdev == 0 ? gx_default_get_xfont_procs(dev) :
316 	    dev_proc(tdev, get_xfont_procs)(tdev));
317 }
318 
319 gx_device *
gx_forward_get_xfont_device(gx_device * dev)320 gx_forward_get_xfont_device(gx_device * dev)
321 {
322     gx_device_forward * const fdev = (gx_device_forward *)dev;
323     gx_device *tdev = fdev->target;
324 
325     return (tdev == 0 ? gx_default_get_xfont_device(dev) :
326 	    dev_proc(tdev, get_xfont_device)(tdev));
327 }
328 
329 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)330 gx_forward_map_rgb_alpha_color(gx_device * dev, gx_color_value r,
331 			       gx_color_value g, gx_color_value b,
332 			       gx_color_value alpha)
333 {
334     gx_device_forward * const fdev = (gx_device_forward *)dev;
335     gx_device *tdev = fdev->target;
336 
337     return (tdev == 0 ?
338 	    gx_default_map_rgb_alpha_color(dev, r, g, b, alpha) :
339 	    dev_proc(tdev, map_rgb_alpha_color)(tdev, r, g, b, alpha));
340 }
341 
342 gx_device *
gx_forward_get_page_device(gx_device * dev)343 gx_forward_get_page_device(gx_device * dev)
344 {
345     gx_device_forward * const fdev = (gx_device_forward *)dev;
346     gx_device *tdev = fdev->target;
347     gx_device *pdev;
348 
349     if (tdev == 0)
350 	return gx_default_get_page_device(dev);
351     pdev = dev_proc(tdev, get_page_device)(tdev);
352     return pdev;
353 }
354 
355 int
gx_forward_get_band(gx_device * dev,int y,int * band_start)356 gx_forward_get_band(gx_device * dev, int y, int *band_start)
357 {
358     gx_device_forward * const fdev = (gx_device_forward *)dev;
359     gx_device *tdev = fdev->target;
360 
361     return (tdev == 0 ?
362 	    gx_default_get_band(dev, y, band_start) :
363 	    dev_proc(tdev, get_band)(tdev, y, band_start));
364 }
365 
366 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)367 gx_forward_copy_rop(gx_device * dev,
368 		    const byte * sdata, int sourcex, uint sraster,
369 		    gx_bitmap_id id, const gx_color_index * scolors,
370 		    const gx_tile_bitmap * texture,
371 		    const gx_color_index * tcolors,
372 		    int x, int y, int width, int height,
373 		    int phase_x, int phase_y, gs_logical_operation_t lop)
374 {
375     gx_device_forward * const fdev = (gx_device_forward *)dev;
376     gx_device *tdev = fdev->target;
377     dev_proc_copy_rop((*proc)) =
378 	(tdev == 0 ? (tdev = dev, gx_default_copy_rop) :
379 	 dev_proc(tdev, copy_rop));
380 
381     return proc(tdev, sdata, sourcex, sraster, id, scolors,
382 		texture, tcolors, x, y, width, height,
383 		phase_x, phase_y, lop);
384 }
385 
386 int
gx_forward_fill_path(gx_device * dev,const gs_imager_state * pis,gx_path * ppath,const gx_fill_params * params,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath)387 gx_forward_fill_path(gx_device * dev, const gs_imager_state * pis,
388 		     gx_path * ppath, const gx_fill_params * params,
389 		     const gx_drawing_color * pdcolor,
390 		     const gx_clip_path * pcpath)
391 {
392     gx_device_forward * const fdev = (gx_device_forward *)dev;
393     gx_device *tdev = fdev->target;
394     dev_proc_fill_path((*proc)) =
395 	(tdev == 0 ? (tdev = dev, gx_default_fill_path) :
396 	 dev_proc(tdev, fill_path));
397 
398     return proc(tdev, pis, ppath, params, pdcolor, pcpath);
399 }
400 
401 int
gx_forward_stroke_path(gx_device * dev,const gs_imager_state * pis,gx_path * ppath,const gx_stroke_params * params,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath)402 gx_forward_stroke_path(gx_device * dev, const gs_imager_state * pis,
403 		       gx_path * ppath, const gx_stroke_params * params,
404 		       const gx_drawing_color * pdcolor,
405 		       const gx_clip_path * pcpath)
406 {
407     gx_device_forward * const fdev = (gx_device_forward *)dev;
408     gx_device *tdev = fdev->target;
409     dev_proc_stroke_path((*proc)) =
410 	(tdev == 0 ? (tdev = dev, gx_default_stroke_path) :
411 	 dev_proc(tdev, stroke_path));
412 
413     return proc(tdev, pis, ppath, params, pdcolor, pcpath);
414 }
415 
416 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)417 gx_forward_fill_mask(gx_device * dev,
418 		     const byte * data, int dx, int raster, gx_bitmap_id id,
419 		     int x, int y, int w, int h,
420 		     const gx_drawing_color * pdcolor, int depth,
421 		     gs_logical_operation_t lop, const gx_clip_path * pcpath)
422 {
423     gx_device_forward * const fdev = (gx_device_forward *)dev;
424     gx_device *tdev = fdev->target;
425     dev_proc_fill_mask((*proc)) =
426 	(tdev == 0 ? (tdev = dev, gx_default_fill_mask) :
427 	 dev_proc(tdev, fill_mask));
428 
429     return proc(tdev, data, dx, raster, id, x, y, w, h, pdcolor, depth,
430 		lop, pcpath);
431 }
432 
433 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)434 gx_forward_fill_trapezoid(gx_device * dev,
435 			  const gs_fixed_edge * left,
436 			  const gs_fixed_edge * right,
437 			  fixed ybot, fixed ytop, bool swap_axes,
438 			  const gx_drawing_color * pdcolor,
439 			  gs_logical_operation_t lop)
440 {
441     gx_device_forward * const fdev = (gx_device_forward *)dev;
442     gx_device *tdev = fdev->target;
443     dev_proc_fill_trapezoid((*proc)) =
444 	(tdev == 0 ? (tdev = dev, gx_default_fill_trapezoid) :
445 	 dev_proc(tdev, fill_trapezoid));
446 
447     return proc(tdev, left, right, ybot, ytop, swap_axes, pdcolor, lop);
448 }
449 
450 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)451 gx_forward_fill_parallelogram(gx_device * dev,
452 		 fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
453 	       const gx_drawing_color * pdcolor, gs_logical_operation_t lop)
454 {
455     gx_device_forward * const fdev = (gx_device_forward *)dev;
456     gx_device *tdev = fdev->target;
457     dev_proc_fill_parallelogram((*proc)) =
458 	(tdev == 0 ? (tdev = dev, gx_default_fill_parallelogram) :
459 	 dev_proc(tdev, fill_parallelogram));
460 
461     return proc(tdev, px, py, ax, ay, bx, by, pdcolor, lop);
462 }
463 
464 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)465 gx_forward_fill_triangle(gx_device * dev,
466 		 fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
467 	       const gx_drawing_color * pdcolor, gs_logical_operation_t lop)
468 {
469     gx_device_forward * const fdev = (gx_device_forward *)dev;
470     gx_device *tdev = fdev->target;
471     dev_proc_fill_triangle((*proc)) =
472 	(tdev == 0 ? (tdev = dev, gx_default_fill_triangle) :
473 	 dev_proc(tdev, fill_triangle));
474 
475     return proc(tdev, px, py, ax, ay, bx, by, pdcolor, lop);
476 }
477 
478 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)479 gx_forward_draw_thin_line(gx_device * dev,
480 			  fixed fx0, fixed fy0, fixed fx1, fixed fy1,
481 	       const gx_drawing_color * pdcolor, gs_logical_operation_t lop)
482 {
483     gx_device_forward * const fdev = (gx_device_forward *)dev;
484     gx_device *tdev = fdev->target;
485     dev_proc_draw_thin_line((*proc)) =
486 	(tdev == 0 ? (tdev = dev, gx_default_draw_thin_line) :
487 	 dev_proc(tdev, draw_thin_line));
488 
489     return proc(tdev, fx0, fy0, fx1, fy1, pdcolor, lop);
490 }
491 
492 int
gx_forward_begin_image(gx_device * dev,const gs_imager_state * pis,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)493 gx_forward_begin_image(gx_device * dev,
494 		       const gs_imager_state * pis, const gs_image_t * pim,
495 		       gs_image_format_t format, const gs_int_rect * prect,
496 		       const gx_drawing_color * pdcolor,
497 		       const gx_clip_path * pcpath,
498 		       gs_memory_t * memory, gx_image_enum_common_t ** pinfo)
499 {
500     gx_device_forward * const fdev = (gx_device_forward *)dev;
501     gx_device *tdev = fdev->target;
502     dev_proc_begin_image((*proc)) =
503 	(tdev == 0 ? (tdev = dev, gx_default_begin_image) :
504 	 dev_proc(tdev, begin_image));
505 
506     return proc(tdev, pis, pim, format, prect, pdcolor, pcpath,
507 		memory, pinfo);
508 }
509 
510 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)511 gx_forward_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles,
512    int x, int y, int w, int h, gx_color_index color0, gx_color_index color1,
513 				int px, int py)
514 {
515     gx_device_forward * const fdev = (gx_device_forward *)dev;
516     gx_device *tdev = fdev->target;
517     dev_proc_strip_tile_rectangle((*proc)) =
518 	(tdev == 0 ? (tdev = dev, gx_default_strip_tile_rectangle) :
519 	 dev_proc(tdev, strip_tile_rectangle));
520 
521     return proc(tdev, tiles, x, y, w, h, color0, color1, px, py);
522 }
523 
524 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)525 gx_forward_strip_copy_rop(gx_device * dev, const byte * sdata, int sourcex,
526 			  uint sraster, gx_bitmap_id id,
527 			  const gx_color_index * scolors,
528 			  const gx_strip_bitmap * textures,
529 			  const gx_color_index * tcolors,
530 			  int x, int y, int width, int height,
531 			  int phase_x, int phase_y, gs_logical_operation_t lop)
532 {
533     gx_device_forward * const fdev = (gx_device_forward *)dev;
534     gx_device *tdev = fdev->target;
535     dev_proc_strip_copy_rop((*proc)) =
536 	(tdev == 0 ? (tdev = dev, gx_default_strip_copy_rop) :
537 	 dev_proc(tdev, strip_copy_rop));
538 
539     return proc(tdev, sdata, sourcex, sraster, id, scolors,
540 		textures, tcolors, x, y, width, height,
541 		phase_x, phase_y, lop);
542 }
543 
544 void
gx_forward_get_clipping_box(gx_device * dev,gs_fixed_rect * pbox)545 gx_forward_get_clipping_box(gx_device * dev, gs_fixed_rect * pbox)
546 {
547     gx_device_forward * const fdev = (gx_device_forward *)dev;
548     gx_device *tdev = fdev->target;
549 
550     if (tdev == 0)
551 	gx_default_get_clipping_box(dev, pbox);
552     else
553 	dev_proc(tdev, get_clipping_box)(tdev, pbox);
554 }
555 
556 int
gx_forward_begin_typed_image(gx_device * dev,const gs_imager_state * pis,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)557 gx_forward_begin_typed_image(gx_device * dev, const gs_imager_state * pis,
558 			     const gs_matrix * pmat,
559 			     const gs_image_common_t * pim,
560 			     const gs_int_rect * prect,
561 			     const gx_drawing_color * pdcolor,
562 			     const gx_clip_path * pcpath,
563 			     gs_memory_t * memory,
564 			     gx_image_enum_common_t ** pinfo)
565 {
566     gx_device_forward * const fdev = (gx_device_forward *)dev;
567     gx_device *tdev = fdev->target;
568     dev_proc_begin_typed_image((*proc)) =
569 	(tdev == 0 ? (tdev = dev, gx_default_begin_typed_image) :
570 	 dev_proc(tdev, begin_typed_image));
571 
572     return proc(tdev, pis, pmat, pim, prect, pdcolor, pcpath,
573 		memory, pinfo);
574 }
575 
576 int
gx_forward_get_bits_rectangle(gx_device * dev,const gs_int_rect * prect,gs_get_bits_params_t * params,gs_int_rect ** unread)577 gx_forward_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
578 		       gs_get_bits_params_t * params, gs_int_rect ** unread)
579 {
580     gx_device_forward * const fdev = (gx_device_forward *)dev;
581     gx_device *tdev = fdev->target;
582     dev_proc_get_bits_rectangle((*proc)) =
583 	(tdev == 0 ? (tdev = dev, gx_default_get_bits_rectangle) :
584 	 dev_proc(tdev, get_bits_rectangle));
585 
586     return proc(tdev, prect, params, unread);
587 }
588 
589 int
gx_forward_map_color_rgb_alpha(gx_device * dev,gx_color_index color,gx_color_value prgba[4])590 gx_forward_map_color_rgb_alpha(gx_device * dev, gx_color_index color,
591 			       gx_color_value prgba[4])
592 {
593     gx_device_forward * const fdev = (gx_device_forward *)dev;
594     gx_device *tdev = fdev->target;
595 
596     return (tdev == 0 ? gx_default_map_color_rgb_alpha(dev, color, prgba) :
597 	    dev_proc(tdev, map_color_rgb_alpha)(tdev, color, prgba));
598 }
599 
600 int
gx_forward_get_hardware_params(gx_device * dev,gs_param_list * plist)601 gx_forward_get_hardware_params(gx_device * dev, gs_param_list * plist)
602 {
603     gx_device_forward * const fdev = (gx_device_forward *)dev;
604     gx_device *tdev = fdev->target;
605 
606     return (tdev == 0 ? gx_default_get_hardware_params(dev, plist) :
607 	    dev_proc(tdev, get_hardware_params)(tdev, plist));
608 }
609 
610 int
gx_forward_text_begin(gx_device * dev,gs_imager_state * pis,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)611 gx_forward_text_begin(gx_device * dev, gs_imager_state * pis,
612 		      const gs_text_params_t * text, gs_font * font,
613 		      gx_path * path, const gx_device_color * pdcolor,
614 		      const gx_clip_path * pcpath, gs_memory_t * memory,
615 		      gs_text_enum_t ** ppenum)
616 {
617     gx_device_forward * const fdev = (gx_device_forward *)dev;
618     gx_device *tdev = fdev->target;
619     dev_proc_text_begin((*proc)) =
620 	(tdev == 0 ? (tdev = dev, gx_default_text_begin) :
621 	 dev_proc(tdev, text_begin));
622 
623     return proc(tdev, pis, text, font, path, pdcolor, pcpath,
624 		memory, ppenum);
625 }
626 
627 /* Forwarding device color mapping procs. */
628 
629 /*
630  * We need to forward the color mapping to the target device.
631  */
632 static void
fwd_map_gray_cs(gx_device * dev,frac gray,frac out[])633 fwd_map_gray_cs(gx_device * dev, frac gray, frac out[])
634 {
635     gx_device_forward * const fdev = (gx_device_forward *)dev;
636     gx_device * const tdev = fdev->target;
637     const gx_cm_color_map_procs * pprocs;
638 
639     /* Verify that all of the pointers and procs are set */
640     /* If not then use a default routine.  This case should be an error */
641     if (tdev == 0 || dev_proc(tdev, get_color_mapping_procs) == 0 ||
642           (pprocs = dev_proc(tdev, get_color_mapping_procs(tdev))) == 0 ||
643           pprocs->map_gray == 0)
644         gray_cs_to_gray_cm(tdev, gray, out);   /* if all else fails */
645     else
646         pprocs->map_gray(tdev, gray, out);
647 }
648 
649 /*
650  * We need to forward the color mapping to the target device.
651  */
652 static void
fwd_map_rgb_cs(gx_device * dev,const gs_imager_state * pis,frac r,frac g,frac b,frac out[])653 fwd_map_rgb_cs(gx_device * dev, const gs_imager_state *pis,
654 				   frac r, frac g, frac b, frac out[])
655 {
656     gx_device_forward * const fdev = (gx_device_forward *)dev;
657     gx_device * const tdev = fdev->target;
658     const gx_cm_color_map_procs * pprocs;
659 
660     /* Verify that all of the pointers and procs are set */
661     /* If not then use a default routine.  This case should be an error */
662     if (tdev == 0 || dev_proc(tdev, get_color_mapping_procs) == 0 ||
663           (pprocs = dev_proc(tdev, get_color_mapping_procs(tdev))) == 0 ||
664           pprocs->map_rgb == 0)
665         rgb_cs_to_rgb_cm(tdev, pis, r, g, b, out);   /* if all else fails */
666     else
667         pprocs->map_rgb(tdev, pis, r, g, b, out);
668 }
669 
670 /*
671  * We need to forward the color mapping to the target device.
672  */
673 static void
fwd_map_cmyk_cs(gx_device * dev,frac c,frac m,frac y,frac k,frac out[])674 fwd_map_cmyk_cs(gx_device * dev, frac c, frac m, frac y, frac k, frac out[])
675 {
676     gx_device_forward * const fdev = (gx_device_forward *)dev;
677     gx_device * const tdev = fdev->target;
678     const gx_cm_color_map_procs * pprocs;
679 
680     /* Verify that all of the pointers and procs are set */
681     /* If not then use a default routine.  This case should be an error */
682     if (tdev == 0 || dev_proc(tdev, get_color_mapping_procs) == 0 ||
683           (pprocs = dev_proc(tdev, get_color_mapping_procs(tdev))) == 0 ||
684           pprocs->map_cmyk == 0)
685         cmyk_cs_to_cmyk_cm(tdev, c, m, y, k, out);   /* if all else fails */
686     else
687         pprocs->map_cmyk(tdev, c, m, y, k, out);
688 }
689 
690 static const gx_cm_color_map_procs FwdDevice_cm_map_procs = {
691     fwd_map_gray_cs, fwd_map_rgb_cs, fwd_map_cmyk_cs
692 };
693 /*
694  * Instead of returning the target device's mapping procs, we need
695  * to return a list of forwarding wrapper procs for the color mapping
696  * procs.  This is required because the target device mapping procs
697  * may also need the target device pointer (instead of the forwarding
698  * device pointer).
699  */
700 const gx_cm_color_map_procs *
gx_forward_get_color_mapping_procs(const gx_device * dev)701 gx_forward_get_color_mapping_procs(const gx_device * dev)
702 {
703     const gx_device_forward * fdev = (const gx_device_forward *)dev;
704     gx_device * tdev = fdev->target;
705 
706     return (tdev == 0 || dev_proc(tdev, get_color_mapping_procs) == 0
707 	? gx_default_DevGray_get_color_mapping_procs(dev)
708 	: &FwdDevice_cm_map_procs);
709 }
710 
711 int
gx_forward_get_color_comp_index(gx_device * dev,const char * pname,int name_size,int component_type)712 gx_forward_get_color_comp_index(gx_device * dev, const char * pname,
713 					int name_size, int component_type)
714 {
715     const gx_device_forward * fdev = (const gx_device_forward *)dev;
716     gx_device *tdev = fdev->target;
717 
718     return (tdev == 0
719 	? gx_error_get_color_comp_index(dev, pname,
720 				name_size, component_type)
721 	: dev_proc(tdev, get_color_comp_index)(tdev, pname,
722 				name_size, component_type));
723 }
724 
725 gx_color_index
gx_forward_encode_color(gx_device * dev,const gx_color_value colors[])726 gx_forward_encode_color(gx_device * dev, const gx_color_value colors[])
727 {
728     gx_device_forward * const fdev = (gx_device_forward *)dev;
729     gx_device *tdev = fdev->target;
730 
731     return (tdev == 0 ? gx_error_encode_color(dev, colors)
732 		      : dev_proc(tdev, encode_color)(tdev, colors));
733 }
734 
735 int
gx_forward_decode_color(gx_device * dev,gx_color_index cindex,gx_color_value colors[])736 gx_forward_decode_color(gx_device * dev, gx_color_index cindex, gx_color_value colors[])
737 {
738     gx_device_forward * const fdev = (gx_device_forward *)dev;
739     gx_device *tdev = fdev->target;
740 
741     if (tdev == 0)	/* If no device - just clear the color values */
742 	memset(colors, 0, sizeof(gx_color_value[GX_DEVICE_COLOR_MAX_COMPONENTS]));
743     else
744 	dev_proc(tdev, decode_color)(tdev, cindex, colors);
745     return 0;
746 }
747 
748 int
gx_forward_pattern_manage(gx_device * dev,gx_bitmap_id id,gs_pattern1_instance_t * pinst,pattern_manage_t function)749 gx_forward_pattern_manage(gx_device * dev, gx_bitmap_id id,
750 		gs_pattern1_instance_t *pinst, pattern_manage_t function)
751 {
752     gx_device_forward * const fdev = (gx_device_forward *)dev;
753     gx_device *tdev = fdev->target;
754 
755     /* Note that clist sets fdev->target == fdev,
756        so this function is unapplicable to clist. */
757     if (tdev == 0)
758 	return 0;
759     else
760 	return dev_proc(tdev, pattern_manage)(tdev, id, pinst, function);
761 }
762 
763 int
gx_forward_fill_rectangle_hl_color(gx_device * dev,const gs_fixed_rect * rect,const gs_imager_state * pis,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath)764 gx_forward_fill_rectangle_hl_color(gx_device *dev,
765     const gs_fixed_rect *rect,
766     const gs_imager_state *pis, const gx_drawing_color *pdcolor,
767     const gx_clip_path *pcpath)
768 {
769     gx_device_forward * const fdev = (gx_device_forward *)dev;
770     gx_device *tdev = fdev->target;
771 
772     /* Note that clist sets fdev->target == fdev,
773        so this function is unapplicable to clist. */
774     if (tdev == 0)
775 	return_error(gs_error_rangecheck);
776     else
777 	return dev_proc(tdev, fill_rectangle_hl_color)(tdev, rect,
778 						pis, pdcolor, NULL);
779 }
780 
781 int
gx_forward_include_color_space(gx_device * dev,gs_color_space * cspace,const byte * res_name,int name_length)782 gx_forward_include_color_space(gx_device *dev, gs_color_space *cspace,
783 	    const byte *res_name, int name_length)
784 {
785     gx_device_forward * const fdev = (gx_device_forward *)dev;
786     gx_device *tdev = fdev->target;
787 
788     /* Note that clist sets fdev->target == fdev,
789        so this function is unapplicable to clist. */
790     if (tdev == 0)
791 	return 0;
792     else
793 	return dev_proc(tdev, include_color_space)(tdev, cspace, res_name, name_length);
794 }
795 
796 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)797 gx_forward_fill_linear_color_scanline(gx_device *dev, const gs_fill_attributes *fa,
798 	int i, int j, int w,
799 	const frac31 *c, const int32_t *addx, const int32_t *mulx, int32_t divx)
800 {
801     gx_device_forward * const fdev = (gx_device_forward *)dev;
802     gx_device *tdev = fdev->target;
803     dev_proc_fill_linear_color_scanline((*proc)) =
804 	(tdev == 0 ? (tdev = dev, gx_default_fill_linear_color_scanline) :
805 	 dev_proc(tdev, fill_linear_color_scanline));
806     return proc(tdev, fa, i, j, w, c, addx, mulx, divx);
807 }
808 
809 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)810 gx_forward_fill_linear_color_trapezoid(gx_device *dev, const gs_fill_attributes *fa,
811 	const gs_fixed_point *p0, const gs_fixed_point *p1,
812 	const gs_fixed_point *p2, const gs_fixed_point *p3,
813 	const frac31 *c0, const frac31 *c1,
814 	const frac31 *c2, const frac31 *c3)
815 {
816     gx_device_forward * const fdev = (gx_device_forward *)dev;
817     gx_device *tdev = fdev->target;
818     dev_proc_fill_linear_color_trapezoid((*proc)) =
819 	(tdev == 0 ? (tdev = dev, gx_default_fill_linear_color_trapezoid) :
820 	 dev_proc(tdev, fill_linear_color_trapezoid));
821     return proc(tdev, fa, p0, p1, p2, p3, c0, c1, c2, c3);
822 }
823 
824 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)825 gx_forward_fill_linear_color_triangle(gx_device *dev, const gs_fill_attributes *fa,
826 	const gs_fixed_point *p0, const gs_fixed_point *p1,
827 	const gs_fixed_point *p2,
828 	const frac31 *c0, const frac31 *c1, const frac31 *c2)
829 {
830     gx_device_forward * const fdev = (gx_device_forward *)dev;
831     gx_device *tdev = fdev->target;
832     dev_proc_fill_linear_color_triangle((*proc)) =
833 	(tdev == 0 ? (tdev = dev, gx_default_fill_linear_color_triangle) :
834 	 dev_proc(tdev, fill_linear_color_triangle));
835     return proc(tdev, fa, p0, p1, p2, c0, c1, c2);
836 }
837 
838 int
gx_forward_update_spot_equivalent_colors(gx_device * dev,const gs_state * pgs)839 gx_forward_update_spot_equivalent_colors(gx_device *dev, const gs_state * pgs)
840 {
841     gx_device_forward * const fdev = (gx_device_forward *)dev;
842     gx_device *tdev = fdev->target;
843     int code = 0;
844 
845     if (tdev != NULL)
846 	code = dev_proc(tdev, update_spot_equivalent_colors)(tdev, pgs);
847     return code;
848 }
849 
850 
851 /* ---------------- The null device(s) ---------------- */
852 
853 private dev_proc_get_initial_matrix(gx_forward_upright_get_initial_matrix);
854 private dev_proc_fill_rectangle(null_fill_rectangle);
855 private dev_proc_copy_mono(null_copy_mono);
856 private dev_proc_copy_color(null_copy_color);
857 private dev_proc_put_params(null_put_params);
858 private dev_proc_copy_alpha(null_copy_alpha);
859 private dev_proc_copy_rop(null_copy_rop);
860 private dev_proc_fill_path(null_fill_path);
861 private dev_proc_stroke_path(null_stroke_path);
862 private dev_proc_fill_trapezoid(null_fill_trapezoid);
863 private dev_proc_fill_parallelogram(null_fill_parallelogram);
864 private dev_proc_fill_triangle(null_fill_triangle);
865 private dev_proc_draw_thin_line(null_draw_thin_line);
866 private dev_proc_decode_color(null_decode_color);
867 /* We would like to have null implementations of begin/data/end image, */
868 /* but we can't do this, because image_data must keep track of the */
869 /* Y position so it can return 1 when done. */
870 private dev_proc_strip_copy_rop(null_strip_copy_rop);
871 
872 #define null_procs(get_initial_matrix, get_page_device) {\
873 	gx_default_open_device,\
874 	get_initial_matrix, /* differs */\
875 	gx_default_sync_output,\
876 	gx_default_output_page,\
877 	gx_default_close_device,\
878 	gx_forward_map_rgb_color,\
879 	gx_forward_map_color_rgb,\
880 	null_fill_rectangle,\
881 	gx_default_tile_rectangle,\
882 	null_copy_mono,\
883 	null_copy_color,\
884 	gx_default_draw_line,\
885 	gx_default_get_bits,\
886 	gx_forward_get_params,\
887 	null_put_params,\
888 	gx_forward_map_cmyk_color,\
889 	gx_forward_get_xfont_procs,\
890 	gx_forward_get_xfont_device,\
891 	gx_forward_map_rgb_alpha_color,\
892 	get_page_device,	/* differs */\
893 	gx_default_get_alpha_bits,\
894 	null_copy_alpha,\
895 	gx_forward_get_band,\
896 	null_copy_rop,\
897 	null_fill_path,\
898 	null_stroke_path,\
899 	gx_default_fill_mask,\
900 	null_fill_trapezoid,\
901 	null_fill_parallelogram,\
902 	null_fill_triangle,\
903 	null_draw_thin_line,\
904 	gx_default_begin_image,\
905 	gx_default_image_data,\
906 	gx_default_end_image,\
907 	gx_default_strip_tile_rectangle,\
908 	null_strip_copy_rop,\
909 	gx_default_get_clipping_box,\
910 	gx_default_begin_typed_image,\
911 	gx_default_get_bits_rectangle,\
912 	gx_forward_map_color_rgb_alpha,\
913 	gx_non_imaging_create_compositor,\
914 	gx_forward_get_hardware_params,\
915 	gx_default_text_begin,\
916 	gx_default_finish_copydevice,\
917 	NULL,				/* begin_transparency_group */\
918 	NULL,				/* end_transparency_group */\
919 	NULL,				/* begin_transparency_mask */\
920 	NULL,				/* end_transparency_mask */\
921 	NULL,				/* discard_transparency_layer */\
922 	gx_default_DevGray_get_color_mapping_procs,	/* get_color_mapping_procs */\
923 	gx_default_DevGray_get_color_comp_index,/* get_color_comp_index */\
924 	gx_default_gray_fast_encode,		/* encode_color */\
925 	null_decode_color,		/* decode_color */\
926 	gx_default_pattern_manage,\
927 	gx_default_fill_rectangle_hl_color,\
928 	gx_default_include_color_space\
929 }
930 
931 const gx_device_null gs_null_device = {
932     std_device_std_body_type_open(gx_device_null, 0, "null", &st_device_null,
933 				  0, 0, 72, 72),
934     null_procs(gx_forward_upright_get_initial_matrix, /* upright matrix */
935                gx_default_get_page_device     /* not a page device */ ),
936     0				/* target */
937 };
938 
939 const gx_device_null gs_nullpage_device = {
940 std_device_std_body_type_open(gx_device_null, 0, "nullpage", &st_device_null,
941 			      72 /*nominal */ , 72 /*nominal */ , 72, 72),
942     null_procs( gx_forward_get_initial_matrix, /* default matrix */
943                 gx_page_device_get_page_device /* a page device */ ),
944     0				/* target */
945 };
946 
947 private void
gx_forward_upright_get_initial_matrix(gx_device * dev,gs_matrix * pmat)948 gx_forward_upright_get_initial_matrix(gx_device * dev, gs_matrix * pmat)
949 {
950     gx_device_forward * const fdev = (gx_device_forward *)dev;
951     gx_device *tdev = fdev->target;
952 
953     if (tdev == 0)
954 	gx_upright_get_initial_matrix(dev, pmat);
955     else
956 	dev_proc(tdev, get_initial_matrix)(tdev, pmat);
957 }
958 
959 private int
null_decode_color(gx_device * dev,gx_color_index cindex,gx_color_value colors[])960 null_decode_color(gx_device * dev, gx_color_index cindex, gx_color_value colors[])
961 {
962     colors[0] = (cindex & 1) ?  gx_max_color_value : 0;
963     return 0;
964 }
965 
966 private int
null_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)967 null_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
968 		    gx_color_index color)
969 {
970     return 0;
971 }
972 private 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)973 null_copy_mono(gx_device * dev, const byte * data, int dx, int raster,
974 	       gx_bitmap_id id, int x, int y, int w, int h,
975 	       gx_color_index zero, gx_color_index one)
976 {
977     return 0;
978 }
979 private 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)980 null_copy_color(gx_device * dev, const byte * data,
981 		int data_x, int raster, gx_bitmap_id id,
982 		int x, int y, int width, int height)
983 {
984     return 0;
985 }
986 private int
null_put_params(gx_device * dev,gs_param_list * plist)987 null_put_params(gx_device * dev, gs_param_list * plist)
988 {
989     /*
990      * If this is not a page device, we must defeat attempts to reset
991      * the size; otherwise this is equivalent to gx_forward_put_params.
992      */
993     int code = gx_forward_put_params(dev, plist);
994 
995     if (code < 0 || dev_proc(dev, get_page_device)(dev) == dev)
996 	return code;
997     dev->width = dev->height = 0;
998     return code;
999 }
1000 private 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)1001 null_copy_alpha(gx_device * dev, const byte * data, int data_x, int raster,
1002 		gx_bitmap_id id, int x, int y, int width, int height,
1003 		gx_color_index color, int depth)
1004 {
1005     return 0;
1006 }
1007 private 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)1008 null_copy_rop(gx_device * dev,
1009 	      const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
1010 	      const gx_color_index * scolors,
1011 	      const gx_tile_bitmap * texture, const gx_color_index * tcolors,
1012 	      int x, int y, int width, int height,
1013 	      int phase_x, int phase_y, gs_logical_operation_t lop)
1014 {
1015     return 0;
1016 }
1017 private int
null_fill_path(gx_device * dev,const gs_imager_state * pis,gx_path * ppath,const gx_fill_params * params,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath)1018 null_fill_path(gx_device * dev, const gs_imager_state * pis,
1019 	       gx_path * ppath, const gx_fill_params * params,
1020 	       const gx_drawing_color * pdcolor, const gx_clip_path * pcpath)
1021 {
1022     return 0;
1023 }
1024 private int
null_stroke_path(gx_device * dev,const gs_imager_state * pis,gx_path * ppath,const gx_stroke_params * params,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath)1025 null_stroke_path(gx_device * dev, const gs_imager_state * pis,
1026 		 gx_path * ppath, const gx_stroke_params * params,
1027 		 const gx_drawing_color * pdcolor, const gx_clip_path * pcpath)
1028 {
1029     return 0;
1030 }
1031 private 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)1032 null_fill_trapezoid(gx_device * dev,
1033 		    const gs_fixed_edge * left, const gs_fixed_edge * right,
1034 		    fixed ybot, fixed ytop, bool swap_axes,
1035 		    const gx_drawing_color * pdcolor,
1036 		    gs_logical_operation_t lop)
1037 {
1038     return 0;
1039 }
1040 private 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)1041 null_fill_parallelogram(gx_device * dev, fixed px, fixed py,
1042 			fixed ax, fixed ay, fixed bx, fixed by,
1043 			const gx_drawing_color * pdcolor,
1044 			gs_logical_operation_t lop)
1045 {
1046     return 0;
1047 }
1048 private 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)1049 null_fill_triangle(gx_device * dev,
1050 		   fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
1051 		   const gx_drawing_color * pdcolor,
1052 		   gs_logical_operation_t lop)
1053 {
1054     return 0;
1055 }
1056 private 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)1057 null_draw_thin_line(gx_device * dev,
1058 		    fixed fx0, fixed fy0, fixed fx1, fixed fy1,
1059 		    const gx_drawing_color * pdcolor,
1060 		    gs_logical_operation_t lop)
1061 {
1062     return 0;
1063 }
1064 private 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)1065 null_strip_copy_rop(gx_device * dev, const byte * sdata, int sourcex,
1066 		    uint sraster, gx_bitmap_id id,
1067 		    const gx_color_index * scolors,
1068 		    const gx_strip_bitmap * textures,
1069 		    const gx_color_index * tcolors,
1070 		    int x, int y, int width, int height,
1071 		    int phase_x, int phase_y, gs_logical_operation_t lop)
1072 {
1073     return 0;
1074 }
1075