xref: /plan9/sys/src/cmd/gs/src/gslib.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1995, 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: gslib.c,v 1.15 2004/09/16 08:03:56 igor Exp $ */
18 /* Test program for Ghostscript library */
19 /* Capture stdin/out/err before gsio.h redefines them. */
20 #include "stdio_.h"
21 static FILE *real_stdin, *real_stdout, *real_stderr;
22 static void
get_real(void)23 get_real(void)
24 {
25     real_stdin = stdin, real_stdout = stdout, real_stderr = stderr;
26 }
27 #include "math_.h"
28 #include "string_.h"
29 #include "gx.h"
30 #include "gp.h"
31 #include "gsalloc.h"
32 #include "gscdefs.h"
33 #include "gserrors.h"
34 #include "gslib.h"
35 #include "gsmatrix.h"
36 #include "gsstate.h"
37 #include "gscspace.h"
38 #include "gscolor2.h"
39 #include "gscoord.h"
40 #include "gscie.h"
41 #include "gscrd.h"
42 #include "gsiparm3.h"
43 #include "gsiparm4.h"
44 #include "gsparam.h"
45 #include "gspaint.h"
46 #include "gspath.h"
47 #include "gspath2.h"
48 #include "gsrop.h"
49 #include "gsstruct.h"
50 #include "gsutil.h"
51 #include "gxalloc.h"
52 #include "gxdcolor.h"		/* for gx_device_white/black */
53 #include "gxdevice.h"
54 #include "gxht.h"		/* for gs_halftone */
55 #include "gdevbbox.h"
56 #include "gdevcmap.h"
57 #include "gshtx.h"
58 
59 /* Define whether we are processing captured data. */
60 /*#define CAPTURE */
61 
62 /* Test programs */
63 private int test1(gs_state *, gs_memory_t *);	/* kaleidoscope */
64 private int test2(gs_state *, gs_memory_t *);	/* pattern fill */
65 private int test3(gs_state *, gs_memory_t *);	/* RasterOp */
66 private int test4(gs_state *, gs_memory_t *);	/* set resolution */
67 private int test5(gs_state *, gs_memory_t *);	/* images */
68 private int test6(gs_state *, gs_memory_t *);	/* CIE API, snapping */
69 private int test7(gs_state *, gs_memory_t *);	/* non-monot HT */
70 private int test8(gs_state *, gs_memory_t *);	/* transp patterns */
71 
72 #ifdef CAPTURE
73 #include "k/capture.c"
74 private int test10(gs_state *, gs_memory_t *);	/* captured data */
75 
76 #endif
77 private int (*tests[]) (gs_state *, gs_memory_t *) =
78 {
79     test1, test2, test3, test4, test5,
80 	test6, test7, test8, 0
81 #ifdef CAPTURE
82 	test10
83 #endif
84 };
85 
86 /* Include the extern for the device list. */
87 extern_gs_lib_device_list();
88 
89 /* Forward references */
90 private float odsf(floatp, floatp);
91 
92 
93 int
main(int argc,const char * argv[])94 main(int argc, const char *argv[])
95 {
96     char achar;
97     gs_ref_memory_t *imem;
98 
99 #define mem ((gs_memory_t *)imem)
100     gs_state *pgs;
101     const gx_device *const *list;
102     gx_device *dev;
103     gx_device_bbox *bbdev;
104     int code;
105 
106     gp_init();
107     get_real();
108     gs_stdin = real_stdin;
109     gs_stdout = real_stdout;
110     gs_stderr = real_stderr;
111     gs_lib_init(stdout);
112     if (argc < 2 || (achar = argv[1][0]) < '1' ||
113 	achar > '0' + countof(tests)
114 	) {
115 	lprintf1("Usage: gslib 1..%c\n", '0' + countof(tests));
116 	exit(1);
117     }
118     gs_debug['@'] = 1;
119     gs_debug['?'] = 1;
120 /*gs_debug['B'] = 1; *//****** PATCH ******/
121 /*gs_debug['L'] = 1; *//****** PATCH ******/
122     imem = ialloc_alloc_state(&gs_memory_default, 20000);
123     imem->space = 0;
124     /*
125      * gs_iodev_init must be called after the rest of the inits, for
126      * obscure reasons that really should be documented!
127      */
128     gs_iodev_init(mem);
129 /****** WRONG ******/
130     gs_lib_device_list(&list, NULL);
131     gs_copydevice(&dev, list[0], mem);
132     check_device_separable(dev);
133     gx_device_fill_in_procs(dev);
134     bbdev =
135 	gs_alloc_struct_immovable(mem, gx_device_bbox, &st_device_bbox,
136 				  "bbox");
137     gx_device_bbox_init(bbdev, dev, mem);
138     /* Print out the device name just to test the gsparam.c API. */
139     {
140 	gs_c_param_list list;
141 	gs_param_string nstr;
142 
143 	gs_c_param_list_write(&list, mem);
144 	code = gs_getdeviceparams(dev, (gs_param_list *) & list);
145 	if (code < 0) {
146 	    lprintf1("getdeviceparams failed! code = %d\n", code);
147 	    exit(1);
148 	}
149 	gs_c_param_list_read(&list);
150 	code = param_read_string((gs_param_list *) & list, "Name", &nstr);
151 	if (code < 0) {
152 	    lprintf1("reading Name failed! code = %d\n", code);
153 	    exit(1);
154 	}
155 	dputs("Device name = ");
156 	debug_print_string(nstr.data, nstr.size);
157 	dputs("\n");
158 	gs_c_param_list_release(&list);
159     }
160     /*
161      * If this is a device that takes an OutputFile, set the OutputFile
162      * to "-" in the copy.
163      */
164     {
165 	gs_c_param_list list;
166 	gs_param_string nstr;
167 
168 	gs_c_param_list_write(&list, mem);
169 	param_string_from_string(nstr, "-");
170 	code = param_write_string((gs_param_list *)&list, "OutputFile", &nstr);
171 	if (code < 0) {
172 	    lprintf1("writing OutputFile failed! code = %d\n", code);
173 	    exit(1);
174 	}
175 	gs_c_param_list_read(&list);
176 	code = gs_putdeviceparams(dev, (gs_param_list *)&list);
177 	gs_c_param_list_release(&list);
178 	if (code < 0 && code != gs_error_undefined) {
179 	    lprintf1("putdeviceparams failed! code = %d\n", code);
180 	    exit(1);
181 	}
182     }
183     dev = (gx_device *) bbdev;
184     pgs = gs_state_alloc(mem);
185     gs_setdevice_no_erase(pgs, dev);	/* can't erase yet */
186     {
187 	gs_point dpi;
188 	gs_screen_halftone ht;
189 
190 	gs_dtransform(pgs, 72.0, 72.0, &dpi);
191 	ht.frequency = min(fabs(dpi.x), fabs(dpi.y)) / 16.001;
192 	ht.angle = 0;
193 	ht.spot_function = odsf;
194 	gs_setscreen(pgs, &ht);
195     }
196     /* gsave and grestore (among other places) assume that */
197     /* there are at least 2 gstates on the graphics stack. */
198     /* Ensure that now. */
199     gs_gsave(pgs);
200     gs_erasepage(pgs);
201 
202     code = (*tests[achar - '1']) (pgs, mem);
203     gs_output_page(pgs, 1, 1);
204     {
205 	gs_rect bbox;
206 
207 	gx_device_bbox_bbox(bbdev, &bbox);
208 	dprintf4("Bounding box: [%g %g %g %g]\n",
209 		 bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y);
210     }
211     if (code)
212 	dprintf1("**** Test returned code = %d.\n", code);
213     dputs("Done.  Press <enter> to exit.");
214     fgetc(gs_stdin);
215     gs_lib_finit(0, 0);
216     return 0;
217 #undef mem
218 }
219 /* Ordered dither spot function */
220 private float
odsf(floatp x,floatp y)221 odsf(floatp x, floatp y)
222 {
223     static const byte dither[256] =
224     {
225 	0x0E, 0x8E, 0x2E, 0xAE, 0x06, 0x86, 0x26, 0xA6, 0x0C, 0x8C, 0x2C, 0xAC, 0x04, 0x84, 0x24, 0xA4,
226 	0xCE, 0x4E, 0xEE, 0x6E, 0xC6, 0x46, 0xE6, 0x66, 0xCC, 0x4C, 0xEC, 0x6C, 0xC4, 0x44, 0xE4, 0x64,
227 	0x3E, 0xBE, 0x1E, 0x9E, 0x36, 0xB6, 0x16, 0x96, 0x3C, 0xBC, 0x1C, 0x9C, 0x34, 0xB4, 0x14, 0x94,
228 	0xFE, 0x7E, 0xDE, 0x5E, 0xF6, 0x76, 0xD6, 0x56, 0xFC, 0x7C, 0xDC, 0x5C, 0xF4, 0x74, 0xD4, 0x54,
229 	0x01, 0x81, 0x21, 0xA1, 0x09, 0x89, 0x29, 0xA9, 0x03, 0x83, 0x23, 0xA3, 0x0B, 0x8B, 0x2B, 0xAB,
230 	0xC1, 0x41, 0xE1, 0x61, 0xC9, 0x49, 0xE9, 0x69, 0xC3, 0x43, 0xE3, 0x63, 0xCB, 0x4B, 0xEB, 0x6B,
231 	0x31, 0xB1, 0x11, 0x91, 0x39, 0xB9, 0x19, 0x99, 0x33, 0xB3, 0x13, 0x93, 0x3B, 0xBB, 0x1B, 0x9B,
232 	0xF1, 0x71, 0xD1, 0x51, 0xF9, 0x79, 0xD9, 0x59, 0xF3, 0x73, 0xD3, 0x53, 0xFB, 0x7B, 0xDB, 0x5B,
233 	0x0D, 0x8D, 0x2D, 0xAD, 0x05, 0x85, 0x25, 0xA5, 0x0F, 0x8F, 0x2F, 0xAF, 0x07, 0x87, 0x27, 0xA7,
234 	0xCD, 0x4D, 0xED, 0x6D, 0xC5, 0x45, 0xE5, 0x65, 0xCF, 0x4F, 0xEF, 0x6F, 0xC7, 0x47, 0xE7, 0x67,
235 	0x3D, 0xBD, 0x1D, 0x9D, 0x35, 0xB5, 0x15, 0x95, 0x3F, 0xBF, 0x1F, 0x9F, 0x37, 0xB7, 0x17, 0x97,
236 	0xFD, 0x7D, 0xDD, 0x5D, 0xF5, 0x75, 0xD5, 0x55, 0xFF, 0x7F, 0xDF, 0x5F, 0xF7, 0x77, 0xD7, 0x57,
237 	0x02, 0x82, 0x22, 0xA2, 0x0A, 0x8A, 0x2A, 0xAA, 0x00, 0x80, 0x20, 0xA0, 0x08, 0x88, 0x28, 0xA8,
238 	0xC2, 0x42, 0xE2, 0x62, 0xCA, 0x4A, 0xEA, 0x6A, 0xC0, 0x40, 0xE0, 0x60, 0xC8, 0x48, 0xE8, 0x68,
239 	0x32, 0xB2, 0x12, 0x92, 0x3A, 0xBA, 0x1A, 0x9A, 0x30, 0xB0, 0x10, 0x90, 0x38, 0xB8, 0x18, 0x98,
240 	0xF2, 0x72, 0xD2, 0x52, 0xFA, 0x7A, 0xDA, 0x5A, 0xF0, 0x70, 0xD0, 0x50, 0xF8, 0x78, 0xD8, 0x58
241     };
242     int i = (int)((x + 1) * 7.9999);
243     int j = (int)((y + 1) * 7.9999);
244 
245     return dither[16 * i + j] / 256.0;
246 }
247 
248 /* Fill a rectangle. */
249 private int
fill_rect1(gs_state * pgs,floatp x,floatp y,floatp w,floatp h)250 fill_rect1(gs_state * pgs, floatp x, floatp y, floatp w, floatp h)
251 {
252     gs_rect r;
253 
254     r.q.x = (r.p.x = x) + w;
255     r.q.y = (r.p.y = y) + h;
256     return gs_rectfill(pgs, &r, 1);
257 }
258 
259 /* Stubs for GC */
260 const gs_ptr_procs_t ptr_struct_procs =
261 {NULL, NULL, NULL};
262 const gs_ptr_procs_t ptr_string_procs =
263 {NULL, NULL, NULL};
264 const gs_ptr_procs_t ptr_const_string_procs =
265 {NULL, NULL, NULL};
266 void *				/* obj_header_t * */
gs_reloc_struct_ptr(const void * obj,gc_state_t * gcst)267 gs_reloc_struct_ptr(const void * /* obj_header_t * */ obj, gc_state_t * gcst)
268 {
269     return (void *)obj;
270 }
271 void
gs_reloc_string(gs_string * sptr,gc_state_t * gcst)272 gs_reloc_string(gs_string * sptr, gc_state_t * gcst)
273 {
274 }
275 void
gs_reloc_const_string(gs_const_string * sptr,gc_state_t * gcst)276 gs_reloc_const_string(gs_const_string * sptr, gc_state_t * gcst)
277 {
278 }
279 
280 /* Other stubs */
281 void
gs_to_exit(const gs_memory_t * mem,int exit_status)282 gs_to_exit(const gs_memory_t *mem, int exit_status)
283 {
284     gs_lib_finit(mem, exit_status, 0);
285 }
286 
287 void
gs_abort(const gs_memory_t * mem)288 gs_abort(const gs_memory_t *mem)
289 {
290     gs_to_exit(mem, 1); /* cleanup */
291     gp_do_exit(1); /* system independent exit() */
292 }
293 
294 
295 /* Return the number with the magnitude of x and the sign of y. */
296 /* This is a BSD addition to libm; not all compilers have it. */
297 private double
gs_copysign(floatp x,floatp y)298 gs_copysign(floatp x, floatp y)
299 {
300    return ( y >= 0  ? fabs(x) : -fabs(x) );
301 }
302 
303 
304 /* ---------------- Test program 1 ---------------- */
305 /* Draw a colored kaleidoscope. */
306 
307 /* Random number generator */
308 private long rand_state = 1;
309 private long
rand(void)310 rand(void)
311 {
312 #define A 16807
313 #define M 0x7fffffff
314 #define Q 127773		/* M / A */
315 #define R 2836			/* M % A */
316     rand_state = A * (rand_state % Q) - R * (rand_state / Q);
317     /* Note that rand_state cannot be 0 here. */
318     if (rand_state <= 0)
319 	rand_state += M;
320 #undef A
321 #undef M
322 #undef Q
323 #undef R
324     return rand_state;
325 }
326 private int
test1(gs_state * pgs,gs_memory_t * mem)327 test1(gs_state * pgs, gs_memory_t * mem)
328 {
329     int n;
330 
331     gs_scale(pgs, 72.0, 72.0);
332     gs_translate(pgs, 4.25, 5.5);
333     gs_scale(pgs, 4.0, 4.0);
334     gs_newpath(pgs);
335     for (n = 200; --n >= 0;) {
336 	int j;
337 
338 #define rf() (rand() / (1.0 * 0x10000 * 0x8000))
339 	double r = rf(), g = rf(), b = rf();
340 	double x0 = rf(), y0 = rf(), x1 = rf(), y1 = rf(), x2 = rf(), y2 = rf();
341 
342 	gs_setrgbcolor(pgs, r, g, b);
343 	for (j = 0; j < 6; j++) {
344 	    gs_gsave(pgs);
345 	    gs_rotate(pgs, 60.0 * j);
346 	    gs_moveto(pgs, x0, y0);
347 	    gs_lineto(pgs, x1, y1);
348 	    gs_lineto(pgs, x2, y2);
349 	    gs_fill(pgs);
350 	    gs_grestore(pgs);
351 	}
352     }
353 #undef mem
354     return 0;
355 }
356 
357 /* ---------------- Test program 2 ---------------- */
358 /* Fill an area with a pattern. */
359 
360 private int
test2(gs_state * pgs,gs_memory_t * mem)361 test2(gs_state * pgs, gs_memory_t * mem)
362 {
363     gs_client_color cc;
364     gx_tile_bitmap tile;
365     /*const */ byte tpdata[] =
366     {
367     /* Define a pattern that looks like this:
368        ..xxxx
369        .....x
370        .....x
371        ..xxxx
372        .x....
373        x.....
374      */
375 	0x3c, 0, 0, 0, 0x04, 0, 0, 0, 0x04, 0, 0, 0, 0x3c, 0, 0, 0,
376 	0x40, 0, 0, 0, 0x80, 0, 0, 0
377     };
378 
379     gs_newpath(pgs);
380     gs_moveto(pgs, 100.0, 300.0);
381     gs_lineto(pgs, 500.0, 500.0);
382     gs_lineto(pgs, 200.0, 100.0);
383     gs_lineto(pgs, 300.0, 500.0);
384     gs_lineto(pgs, 500.0, 200.0);
385     gs_closepath(pgs);
386     gs_setrgbcolor(pgs, 0.0, 0.0, 0.0);
387     gs_gsave(pgs);
388     gs_fill(pgs);
389     gs_grestore(pgs);
390     tile.data = tpdata;
391     tile.raster = 4;
392     tile.size.x = tile.rep_width = 6;
393     tile.size.y = tile.rep_height = 6;
394     tile.id = gx_no_bitmap_id;
395     gs_makebitmappattern(&cc, &tile, true, pgs, NULL);
396     /* Note: color space is DeviceRGB */
397     cc.paint.values[0] = 0.0;
398     cc.paint.values[1] = 1.0;
399     cc.paint.values[2] = 1.0;
400     gs_setpattern(pgs, &cc);
401     gs_eofill(pgs);
402     gs_makebitmappattern(&cc, &tile, false, pgs, NULL);
403     gs_setcolor(pgs, &cc);
404     gs_moveto(pgs, 50.0, 50.0);
405     gs_lineto(pgs, 300.0, 50.0);
406     gs_lineto(pgs, 50.0, 300.0);
407     gs_closepath(pgs);
408     gs_setrgbcolor(pgs, 1.0, 0.0, 0.0);
409     gs_gsave(pgs);
410     gs_fill(pgs);
411     gs_grestore(pgs);
412     gs_setpattern(pgs, &cc);
413     gs_eofill(pgs);
414     return 0;
415 }
416 
417 /* ---------------- Test program 3 ---------------- */
418 /* Exercise RasterOp a little. */
419 /* Currently, this only works with monobit devices. */
420 
421 private int
test3(gs_state * pgs,gs_memory_t * mem)422 test3(gs_state * pgs, gs_memory_t * mem)
423 {
424     gx_device *dev = gs_currentdevice(pgs);
425     gx_color_index black = gx_device_black(dev);
426     gx_color_index white = gx_device_white(dev);
427     gx_color_index black2[2];
428     gx_color_index black_white[2];
429     gx_color_index white_black[2];
430     long pattern[max(align_bitmap_mod / sizeof(long), 1) * 4];
431 
432 #define pbytes ((byte *)pattern)
433     gx_tile_bitmap tile;
434 
435     black2[0] = black2[1] = black;
436     black_white[0] = white_black[1] = black;
437     black_white[1] = white_black[0] = white;
438     pbytes[0] = 0xf0;
439     pbytes[align_bitmap_mod] = 0x90;
440     pbytes[align_bitmap_mod * 2] = 0x90;
441     pbytes[align_bitmap_mod * 3] = 0xf0;
442     tile.data = pbytes;
443     tile.raster = align_bitmap_mod;
444     tile.size.x = tile.size.y = 4;
445     tile.id = gs_next_ids(1);
446     tile.rep_width = tile.rep_height = 4;
447     (*dev_proc(dev, copy_rop))
448 	(dev, NULL, 0, 0, gx_no_bitmap_id, black2,
449 	 &tile, white_black, 100, 100, 150, 150, 0, 0, rop3_T);
450     (*dev_proc(dev, copy_rop))
451 	(dev, NULL, 0, 0, gx_no_bitmap_id, black2,
452 	 NULL, NULL, 120, 120, 110, 110, 0, 0, ~rop3_S & rop3_1);
453     (*dev_proc(dev, copy_rop))
454 	(dev, NULL, 0, 0, gx_no_bitmap_id, black2,
455 	 &tile, white_black, 110, 110, 130, 130, 0, 0, rop3_T ^ rop3_D);
456 #undef pbytes
457     return 0;
458 }
459 
460 /* ---------------- Test program 4 ---------------- */
461 /* Set the resolution dynamically. */
462 
463 private int
test4(gs_state * pgs,gs_memory_t * mem)464 test4(gs_state * pgs, gs_memory_t * mem)
465 {
466     gs_c_param_list list;
467     float resv[2];
468     gs_param_float_array ares;
469     int code;
470     gx_device *dev = gs_currentdevice(pgs);
471 
472     gs_c_param_list_write(&list, mem);
473     resv[0] = resv[1] = 100;
474     ares.data = resv;
475     ares.size = 2;
476     ares.persistent = true;
477     code = param_write_float_array((gs_param_list *) & list,
478 				   "HWResolution", &ares);
479     if (code < 0) {
480 	lprintf1("Writing HWResolution failed: %d\n", code);
481 	exit(1);
482     }
483     gs_c_param_list_read(&list);
484     code = gs_putdeviceparams(dev, (gs_param_list *) & list);
485     gs_c_param_list_release(&list);
486     if (code < 0) {
487 	lprintf1("Setting HWResolution failed: %d\n", code);
488 	exit(1);
489     }
490     gs_initmatrix(pgs);
491     gs_initclip(pgs);
492     if (code == 1) {
493 	code = (*dev_proc(dev, open_device)) (dev);
494 	if (code < 0) {
495 	    lprintf1("Reopening device failed: %d\n", code);
496 	    exit(1);
497 	}
498     }
499     gs_moveto(pgs, 0.0, 72.0);
500     gs_rlineto(pgs, 72.0, 0.0);
501     gs_rlineto(pgs, 0.0, 72.0);
502     gs_closepath(pgs);
503     gs_stroke(pgs);
504     return 0;
505 }
506 
507 /* ---------------- Test program 5 ---------------- */
508 /* Test masked (and non-masked) images. */
509 
510 private int
test5(gs_state * pgs,gs_memory_t * mem)511 test5(gs_state * pgs, gs_memory_t * mem)
512 {
513     gx_device *dev = gs_currentdevice(pgs);
514     gx_image_enum_common_t *info;
515     gx_image_plane_t planes[5];
516     gx_drawing_color dcolor;
517     int code;
518     static const byte data3[] =
519     {
520 	0x00, 0x44, 0x88, 0xcc,
521 	0x44, 0x88, 0xcc, 0x00,
522 	0x88, 0xcc, 0x00, 0x44,
523 	0xcc, 0x00, 0x44, 0x88
524     };
525     gs_color_space gray_cs;
526 
527     gs_cspace_init_DeviceGray(&gray_cs);
528 
529     /*
530      * Neither ImageType 3 nor 4 needs a current color,
531      * but some intermediate code assumes it's valid.
532      */
533     set_nonclient_dev_color(&dcolor, 0);
534 
535     /* Scale everything up, and fill the background. */
536     {
537 	gs_matrix mat;
538 
539 	gs_currentmatrix(pgs, &mat);
540 	mat.xx = gs_copysign(98.6, mat.xx);
541 	mat.yy = gs_copysign(98.6, mat.yy);
542 	mat.tx = floor(mat.tx) + 0.499;
543 	mat.ty = floor(mat.ty) + 0.499;
544 	gs_setmatrix(pgs, &mat);
545     }
546     gs_setrgbcolor(pgs, 1.0, 0.9, 0.9);
547     fill_rect1(pgs, 0.25, 0.25, 4.0, 6.0);
548     gs_setrgbcolor(pgs, 0.5, 1.0, 0.5);
549 
550 #if 0
551     /* Make things a little more interesting.... */
552     gs_translate(pgs, 1.0, 1.0);
553     gs_rotate(pgs, 10.0);
554     gs_scale(pgs, 1.3, 0.9);
555 #endif
556 
557 #define do_image(image, idata)\
558   BEGIN\
559   code = gx_device_begin_typed_image(dev, (gs_imager_state *)pgs, NULL,\
560      (gs_image_common_t *)&image, NULL, &dcolor, NULL, mem, &info);\
561   /****** TEST code >= 0 ******/\
562   planes[0].data = idata;\
563   planes[0].data_x = 0;\
564   planes[0].raster = (image.Height * image.BitsPerComponent + 7) >> 3;\
565   code = gx_image_plane_data(info, planes, image.Height);\
566   /****** TEST code == 1 ******/\
567   code = gx_image_end(info, true);\
568   /****** TEST code >= 0 ******/\
569   END
570 
571 #define W 4
572 #define H 4
573 
574     /* Test an unmasked image. */
575     gs_gsave(pgs);
576     {
577 	gs_image1_t image1;
578 	void *info1;
579         gs_color_space cs;
580 
581         gs_cspace_init_DeviceGray(&cs);
582 	gs_image_t_init(&image1, &cs);
583 	/* image */
584 	image1.ImageMatrix.xx = W;
585 	image1.ImageMatrix.yy = -H;
586 	image1.ImageMatrix.ty = H;
587 	/* data_image */
588 	image1.Width = W;
589 	image1.Height = H;
590 	image1.BitsPerComponent = 8;
591 
592 	gs_translate(pgs, 0.5, 4.0);
593 	code = gx_device_begin_image(dev, (gs_imager_state *) pgs,
594 				     &image1, gs_image_format_chunky,
595 				     NULL, &dcolor, NULL, mem, &info1);
596 /****** TEST code >= 0 ******/
597 	planes[0].data = data3;
598 	planes[0].data_x = 0;
599 	planes[0].raster =
600 	    (image1.Height * image1.BitsPerComponent + 7) >> 3;
601 	/* Use the old image_data API. */
602 	code = gx_image_data(info1, &planes[0].data, 0,
603 			     planes[0].raster, image1.Height);
604 /****** TEST code == 1 ******/
605 	code = gx_image_end(info1, true);
606 /****** TEST code >= 0 ******/
607     }
608     gs_grestore(pgs);
609 
610     /* Test an explicitly masked image. */
611     gs_gsave(pgs);
612     {
613 	gs_image3_t image3;
614 	static const byte data3mask[] =
615 	{
616 	    0x60,
617 	    0x90,
618 	    0x90,
619 	    0x60
620 	};
621 	static const byte data3x2mask[] =
622 	{
623 	    0x66,
624 	    0x99,
625 	    0x99,
626 	    0x66,
627 	    0x66,
628 	    0x99,
629 	    0x99,
630 	    0x66
631 	};
632 
633 	gs_image3_t_init(&image3, &gray_cs, interleave_scan_lines);
634 	/* image */
635 	image3.ImageMatrix.xx = W;
636 	image3.ImageMatrix.yy = -H;
637 	image3.ImageMatrix.ty = H;
638 	/* data_image */
639 	image3.Width = W;
640 	image3.Height = H;
641 	image3.BitsPerComponent = 8;
642 	/* MaskDict */
643 	image3.MaskDict.ImageMatrix = image3.ImageMatrix;
644 	image3.MaskDict.Width = image3.Width;
645 	image3.MaskDict.Height = image3.Height;
646 
647 	/* Display with 1-for-1 mask and image. */
648 	gs_translate(pgs, 0.5, 2.0);
649 	code = gx_device_begin_typed_image(dev, (gs_imager_state *) pgs,
650 				       NULL, (gs_image_common_t *) & image3,
651 					   NULL, &dcolor, NULL, mem, &info);
652 /****** TEST code >= 0 ******/
653 	planes[0].data = data3mask;
654 	planes[0].data_x = 0;
655 	planes[0].raster = (image3.MaskDict.Height + 7) >> 3;
656 	planes[1].data = data3;
657 	planes[1].data_x = 0;
658 	planes[1].raster =
659 	    (image3.Height * image3.BitsPerComponent + 7) >> 3;
660 	code = gx_image_plane_data(info, planes, image3.Height);
661 /****** TEST code == 1 ******/
662 	code = gx_image_end(info, true);
663 /****** TEST code >= 0 ******/
664 
665 	/* Display with 2-for-1 mask and image. */
666 	image3.MaskDict.ImageMatrix.xx *= 2;
667 	image3.MaskDict.ImageMatrix.yy *= 2;
668 	image3.MaskDict.ImageMatrix.ty *= 2;
669 	image3.MaskDict.Width *= 2;
670 	image3.MaskDict.Height *= 2;
671 	gs_translate(pgs, 1.5, 0.0);
672 	code = gx_device_begin_typed_image(dev, (gs_imager_state *) pgs,
673 				       NULL, (gs_image_common_t *) & image3,
674 					   NULL, &dcolor, NULL, mem, &info);
675 /****** TEST code >= 0 ******/
676 	planes[0].data = data3x2mask;
677 	planes[0].raster = (image3.MaskDict.Width + 7) >> 3;
678 	{
679 	    int i;
680 
681 	    for (i = 0; i < H; ++i) {
682 		planes[1].data = 0;
683 		code = gx_image_plane_data(info, planes, 1);
684 		planes[0].data += planes[0].raster;
685 /****** TEST code == 0 ******/
686 		planes[1].data = data3 + i * planes[1].raster;
687 		code = gx_image_plane_data(info, planes, 1);
688 		planes[0].data += planes[0].raster;
689 /****** TEST code >= 0 ******/
690 	    }
691 	}
692 /****** TEST code == 1 ******/
693 	code = gx_image_end(info, true);
694 /****** TEST code >= 0 ******/
695     }
696     gs_grestore(pgs);
697 
698     /* Test a chroma-keyed masked image. */
699     gs_gsave(pgs);
700     {
701 	gs_image4_t image4;
702 	const byte *data4 = data3;
703 
704 	gs_image4_t_init(&image4, &gray_cs);
705 	/* image */
706 	image4.ImageMatrix.xx = W;
707 	image4.ImageMatrix.yy = -H;
708 	image4.ImageMatrix.ty = H;
709 	/* data_image */
710 	image4.Width = W;
711 	image4.Height = H;
712 	image4.BitsPerComponent = 8;
713 
714 	/* Display with a single mask color. */
715 	gs_translate(pgs, 0.5, 0.5);
716 	image4.MaskColor_is_range = false;
717 	image4.MaskColor[0] = 0xcc;
718 	do_image(image4, data4);
719 
720 	/* Display a second time with a color range. */
721 	gs_translate(pgs, 1.5, 0.0);
722 	image4.MaskColor_is_range = true;
723 	image4.MaskColor[0] = 0x40;
724 	image4.MaskColor[1] = 0x90;
725 	do_image(image4, data4);
726     }
727     gs_grestore(pgs);
728 
729 #undef W
730 #undef H
731 #undef do_image
732     return 0;
733 }
734 
735 /* ---------------- Test program 6 ---------------- */
736 /* Test the C API for CIE CRDs, and color snapping. */
737 
738 private void
spectrum(gs_state * pgs,int n)739 spectrum(gs_state * pgs, int n)
740 {
741     float den = n;
742     float den1 = n - 1;
743     float den2 = (n * 2 - 1) * n;
744     int a, b, c;
745 
746     for (a = 0; a < n; ++a)
747 	for (b = 0; b < n; ++b)
748 	    for (c = 0; c < n; ++c) {
749 		double size = (n * 2 - c * 2 - 1) / den2;
750 		gs_client_color cc;
751 
752 		cc.paint.values[0] = a / den1;
753 		cc.paint.values[1] = b / den1;
754 		cc.paint.values[2] = c / den1;
755 		gs_setcolor(pgs, &cc);
756 		fill_rect1(pgs,
757 			   a / den + c / den2, b / den + c / den2,
758 			   size, size);
759 	    }
760 }
761 private float
render_abc(floatp v,const gs_cie_render * ignore_crd)762 render_abc(floatp v, const gs_cie_render * ignore_crd)
763 {
764     return v / 2;
765 }
766 private int
set_cmap_method(gx_device_cmap * cmdev,gx_device_color_mapping_method_t method,gs_state * pgs,gs_memory_t * mem)767 set_cmap_method(gx_device_cmap *cmdev, gx_device_color_mapping_method_t method,
768 		gs_state *pgs, gs_memory_t *mem)
769 {
770     gs_c_param_list list;
771     int cmm = method;
772 
773     gs_c_param_list_write(&list, mem);
774     param_write_int((gs_param_list *)&list, "ColorMappingMethod", &cmm);
775     gs_c_param_list_read(&list);
776     gs_putdeviceparams((gx_device *)cmdev, (gs_param_list *)&list);
777     gs_c_param_list_release(&list);
778     gs_setdevice_no_init(pgs, (gx_device *)cmdev);
779     return 0;
780 }
781 private int
test6(gs_state * pgs,gs_memory_t * mem)782 test6(gs_state * pgs, gs_memory_t * mem)
783 {
784     gs_color_space *pcs;
785     gs_cie_abc *pabc;
786     gs_cie_render *pcrd;
787     static const gs_vector3 white_point =
788     {1, 1, 1};
789     static const gs_cie_render_proc3 encode_abc =
790     {
791 	{render_abc, render_abc, render_abc}
792     };
793     gx_device_cmap *cmdev;
794     int code;
795     gs_color_space rgb_cs;
796 
797     gs_cspace_init_DeviceRGB(&rgb_cs);
798 
799     gs_scale(pgs, 150.0, 150.0);
800     gs_translate(pgs, 0.5, 0.5);
801     gs_setcolorspace(pgs, &rgb_cs);
802     spectrum(pgs, 5);
803     gs_translate(pgs, 1.2, 0.0);
804     /* We must set the CRD before the color space. */
805     code = gs_cie_render1_build(&pcrd, mem, "test6");
806     if (code < 0)
807 	return code;
808     gs_cie_render1_initialize(pcrd, NULL, &white_point, NULL,
809 			      NULL, NULL, NULL,
810 			      NULL, NULL, NULL,
811 			      NULL, &encode_abc, NULL,
812 			      NULL);
813     gs_setcolorrendering(pgs, pcrd);
814     gs_cspace_build_CIEABC(&pcs, NULL, mem);
815     /* There should be an API for initializing CIE color spaces too.... */
816     pabc = pcs->params.abc;
817     pabc->common.points.WhitePoint = white_point;
818     gs_cie_abc_complete(pabc);
819     /* End of initializing the color space. */
820     gs_setcolorspace(pgs, pcs);
821     spectrum(pgs, 5);
822     /* Now test color snapping. */
823     cmdev =
824 	gs_alloc_struct_immovable(mem, gx_device_cmap, &st_device_cmap,
825 				  "cmap device");
826     gdev_cmap_init(cmdev, gs_currentdevice(pgs),
827 		   device_cmap_snap_to_primaries);
828     gs_setdevice_no_init(pgs, (gx_device *) cmdev);
829     gs_setrgbcolor(pgs, 0.0, 0.0, 0.0);		/* back to DeviceRGB space */
830     gs_translate(pgs, -1.2, 1.2);
831     spectrum(pgs, 5);
832     gs_translate(pgs, 1.2, 0.0);
833     set_cmap_method(cmdev, device_cmap_monochrome, pgs, mem);
834     spectrum(pgs, 5);
835     gs_translate(pgs, -1.2, 1.2);
836     set_cmap_method(cmdev, device_cmap_color_to_black_over_white, pgs, mem);
837     spectrum(pgs, 5);
838     return 0;
839 }
840 
841 /* ---------------- Test program 7 ---------------- */
842 /* Test the C API for non-monotonic halftones. */
843 
844 private int
test7(gs_state * pgs,gs_memory_t * mem)845 test7(gs_state * pgs, gs_memory_t * mem)
846 {
847     /* Define a non-monotonic 4 x 4 halftone with 4 gray levels. */
848     static const byte masks[1 * 4 * 4] =
849     {
850     /* 0% */
851 	0x00, 0x00, 0x00, 0x00,
852     /* 25% */
853 	0x80, 0x40, 0x20, 0x10,
854     /* 50% */
855 	0xa0, 0xa0, 0x50, 0x50,
856     /* 75% */
857 	0xd0, 0xe0, 0x70, 0xb0
858     };
859     gs_ht *pht;
860     int code;
861     int i;
862 
863     /* Fabricate a Type 5 halftone. */
864     code = gs_ht_build(&pht, 1, mem);
865     dprintf1("ht build code = %d\n", code);
866     code = gs_ht_set_mask_comp(pht, 0,
867 			       4, 4, 4, masks, NULL, NULL);
868     dprintf1("set mask code = %d\n", code);
869     code = gs_sethalftone(pgs, pht);
870     dprintf1("sethalftone code = %d\n", code);
871     for (i = 0; i <= 4; ++i) {
872 	gs_setgray(pgs, i / 4.0);
873 	fill_rect1(pgs, 100 + i * 100, 100, 50, 50);
874     }
875     return 0;
876 }
877 
878 /* ---------------- Test program 8 ---------------- */
879 /* Test partially transparent patterns */
880 
881 private int
test8(gs_state * pgs,gs_memory_t * mem)882 test8(gs_state * pgs, gs_memory_t * mem)
883 {
884     /*
885      * Define a 16 x 16 pattern using a 4-entry palette
886      * (white, red, green, black).
887      */
888     static const byte pdata[] =
889     {
890 	0x7f, 0xff, 0x00, 0x03,
891 	0x7f, 0xff, 0x00, 0x0c,
892 	0x50, 0x00, 0x00, 0x30,
893 	0x50, 0x00, 0x00, 0xc0,
894 	0x50, 0x00, 0x03, 0x00,
895 	0x50, 0x00, 0x0c, 0x00,
896 	0x50, 0x00, 0x30, 0x00,
897 	0x50, 0x00, 0xc0, 0x00,
898 	0xf0, 0x00, 0xc0, 0x00,
899 	0xf0, 0x00, 0x30, 0x00,
900 	0xf0, 0x00, 0x0c, 0x00,
901 	0xf0, 0x00, 0x03, 0x00,
902 	0xf0, 0x00, 0x00, 0xc0,
903 	0xf0, 0x00, 0x00, 0x30,
904 	0xea, 0x55, 0xaa, 0x5c,
905 	0xea, 0x55, 0xaa, 0x57,
906     };
907     gs_depth_bitmap ptile;
908     gs_const_string table;
909     gs_color_space *pcs;
910     gs_client_color ccolor;
911     gs_color_space rgb_cs;
912 
913     gs_cspace_init_DeviceRGB(&rgb_cs);
914 
915     table.data =
916 	(const byte *)"\377\377\377\377\000\000\000\377\000\000\000\000";
917     table.size = 12;
918     gs_cspace_build_Indexed(&pcs, &rgb_cs, 4, &table, mem);
919     ptile.data = pdata;
920     ptile.raster = 4;
921     ptile.size.x = ptile.size.y = 16;
922     ptile.id = gs_no_bitmap_id;
923     ptile.pix_depth = 2;
924     ptile.num_comps = 1;
925     gs_makepixmappattern(&ccolor, &ptile, false /*mask */ , NULL /*pmat */ ,
926 			 gs_no_id, pcs, 0 /*white_index */ , pgs, mem);
927     {
928 	gs_rect r;
929 
930 	r.p.x = 100;
931 	r.p.y = 100;
932 	r.q.x = 200;
933 	r.q.y = 200;
934 	gs_setrgbcolor(pgs, 1.0, 1.0, 0.0);
935 	gs_rectfill(pgs, &r, 1);
936 	gs_setpattern(pgs, &ccolor);
937 	gs_settexturetransparent(pgs, true);
938 	gs_rectfill(pgs, &r, 1);
939 	r.p.x += 150;
940 	r.q.x += 150;
941 	gs_setrgbcolor(pgs, 1.0, 1.0, 0.0);
942 	gs_rectfill(pgs, &r, 1);
943 	gs_setpattern(pgs, &ccolor);
944 	gs_settexturetransparent(pgs, false);
945 	gs_rectfill(pgs, &r, 1);
946     }
947     return 0;
948 }
949 
950 
951 #ifdef CAPTURE
952 
953 /* ---------------- Test program 10 ---------------- */
954 /* Replay captured data for printer output. */
955 
956 private const char outfile[] = "t.pbm";
957 private const float ypage_wid = 11.0;
958 private const float xpage_len = 17.0;
959 private const int rotate_value = 0;
960 private const float scale_x = 0.45;
961 private const float scale_y = 0.45;
962 private const float xmove_origin = 0.0;
963 private const float ymove_origin = 0.0;
964 
965 private int
test10(gs_state * pgs,gs_memory_t * mem)966 test10(gs_state * pgs, gs_memory_t * mem)
967 {
968     gs_c_param_list list;
969     gs_param_string nstr, OFstr;
970     gs_param_float_array PSa;
971     gs_param_float_array HWRa;
972     gs_param_int_array HWSa;
973     int HWSize[2];
974     float HWResolution[2], PageSize[2];
975     long MaxBitmap;
976     int code;
977     gx_device *dev = gs_currentdevice(pgs);
978     float xlate_x, xlate_y;
979     gs_rect cliprect;
980 
981     gs_c_param_list_write(&list, mem);
982     code = gs_getdeviceparams(dev, (gs_param_list *) & list);
983     if (code < 0) {
984 	lprintf1("getdeviceparams failed! code = %d\n", code);
985 	exit(1);
986     }
987     gs_c_param_list_read(&list);
988     code = param_read_string((gs_param_list *) & list, "Name", &nstr);
989     if (code < 0) {
990 	lprintf1("reading Name failed! code = %d\n", code);
991 	exit(1);
992     }
993     code = param_read_int_array((gs_param_list *) & list,
994 				"HWSize", &HWSa);
995     if (code < 0) {
996 	lprintf1("reading HWSize failed! code = %d\n", code);
997 	exit(1);
998     }
999     eprintf3("HWSize[%d] = [ %d, %d ]\n", HWSa.size,
1000 	     HWSa.data[0], HWSa.data[1]);
1001     code = param_read_float_array((gs_param_list *) & list,
1002 				  "HWResolution", &HWRa);
1003     if (code < 0) {
1004 	lprintf1("reading Resolution failed! code = %d\n", code);
1005 	exit(1);
1006     }
1007     eprintf3("HWResolution[%d] = [ %f, %f ]\n", HWRa.size,
1008 	     HWRa.data[0], HWRa.data[1]);
1009     code = param_read_float_array((gs_param_list *) & list,
1010 				  "PageSize", &PSa);
1011     if (code < 0) {
1012 	lprintf1("reading PageSize failed! code = %d\n", code);
1013 	exit(1);
1014     }
1015     eprintf3("PageSize[%d] = [ %f, %f ]\n", PSa.size,
1016 	     PSa.data[0], PSa.data[1]);
1017     code = param_read_long((gs_param_list *) & list,
1018 			   "MaxBitmap", &MaxBitmap);
1019     if (code < 0) {
1020 	lprintf1("reading MaxBitmap failed! code = %d\n", code);
1021 	exit(1);
1022     }
1023     eprintf1("MaxBitmap = %ld\n", MaxBitmap);
1024     /* Switch to param list functions to "write" */
1025     gs_c_param_list_write(&list, mem);
1026     /* Always set the PageSize. */
1027     PageSize[0] = 72.0 * ypage_wid;
1028     PageSize[1] = 72.0 * xpage_len;
1029     PSa.data = PageSize;
1030     code = param_write_float_array((gs_param_list *) & list,
1031 				   "PageSize", &PSa);
1032     if (nstr.data[0] != 'v') {
1033 	/* Set the OutputFile string file name */
1034 	OFstr.persistent = false;
1035 	OFstr.data = outfile;
1036 	OFstr.size = strlen(outfile);
1037 	code = param_write_string((gs_param_list *) & list,
1038 				  "OutputFile", &OFstr);
1039 	if (code < 0) {
1040 	    lprintf1("setting OutputFile name failed, code=%d\n",
1041 		     code);
1042 	    exit(1);
1043 	}
1044 	if (nstr.data[0] == 'x') {
1045 	    HWResolution[0] = HWResolution[1] = 72.0;
1046 	} else {
1047 	    HWResolution[0] = HWResolution[1] = 360.0;
1048 	}
1049 	HWRa.data = HWResolution;
1050 	HWSize[0] = (int)(HWResolution[0] * ypage_wid);
1051 	HWSize[1] = (int)(HWResolution[1] * xpage_len);
1052 	eprintf3("	HWSize = [%d,%d], HWResolution = %f dpi\n",
1053 		 HWSize[0], HWSize[1], HWResolution[0]);
1054 	HWSa.data = HWSize;
1055 	code = param_write_float_array((gs_param_list *) & list,
1056 				       "HWResolution", &HWRa);
1057 	code = param_write_int_array((gs_param_list *) & list,
1058 				     "HWSize", &HWSa);
1059 	MaxBitmap = 1000000L;
1060 	code = param_write_long((gs_param_list *) & list,
1061 				"MaxBitmap", &MaxBitmap);
1062     }
1063     gs_c_param_list_read(&list);
1064     code = gs_putdeviceparams(dev, (gs_param_list *) & list);
1065     eprintf1("putdeviceparams: code=%d\n", code);
1066     gs_c_param_list_release(&list);
1067 
1068     /* note: initgraphics no longer resets the color or color space */
1069     gs_erasepage(pgs);
1070     gs_initgraphics(pgs);
1071     {
1072         gs_color_space cs;
1073 
1074         gs_cspace_init_DeviceGray(&cs);
1075         gs_setcolorspace(pgs, &cs);
1076     }
1077 
1078     gs_clippath(pgs);
1079     gs_pathbbox(pgs, &cliprect);
1080     eprintf4("	cliprect = [[%g,%g],[%g,%g]]\n",
1081 	     cliprect.p.x, cliprect.p.y, cliprect.q.x, cliprect.q.y);
1082     gs_newpath(pgs);
1083 
1084     switch (((rotate_value + 270) / 90) & 3) {
1085 	default:
1086 	case 0:		/* 0 = 360 degrees in PS == 90 degrees in printer */
1087 	    xlate_x = cliprect.p.x;
1088 	    xlate_y = cliprect.p.y;
1089 	    break;
1090 	case 1:		/* 90 degrees in PS = 180 degrees printer */
1091 	    xlate_x = cliprect.q.x;
1092 	    xlate_y = cliprect.p.y;
1093 	    break;
1094 	case 2:		/* 180 degrees in PS == 270 degrees in printer */
1095 	    xlate_x = cliprect.q.x;
1096 	    xlate_y = cliprect.q.y;
1097 	    break;
1098 	case 3:		/* 270 degrees in PS == 0 degrees in printer */
1099 	    xlate_x = cliprect.p.x;
1100 	    xlate_y = cliprect.q.y;
1101 	    break;
1102     }
1103     eprintf2("translate origin to [ %f, %f ]\n", xlate_x, xlate_y);
1104     gs_translate(pgs, xlate_x, xlate_y);
1105 
1106     /* further move (before rotate) by user requested amount */
1107     gs_translate(pgs, 72.0 * (float)xmove_origin, 72.0 * (float)ymove_origin);
1108 
1109     gs_rotate(pgs, (float)rotate_value + 270.0);
1110     gs_scale(pgs, scale_x * 72.0 / 2032.0,
1111 	     scale_y * 72.0 / 2032.0);
1112     gs_setlinecap(pgs, gs_cap_butt);
1113     gs_setlinejoin(pgs, gs_join_bevel);
1114     gs_setfilladjust(pgs, 0.0, 0.0);
1115 
1116     capture_exec(pgs);
1117     return 0;
1118 }
1119 
1120 #endif /* CAPTURE */
1121