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