File: | x2jet.c |
Location: | line 753, column 21 |
Description: | The left operand of '<<' is a garbage value |
1 | /* $XConsortium: x2jet.c,v 1.6 94/04/17 20:44:03 rws Exp $ */ | ||
2 | |||
3 | /* -*-C-*- | ||
4 | ******************************************************************************** | ||
5 | * | ||
6 | * File: x2jet.c | ||
7 | * RCS: x2jet.c,v 1.23 89/07/17 12:02:51 lori Exp | ||
8 | * Description: xpr support for HP LaserJet and PaintJet printers | ||
9 | * Author: Larry Rupp, HP Graphics Technology Division | ||
10 | * Created: Fri Jul 15 15:22:26 1988 | ||
11 | * Modified: Thu Sep 15 11:59:34 1988 (Larry Rupp) ler@hpfcler | ||
12 | * Tue Dec 6 10:04:43 PST 1988 (Marc Ayotte) marca@hp-pcd | ||
13 | * Language: C | ||
14 | * Package: N/A | ||
15 | * Status: Released to MIT | ||
16 | * | ||
17 | * (c) Copyright 1988, Hewlett-Packard Company. | ||
18 | * | ||
19 | ******************************************************************************** | ||
20 | */ | ||
21 | |||
22 | |||
23 | |||
24 | |||
25 | |||
26 | /******************************************************** | ||
27 | |||
28 | Copyright (c) 1988 by Hewlett-Packard Company | ||
29 | |||
30 | Permission to use, copy, modify, and distribute this software | ||
31 | and its documentation for any purpose and without fee is hereby | ||
32 | granted, provided that the above copyright notice appear in all | ||
33 | copies and that both that copyright notice and this permission | ||
34 | notice appear in supporting documentation, and that | ||
35 | Hewlett-Packard not be used in advertising or publicity | ||
36 | pertaining to distribution of the software without specific, written | ||
37 | prior permission. | ||
38 | |||
39 | ********************************************************/ | ||
40 | /* | ||
41 | |||
42 | Copyright (c) 1988 X Consortium | ||
43 | |||
44 | Permission is hereby granted, free of charge, to any person obtaining | ||
45 | a copy of this software and associated documentation files (the | ||
46 | "Software"), to deal in the Software without restriction, including | ||
47 | without limitation the rights to use, copy, modify, merge, publish, | ||
48 | distribute, sublicense, and/or sell copies of the Software, and to | ||
49 | permit persons to whom the Software is furnished to do so, subject to | ||
50 | the following conditions: | ||
51 | |||
52 | The above copyright notice and this permission notice shall be included | ||
53 | in all copies or substantial portions of the Software. | ||
54 | |||
55 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
56 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
57 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
58 | IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
59 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
60 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
61 | OTHER DEALINGS IN THE SOFTWARE. | ||
62 | |||
63 | Except as contained in this notice, the name of the X Consortium shall | ||
64 | not be used in advertising or otherwise to promote the sale, use or | ||
65 | other dealings in this Software without prior written authorization | ||
66 | from the X Consortium. | ||
67 | |||
68 | */ | ||
69 | |||
70 | |||
71 | #include <stdio.h> | ||
72 | #include <stdarg.h> | ||
73 | #include <X11/Xlib.h> | ||
74 | #include <X11/XWDFile.h> | ||
75 | #include <X11/Xfuncproto.h> | ||
76 | |||
77 | #include "xpr.h" | ||
78 | |||
79 | #ifdef NLS16 | ||
80 | #ifndef NLS | ||
81 | #define NLS | ||
82 | #endif | ||
83 | #endif | ||
84 | |||
85 | #ifndef NLS | ||
86 | #define catgets(i, sn,mn,s)(s) (s) | ||
87 | #else /* NLS */ | ||
88 | #define NL_SETN 2 /* set number */ | ||
89 | #include <nl_types.h> | ||
90 | |||
91 | extern nl_catd nlmsg_fd; | ||
92 | |||
93 | #endif /* NLS */ | ||
94 | |||
95 | #ifndef TRUE1 | ||
96 | # define FALSE0 0 | ||
97 | # define TRUE1 1 | ||
98 | #endif | ||
99 | |||
100 | /* default printable page area (inches) */ | ||
101 | #define STDWIDTH8.0 8.0 | ||
102 | #define STDHEIGHT10.5 10.5 | ||
103 | |||
104 | /* header & trailer character cell size (centipoints) */ | ||
105 | #define CHARWIDTH720 720 | ||
106 | #define CHARHEIGHT1200 1200 | ||
107 | |||
108 | #define XWDHEADERSIZE(sizeof(XWDFileHeader)) (sizeof(XWDFileHeader)) | ||
109 | #define XCOLORSIZE(sizeof(XColor)) (sizeof(XColor)) | ||
110 | |||
111 | |||
112 | typedef struct { long width, height; } Area; | ||
113 | typedef struct { long x, y; } Location; | ||
114 | |||
115 | |||
116 | static Area limit; /* image clip limits (dots) */ | ||
117 | static Area page; /* printable page size (centipoints) */ | ||
118 | |||
119 | static Location headerloc; /* centipoint location of header string */ | ||
120 | static Location trailerloc; /* centipoint location of trailer string */ | ||
121 | static Location imageloc; /* centipoint location of image */ | ||
122 | |||
123 | static int headerlimit; /* number of chars which will printed for */ | ||
124 | static int trailerlimit; /* the image's header/trailer strings */ | ||
125 | |||
126 | static XWDFileHeader xwd_header; | ||
127 | |||
128 | static XColor *xwd_colors; | ||
129 | |||
130 | static char *xwd_image; | ||
131 | |||
132 | static unsigned long Z_pixel_mask; | ||
133 | |||
134 | static int true_scale; | ||
135 | |||
136 | typedef struct { | ||
137 | unsigned long Rmask, Gmask, Bmask; | ||
138 | int Rshift, Gshift, Bshift; | ||
139 | } RGBshiftmask; | ||
140 | |||
141 | /* Local prototypes */ | ||
142 | static void set_image_limits ( int scale, int density, enum orientation orient, Area print_area); | ||
143 | static void set_header_trailer_limits (char *header, char *trailer, long printwidth); | ||
144 | static void set_print_locations ( int scale, int density, int top, int left, const char *header, const char *trailer, enum orientation orient, int position_on_page); | ||
145 | static int scale_raster ( | ||
146 | int density, | ||
147 | enum orientation orient, | ||
148 | Area print_area); | ||
149 | static void scale_and_orient_image ( | ||
150 | int *scale, int *density, | ||
151 | int width, int height, int left, int top, /* in 300ths of an inch */ | ||
152 | const char *header, const char *trailer, | ||
153 | enum orientation *orient, | ||
154 | int position_on_page, | ||
155 | enum device device); | ||
156 | static void setup_RGBshiftmask (RGBshiftmask *sm, unsigned long rmask, unsigned long gmask, unsigned long bmask); | ||
157 | static void swap_black_and_white (void); | ||
158 | static void reset_color_mapping (void); | ||
159 | static void prepare_color_mapping ( | ||
160 | int invert, int paintjet, | ||
161 | unsigned int cutoff, | ||
162 | FILE *out); | ||
163 | static | ||
164 | void select_grey (int level, int *r, int *g, int *b); | ||
165 | static int load_printer_color ( | ||
166 | long index, | ||
167 | int nearmatch, | ||
168 | enum device device); | ||
169 | static int lookup_color_index (long i); | ||
170 | static void select_printer_color ( | ||
171 | long index, | ||
172 | int *red, int *green, int *blue, | ||
173 | long *compositeRGB, | ||
174 | enum device device); | ||
175 | static int color_already_in_printer (long compositeRGB, long *pindex); | ||
176 | static int program_new_printer_color ( | ||
177 | int red, int green, int blue, | ||
178 | long compositeRGB, | ||
179 | long *pindex); | ||
180 | static long composite_diff (long x, long y); | ||
181 | static long find_nearest_programmed_color (long compositeRGB); | ||
182 | static void add_index_to_chain ( | ||
183 | long cindex, | ||
184 | long pindex); | ||
185 | static int load_printer_color_DT ( | ||
186 | long index, | ||
187 | int nearmatch, | ||
188 | enum device device); | ||
189 | static int load_line_colors ( | ||
190 | long *line, | ||
191 | int length, int nearmatch, | ||
192 | enum device device); | ||
193 | static void download_colors ( | ||
194 | long *line, | ||
195 | int length, | ||
196 | enum device device); | ||
197 | static void validate_visual(void); | ||
198 | static void read_xwd_data (FILE *in); | ||
199 | static void write_image_prefix ( | ||
200 | FILE *out, | ||
201 | int scale, int density, | ||
202 | const char *header, | ||
203 | enum device device, | ||
204 | int position_on_page, int initial_formfeed, | ||
205 | enum orientation orient, | ||
206 | float gamma, | ||
207 | int render, | ||
208 | int slide); | ||
209 | static void write_image_suffix ( | ||
210 | FILE *out, | ||
211 | const char *trailer, | ||
212 | int position_on_page, | ||
213 | int slide, int render, | ||
214 | enum device device); | ||
215 | static unsigned long Z_image_pixel (int x, int y); | ||
216 | static unsigned long XY_image_pixel (int x, int y); | ||
217 | static void direct_by_pixel( | ||
218 | FILE *out, | ||
219 | long *line, | ||
220 | int length, | ||
221 | enum device device); | ||
222 | static void index_by_pixel( | ||
223 | FILE *out, | ||
224 | long *line, | ||
225 | int length); | ||
226 | static void write_raster_line ( | ||
227 | FILE *out, | ||
228 | int scale, | ||
229 | enum device device, | ||
230 | long *line, | ||
231 | int length); | ||
232 | static void write_portrait_Z_image ( | ||
233 | FILE *out, | ||
234 | int scale, | ||
235 | enum device device); | ||
236 | static void write_landscape_Z_image ( | ||
237 | FILE *out, | ||
238 | int scale, | ||
239 | enum device device); | ||
240 | static void write_portrait_XY_image ( | ||
241 | FILE *out, | ||
242 | int scale, | ||
243 | enum device device); | ||
244 | static void write_landscape_XY_image ( | ||
245 | FILE *out, | ||
246 | int scale, | ||
247 | enum device device); | ||
248 | static void write_Z_image ( | ||
249 | FILE *out, | ||
250 | int scale, | ||
251 | enum orientation orient, | ||
252 | enum device device); | ||
253 | static void write_XY_image ( | ||
254 | FILE *out, | ||
255 | int scale, | ||
256 | enum orientation orient, | ||
257 | enum device device); | ||
258 | static void write_image ( | ||
259 | FILE *out, | ||
260 | int scale, | ||
261 | enum orientation orient, | ||
262 | enum device device); | ||
263 | static void fatal_err (const char *s, ...) | ||
264 | _X_NORETURN__attribute((noreturn)) _X_ATTRIBUTE_PRINTF(1,2)__attribute__((__format__(__printf__,1,2))); | ||
265 | |||
266 | |||
267 | /* Computes the centipoint width of one printer dot. */ | ||
268 | #define dot_centipoints(s,d)((7200.0 * (s)) / (d)) ((7200.0 * (s)) / (d)) | ||
269 | |||
270 | static | ||
271 | void set_image_limits ( | ||
272 | int scale, int density, | ||
273 | enum orientation orient, | ||
274 | Area print_area) | ||
275 | { | ||
276 | Area print_dots; | ||
277 | double dotsize; | ||
278 | |||
279 | /* Set dotsize to the centipoint width of one printer dot. */ | ||
280 | dotsize = dot_centipoints(scale, density)((7200.0 * (scale)) / (density)); | ||
281 | |||
282 | if (orient == PORTRAIT) { | ||
283 | print_dots.width = print_area.width / dotsize; | ||
284 | print_dots.height = print_area.height / dotsize; | ||
285 | } else { | ||
286 | print_dots.height = print_area.width / dotsize; | ||
287 | print_dots.width = print_area.height / dotsize; | ||
288 | } | ||
289 | |||
290 | limit.width = (print_dots.width < xwd_header.pixmap_width) | ||
291 | ? print_dots.width : xwd_header.pixmap_width; | ||
292 | limit.height = (print_dots.height < xwd_header.pixmap_height) | ||
293 | ? print_dots.height : xwd_header.pixmap_height; | ||
294 | |||
295 | if ((limit.width != xwd_header.pixmap_width) | ||
296 | || (limit.height != xwd_header.pixmap_height)) | ||
297 | fprintf(stderrstderr,(catgets(nlmsg_fd,NL_SETN,1, "%s: Warning: %d x %d image clipped to %ld x %ld.\n")("%s: Warning: %d x %d image clipped to %ld x %ld.\n")), | ||
298 | progname, | ||
299 | xwd_header.pixmap_width, xwd_header.pixmap_height, | ||
300 | limit.width, limit.height); | ||
301 | } | ||
302 | |||
303 | |||
304 | static | ||
305 | void set_header_trailer_limits (char *header, char *trailer, long printwidth) | ||
306 | { | ||
307 | /* Determine the number of header and trailer characters | ||
308 | * that will fit into the available printing area. | ||
309 | */ | ||
310 | headerlimit = header ? (((strlen(header) * CHARWIDTH720) <= printwidth) | ||
311 | ? strlen(header) : (printwidth / CHARWIDTH720)) | ||
312 | : 0; | ||
313 | if (header && headerlimit != strlen(header)) { | ||
314 | fprintf(stderrstderr,(catgets(nlmsg_fd,NL_SETN,2,("%s: Warning: Header string clipped to %d characters.\n") | ||
315 | "%s: Warning: Header string clipped to %d characters.\n")("%s: Warning: Header string clipped to %d characters.\n")), | ||
316 | progname, headerlimit); | ||
317 | header[headerlimit] = '\0'; | ||
318 | } | ||
319 | |||
320 | trailerlimit = trailer ? (((strlen(trailer) * CHARWIDTH720) <= printwidth) | ||
321 | ? strlen(trailer) : (printwidth / CHARWIDTH720)) | ||
322 | : 0; | ||
323 | if (trailer && trailerlimit != strlen(trailer)) { | ||
324 | fprintf(stderrstderr,(catgets(nlmsg_fd,NL_SETN,3,("%s: Warning: Trailer string clipped to %d characters.\n") | ||
325 | "%s: Warning: Trailer string clipped to %d characters.\n")("%s: Warning: Trailer string clipped to %d characters.\n")), | ||
326 | progname, trailerlimit); | ||
327 | trailer[headerlimit] = '\0'; | ||
328 | } | ||
329 | } | ||
330 | |||
331 | |||
332 | static | ||
333 | void set_print_locations ( | ||
334 | int scale, int density, | ||
335 | int top, int left, | ||
336 | const char *header, const char *trailer, | ||
337 | enum orientation orient, | ||
338 | int position_on_page) | ||
339 | { | ||
340 | Area image; | ||
341 | double dotsize; | ||
342 | |||
343 | /* Set dotsize to the centipoint width of one printer dot. */ | ||
344 | dotsize = dot_centipoints(scale, density)((7200.0 * (scale)) / (density)); | ||
345 | |||
346 | /* Compute the centipoint size of the clipped image area. */ | ||
347 | if (orient == PORTRAIT) { | ||
348 | image.width = limit.width * dotsize; | ||
349 | image.height = limit.height * dotsize; | ||
350 | } else { | ||
351 | image.height = limit.width * dotsize; | ||
352 | image.width = limit.height * dotsize; | ||
353 | } | ||
354 | |||
355 | if (position_on_page) { | ||
356 | /* set vertical positions */ | ||
357 | imageloc.y = (top >= 0) | ||
358 | ? top * 24 + ((header) ? CHARHEIGHT1200 : 0) | ||
359 | : ((page.height - ((header) ? CHARHEIGHT1200 : 0) | ||
360 | - image.height - ((trailer) ? CHARHEIGHT1200 : 0)) / 2) | ||
361 | + ((header) ? CHARHEIGHT1200 : 0); | ||
362 | headerloc.y = imageloc.y - CHARHEIGHT1200 / 4; | ||
363 | trailerloc.y = imageloc.y + image.height + (3 * CHARHEIGHT1200) / 4; | ||
364 | |||
365 | /* set horizontal positions */ | ||
366 | if (left >= 0) | ||
367 | headerloc.x = imageloc.x = trailerloc.x = left * 24; | ||
368 | else { | ||
369 | headerloc.x = (page.width - headerlimit * CHARWIDTH720) / 2; | ||
370 | imageloc.x = (page.width - image.width) / 2; | ||
371 | trailerloc.x = (page.width - trailerlimit * CHARWIDTH720) / 2; | ||
372 | } | ||
373 | } | ||
374 | } | ||
375 | |||
376 | |||
377 | static | ||
378 | int scale_raster ( | ||
379 | int density, | ||
380 | enum orientation orient, | ||
381 | Area print_area) | ||
382 | { | ||
383 | Area image; | ||
384 | int h_scale, v_scale; | ||
385 | |||
386 | /* Set the image dimensions to the number of centipoints that would be | ||
387 | * required for printing at the selected density. | ||
388 | */ | ||
389 | if (orient == PORTRAIT) { | ||
390 | image.width = xwd_header.pixmap_width * 7200 / density; | ||
391 | image.height = xwd_header.pixmap_height * 7200 / density; | ||
392 | } else { | ||
393 | image.height = xwd_header.pixmap_width * 7200 / density; | ||
394 | image.width = xwd_header.pixmap_height * 7200 / density; | ||
395 | } | ||
396 | |||
397 | /* Calculate the maximum image multiplier along | ||
398 | * the horizontal and vertical dimensions. | ||
399 | */ | ||
400 | h_scale = print_area.width / image.width; | ||
401 | v_scale = print_area.height / image.height; | ||
402 | |||
403 | /* If the image can be expanded, return the lesser of the horizontal and | ||
404 | * vertical multipliers. Otherwise, the image will not completely fit | ||
405 | * the available print area, so just return 1 as the expansion factor. | ||
406 | */ | ||
407 | return (((h_scale > 0) && (v_scale > 0)) | ||
408 | ? ((h_scale<v_scale) ? h_scale : v_scale) | ||
409 | : 1); | ||
410 | } | ||
411 | |||
412 | |||
413 | static | ||
414 | void scale_and_orient_image ( | ||
415 | int *scale, int *density, | ||
416 | int width, int height, int left, int top, /* in 300ths of an inch */ | ||
417 | const char *header, const char *trailer, | ||
418 | enum orientation *orient, | ||
419 | int position_on_page, | ||
420 | enum device device) | ||
421 | { | ||
422 | Area usable; | ||
423 | |||
424 | /* Determine printable area expressed in centipoints. There are 7200 | ||
425 | * centipoints to the inch. The width and height parameters passed in | ||
426 | * are expressed in 300ths of an inch, therefore a 24x conversion factor | ||
427 | * is used on the parameter values. The default page dimensions STDWIDTH | ||
428 | * and STDHEIGHT are expressed in inches so must be multiplied by 7200 | ||
429 | * to convert to centipoints. | ||
430 | */ | ||
431 | page.width = (width >= 0) ? width * 24 : STDWIDTH8.0 * 7200; | ||
432 | page.height = (height >= 0) ? height * 24 : STDHEIGHT10.5 * 7200; | ||
433 | |||
434 | /* Paintjet Xl has a mechanical form feed, not a strip feed. It has | ||
435 | * a slop of about 1/4 to 1/2 of an inch at the top and bottom. | ||
436 | * deduct it from the page height. | ||
437 | */ | ||
438 | if (device == PJETXL) | ||
439 | page.height = page.height - 7200; | ||
440 | |||
441 | /* Determine the area usable for the image. This area will be smaller | ||
442 | * than the total printable area if margins or header/trailer strings | ||
443 | * have been specified. Margins, like width and height discussed above, | ||
444 | * are expressed in 300ths of an inch and must be converted to centipoints. | ||
445 | * Header and trailer strings each reduce the available image height | ||
446 | * by 1/6 inch, or 1200 centipoints (aka CHARHEIGHT). | ||
447 | */ | ||
448 | usable.width = page.width - ((left > 0) ? (left * 24) : 0); | ||
449 | usable.height = page.height - ((top > 0) ? (top * 24) : 0) | ||
450 | - ((header) ? CHARHEIGHT1200 : 0) | ||
451 | - ((trailer) ? CHARHEIGHT1200 : 0); | ||
452 | |||
453 | /* Quit here if there is no usable image space. */ | ||
454 | if ((usable.width <= 0) || (usable.height <= 0)) { | ||
455 | fatal_err((catgets(nlmsg_fd,NL_SETN,4,("No space available on page for image.") | ||
456 | "No space available on page for image.")("No space available on page for image."))); | ||
457 | } | ||
458 | |||
459 | /* Determine image orientation. The orientation will only be changed if | ||
460 | * it was not specified by a command line option. Portrait mode will be | ||
461 | * used if either the usable printing area or the image area are square. | ||
462 | * Portrait mode will also be used if the long dimensions of the usable | ||
463 | * printing area and the image area match, otherwise landscape mode is | ||
464 | * used. Portrait mode really means "don't rotate" and landscape mode | ||
465 | * means "rotate". | ||
466 | */ | ||
467 | if (*orient == UNSPECIFIED) { | ||
468 | if ((usable.width == usable.height) | ||
469 | || (xwd_header.pixmap_width == xwd_header.pixmap_height)) | ||
470 | *orient = PORTRAIT; | ||
471 | else | ||
472 | *orient = ((usable.width < usable.height) | ||
473 | == (xwd_header.pixmap_width < xwd_header.pixmap_height)) | ||
474 | ? PORTRAIT : LANDSCAPE; | ||
475 | } | ||
476 | |||
477 | /* Set the dots-per-inch print density if it was not specified */ | ||
478 | if (*density <= 0) { | ||
479 | switch(device) { | ||
480 | case LJET: *density = 300; | ||
481 | break; | ||
482 | case PJET: *density = 90; | ||
483 | break; | ||
484 | case PJETXL: | ||
485 | default: *density = 180; | ||
486 | break; | ||
487 | } | ||
488 | } | ||
489 | |||
490 | /* Fit image to available area if scale was not specified */ | ||
491 | if (*scale <= 0) | ||
492 | *scale = scale_raster(*density, *orient, usable); | ||
493 | |||
494 | /* Determine image clipping limits */ | ||
495 | set_image_limits(*scale, *density, *orient, usable); | ||
496 | |||
497 | /* Determine header/trailer string length clipping */ | ||
498 | set_header_trailer_limits((char *)header, (char *)trailer, usable.width); | ||
499 | |||
500 | /* Calculate locations for page layout */ | ||
501 | set_print_locations(*scale, *density, top, left, | ||
502 | header, trailer, *orient, position_on_page); | ||
503 | |||
504 | } | ||
505 | |||
506 | |||
507 | static unsigned short fullintensity; | ||
508 | |||
509 | #define BLACK1 1 | ||
510 | #define WHITE0 0 | ||
511 | #define EMPTY-1 -1 | ||
512 | #define MAX_PJ_COLOR16 16 | ||
513 | |||
514 | #define RGBmatch(r,g,b,i)(r == i) && (g == i) && (b == i) (r == i) && (g == i) && (b == i) | ||
515 | |||
516 | |||
517 | /* Colormap array is used to map from the Xcolor array (xwd_colors) index | ||
518 | * numbers into a pjcolor index number. This style of mapping is done when | ||
519 | * interpreting non-Direct/TrueColor visual types. | ||
520 | */ | ||
521 | static long *colormap; | ||
522 | |||
523 | |||
524 | /* Pjcolor array is used to hold the scaled RGB triple values | ||
525 | * programmed into the printer. | ||
526 | */ | ||
527 | static long pjcolor[MAX_PJ_COLOR16]; | ||
528 | |||
529 | |||
530 | static int color_warning_given = FALSE0; | ||
531 | |||
532 | |||
533 | /* Global visual type indicator, used to select color interpretation method. */ | ||
534 | static char Direct_or_TrueColor; | ||
535 | |||
536 | |||
537 | /* Color index element definition, these are linked into a circular list | ||
538 | * for interpretation of DirectColor or TrueColor visual types. | ||
539 | */ | ||
540 | typedef struct colorindex { | ||
541 | long index; | ||
542 | long pjcolor_index; | ||
543 | struct colorindex *next; | ||
544 | } COLORINDEX; | ||
545 | |||
546 | |||
547 | /* Global data for color interpretation. This structure serves as a home | ||
548 | * for the color index lists (only used when processing DirectColor or | ||
549 | * TrueColor visual types). It also holds color processing switches and a | ||
550 | * pointer to the output file to reduce parameter passing overhead. | ||
551 | */ | ||
552 | static struct { | ||
553 | int PaintJet; | ||
554 | int Invert; | ||
555 | unsigned int CutOff; | ||
556 | FILE *OutFile; | ||
557 | COLORINDEX *indexchain, *freechain; | ||
558 | RGBshiftmask sm; | ||
559 | } color; | ||
560 | |||
561 | |||
562 | static | ||
563 | void setup_RGBshiftmask ( | ||
564 | RGBshiftmask *sm, | ||
565 | unsigned long rmask, unsigned long gmask, unsigned long bmask) | ||
566 | { | ||
567 | sm->Rmask = rmask; sm->Gmask = gmask; sm->Bmask = bmask; | ||
568 | sm->Rshift = 0; sm->Gshift = 0; sm->Bshift = 0; | ||
569 | |||
570 | if (!rmask) | ||
571 | fatal_err((catgets(nlmsg_fd,NL_SETN,5, "red mask for visual is zero.")("red mask for visual is zero."))); | ||
572 | if (!gmask) | ||
573 | fatal_err((catgets(nlmsg_fd,NL_SETN,6, "green mask for visual is zero.")("green mask for visual is zero."))); | ||
574 | if (!bmask) | ||
575 | fatal_err((catgets(nlmsg_fd,NL_SETN,7, "blue mask for visual is zero.")("blue mask for visual is zero."))); | ||
576 | |||
577 | for (; !(rmask & 1); sm->Rshift++) | ||
578 | rmask >>= 1; | ||
579 | for (; !(gmask & 1); sm->Gshift++) | ||
580 | gmask >>= 1; | ||
581 | for (; !(bmask & 1); sm->Bshift++) | ||
582 | bmask >>= 1; | ||
583 | } | ||
584 | |||
585 | |||
586 | static | ||
587 | void swap_black_and_white (void) | ||
588 | { | ||
589 | /* Reverse black and white in the Xcolor structure array. */ | ||
590 | |||
591 | XColor *color; | ||
592 | int n; | ||
593 | |||
594 | for (n=xwd_header.ncolors, color=xwd_colors; n>0; n--, color++) | ||
595 | if (RGBmatch((color->red & fullintensity), (color->green & fullintensity),((color->red & fullintensity) == fullintensity) && ((color->green & fullintensity) == fullintensity) && ((color->blue & fullintensity) == fullintensity) | ||
596 | (color->blue & fullintensity), fullintensity)((color->red & fullintensity) == fullintensity) && ((color->green & fullintensity) == fullintensity) && ((color->blue & fullintensity) == fullintensity)) | ||
597 | color->red = color->green = color->blue = 0; | ||
598 | else if (RGBmatch(color->red, color->green, color->blue, 0)(color->red == 0) && (color->green == 0) && (color->blue == 0)) | ||
599 | color->red = color->green = color->blue = fullintensity; | ||
600 | } | ||
601 | |||
602 | |||
603 | static | ||
604 | void reset_color_mapping (void) | ||
605 | { | ||
606 | int n; | ||
607 | long *cmap; | ||
608 | COLORINDEX *splice; | ||
609 | |||
610 | for (n=0; n<MAX_PJ_COLOR16; n++) | ||
611 | pjcolor[n] = EMPTY-1; | ||
612 | |||
613 | if (!color.PaintJet) { | ||
614 | /* preload for monochrome output */ | ||
615 | pjcolor[0] = WHITE0; | ||
616 | pjcolor[1] = BLACK1; | ||
617 | } | ||
618 | |||
619 | if (Direct_or_TrueColor) { | ||
620 | /* move color index chain cells onto the free list */ | ||
621 | if (color.indexchain != NULL((void*)0)) { | ||
622 | splice = color.indexchain->next; | ||
623 | color.indexchain->next = color.freechain; | ||
624 | color.freechain = splice; | ||
625 | color.indexchain = NULL((void*)0); | ||
626 | } | ||
627 | } else if (color.PaintJet) | ||
628 | for (n=xwd_header.ncolors, cmap=colormap; n>0; n--, cmap++) | ||
629 | *cmap = EMPTY-1; | ||
630 | } | ||
631 | |||
632 | |||
633 | #define Intensity(r,g,b)((r) * 0.30 + (g) * 0.59 + (b) * 0.11) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11) | ||
634 | |||
635 | static | ||
636 | void prepare_color_mapping ( | ||
637 | int invert, int paintjet, | ||
638 | unsigned int cutoff, | ||
639 | FILE *out) | ||
640 | { | ||
641 | int n; | ||
642 | long *cmap; | ||
643 | XColor *xcolor; | ||
644 | |||
645 | for (n = xwd_header.bits_per_rgb, fullintensity = 0; n > 0; n--) | ||
646 | fullintensity = (fullintensity << 1) | 1; | ||
647 | for (n = sizeof(short) * 8 - xwd_header.bits_per_rgb; n > 0; n--) | ||
648 | fullintensity = (fullintensity << 1); | ||
649 | |||
650 | Direct_or_TrueColor = (xwd_header.visual_class == DirectColor5 | ||
651 | || xwd_header.visual_class == TrueColor4); | ||
652 | color.PaintJet = paintjet; | ||
653 | color.Invert = invert; | ||
654 | color.CutOff = cutoff; | ||
655 | color.OutFile = out; | ||
656 | color.indexchain = NULL((void*)0); | ||
657 | color.freechain = NULL((void*)0); | ||
658 | |||
659 | if (Direct_or_TrueColor) | ||
660 | setup_RGBshiftmask(&color.sm, xwd_header.red_mask, | ||
661 | xwd_header.green_mask, xwd_header.blue_mask); | ||
662 | else { | ||
663 | if (!(colormap = (long *) malloc(xwd_header.ncolors * sizeof(long)))) | ||
664 | fatal_err((catgets(nlmsg_fd,NL_SETN,24,("Could not allocate memory for X-to-printer colormap.") | ||
665 | "Could not allocate memory for X-to-printer colormap.")("Could not allocate memory for X-to-printer colormap."))); | ||
666 | |||
667 | /* For PaintJet, color map assignment will be done one line at a time. | ||
668 | * So for now just interchange the Xcolor structure's black and white | ||
669 | * if the -rv command line option was specified. | ||
670 | */ | ||
671 | if (paintjet && invert) | ||
672 | swap_black_and_white(); | ||
673 | |||
674 | /* For LaserJet, map each color to black or white based upon the | ||
675 | * combined intensity of the RGB components. Note that the normal | ||
676 | * non-reversed (-rv) LaserJet mapping will represent light areas | ||
677 | * of the screen as black on the paper. | ||
678 | */ | ||
679 | if (!paintjet) | ||
680 | for (n=xwd_header.ncolors, xcolor=xwd_colors, cmap=colormap; n>0; | ||
681 | n--, xcolor++, cmap++) | ||
682 | *cmap = (Intensity(xcolor->red, xcolor->green, xcolor->blue)((xcolor->red) * 0.30 + (xcolor->green) * 0.59 + (xcolor ->blue) * 0.11) < cutoff) | ||
683 | ? (invert ? BLACK1 : WHITE0) | ||
684 | : (invert ? WHITE0 : BLACK1); | ||
685 | } | ||
686 | reset_color_mapping(); | ||
687 | } | ||
688 | |||
689 | |||
690 | /* On a PaintJet printer, the programmable color intensity ranges are: | ||
691 | * | ||
692 | * red: 4..90 green: 4..88 blue: 6..85 | ||
693 | * | ||
694 | * The following macros map the 0..65535 intensity ranges of X colors | ||
695 | * into the PaintJet's ranges. | ||
696 | */ | ||
697 | |||
698 | #define fixred(x)(x / 762 + 4) (x / 762 + 4) | ||
699 | #define fixgreen(x)(x / 780 + 4) (x / 780 + 4) | ||
700 | #define fixblue(x)(x / 829 + 6) (x / 829 + 6) | ||
701 | |||
702 | #define is_grey(r,g,b)((r == g) && (r == b)) ((r == g) && (r == b)) | ||
703 | |||
704 | |||
705 | static | ||
706 | void select_grey (int level, int *r, int *g, int *b) | ||
707 | { | ||
708 | /* Forced selection of a grey. This is done since the PaintJet does | ||
709 | * not do very well when picking greys, they tend to become pink! | ||
710 | */ | ||
711 | if (level > 66) { /* white */ | ||
712 | *r = 90; *g = 88; *b = 85; | ||
713 | } else if (level > 35) { | ||
714 | *r = 43; *g = 43; *b = 45; | ||
715 | } else if (level > 21) { | ||
716 | *r = 25; *g = 25; *b = 33; | ||
717 | } else if (level > 15) { | ||
718 | *r = 15; *g = 16; *b = 18; | ||
719 | } else if (level > 11) { | ||
720 | *r = 14; *g = 14; *b = 18; | ||
721 | } else if (level > 6) { | ||
722 | *r = 6; *g = 7; *b = 8; | ||
723 | } else { /* black */ | ||
724 | *r = 4; *g = 4; *b = 6; | ||
725 | } | ||
726 | } | ||
727 | |||
728 | |||
729 | static | ||
730 | int load_printer_color ( | ||
731 | long index, | ||
732 | int nearmatch, | ||
733 | enum device device) /* for non Direct/TrueColor */ | ||
734 | { | ||
735 | int n, red, blue, green, xred, xgreen, xblue; | ||
| |||
736 | long compositeRGB; | ||
737 | |||
738 | if (colormap[index] != EMPTY-1) | ||
| |||
739 | /* printer has already been programmed for this color index */ | ||
740 | return(1); /* "success" */ | ||
741 | else { | ||
742 | xred = xwd_colors[index].red; | ||
743 | xgreen = xwd_colors[index].green; | ||
744 | xblue = xwd_colors[index].blue; | ||
745 | /* determine the scaled RGB PaintJet color values */ | ||
746 | if (device == PJET) { | ||
| |||
| |||
747 | red = fixred(xred)(xred / 762 + 4); | ||
748 | green = fixgreen(xgreen)(xgreen / 780 + 4); | ||
749 | blue = fixblue(xblue)(xblue / 829 + 6); | ||
750 | if (is_grey(xred, xgreen, xblue)((xred == xgreen) && (xred == xblue))) /* assist grey selection */ | ||
751 | select_grey(red, &red, &green, &blue); | ||
752 | } | ||
753 | compositeRGB = (red << 16) | (green << 8) | blue; | ||
| |||
754 | /* search for a matching or unused PaintJet mapping entry */ | ||
755 | for (n=0; n<MAX_PJ_COLOR16; n++) { | ||
756 | if (pjcolor[n] == compositeRGB) { | ||
757 | /* record mapping for this index */ | ||
758 | colormap[index] = n; | ||
759 | /* return "success" */ | ||
760 | return(1); | ||
761 | } else if (pjcolor[n] == EMPTY-1) { | ||
762 | /* download color to printer */ | ||
763 | fprintf(color.OutFile,"\033*v%dA", red); | ||
764 | fprintf(color.OutFile,"\033*v%dB", green); | ||
765 | fprintf(color.OutFile,"\033*v%dC", blue); | ||
766 | fprintf(color.OutFile,"\033*v%dI", n); | ||
767 | /* record that this is now programmed */ | ||
768 | pjcolor[n] = compositeRGB; | ||
769 | colormap[index] = n; | ||
770 | /* return "success" */ | ||
771 | return(1); | ||
772 | } | ||
773 | } | ||
774 | /* unable to find or program this color */ | ||
775 | if (nearmatch) | ||
776 | colormap[index] = find_nearest_programmed_color(compositeRGB); | ||
777 | } | ||
778 | return(0); /* "failure" */ | ||
779 | } | ||
780 | |||
781 | |||
782 | /* Lookup the image color index on the color.indexchain list. If found | ||
783 | * return the corresponding printer color index, otherwise -1. The index | ||
784 | * chain is a singly linked circular list. Its head pointer is left at | ||
785 | * the last cell matched on the theory that this will allow faster lookup | ||
786 | * for runs of color. | ||
787 | */ | ||
788 | static | ||
789 | int lookup_color_index (long i) | ||
790 | { | ||
791 | COLORINDEX *start, *current; | ||
792 | |||
793 | start = current = color.indexchain; | ||
794 | |||
795 | if (current == NULL((void*)0)) | ||
796 | return(-1); /* not found */ | ||
797 | |||
798 | do { | ||
799 | if (current->index == i) { | ||
800 | color.indexchain = current; | ||
801 | return(current->pjcolor_index); /* found */ | ||
802 | } | ||
803 | current = current->next; | ||
804 | } while (current != start); | ||
805 | |||
806 | return(-1); /* not found */ | ||
807 | } | ||
808 | |||
809 | |||
810 | /* Calculate the individual and composite printer RGB values. (Only the | ||
811 | * composite value is set for monochrome output.) | ||
812 | */ | ||
813 | static | ||
814 | void select_printer_color ( | ||
815 | long index, | ||
816 | int *red, int *green, int *blue, | ||
817 | long *compositeRGB, | ||
818 | enum device device) | ||
819 | { | ||
820 | int xred, xgreen, xblue; | ||
821 | |||
822 | xred = xwd_colors[((index & color.sm.Rmask) >> color.sm.Rshift)].red; | ||
823 | xgreen = xwd_colors[((index & color.sm.Gmask) >> color.sm.Gshift)].green; | ||
824 | xblue = xwd_colors[((index & color.sm.Bmask) >> color.sm.Bshift)].blue; | ||
825 | |||
826 | if (color.PaintJet) { | ||
827 | if (color.Invert) { | ||
828 | if (RGBmatch((xred & fullintensity), (xgreen & fullintensity),((xred & fullintensity) == fullintensity) && ((xgreen & fullintensity) == fullintensity) && ((xblue & fullintensity) == fullintensity) | ||
829 | (xblue & fullintensity), fullintensity)((xred & fullintensity) == fullintensity) && ((xgreen & fullintensity) == fullintensity) && ((xblue & fullintensity) == fullintensity)) | ||
830 | xred = xgreen = xblue = 0; | ||
831 | else if (RGBmatch(xred, xgreen, xblue, 0)(xred == 0) && (xgreen == 0) && (xblue == 0)) | ||
832 | xred = xgreen = xblue = fullintensity; | ||
833 | } | ||
834 | /* determine the scaled RGB PaintJet color values */ | ||
835 | if (device == PJET) { | ||
836 | *red = fixred(xred)(xred / 762 + 4); | ||
837 | *green = fixgreen(xgreen)(xgreen / 780 + 4); | ||
838 | *blue = fixblue(xblue)(xblue / 829 + 6); | ||
839 | if (is_grey(xred, xgreen, xblue)((xred == xgreen) && (xred == xblue))) /* assist grey selection */ | ||
840 | select_grey(*red, red, green, blue); | ||
841 | } | ||
842 | if (device == PJETXL) { | ||
843 | *red = xred >> 8; | ||
844 | *green = xgreen >> 8; | ||
845 | *blue = xblue >> 8; | ||
846 | } | ||
847 | *compositeRGB = (*red << 16) | (*green << 8) | *blue; | ||
848 | } else /* monochrome */ | ||
849 | *compositeRGB = (Intensity(xred, xgreen, xblue)((xred) * 0.30 + (xgreen) * 0.59 + (xblue) * 0.11) < color.CutOff) | ||
850 | ? (color.Invert ? BLACK1 : WHITE0) | ||
851 | : (color.Invert ? WHITE0 : BLACK1); | ||
852 | } | ||
853 | |||
854 | |||
855 | |||
856 | /* Search for a color matching the compositeRGB value in the array of | ||
857 | * colors already programmed into the printer. Returns 1 if found, | ||
858 | * 0 otherwise. The matching array index is returned in pindex. | ||
859 | */ | ||
860 | static | ||
861 | int color_already_in_printer (long compositeRGB, long *pindex) | ||
862 | { | ||
863 | int n; | ||
864 | |||
865 | for (n=0; n<MAX_PJ_COLOR16; n++) | ||
866 | if (pjcolor[n] == EMPTY-1) | ||
867 | return(0); /* not found */ | ||
868 | else if (pjcolor[n] == compositeRGB) { | ||
869 | *pindex = n; | ||
870 | return(1); /* found */ | ||
871 | } | ||
872 | return(0); /* not found */ | ||
873 | } | ||
874 | |||
875 | |||
876 | static | ||
877 | int program_new_printer_color ( | ||
878 | int red, int green, int blue, | ||
879 | long compositeRGB, | ||
880 | long *pindex) | ||
881 | { | ||
882 | int n; | ||
883 | |||
884 | for (n=0; n<MAX_PJ_COLOR16; n++) | ||
885 | if (pjcolor[n] == EMPTY-1) { | ||
886 | /* download color to printer */ | ||
887 | fprintf(color.OutFile,"\033*v%dA", red); | ||
888 | fprintf(color.OutFile,"\033*v%dB", green); | ||
889 | fprintf(color.OutFile,"\033*v%dC", blue); | ||
890 | fprintf(color.OutFile,"\033*v%dI", n); | ||
891 | /* record that this is now programmed */ | ||
892 | pjcolor[n] = compositeRGB; | ||
893 | *pindex = n; | ||
894 | /* return "success" */ | ||
895 | return(1); | ||
896 | } | ||
897 | /* unable to program this color, return "failure" */ | ||
898 | return(0); | ||
899 | } | ||
900 | |||
901 | |||
902 | static | ||
903 | long composite_diff (long x, long y) | ||
904 | { | ||
905 | long r = (x >> 16 & 0xFF) - (y >> 16 & 0xFF); | ||
906 | long g = (x >> 8 & 0xFF) - (y >> 8 & 0xFF); | ||
907 | long b = (x & 0xFF) - (y & 0xFF); | ||
908 | |||
909 | return(r*r + g*g + b*b); | ||
910 | } | ||
911 | |||
912 | |||
913 | static | ||
914 | long find_nearest_programmed_color (long compositeRGB) | ||
915 | { | ||
916 | int n, nearest = 0; | ||
917 | long neardiff = composite_diff(pjcolor[0], compositeRGB); | ||
918 | long diff; | ||
919 | |||
920 | for (n=1; n<MAX_PJ_COLOR16; n++) { | ||
921 | diff = composite_diff(pjcolor[n], compositeRGB); | ||
922 | if (diff < neardiff) { | ||
923 | neardiff = diff; | ||
924 | nearest = n; | ||
925 | } | ||
926 | } | ||
927 | return(nearest); | ||
928 | } | ||
929 | |||
930 | |||
931 | static | ||
932 | void add_index_to_chain ( | ||
933 | long cindex, | ||
934 | long pindex) | ||
935 | { | ||
936 | COLORINDEX *new; | ||
937 | |||
938 | /* Get a new cell for the color index chain. Take it from the free list | ||
939 | * if possible, otherwise malloc space. | ||
940 | */ | ||
941 | if (color.freechain == NULL((void*)0)) { | ||
942 | if (!(new = (COLORINDEX *) malloc(sizeof(COLORINDEX)))) | ||
943 | fatal_err((catgets(nlmsg_fd,NL_SETN,8,("Could not allocate memory for color translation.") | ||
944 | "Could not allocate memory for color translation.")("Could not allocate memory for color translation."))); | ||
945 | } else { | ||
946 | new = color.freechain; | ||
947 | color.freechain = color.freechain->next; | ||
948 | } | ||
949 | |||
950 | /* put index values in the new cell */ | ||
951 | new->index = cindex; | ||
952 | new->pjcolor_index = pindex; | ||
953 | |||
954 | /* link the new cell into the chain */ | ||
955 | if (color.indexchain == NULL((void*)0)) | ||
956 | new->next = new; | ||
957 | else { | ||
958 | new->next = color.indexchain->next; | ||
959 | color.indexchain->next = new; | ||
960 | } | ||
961 | /* leave head pointer at the new cell */ | ||
962 | color.indexchain = new; | ||
963 | } | ||
964 | |||
965 | |||
966 | static | ||
967 | int load_printer_color_DT ( | ||
968 | long index, | ||
969 | int nearmatch, | ||
970 | enum device device) /* for Direct/TrueColor */ | ||
971 | { | ||
972 | int pjred, pjgreen, pjblue; | ||
973 | long compositeRGB; | ||
974 | long pindex; | ||
975 | |||
976 | if (lookup_color_index(index) >= 0) | ||
977 | return(1); /* "success" */ | ||
978 | else { | ||
979 | select_printer_color(index, &pjred, &pjgreen, &pjblue, &compositeRGB, | ||
980 | device); | ||
981 | if (color_already_in_printer(compositeRGB, &pindex)) { | ||
982 | add_index_to_chain(index, pindex); | ||
983 | return(1); /* success */ | ||
984 | } else if (program_new_printer_color(pjred, pjgreen, pjblue, | ||
985 | compositeRGB, &pindex)) { | ||
986 | add_index_to_chain(index, pindex); | ||
987 | return(1); /* success */ | ||
988 | } else if (nearmatch) { | ||
989 | add_index_to_chain(index, find_nearest_programmed_color(compositeRGB)); | ||
990 | return(0); /* failure, sorta... */ | ||
991 | } | ||
992 | } | ||
993 | return(0); /* failure */ | ||
994 | } | ||
995 | |||
996 | |||
997 | static | ||
998 | int load_line_colors ( | ||
999 | long *line, | ||
1000 | int length, int nearmatch, | ||
1001 | enum device device) | ||
1002 | { | ||
1003 | int result = 1; /* initialized to "success" */ | ||
1004 | |||
1005 | for (; length>0; length--, line++) { | ||
1006 | result &= Direct_or_TrueColor | ||
1007 | ? load_printer_color_DT(*line, nearmatch, device) | ||
1008 | : load_printer_color(*line, nearmatch, device); | ||
1009 | if (!(nearmatch || result)) | ||
1010 | break; | ||
1011 | } | ||
1012 | return(result); | ||
1013 | } | ||
1014 | |||
1015 | |||
1016 | static | ||
1017 | void download_colors ( | ||
1018 | long *line, | ||
1019 | int length, | ||
1020 | enum device device) | ||
1021 | { | ||
1022 | /* For the first attempt at loading the colors for a line only exact | ||
1023 | * color matches are accepted. If this fails, the closest colors are | ||
1024 | * accepted on the second attempt. | ||
1025 | * | ||
1026 | * Note: The first "if" test below bypasses the initial color loading | ||
1027 | * attempt for monochrome output (which will only come here for Direct | ||
1028 | * or TrueColor mono). This forces reset_color_mapping which is | ||
1029 | * necessary to keep the color index chain down to a tolerable length. | ||
1030 | */ | ||
1031 | if (!color.PaintJet || !load_line_colors(line, length, FALSE0, device)) { | ||
1032 | reset_color_mapping(); | ||
1033 | if (!load_line_colors(line, length, TRUE1, device) && | ||
1034 | !color_warning_given) { | ||
1035 | fprintf(stderrstderr,(catgets(nlmsg_fd,NL_SETN,9,("%s: Warning: Cannot print all image colors.\n") | ||
1036 | "%s: Warning: Cannot print all image colors.\n")("%s: Warning: Cannot print all image colors.\n")), | ||
1037 | progname); | ||
1038 | color_warning_given = TRUE1; | ||
1039 | } | ||
1040 | } | ||
1041 | } | ||
1042 | |||
1043 | |||
1044 | static _X_INLINEinline _X_NORETURN__attribute((noreturn)) | ||
1045 | void invalid_depth_for_visual(int depth, const char *name) | ||
1046 | { | ||
1047 | fatal_err(catgets(nlmsg_fd,NL_SETN,25,("%d bit deep %s bitmap not supported.\n") | ||
1048 | "%d bit deep %s bitmap not supported.\n")("%d bit deep %s bitmap not supported.\n"), | ||
1049 | depth, name); | ||
1050 | } | ||
1051 | |||
1052 | static | ||
1053 | void validate_visual(void) | ||
1054 | { | ||
1055 | int depth = xwd_header.pixmap_depth; | ||
1056 | |||
1057 | switch (xwd_header.visual_class) { | ||
1058 | case GrayScale1: | ||
1059 | if (depth > 8) invalid_depth_for_visual(depth, "GrayScale"); break; | ||
1060 | case StaticGray0: | ||
1061 | if (depth > 8) invalid_depth_for_visual(depth, "StaticGray"); break; | ||
1062 | case PseudoColor3: | ||
1063 | if (depth > 8) invalid_depth_for_visual(depth, "PseudoColor"); break; | ||
1064 | case StaticColor2: | ||
1065 | if (depth > 8) invalid_depth_for_visual(depth, "StaticColor"); break; | ||
1066 | case DirectColor5: | ||
1067 | if (depth != 12 && depth != 24) | ||
1068 | invalid_depth_for_visual(depth, "DirectColor"); | ||
1069 | break; | ||
1070 | case TrueColor4: | ||
1071 | if (depth != 12 && depth != 24) | ||
1072 | invalid_depth_for_visual(depth, "TrueColor"); | ||
1073 | break; | ||
1074 | default: | ||
1075 | fatal_err((catgets(nlmsg_fd,NL_SETN,26,("visual class #%d not supported.\n") | ||
1076 | "visual class #%d not supported.\n")("visual class #%d not supported.\n")), | ||
1077 | (int)xwd_header.visual_class); | ||
1078 | } | ||
1079 | } | ||
1080 | |||
1081 | static | ||
1082 | void read_xwd_data (FILE *in) | ||
1083 | { | ||
1084 | # define WINDOW_NAME_ALLOC32 32 | ||
1085 | unsigned long swaptest = 1; | ||
1086 | int window_name_size; | ||
1087 | int image_size; | ||
1088 | int n; | ||
1089 | char window_name [WINDOW_NAME_ALLOC32]; | ||
1090 | |||
1091 | /* Read in XWDFileHeader structure */ | ||
1092 | if (fread((char*) &xwd_header, 1, XWDHEADERSIZE(sizeof(XWDFileHeader)), in) != XWDHEADERSIZE(sizeof(XWDFileHeader))) | ||
1093 | fatal_err((catgets(nlmsg_fd,NL_SETN,10,("Could not read xwd file's header.") | ||
1094 | "Could not read xwd file's header.")("Could not read xwd file's header."))); | ||
1095 | |||
1096 | if (*(char *) &swaptest) | ||
1097 | _swaplong((char *) &xwd_header, XWDHEADERSIZE(sizeof(XWDFileHeader))); | ||
1098 | |||
1099 | validate_visual(); | ||
1100 | |||
1101 | /* Skip over window name */ | ||
1102 | window_name_size = xwd_header.header_size - XWDHEADERSIZE(sizeof(XWDFileHeader)); | ||
1103 | while (window_name_size > 0) { | ||
1104 | n = window_name_size > WINDOW_NAME_ALLOC32 | ||
1105 | ? WINDOW_NAME_ALLOC32 : window_name_size; | ||
1106 | if (fread(window_name, 1, n, in) != n) | ||
1107 | fatal_err((catgets(nlmsg_fd,NL_SETN,11,("Could not read xwd file's window name.") | ||
1108 | "Could not read xwd file's window name.")("Could not read xwd file's window name."))); | ||
1109 | window_name_size -= n; | ||
1110 | } | ||
1111 | |||
1112 | /* Allocate space for xwd color structures */ | ||
1113 | if (!(xwd_colors = (XColor*) malloc(sizeof(XColor) * xwd_header.ncolors))) | ||
1114 | fatal_err((catgets(nlmsg_fd,NL_SETN,12,("Could not allocate memory for xwdfile color table.") | ||
1115 | "Could not allocate memory for xwdfile color table.")("Could not allocate memory for xwdfile color table."))); | ||
1116 | |||
1117 | /* Read in xwd color structures */ | ||
1118 | for (n = 0; n < xwd_header.ncolors; n++) | ||
1119 | if (fread(&xwd_colors[n], 1, XCOLORSIZE(sizeof(XColor)), in) != XCOLORSIZE(sizeof(XColor))) | ||
1120 | fatal_err((catgets(nlmsg_fd,NL_SETN,13,("Could not read xwd file's color table.") | ||
1121 | "Could not read xwd file's color table.")("Could not read xwd file's color table."))); | ||
1122 | |||
1123 | if (*(char *) &swaptest) { | ||
1124 | for (n = 0; n < xwd_header.ncolors; n++) { | ||
1125 | _swaplong((char *) &xwd_colors[n].pixel, sizeof(long)); | ||
1126 | _swapshort((char *) &xwd_colors[n].red, 3 * sizeof(short)); | ||
1127 | } | ||
1128 | } | ||
1129 | |||
1130 | /* Allocate space for xwd image */ | ||
1131 | if (xwd_header.pixmap_format == ZPixmap2) | ||
1132 | image_size = 1; | ||
1133 | else if (xwd_header.pixmap_format == XYPixmap1) | ||
1134 | image_size = xwd_header.pixmap_depth; | ||
1135 | else | ||
1136 | fatal_err((catgets(nlmsg_fd,NL_SETN,14,("Image in xwd file is not in Z or XY pixmap format.") | ||
1137 | "Image in xwd file is not in Z or XY pixmap format.")("Image in xwd file is not in Z or XY pixmap format."))); | ||
1138 | image_size *= xwd_header.bytes_per_line * xwd_header.pixmap_height; | ||
1139 | if (!(xwd_image = malloc(image_size))) | ||
1140 | fatal_err((catgets(nlmsg_fd,NL_SETN,15,("Could not allocate memory for xwd file's image.") | ||
1141 | "Could not allocate memory for xwd file's image.")("Could not allocate memory for xwd file's image."))); | ||
1142 | |||
1143 | /* Read in xwd image */ | ||
1144 | if (fread(xwd_image, 1, image_size, in) != image_size) | ||
1145 | fatal_err((catgets(nlmsg_fd,NL_SETN,16,("Could not read xwd file's image.") | ||
1146 | "Could not read xwd file's image.")("Could not read xwd file's image."))); | ||
1147 | |||
1148 | } | ||
1149 | |||
1150 | |||
1151 | static | ||
1152 | void write_image_prefix ( | ||
1153 | FILE *out, | ||
1154 | int scale, int density, | ||
1155 | const char *header, | ||
1156 | enum device device, | ||
1157 | int position_on_page, int initial_formfeed, | ||
1158 | enum orientation orient, | ||
1159 | float gamma, | ||
1160 | int render, | ||
1161 | int slide) | ||
1162 | { | ||
1163 | if (initial_formfeed) | ||
1164 | fprintf(out,"\014"); | ||
1165 | |||
1166 | /* Write out header & positioning commands */ | ||
1167 | if (header) { | ||
1168 | if (position_on_page) | ||
1169 | fprintf(out,"\033&a%dH\033&a%dV", | ||
1170 | /* headerloc x & y are written in decipoints */ | ||
1171 | (int) headerloc.x / 10, (int) headerloc.y / 10); | ||
1172 | fprintf(out,"%s\n", header); | ||
1173 | } | ||
1174 | |||
1175 | /* Prepare printer for raster graphics: */ | ||
1176 | |||
1177 | /* Write image positioning commands */ | ||
1178 | if (position_on_page) | ||
1179 | fprintf(out,"\033&a%dH\033&a%dV", | ||
1180 | /* imageloc x & y are written in decipoints */ | ||
1181 | (int) imageloc.x / 10, (int) imageloc.y / 10); | ||
1182 | |||
1183 | /* If doing transparencies, tell the printer before raster graphics */ | ||
1184 | if (slide && device != LJET) | ||
1185 | fprintf(out, "\033&k3W"); | ||
1186 | |||
1187 | /* Set printer resolution */ | ||
1188 | fprintf(out,"\033*t%dR", density); | ||
1189 | |||
1190 | /* | ||
1191 | * do device dependent escape sequences | ||
1192 | */ | ||
1193 | if (device == PJET) { | ||
1194 | /* Enable all four "planes" for PaintJet */ | ||
1195 | fprintf(out,"\033*r4U"); | ||
1196 | |||
1197 | /* Set picture width for PaintJet */ | ||
1198 | fprintf(out,"\033*r%dS", | ||
1199 | (int) (((orient == PORTRAIT) ? limit.width : limit.height) | ||
1200 | * scale)); | ||
1201 | } | ||
1202 | |||
1203 | /* Enable various options for PaintJet XL */ | ||
1204 | if (device == PJETXL) { | ||
1205 | double dotsize; | ||
1206 | int n; | ||
1207 | |||
1208 | /* Speed up printing by telling that there | ||
1209 | * will be no negative positioning | ||
1210 | */ | ||
1211 | fprintf(out, "\033&a1N"); | ||
1212 | |||
1213 | if (gamma > 0.009) | ||
1214 | fprintf(out, "\033*t%.2fI", gamma); | ||
1215 | |||
1216 | if (render > 0) | ||
1217 | fprintf(out, "\033*t%dJ", render); | ||
1218 | |||
1219 | if (Direct_or_TrueColor) | ||
1220 | /* Enable direct by pixel for PaintJet XL */ | ||
1221 | fwrite("\033*v6W\000\003\010\010\010\010", 1, 11, out); | ||
1222 | else { | ||
1223 | /* Enable index by pixel for PaintJet XL */ | ||
1224 | fwrite("\033*v6W\000\001\010\010\010\010", 1, 11, out); | ||
1225 | |||
1226 | /* Program the palette */ | ||
1227 | for (n = 0; n < xwd_header.ncolors; n++) { | ||
1228 | fprintf(out,"\033*v%dA", (xwd_colors[n].red >> 8)); | ||
1229 | fprintf(out,"\033*v%dB", (xwd_colors[n].green >> 8)); | ||
1230 | fprintf(out,"\033*v%dC", (xwd_colors[n].blue >> 8)); | ||
1231 | fprintf(out,"\033*v%dI", n); | ||
1232 | } | ||
1233 | } | ||
1234 | |||
1235 | /**************************************** | ||
1236 | * * | ||
1237 | * PaintJet XL will do its own scaling * | ||
1238 | * * | ||
1239 | * Set picture width for PaintJet XL * | ||
1240 | ****************************************/ | ||
1241 | fprintf(out,"\033*r%dS", | ||
1242 | (int) ((orient == PORTRAIT) ? xwd_header.pixmap_width | ||
1243 | : xwd_header.pixmap_height)); | ||
1244 | fprintf(out,"\033*r%dT", | ||
1245 | (int) ((orient == PORTRAIT) ? xwd_header.pixmap_height | ||
1246 | : xwd_header.pixmap_width)); | ||
1247 | |||
1248 | dotsize = dot_centipoints(scale, density)((7200.0 * (scale)) / (density)); | ||
1249 | |||
1250 | fprintf(out,"\033*t%dH", | ||
1251 | (int)(((orient == PORTRAIT) ? xwd_header.pixmap_width | ||
1252 | : xwd_header.pixmap_height) | ||
1253 | * dotsize / 10)); | ||
1254 | |||
1255 | fprintf(out,"\033*t%dV", | ||
1256 | (int)(((orient == PORTRAIT) ? xwd_header.pixmap_height | ||
1257 | : xwd_header.pixmap_width) | ||
1258 | * dotsize / 10)); | ||
1259 | } | ||
1260 | |||
1261 | /* Switch to raster graphics mode */ | ||
1262 | if (device != PJETXL) | ||
1263 | fprintf(out,"\033*r1A"); | ||
1264 | else | ||
1265 | fprintf(out,"\033*r3A"); | ||
1266 | |||
1267 | } | ||
1268 | |||
1269 | |||
1270 | static | ||
1271 | void write_image_suffix ( | ||
1272 | FILE *out, | ||
1273 | const char *trailer, | ||
1274 | int position_on_page, | ||
1275 | int slide, int render, | ||
1276 | enum device device) | ||
1277 | { | ||
1278 | /* Exit raster graphics mode */ | ||
1279 | if (device == PJETXL) | ||
1280 | fprintf(out,"\033*rC"); | ||
1281 | else | ||
1282 | fprintf(out,"\033*rB"); | ||
1283 | |||
1284 | /* If doing transparencies, tell it to stop */ | ||
1285 | if (slide && device != LJET) | ||
1286 | fprintf(out, "\033&k1W"); | ||
1287 | |||
1288 | if (device == PJETXL) { | ||
1289 | /* If selected a rendering algorithm, tell it to stop */ | ||
1290 | if (render) | ||
1291 | fprintf(out, "\033*t3J"); | ||
1292 | fprintf(out, "\033&a0N"); | ||
1293 | } | ||
1294 | |||
1295 | /* Write out trailer & positioning commands */ | ||
1296 | if (trailer) { | ||
1297 | if (position_on_page) | ||
1298 | fprintf(out,"\033&a%dH\033&a%dV", | ||
1299 | /* trailerloc x & y are written in decipoints */ | ||
1300 | (int) trailerloc.x / 10, (int) trailerloc.y / 10); | ||
1301 | fprintf(out,"%s\n", trailer); | ||
1302 | } | ||
1303 | } | ||
1304 | |||
1305 | |||
1306 | static | ||
1307 | unsigned long Z_image_pixel (int x, int y) | ||
1308 | { | ||
1309 | int pixel_bytes, offset; | ||
1310 | unsigned char *image; | ||
1311 | unsigned long pixel; | ||
1312 | |||
1313 | pixel_bytes = xwd_header.bits_per_pixel >> 3; | ||
1314 | offset = ((xwd_header.bits_per_pixel == 4) ? (x / 2) | ||
1315 | : ((xwd_header.bits_per_pixel == 1) ? (x / 8) | ||
1316 | : (x * pixel_bytes))) | ||
1317 | + (y * xwd_header.bytes_per_line); | ||
1318 | |||
1319 | image = (unsigned char *) &xwd_image[offset]; | ||
1320 | |||
1321 | switch (pixel_bytes) { | ||
1322 | case 0: /* pixel per nibble or bit per pixel packing */ | ||
1323 | if (xwd_header.bits_per_pixel == 1) { | ||
1324 | if (xwd_header.byte_order == MSBFirst1) | ||
1325 | pixel = *image >> (7 - (x % 8)); | ||
1326 | else | ||
1327 | pixel = *image >> (x % 8); | ||
1328 | } else { /* xwd_header.bits_per_pixel == 4 */ | ||
1329 | if (xwd_header.byte_order == MSBFirst1) | ||
1330 | pixel = (x & 1) ? *image : (*image >> 4); | ||
1331 | else | ||
1332 | pixel = (x & 1) ? (*image >> 4) : *image; | ||
1333 | } | ||
1334 | break; | ||
1335 | case 1: | ||
1336 | pixel = *image; | ||
1337 | break; | ||
1338 | case 2: | ||
1339 | pixel = (xwd_header.byte_order == MSBFirst1) | ||
1340 | ? ((unsigned long)*image << 8 | *(image + 1)) | ||
1341 | : (*image | (unsigned long)*(image + 1) << 8); | ||
1342 | break; | ||
1343 | case 3: | ||
1344 | pixel = (xwd_header.byte_order == MSBFirst1) | ||
1345 | ? ((unsigned long)*image << 16 | | ||
1346 | (unsigned long)*(image + 1) << 8 | | ||
1347 | (unsigned long)*(image + 2)) | ||
1348 | : (*image | | ||
1349 | (unsigned long)*(image + 1) << 8 | | ||
1350 | (unsigned long)*(image + 2) << 16); | ||
1351 | break; | ||
1352 | case 4: | ||
1353 | pixel = (xwd_header.byte_order == MSBFirst1) | ||
1354 | ? ((unsigned long)*image << 24 | | ||
1355 | (unsigned long)*(image+1) << 16 | | ||
1356 | (unsigned long)*(image+2) << 8 | | ||
1357 | *(image+3)) | ||
1358 | : (*image | | ||
1359 | (unsigned long)*(image+1) << 8 | | ||
1360 | (unsigned long)*(image+2) << 16 | | ||
1361 | (unsigned long)*(image+3) << 24); | ||
1362 | break; | ||
1363 | default: | ||
1364 | pixel = 0; | ||
1365 | break; | ||
1366 | } | ||
1367 | return (pixel & Z_pixel_mask); | ||
1368 | } | ||
1369 | |||
1370 | |||
1371 | static | ||
1372 | unsigned long XY_image_pixel (int x, int y) | ||
1373 | { | ||
1374 | int plane_start, line_start, bytes_per_bitmap_unit, bitmap_unit_start, | ||
1375 | byte_within_bitmap_unit, offset, byte_mask; | ||
1376 | |||
1377 | plane_start = (xwd_header.pixmap_depth - 1) * xwd_header.pixmap_height | ||
1378 | * xwd_header.bytes_per_line; | ||
1379 | line_start = xwd_header.bytes_per_line * y; | ||
1380 | bytes_per_bitmap_unit = xwd_header.bitmap_unit >> 3; | ||
1381 | bitmap_unit_start = (x / xwd_header.bitmap_unit) * bytes_per_bitmap_unit; | ||
1382 | byte_within_bitmap_unit = (xwd_header.byte_order == MSBFirst1) | ||
1383 | ? (x % xwd_header.bitmap_unit) >> 3 | ||
1384 | : bytes_per_bitmap_unit - ((x % xwd_header.bitmap_unit) >> 3) - 1; | ||
1385 | |||
1386 | offset = plane_start + line_start + bitmap_unit_start | ||
1387 | + byte_within_bitmap_unit; | ||
1388 | |||
1389 | byte_mask = (xwd_header.bitmap_bit_order == MSBFirst1) | ||
1390 | ? 0x80 >> (x % 8) : 0x01 << (x % 8); | ||
1391 | |||
1392 | return(xwd_image[offset] & byte_mask ? 1 : 0); | ||
1393 | } | ||
1394 | |||
1395 | |||
1396 | static | ||
1397 | void direct_by_pixel( | ||
1398 | FILE *out, | ||
1399 | long *line, | ||
1400 | int length, | ||
1401 | enum device device) | ||
1402 | { | ||
1403 | int red, green, blue; | ||
1404 | long compositeRGB; | ||
1405 | |||
1406 | fprintf(out, "\033*b%dW", length * 3); | ||
1407 | for (; length>0; length--, line++) { | ||
1408 | select_printer_color(*line, &red, &green, &blue, &compositeRGB, device); | ||
1409 | fprintf(out, "%c%c%c", (char) red, (char) green, (char) blue); | ||
1410 | } | ||
1411 | } | ||
1412 | |||
1413 | |||
1414 | static | ||
1415 | void index_by_pixel( | ||
1416 | FILE *out, | ||
1417 | long *line, | ||
1418 | int length) | ||
1419 | { | ||
1420 | register int n; | ||
1421 | long *lp; | ||
1422 | char *line_pixels; | ||
1423 | register char *lc; | ||
1424 | |||
1425 | if (!(line_pixels = malloc(length))) | ||
1426 | fatal_err((catgets(nlmsg_fd,NL_SETN,17,("Could not allocate raster line memory.") | ||
1427 | "Could not allocate raster line memory.")("Could not allocate raster line memory."))); | ||
1428 | |||
1429 | for (n=0, lc=line_pixels, lp=line; n<length; n++) | ||
1430 | *lc++ = (char) *lp++; | ||
1431 | |||
1432 | fprintf(out, "\033*b%dW", length); | ||
1433 | fwrite(line_pixels, 1, length, out); | ||
1434 | |||
1435 | free(line_pixels); | ||
1436 | } | ||
1437 | |||
1438 | |||
1439 | static | ||
1440 | void write_raster_line ( | ||
1441 | FILE *out, | ||
1442 | int scale, | ||
1443 | enum device device, | ||
1444 | long *line, | ||
1445 | int length) | ||
1446 | { | ||
1447 | int planes = (device == PJET) ? 4 : 1; | ||
1448 | int raster_bytes = (length * scale + 7) / 8; | ||
1449 | register int bytebits, n, p, e, bit; | ||
1450 | long *lp; | ||
1451 | char *line_colors, *raster_line; | ||
1452 | register char *lc, *rl, byte = 0; | ||
1453 | |||
1454 | if (device == PJETXL) { | ||
1455 | if (Direct_or_TrueColor) | ||
1456 | direct_by_pixel(out, line, length, device); | ||
1457 | else | ||
1458 | index_by_pixel(out, line, length); | ||
1459 | return; | ||
1460 | } | ||
1461 | |||
1462 | if (!(line_colors = malloc(length)) | ||
1463 | || !(raster_line = malloc(raster_bytes * planes))) | ||
1464 | fatal_err((catgets(nlmsg_fd,NL_SETN,17,("Could not allocate raster line memory.") | ||
1465 | "Could not allocate raster line memory.")("Could not allocate raster line memory."))); | ||
1466 | |||
1467 | if (device == PJET || Direct_or_TrueColor) | ||
1468 | download_colors(line, length, device); | ||
1469 | |||
1470 | /* Map the line's colors into output color index numbers */ | ||
1471 | if (Direct_or_TrueColor) | ||
1472 | for (n=0, lc=line_colors, lp=line; n<length; n++) | ||
1473 | *lc++ = (char) lookup_color_index(*lp++); | ||
1474 | else | ||
1475 | for (n=0, lc=line_colors, lp=line; n<length; n++) | ||
1476 | *lc++ = (char) colormap[*lp++]; | ||
1477 | |||
1478 | for (p=0; p<planes; p++) { | ||
1479 | bytebits = 0; | ||
1480 | n = length; | ||
1481 | lc = line_colors; | ||
1482 | rl = &raster_line[raster_bytes * p]; | ||
1483 | while (n-- > 0) { | ||
1484 | bit = (*lc++ >> p) & 0x01; | ||
1485 | e = scale; | ||
1486 | while (e--) { | ||
1487 | byte = (byte << 1) | bit; | ||
1488 | bytebits++; | ||
1489 | if (bytebits == 8) { | ||
1490 | *rl++ = byte; | ||
1491 | bytebits = 0; | ||
1492 | } | ||
1493 | } | ||
1494 | } | ||
1495 | if (bytebits) | ||
1496 | *rl = byte << (8 - bytebits); | ||
1497 | } | ||
1498 | |||
1499 | e = scale; | ||
1500 | while (e--) { | ||
1501 | for (p=0; p<planes; p++) { | ||
1502 | fprintf(out,"\033*b%d%c", raster_bytes, (p+1 == planes) ? 'W' : 'V'); | ||
1503 | fwrite(&raster_line[raster_bytes * p], 1, raster_bytes, out); | ||
1504 | } | ||
1505 | } | ||
1506 | |||
1507 | free(line_colors); | ||
1508 | free(raster_line); | ||
1509 | } | ||
1510 | |||
1511 | |||
1512 | static | ||
1513 | void write_portrait_Z_image ( | ||
1514 | FILE *out, | ||
1515 | int scale, | ||
1516 | enum device device) | ||
1517 | { | ||
1518 | int x, y; | ||
1519 | int width = limit.width; | ||
1520 | int height = limit.height; | ||
1521 | long *line, *lp; | ||
1522 | |||
1523 | if (!(line = (long *) malloc(width * sizeof(long)))) | ||
1524 | fatal_err((catgets(nlmsg_fd,NL_SETN,18,("Could not allocate memory for image line buffer.") | ||
1525 | "Could not allocate memory for image line buffer.")("Could not allocate memory for image line buffer."))); | ||
1526 | |||
1527 | for (y=0; y<height; y++) { | ||
1528 | |||
1529 | for (x=0, lp=line; x<width; x++) | ||
1530 | *lp++ = Z_image_pixel(x,y); | ||
1531 | |||
1532 | write_raster_line(out, scale, device, line, width); | ||
1533 | } | ||
1534 | } | ||
1535 | |||
1536 | |||
1537 | static | ||
1538 | void write_landscape_Z_image ( | ||
1539 | FILE *out, | ||
1540 | int scale, | ||
1541 | enum device device) | ||
1542 | { | ||
1543 | int x, y; | ||
1544 | int width = limit.height; | ||
1545 | int height = limit.width; | ||
1546 | long *line, *lp; | ||
1547 | |||
1548 | if (!(line = (long *) malloc(width * sizeof(long)))) | ||
1549 | fatal_err((catgets(nlmsg_fd,NL_SETN,19,("Could not allocate memory for image line buffer.") | ||
1550 | "Could not allocate memory for image line buffer.")("Could not allocate memory for image line buffer."))); | ||
1551 | |||
1552 | for (x=0; x<height; x++) { | ||
1553 | |||
1554 | for (y=width-1, lp=line; y>=0; y--) | ||
1555 | *lp++ = Z_image_pixel(x,y); | ||
1556 | |||
1557 | write_raster_line(out, scale, device, line, width); | ||
1558 | } | ||
1559 | } | ||
1560 | |||
1561 | |||
1562 | static | ||
1563 | void write_portrait_XY_image ( | ||
1564 | FILE *out, | ||
1565 | int scale, | ||
1566 | enum device device) | ||
1567 | { | ||
1568 | int x, y; | ||
1569 | int width = limit.width; | ||
1570 | int height = limit.height; | ||
1571 | long *line, *lp; | ||
1572 | |||
1573 | if (!(line = (long *) malloc(width * sizeof(long)))) | ||
1574 | fatal_err((catgets(nlmsg_fd,NL_SETN,20,("Could not allocate memory for image line buffer.") | ||
1575 | "Could not allocate memory for image line buffer.")("Could not allocate memory for image line buffer."))); | ||
1576 | |||
1577 | for (y=0; y<height; y++) { | ||
1578 | |||
1579 | for (x=0, lp=line; x<width; x++) | ||
1580 | *lp++ = XY_image_pixel(x,y); | ||
1581 | |||
1582 | write_raster_line(out, scale, device, line, width); | ||
1583 | } | ||
1584 | } | ||
1585 | |||
1586 | |||
1587 | static | ||
1588 | void write_landscape_XY_image ( | ||
1589 | FILE *out, | ||
1590 | int scale, | ||
1591 | enum device device) | ||
1592 | { | ||
1593 | int x, y; | ||
1594 | int width = limit.height; | ||
1595 | int height = limit.width; | ||
1596 | long *line, *lp; | ||
1597 | |||
1598 | if (!(line = (long *) malloc(width * sizeof(long)))) | ||
1599 | fatal_err((catgets(nlmsg_fd,NL_SETN,21,("Could not allocate memory for image line buffer.") | ||
1600 | "Could not allocate memory for image line buffer.")("Could not allocate memory for image line buffer."))); | ||
1601 | |||
1602 | for (x=0; x<height; x++) { | ||
1603 | |||
1604 | for (y=width-1, lp=line; y>=0; y--) | ||
1605 | *lp++ = XY_image_pixel(x,y); | ||
1606 | |||
1607 | write_raster_line(out, scale, device, line, width); | ||
1608 | } | ||
1609 | } | ||
1610 | |||
1611 | |||
1612 | static | ||
1613 | void write_Z_image ( | ||
1614 | FILE *out, | ||
1615 | int scale, | ||
1616 | enum orientation orient, | ||
1617 | enum device device) | ||
1618 | { | ||
1619 | if (orient == PORTRAIT) { | ||
1620 | write_portrait_Z_image(out, scale, device); | ||
1621 | } else | ||
1622 | write_landscape_Z_image(out, scale, device); | ||
1623 | } | ||
1624 | |||
1625 | |||
1626 | static | ||
1627 | void write_XY_image ( | ||
1628 | FILE *out, | ||
1629 | int scale, | ||
1630 | enum orientation orient, | ||
1631 | enum device device) | ||
1632 | { | ||
1633 | if (xwd_header.pixmap_depth > 1) | ||
1634 | fatal_err((catgets(nlmsg_fd,NL_SETN,22,("XY format image, multiplane images must be Z format.") | ||
1635 | "XY format image, multiplane images must be Z format.")("XY format image, multiplane images must be Z format."))); | ||
1636 | |||
1637 | if (orient == PORTRAIT) { | ||
1638 | write_portrait_XY_image(out, scale, device); | ||
1639 | } else | ||
1640 | write_landscape_XY_image(out, scale, device); | ||
1641 | } | ||
1642 | |||
1643 | |||
1644 | static | ||
1645 | void write_image ( | ||
1646 | FILE *out, | ||
1647 | int scale, | ||
1648 | enum orientation orient, | ||
1649 | enum device device) | ||
1650 | { | ||
1651 | switch (xwd_header.pixmap_format) { | ||
1652 | case XYPixmap1: | ||
1653 | write_XY_image(out, scale, orient, device); break; | ||
1654 | case ZPixmap2: | ||
1655 | write_Z_image(out, scale, orient, device); break; | ||
1656 | default: | ||
1657 | fatal_err((catgets(nlmsg_fd,NL_SETN,23, "image not in XY or Z format.")("image not in XY or Z format."))); | ||
1658 | } | ||
1659 | } | ||
1660 | |||
1661 | |||
1662 | void x2jet( | ||
1663 | FILE *in, FILE *out, | ||
1664 | int scale, int density, | ||
1665 | int width, int height, int left, int top, /* in 300ths of an inch */ | ||
1666 | const char *header, const char *trailer, | ||
1667 | enum orientation orient, | ||
1668 | int invert, int initial_formfeed, int position_on_page, int slide, | ||
1669 | enum device device, | ||
1670 | unsigned int cutoff, | ||
1671 | float gamma, | ||
1672 | int render) | ||
1673 | { | ||
1674 | int paintjet = FALSE0; | ||
1675 | |||
1676 | true_scale = scale; | ||
1677 | |||
1678 | if (device != LJET) | ||
1679 | paintjet = TRUE1; | ||
1680 | |||
1681 | read_xwd_data(in); | ||
1682 | |||
1683 | Z_pixel_mask = ~(0xFFFFFFFFUL << xwd_header.pixmap_depth); | ||
1684 | |||
1685 | prepare_color_mapping(invert, paintjet, cutoff, out); | ||
1686 | |||
1687 | scale_and_orient_image(&scale, &density, width, height, left, top, | ||
1688 | header, trailer, | ||
1689 | &orient, position_on_page, device); | ||
1690 | |||
1691 | write_image_prefix(out, scale, density, header, device, position_on_page, | ||
1692 | initial_formfeed, orient, gamma, render, slide); | ||
1693 | |||
1694 | write_image(out, scale, orient, device); | ||
1695 | |||
1696 | write_image_suffix(out, trailer, position_on_page, slide, render, device); | ||
1697 | |||
1698 | fclose(out); | ||
1699 | } | ||
1700 | |||
1701 | static | ||
1702 | void fatal_err (const char *s, ...) | ||
1703 | { | ||
1704 | va_list ap; | ||
1705 | |||
1706 | fprintf(stderrstderr, "%s: ", progname); | ||
1707 | va_start(ap, s)__builtin_va_start(ap, s); | ||
1708 | vfprintf(stderrstderr, s, ap); | ||
1709 | va_end(ap)__builtin_va_end(ap); | ||
1710 | fputc('\n', stderrstderr); | ||
1711 | exit(EXIT_FAILURE1); | ||
1712 | } | ||
1713 |