1 /* Copyright (C) 1997-2004 artofcode LLC. 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: gdevupd.c,v 1.16 2004/08/04 19:36:12 stefan Exp $ */
18 /* gdevupd.c Revision: 1.88 */
19 /* "uniprint" -- Ugly Printer Driver by Gunther Hess (ghess@elmos.de) */
20
21 /* Revision-History:
22 23-Mar-1997 - 1.43: First published version
23 24-Mar-1997 - 1.44: gs4.03 compatible version on the web
24 31-Mar-1997 - 1.53: First Version inside gs-fileset (limited)
25 28-Apr-1997 - 1.54: Version intended for public gs-release
26 4-May-1997 - 1.55: Deactivated an accidentially active Debug-Option
27 14-Jun-1997 - 1.56: Bug-Workaround for White on White Printing (gs5.0)
28 17-Jun-1997 - 1.57: More reasonable Fix for the above Bug
29 ...
30 7-Jul-1997 - 1.68: NULL-Param-BUG, HR's BJC, Pwidth/-height BUG, YFlip
31 25-Jul-1997 - 1.69: Bug-Fix: incomplete Change of PHEIGHT-Treatment
32 4-Aug-1997 - 1.70: Arrgh: still incomplete Change of PHEIGHT-Treatment
33 17-AUG-1997 - 1.71: Fix of BSD-sprintf bug. (returns char * there)
34 ...
35 28-Sep-1997 - 1.77: Fixed the byte<>char and casted-lvalue Problems
36 ...
37 12-Mar-1998 - 1.80: Some PJL-Functions, Map-Bug-Fix (by Wonder-Wolfgang)
38 21-Oct-1998 - 1.81: Added RGB2CMY[_]K Modi (Eric Domenjoud)
39 ...
40 27-Feb-2000 - 1.84: CMYKgenerate with forced K-Control [distributed]
41 2-Apr-2000 - Unofficial modifications for Epson Stylus Color 300. GR
42 5-Apr-2000 - GR fixed last row not filled bug in wrtescnm
43 7-May-2000 - 1.85: Always BOP/EOP-Massaging for RTL-Output (Dan Coby)
44 ...
45 7-May-2000 - 1.87: integrated stc300-code by Glenn Ramsey
46 " - 1.88: reduced "cast discards `const'" warnings to 1
47
48 */
49
50 /* Canon BJC 610 additions from (hr)
51 Helmut Riegler <helmut-riegler@net4you.co.at>
52
53 The BJC-4000 can be supported very easily, only by creating the right .upp
54 parameter file. If you have this printer and you are willing to do this,
55 contact me, I'll give you the technical details (ESC codes).
56 */
57
58 /* Epson Stylus Color 300 (FMT_ESCNMY) additions 2-Apr-2000.
59 Glenn Ramsey <glennr@es.co.nz>
60 */
61
62 /* ------------------------------------------------------------------- */
63 /* Compile-Time-Options */
64 /* ------------------------------------------------------------------- */
65
66 /**
67 There are two compile-time options for this driver:
68 1. UPD_SIGNAL enables interrupt detection, that aborts printing and
69 2. UPD_MESSAGES controls the amount of messages generated by the driver
70 */
71
72 #ifndef UPD_SIGNAL
73 #ifdef __unix__
74 #define UPD_SIGNAL 1 /** Activated, if undefined, on UNIX-Systems */
75 #else /* !__unix__ */
76 #define UPD_SIGNAL 0 /** Inactive on others, by default */
77 #endif /* ?__unix__ */
78 #endif /* UPD_SIGNAL */
79
80 #ifndef UPD_MESSAGES
81 #define UPD_MESSAGES UPD_M_ERROR /** Error-messages only, if not defined */
82 #endif /* UPD_MESSAGES */
83
84 /* ------------------------------------------------------------------- */
85 /* Required Header-Files */
86 /* ------------------------------------------------------------------- */
87
88 #include "stdint_.h"
89
90 #ifndef hess_test_INCLUDED /* A private test-Option */
91
92 #include "gdevprn.h" /** Printer-superclass header */
93 #include "gsparam.h" /** For the Parameter-Handling (optional) */
94
95 #include <stdlib.h> /** for rand */
96 #include <limits.h> /** for INT_MIN */
97 #include <ctype.h> /** for isupper */
98
99 #endif /* hess_test_INCLUDED A private test-Option */
100
101 #if UPD_SIGNAL
102 #include <signal.h> /** Only included, if UPD_SIGNAL is active (true) */
103 #endif /* UPD_SIGNAL */
104
105 /* ------------------------------------------------------------------- */
106 /* Device-Structure (including an additional Structure-Pointer-Type) */
107 /* ------------------------------------------------------------------- */
108
109 typedef struct upd_s upd_t,*upd_p; /** Type & Pointer of device-specifics */
110 typedef const upd_t *upd_pc; /** Pointer to constant device-specfics */
111
112 typedef struct upd_device_s { /** The driver must typedef ... */
113 gx_device_common; /** common fields for all devices */
114 gx_prn_device_common; /** common fields for printing-devices */
115 gs_param_string upd_version; /** Source-Code Version */
116 upd_p upd; /** uniprint-specific extension */
117 } upd_device; /** some type usually <name>_device> */
118
119 /* ------------------------------------------------------------------- */
120 /* Major Driver-Functions */
121 /* ------------------------------------------------------------------- */
122
123 private dev_proc_print_page(upd_print_page); /** print a page (required) */
124
125 private dev_proc_open_device(upd_open); /** device-initialization (opt) */
126 private dev_proc_close_device(upd_close); /** device-release (opt) */
127
128 private dev_proc_get_params(upd_get_params); /** export parameters (opt) */
129 private dev_proc_put_params(upd_put_params); /** import parameters (opt) */
130
131 /**
132 A `normal' Device-Driver wil only implement one of the following pairs
133 of functions for the colormapping. But "uniprint" is something special and
134 it really provides all four reasonable pairs and in addition to that
135 a fifth set of functions, that delivers better FS-Results with KCMY.
136
137 The first pair is for the mapping into a single stored component, that
138 usually represents a grayscale. But nevertheless GHOSTSCRIPT deals with
139 RGB-Values, but promises to deal with R==G==B-Values when asking to map.
140
141 The second pair deals with RGB-Values.
142 */
143
144 private dev_proc_encode_color( upd_rgb_1color); /** Gray-Gray->Index */
145 private dev_proc_decode_color( upd_1color_rgb); /** Gray-Index->Gray */
146
147 private dev_proc_encode_color( upd_rgb_3color); /** RGB->RGB-Index */
148 private dev_proc_decode_color( upd_3color_rgb); /** RGB-Index->RGB */
149
150 /**
151 The third pair maps RGB-Values into four components, which one might
152 expect to be KCMY-Values, but they are not: "uniprint" considers this four
153 Values as White+RGB Values!
154 */
155
156 private dev_proc_encode_color( upd_rgb_4color); /** RGB->WRGB-Index */
157 private dev_proc_decode_color(upd_4color_rgb); /** WRGB-Index->RGB */
158
159 /**
160 The fourth pair deals with KCMY-Values. The Mapping-Function
161 is of a different type, due to the additional argument, but the
162 inverse-Function is of the same type, and expects RGB-Values to be
163 deliverd into the receiving 3-Component-Array!
164 */
165
166 private dev_proc_encode_color(upd_cmyk_icolor); /** KCMY->KCMY-Index */
167 private dev_proc_decode_color( upd_icolor_rgb); /** KCMY->RGB-Index */
168
169 /**
170 The difference between the icolor-pair and the kcolor-pair is the enforced
171 black-generation in the forward-mapping. that is taken into account by the
172 reverse-mapping too.
173 */
174
175 private dev_proc_encode_color(upd_cmyk_kcolor); /** adds black generation */
176 private dev_proc_decode_color( upd_kcolor_rgb); /** watches black-gen */
177
178 /**
179 "ovcolor" is CMYK with Black-Generation and Undercolor-Removal, which
180 is suitable for overprinting:
181 CMY' = (CMY-K')/(1-K')
182 with
183 K' = min(C,M,Y)
184 */
185
186 private dev_proc_encode_color(upd_rgb_ovcolor); /** RGB->CMYK-Index */
187 #define upd_ovcolor_rgb upd_icolor_rgb /** CMYK-Index->RGB */
188
189 /**
190 "novcolor" is CMYK with Black-Generation and Undercolor-Removal, which
191 is suitable for CMY / K - Printing:
192 CMY' = CMY-K'
193 with
194 K' = min(C,M,Y)
195 */
196
197 private dev_proc_encode_color(upd_rgb_novcolor); /** RGB->CMYK-Index */
198 #define upd_novcolor_rgb upd_icolor_rgb /** CMYK-Index->RGB */
199
200 /**
201 For the sake of efficiency there is that bunch of functions and they
202 perform no validity checks, thus it has to be assured that they are
203 only active, if there is a valid device-structure for then.
204 upd_procs_map performs this task.
205 */
206
207 private int upd_procs_map( upd_device *udev);
208
209 /* ------------------------------------------------------------------- */
210 /* Prototype of the Device-Structure (the only thing exported!) */
211 /* ------------------------------------------------------------------- */
212
213 /**
214 "uniprint" needs a procedure-table of its own, since it provides several
215 optional procedures. Simpler-Drivers (e.g. non-color-drivers) may use
216 prn_std_procs instead of defining their own procedure-table.
217 */
218
219 #define upd_set_dev_proc(dev, p, proc) \
220 ((dev)->std_procs.p = (dev)->orig_procs.p = (proc))
221
222 private gx_device_procs upd_procs = { /** Table of procedures */
223 upd_open, /** open-function, upd-special */
224 gx_default_get_initial_matrix, /** retrieve matrix */
225 gx_default_sync_output, /** sync display */
226 gdev_prn_output_page, /** superclass-print (calls back) */
227 upd_close, /** close-function, upd-special */
228 gx_default_map_rgb_color, /** RGB-mapping */
229 gx_default_map_color_rgb, /** reverse mapping */
230 NULL, /** fill_rectangle */
231 NULL, /** tile_rectangle */
232 NULL, /** copy_mono */
233 NULL, /** copy_color */
234 NULL, /** draw_line */
235 gx_default_get_bits, /** reads scanlines, e.g. for the driver */
236 upd_get_params, /** Export parameters, upd-special */
237 upd_put_params, /** Import parameters, upd-special */
238 gx_default_map_cmyk_color /** KCMY-mapping */
239 }; /** */
240
241 /**
242 The prototype-instance of the device-structure _must_ have the name
243 "gs_uniprint_device", where "uniprint" is the external name of the driver.
244 This notice is bluntly copied from drivers.txt, which a potential
245 driver-author should carefully read.
246
247 Just to mention: this prototype is quite similar to the one, that
248 "prn_device" produces and it identifies "uniprint" as a monochrome 1Bit
249 device to GHOSTSCRIPT. But during the lifetime of a driver-instance
250 this might change.
251
252 This is the end of the part of declarations, that are common for
253 color-drivers. The next sections address "uniprint"-specific data-types
254 and the reader might directly skip to the section titled
255
256 upd_print_page: The main workhorse
257 */
258
259 upd_device far_data gs_uniprint_device = { /** */
260 prn_device_body(upd_device, upd_procs, /** The Type and Procedures */
261 "uniprint", /** External name of the Device */
262 DEFAULT_WIDTH_10THS, /** X-Size (1/10") */
263 DEFAULT_HEIGHT_10THS, /** Y-Size (1/10") */
264 72, 72, /** X,Y-DpI */
265 0.0, 0.0, 0.0, 0.0, /** L,B,R,T-Margin */
266 1, /** color_info.num_components 1/3/4 */
267 1, /** color_info.depth 1/2/4/8/16/24/32 */
268 1, /** color_info.max_gray # of distinct gray levels -1 (255/1) */
269 0, /** color_info.max_color # of distinct color levels -1 (255/1/0)*/
270 2, /** color_info.dither_grays size of gray ramp for dithering (256/2) */
271 0, /** color_info.dither_colors size of color cube ditto (256/2/0) */
272 upd_print_page), /** Print-procedure */
273 { NULL, 0, true }, /** Driver-Version */
274 NULL /** upd-field: Initially none */
275 }; /** */
276
277
278 /* ------------------------------------------------------------------- */
279 /* UPD-Data- and Prototypes */
280 /* ------------------------------------------------------------------- */
281
282 /*@ gdevupd.h < */
283 /* ------------------------------------------------------------------- */
284 /* External names of the UPD-Parameters */
285 /* ------------------------------------------------------------------- */
286
287 /** UPD-Parameters
288
289 "uniprint" supports a hole bunch of external parameters. This Parameters
290 fall into the following categories:
291
292 0. special-string the upd_version, readonly upd_version
293 1. choice name-indices, stored in upd->choice
294 2. boolean single bits, stored in upd->flags
295 3. integers single numbers, stored in upd->ints
296 4. integer-Arrays arrays of numbers, stored in upd->int_a
297 5. string device-commands, stored in upd->strings
298 6. string-Arrays arrayed device-commands, stored in upd->string_a
299 7. float-Arrays arrays of floats, stored in upd->float_a
300
301 Currently there is no need for single floats, but they may be introduced in
302 future versions. Since "uniprint" somtimes manipulates the contents of the
303 array-variables it dynamically allocates storage for all this parameters.
304
305 The following sections defines the names for this parameters in the order,
306 they are stored within the mentioned dynamic fields of the upd-structure.
307 A NULL-name means that the corresponding parameter is not externally visible.
308 Besides the name, there is always a symbolic index #defined, that MUST match
309 the Index-Number of the name.
310 Actually
311 */
312
313 static const char *const upd_version = "upVersion"; /** Readonly Version */
314
315 /** Names for the multiple-choice-Parameters
316
317 Currently there are three Parameters, that are handled as named choices.
318 For each of them, there is an array of constant strings that consists of
319
320 1. the Parameter-Name
321 2. - n-1 the available choices.
322 n. A terminating NULL
323 */
324
325 static const char *const upd_mapper[] = { "upColorModel",
326 #define MAP_GRAY 1 /** Monochrome & Grayscale Devices */
327 "DeviceGray", /** Monochrome & Grayscale Devices */
328 #define MAP_RGBW 2 /** RGB with White-Generation */
329 "DeviceRGBW", /** RGB with White-Generation */
330 #define MAP_RGB 3 /** RGB-Mapping */
331 "DeviceRGB", /** RGB-Mapping */
332 #define MAP_CMYK 4 /** CMYK-Mapping */
333 "DeviceCMYK", /** CMYK-Mapping */
334 #define MAP_CMYKGEN 5 /** CMYK-Mapping with Black-Generation */
335 "DeviceCMYKgenerate", /** CMYK-Mapping with Black-Generation */
336 #define MAP_RGBOV 6 /** RGB->CMYK with BG and UCR for CMYK */
337 "DeviceRGB2CMYK", /** RGB->CMYK with BG and UCR for CMYK */
338 #define MAP_RGBNOV 7 /** RGB->CMYK with BG and UCR for CMY + K */
339 "DeviceRGB2CMY_K", /** RGB->CMYK with BG and UCR for CMY + K */
340 NULL
341 };
342
343 static const char *const upd_render[] = { "upRendering",
344 #define RND_FSCOMP 1 /** Componentwise Floyd-Steinberg */
345 "ErrorDiffusion", /** Componentwise Floyd-Steinberg */
346 #define RND_FSCMYK 2 /** CMYK-specialized 32Bit Floyd-Steinberg */
347 "FSCMYK32", /** CMYK-specialized 32Bit Floyd-Steinberg */
348 #define RND_FSCMY_K 3 /** CMY_K Rendering */
349 "FSCMY_K",
350 NULL
351 };
352
353 static const char *const upd_format[] = { "upOutputFormat",
354 #define FMT_RAS 1 /** Generates SUN-Rasterfiles */
355 "SunRaster", /** Generates SUN-Rasterfiles */
356 #define FMT_EPSON 2 /** Generates X+Y-Weaved ESC/P-Output */
357 "Epson", /** Generates X+Y-Weaved ESC/P-Output */
358 #define FMT_ESCP2Y 3 /** Generates Y-Weaved ESC/P2-Output */
359 "EscP2", /** Generates Y-Weaved ESC/P2-Output */
360 #define FMT_ESCP2XY 4 /** Generates X+Y-Weaved ESC/P2-Output */
361 "EscP2XY", /** Generates X+Y-Weaved ESC/P2-Output */
362 #define FMT_RTL 5 /** Generates HP-PCL/RTL-Output */
363 "Pcl", /** Generates HP-PCL/RTL-Output */
364 #define FMT_CANON 6 /** Generates Output for Canon extended mode (hr) */
365 "Canon", /** Generates Output for Canon extended mode (hr) */
366 #define FMT_ESCNMY 7 /** Generates Output for Epson Stylus Color 300 (GR) */
367 "EscNozzleMap", /** Generates Output for Epson Stylus Color 300 (GR) */
368 NULL
369 };
370
371 static const char *const *const upd_choice[] = {
372 #define C_MAPPER 0 /** the selected Mapper */
373 upd_mapper,
374 #define C_RENDER 1 /** the selected Rendering */
375 upd_render,
376 #define C_FORMAT 2 /** the selected Choice */
377 upd_format
378 };
379
380 /** Names for the flags (bool)
381 */
382
383 static const char *const upd_flags[] = { /** */
384 #define B_REVDIR ((uint32_t) 1<<0) /** FS-Dir-Flag */
385 "upFSReverseDirection", /** FS-Dir-Flag */
386 #define B_FIXDIR ((uint32_t) 1<<1) /** Do not alter FS-direction */
387 "upFSFixedDirection", /** Do not alter FS-direction */
388 #define B_FSWHITE ((uint32_t) 1<<2) /** Process white in FS */
389 "upFSProcessWhiteSpace", /** Process white in FS */
390 #define B_FSZERO ((uint32_t) 1<<3) /** Zero FS-Initialization */
391 "upFSZeroInit", /** Zero FS-Initialization */
392
393 #define B_PAGEWIDTH ((uint32_t) 1<<4) /** Adjust Width in BOP */
394 "upAdjustPageWidthCommand", /** Adjust Page-Width in BOP */
395 #define B_PAGELENGTH ((uint32_t) 1<<5) /** Adjust Length in BOP */
396 "upAdjustPageLengthCommand", /** Adjust Page-Length in BOP */
397 #define B_TOPMARGIN ((uint32_t) 1<<6) /** Adjust Top-Margin in BOP */
398 "upAdjustTopMarginCommand", /** Adjust Top-Margin in BOP */
399 #define B_BOTTOMMARGIN ((uint32_t) 1<<7) /** Adjust Bottom-Margin in BOP */
400 "upAdjustBottomMarginCommand", /** Adjust Bottom-Margin in BOP */
401 #define B_RESOLUTION ((uint32_t) 1<<8) /** Adjust Resolution in BOP */
402 "upAdjustResolutionCommand", /** Adjust Resolution in BOP */
403 #define B_MEDIASIZE ((uint32_t) 1<<9) /** Adjust Mediasize in BOP */
404 "upAdjustMediaSize", /** Adjust Mediasize in BOP */
405
406 #define B_XABS ((uint32_t) 1<<10) /** Use Absolute X-Values */
407 "upFormatXabsolute", /** Use Absolute X-Values */
408 #define B_YABS ((uint32_t) 1<<11) /** Use Absolute Y-Values */
409 "upFormatYabsolute", /** Use Absolute Y-Values */
410
411 #define B_MAP ((uint32_t) 1<<12) /** Mapping Initialized */
412 "upColorModelInitialized", /** Mapping Initialized */
413 #define B_BUF ((uint32_t) 1<<13) /** Raster-Buffer Initialized */
414 "upRasterBufferInitialized", /** Raster-Buffer Initialized */
415 #define B_RENDER ((uint32_t) 1<<14) /** Rendering Initialized */
416 "upRenderingInitialized", /** Rendering Initialized */
417 #define B_FORMAT ((uint32_t) 1<<15) /** Formatter Initialized */
418 "upOutputFormatInitialized", /** Formatter Initialized */
419 #define B_ABORT ((uint32_t) 1<<16) /** Abort on Interrupt */
420 "upOutputAborted", /** Abort on Interrupt */
421 #define B_ERROR ((uint32_t) 1<<17) /** Severe Error detected */
422 "upErrorDetected", /** Severe Error detected */
423
424 #define B_OPEN ((uint32_t) 1<<18) /** Open-Command written */
425 "upWroteData", /** Open-Command written */
426
427 #define B_YFLIP ((uint32_t) 1<<19) /** Mirrored printing (hr) */
428 "upYFlip", /** Mirrored printing (hr) */
429
430 #define B_REDUCEK ((uint32_t) 1<<20) /** CMY->Black Reduction */
431 "upFSReduceK"
432
433 };
434
435 /** B_OK4GO: Bits required to execute the print-loop */
436
437 #define B_OK4GO (B_MAP | B_BUF | B_RENDER | B_FORMAT)
438
439 /** Names for the ints
440 */
441
442 static const char *const upd_ints[] = {
443 #define I_PWIDTH 0 /** Output-Width */
444 "upOutputWidth",
445 #define I_PHEIGHT 1 /** Output-Height */
446 "upOutputHeight",
447 #define I_OCOMP 2 /** Output-Components */
448 "upOutputComponents",
449 #define I_NSCNBUF 3 /** Output-Buffers */
450 "upOutputBuffers",
451 #define I_XSTEP 4 /** Unit-Step */
452 "upOutputXStep", /* > 0 -> divide Raster-X, < 0 muliply Raster-X */
453 #define I_XOFS 5 /** abs. X-Offset */
454 "upOutputXOffset",
455 #define I_YSTEP 6 /** Unit-Step */
456 "upOutputYStep", /* > 0 -> divide Raster-Y, < 0 muliply Raster-Y */
457 #define I_YOFS 7 /** abs. Y-Offset */
458 "upOutputYOffset",
459 #define I_PINS2WRITE 8 /** Number of Pins */
460 "upOutputPins",
461
462 #define I_NXPASS 9 /** X-Passes */
463 "upWeaveXPasses",
464 #define I_NYPASS 10 /** Y-Passes */
465 "upWeaveYPasses",
466 #define I_NPASS 11 /** Total # Passes */
467 "upWeavePasses",
468 #define I_BEG_Y 12 /** Start of normal Weaving */
469 "upWeaveInitialScan",
470 #define I_END_Y 13 /** End of normal Weaving */
471 "upWeaveFinalScan",
472 #define I_BEGSKIP 14 /** A Scan-Offset */
473 "upWeaveYOffset",
474 #define I_ROWS 15 /** Output rows per pass */
475 "upNozzleMapRowsPerPass",
476 #define I_PATRPT 16 /** mask pattern repeat interval */
477 "upNozzleMapPatternRepeat"
478 };
479
480 /** Names for the Integer-Arrays
481 */
482
483 static const char *const upd_int_a[] = { /** */
484 #define IA_COLOR_INFO 0 /** external color_info */
485 "upColorInfo", /** external color_info */
486
487 #define IA_COMPBITS 1 /** Bits stored per Component */
488 "upComponentBits", /** Bits stored per Component */
489 #define IA_COMPSHIFT 2 /** Shift for the stored Bits */
490 "upComponentShift", /** Shift for the stored Bits */
491 #define IA_COMPORDER 3 /** Order of Output-Components */
492 "upOutputComponentOrder", /** Order of Output-Components */
493
494 #define IA_STD_DY 4 /** Standard-Weave Feeds */
495 "upWeaveYFeeds", /** Standard-Weave Feeds */
496 #define IA_STD_IX 5 /** Standard-Weave X-Passes */
497 "upWeaveXStarts", /** Standard-Weave X-Start */
498 #define IA_BEG_DY 6 /** Initial-Weave Feeds */
499 "upWeaveInitialYFeeds", /** Initial-Weave Feeds */
500 #define IA_BEG_IX 7 /** Initial-Weave X-Start */
501 "upWeaveInitialXStarts", /** Initial-Weave X-Start */
502 #define IA_BEGBOT 8 /** Initial-Weave #Pins */
503 "upWeaveInitialPins", /** Initial-Weave #Pins */
504 #define IA_END_DY 9 /** Final-Weave Feeds */
505 "upWeaveFinalYFeeds", /** Final-Weave Feeds */
506 #define IA_END_IX 10 /** Final-Weave X-Start */
507 "upWeaveFinalXStarts", /** Final-Weave X-Start */
508 #define IA_ENDTOP 11 /** Final-Weave #Pins */
509 "upWeaveFinalPins", /** Final-Weave #Pins */
510 #define IA_ROWMASK 12 /** The nozzle to row map */
511 "upNozzleMapRowMask",
512 #define IA_SCNOFS 13 /** Mask to scan map */
513 "upNozzleMapMaskScanOffset"
514 };
515
516 /** Names of the String-Parameters
517 */
518
519 static const char *const upd_strings[] = { /** */
520 #define S_MODEL 0 /** Name of the Printer-Model */
521 "upModel", /** Name of the Printer-Model */
522 #define S_OPEN 1 /** Printer-Begin-Job */
523 "upBeginJobCommand", /** Printer-Begin-Job */
524 #define S_CLOSE 2 /** Printer-End-Job */
525 "upEndJobCommand", /** Printer-End-Job */
526 #define S_BEGIN 3 /** Printer-Begin-Page */
527 "upBeginPageCommand", /** Printer-Begin-Page */
528 #define S_END 4 /** Printer-End-Page */
529 "upEndPageCommand", /** Printer-End-Page */
530 #define S_ABORT 5 /** Printer-Abort-Command */
531 "upAbortCommand", /** Printer-Abort-Command */
532
533 #define S_XMOVE 6 /** X-Positioning-Command */
534 "upXMoveCommand", /** X-Positioning-Command */
535 #define S_XSTEP 7 /** X-Step Command (1<I_XSTEP) */
536 "upXStepCommand", /** X-Step Command (1<I_XSTEP) */
537 #define S_SETLF 8 /** Set-Linefeed-Command */
538 "upSetLineFeedCommand", /** Set-Linefeed-Command */
539 #define S_YMOVE 9 /** Y-Positioning-Command */
540 "upYMoveCommand", /** Y-Positioning-Command */
541 #define S_YSTEP 10 /** Y-Step Command (1<I_YSTEP) */
542 "upYStepCommand" /** Y-Step Command (1<I_YSTEP) */
543 }; /** */
544
545 /** Names for the String-Arrays
546 */
547
548 static const char *const upd_string_a[] = { /** */
549 #define SA_SETCOMP 0 /** Select Components */
550 "upSelectComponentCommands", /** Select Components */
551 #define SA_WRITECOMP 1 /** Write Component Comands */
552 "upWriteComponentCommands" /** Write Component Commands */
553 }; /** */
554
555 /** Names for the float-Arrays
556 */
557 static const char *const upd_float_a[] = { /** */
558 #define FA_WXFER 0 /** White-Transfer */
559 "upWhiteTransfer", /** White-Transfer */
560 #define FA_RXFER 1 /** Red-Transfer */
561 "upRedTransfer", /** Red-Transfer */
562 #define FA_GXFER 2 /** Green-Transfer */
563 "upGreenTransfer", /** Green-Transfer */
564 #define FA_BXFER 3 /** Blue-Transfer */
565 "upBlueTransfer", /** Blue-Transfer */
566 #define FA_KXFER 4 /** Black-Transfer */
567 "upBlackTransfer", /** Black-Transfer */
568 #define FA_CXFER 5 /** Cyan-Transfer */
569 "upCyanTransfer", /** Cyan-Transfer */
570 #define FA_MXFER 6 /** Magenta-Transfer */
571 "upMagentaTransfer", /** Magenta-Transfer */
572 #define FA_YXFER 7 /** Yellow-Transfer */
573 "upYellowTransfer", /** Yellow-Transfer */
574 #define FA_MARGINS 8 /** private Margins */
575 "upMargins", /** private Margins */
576 #define FA_MAP 9 /** Color-Map */
577 "upColorMap" /** Color-Map */
578 }; /** */
579
580 /* ------------------------------------------------------------------- */
581 /* UPD-specific datatypes */
582 /* ------------------------------------------------------------------- */
583
584 /**
585 int32_t and uint32_t are 32Bit-Integer-Types used in the
586 Floyd-Steinberg Algorithm and instead of gx_color_index. The
587 8-Byte long's on some 64Bit-Machines are apparently useless,
588 since gdevprn.c does (currently) support only 32-Bit Rasterdata.
589 */
590
591 #undef INT32_MIN
592 #undef INT32_MAX
593 #undef UINT32_MAX
594
595 #if arch_log2_sizeof_int < 2 /* int is too small */
596 #define INT32_MIN LONG_MIN
597 #define INT32_MAX LONG_MAX
598 #define UINT32_MAX ULONG_MAX
599 #else /* int is sufficient */
600 #define INT32_MIN INT_MIN
601 #define INT32_MAX INT_MAX
602 #define UINT32_MAX UINT_MAX
603 #endif /* use int or long ? */
604
605 /**
606 "updcmap" is used by the color-mapping functions of the driver.
607 there are four cmaps in the "uniprint"-structure, one for each component.
608 To be exact, it's not "4" but rather "UPD_CMAP_MAX", which is a synonym.
609 */
610
611 typedef struct updcmap_s { /** */
612 gx_color_value *code; /** Values related to codes */
613 uint32_t bitmsk; /** Mask, right justified */
614 int bitshf; /** Shift to right-justify */
615 int xfer; /** Index to the Xfer-Array */
616 int bits; /** # of Bits */
617 int comp; /** Output-Number */
618 bool rise; /* Rising/Falling Curve */
619 } updcmap_t, *updcmap_p; /** */
620 typedef const updcmap_t *updcmap_pc;
621
622
623 /**
624 "updcomp" holds similar informations, but is used for the rendering
625 */
626
627 typedef struct updcomp_s { /* Parameters for Floyd-Steinberg */
628 int32_t offset; /* Offset added to scaled values */
629 int32_t scale; /* Scale for the raw values */
630 int32_t threshold; /* Val must be larger than this to fire */
631 int32_t spotsize; /* subtracted from Val when fired */
632 uint32_t bitmsk; /* Mask */
633 int bitshf; /* shift */
634 int bits; /* # of Bits */
635 int cmap; /* Index for the Parameter-name */
636 } updcomp_t, *updcomp_p; /* Parameters for Floyd-Steinberg */
637
638 /** updscan is the Element of the scan-buffer. */
639
640 typedef struct updscan_s { /* Single Scanline (1 Bit/Pixel) */
641 byte *bytes; /* Buffer used w. 32-Bit Words */
642 int *xbegin; /* 1st Pixel set (or nbytes<<3 if none) */
643 int *xend; /* last Pixel set (or -1, if none) */
644 } updscan_t, *updscan_p; /* Single Scanline (1 Bit/Pixel) */
645
646
647 /** Main upd-Structure ***/
648
649 #define UPD_CMAP_MAX 4 /** Number of Colormaps provided */
650 #define UPD_VALPTR_MAX 32 /** Number of valbuf-Pointers */
651
652 #define upd_proc_pxlget(name) uint32_t name(upd_p upd)
653 #define upd_proc_render(name) int name(upd_p upd)
654 #define upd_proc_writer(name) int name(upd_p upd,FILE *out)
655
656 struct upd_s { /* All upd-specific data */
657
658 int *choice; /** Named-Choices */
659 int *ints; /** Integers */
660 gs_param_int_array *int_a; /** Integer-Arrays */
661 gs_param_string *strings; /** Strings */
662 gs_param_string_array *string_a; /** String-Arrays */
663 gs_param_float_array *float_a; /** Float-Arrays */
664
665 updcmap_t cmap[UPD_CMAP_MAX]; /** Mapping-Data */
666
667 byte *gsbuf; /* Storage for GS-Rasterdata */
668 byte *gsscan; /* Begin of GS-Rasterdata */
669
670 byte *pxlptr; /* Source for pxlget */
671 upd_proc_pxlget( (*pxlget)); /* The Pixel-Reader */
672 upd_proc_render( (*render)); /* Actual Rendering */
673 upd_proc_writer( (*writer));
674
675 updscan_p *scnbuf; /* Output-Values */
676 int32_t *valbuf; /* Floyd-Steinberg-Buffer */
677 void *valptr[UPD_VALPTR_MAX];
678
679 byte *outbuf; /* Output-Buffer */
680 upd_proc_render( (*start_render)); /* Setup for rendering */
681 upd_proc_writer( (*start_writer)); /* Setup for writilg */
682
683 uint32_t flags; /** Some flags */
684 int pdwidth; /** pdev-width upon open */
685 int pdheight; /** pdev-height upon open */
686
687 uint ngsbuf; /* Size of gsbuf */
688 int gswidth; /* Width in GS-Pixels */
689 int gsheight; /* Height in GS-Pixels */
690
691 int rwidth; /* Rendering-Width */
692
693 int pwidth; /* Printing-Width */
694 int pheight; /* # scanlines printed */
695
696 int ncomp; /* # Components in gsbuf */
697 int nmap; /* # Entries in color-map */
698
699 uint nvalbuf; /* Size of valbuf */
700 int nscnbuf; /* Number of entries in scnbuf. */
701
702 int ocomp; /* # Components written */
703 int nbytes; /* Size of scnbuf[][].words */
704 int nlimits; /* Size of scnbuf[][].xbegin/end */
705 int scnmsk; /* Size of scanbuf - 1 */
706 uint noutbuf; /* Size of the Output-Buffer */
707
708 int ixpass; /* Current X-pass (0 ... nxpass-1) */
709 int ipass; /* Current pass (0 ... npass-1) */
710 int icomp; /* Selected Component */
711 int lf; /* Selected Line-Space */
712
713 int xprinter; /* Actual X-Position */
714
715 int yscan; /* Top-Scan (page-vari) */
716 int yprinter; /* Actual Y-Position (page-vari) */
717 int yscnbuf; /* Y not yet buffered */
718 }; /* All upd-specific data */
719
720
721 /* ------------------------------------------------------------------- */
722 /* Various Message-Levels */
723 /* ------------------------------------------------------------------- */
724
725 /**
726 UPD_MESSAGES, Is collection of Bits, that controls Messages
727 */
728
729 #define UPD_M_NONE 0x0000 /** No Messages at all */
730 #define UPD_M_ERROR 0x0001 /** Errors */
731 #define UPD_M_WARNING 0x0002 /** Warnings */
732 #define UPD_M_TOPCALLS 0x0004 /** Log Calls to main Functions */
733 #define UPD_M_MAPCALLS 0x0008 /** Log Color-Mapping-Calls */
734 #define UPD_M_SETUP 0x0010 /** Log Setup-Activity */
735 #define UPD_M_FSBUF 0x0020 /** Error-Summary for valbuf */
736 #define UPD_M_FMTVARS 0x0040 /** (GR) Formatting variables */
737
738 /* ------------------------------------------------------------------- */
739 /* The UPD-Routines */
740 /* ------------------------------------------------------------------- */
741
742 /**
743 Besides the main routines required for the color-mapping, that were
744 declared near the beginning, there are some auxillary functions.
745 Most prominent are "upd_open_map" and "upd_close_map", which
746 do the proper actions when opening and closing the device.
747 */
748
749 private int upd_open_map( upd_device *udev);
750 private int upd_close_map(upd_device *udev);
751
752 /**
753 But "upd_truncate" and "upd_expand" are also mentionable. They are
754 the actual workhorses for the component-oriented mapping. When mapping
755 the 16Bit Component-Values to the indices, some truncation takes place
756 and this is what "upd_truncate" does, in the most general manner i can
757 think of and with O(log(n)) in time. "upd_expand" is required for the
758 reverse mapping-functions and is a constant-time `algorithm'.
759 */
760 private inline uint32_t upd_truncate(upd_pc,int,gx_color_value);
761
762 /* ------------------------------------------------------------------- */
763 /* Return the gx_color_value for a given component */
764 /* ------------------------------------------------------------------- */
765 private inline gx_color_value
upd_expand(upd_pc upd,int i,gx_color_index ci0)766 upd_expand(upd_pc upd,int i,gx_color_index ci0)
767 {
768 const updcmap_pc cmap = upd->cmap + i; /* Writing-Shortcut */
769 uint32_t ci = (uint32_t)((ci0 >> cmap->bitshf) & cmap->bitmsk); /* Extract the component */
770
771 if(!cmap->rise) ci = cmap->bitmsk - ci; /* Invert, if necessary */
772 /* no Truncation/Expansion on full range */
773 if(gx_color_value_bits > cmap->bits) return cmap->code[ci];
774 else return (gx_color_value) ci;
775 }
776 /* That's simple, isn't it? */
777
778 /**
779 The next group of internal functions adresses the rendering. Besides
780 the main-functions "upd_open_render" and "upd_close_render", there
781 are groups of up to 3 Functions, for each algorithm available with
782 UPD. Two routines are invoked during open and close and the third
783 is called for each scanline. Actually a fourth function is provided,
784 that is invoked at the beginning of each page to be printed, but the
785 current algorithms do not need it.
786 */
787 private void upd_open_render( upd_device *udev);
788 private void upd_close_render( upd_device *udev);
789
790 private void upd_open_fscomp( upd_device *udev);
791 private int upd_fscomp( upd_p upd);
792 private void upd_close_fscomp( upd_device *udev);
793
794 private void upd_open_fscmyk( upd_device *udev);
795 private int upd_fscmyk( upd_p upd);
796
797 private void upd_open_fscmy_k( upd_device *udev);
798 private int upd_fscmy_k( upd_p upd);
799
800 /**
801 I hope that the formatting stuff can be kept simple and thus most
802 of the work is done inside the general open and close-functions.
803 During open, there is a call to a format-specific open-function, but
804 this is only for checking and determining the amount of of bytes required
805 for the output-buffer (and limit-values in the scan-buffer).
806 */
807 private int upd_open_writer( upd_device *udev);
808 private void upd_close_writer( upd_device *udev);
809 #if UPD_SIGNAL
810 private void upd_signal_handler(int sig);
811 #endif
812
813 /**
814 The first format are the uncompressed! SUN-Rasterfiles. The primary intention
815 of this format is testing, but it might turn out to be useful for other
816 purposes, even if the amount of generated data is huge. On the other hand
817 it is a violation of UPD's rules: the start-routine computes the Begin-Page
818 sequence (the Rasterfile header) since it would be a nuisance to provide
819 this code within each (test-)personalization in PostScript.
820 */
821 private int upd_open_rascomp( upd_device *udev);
822 private int upd_start_rascomp( upd_p upd, FILE *out);
823 private int upd_rascomp( upd_p upd, FILE *out);
824
825 /**
826 The second format is ESC/P, the format introduced with the first Epson
827 impact printers. This format is used by a lot of other printers too.
828 It is also uncompressed. This formatter supports X- and Y-Weaving,
829 which makes it the most sophisticated one inside this driver.
830 */
831
832 private void upd_limits( upd_p upd, bool check);
833 private int upd_open_wrtescp( upd_device *udev);
834 private int upd_wrtescp( upd_p upd, FILE *out);
835
836 /**
837 The third format is ESC/P2, the format use by the newer Epson-Printers.
838 It allows runlength-Compression similar to the RTL/PCL-Family of Printers.
839 This formatter does not allow for X-Weaving.
840
841 The fourth writer is a ESC/P2-Writer, that supports X-Weaving
842 */
843 private int upd_rle(byte *out,const byte *in,int nbytes);
844 private int upd_open_wrtescp2( upd_device *udev);
845 private int upd_wrtescp2( upd_p upd, FILE *out);
846 private int upd_wrtescp2x( upd_p upd, FILE *out);
847
848 /**
849 The fifth writer is a HP-RTL/PCL-Writer
850 */
851
852 private int upd_open_wrtrtl( upd_device *udev);
853 private int upd_wrtrtl( upd_p upd, FILE *out);
854
855 /**
856 The sixth writer is for Canon Extended Mode (currently BJC610) (hr)
857 */
858
859 private int upd_open_wrtcanon( upd_device *udev);
860 private int upd_wrtcanon( upd_p upd, FILE *out);
861
862 /**
863 The seventh writer is for ESC P/2 Nozzle Map Mode (currently Stylus Color 300) (GR)
864 */
865
866 private int upd_wrtescnm( upd_p upd, FILE *out);
867
868
869 /**
870 Generalized Pixel Get & Read
871 */
872 private uint32_t upd_pxlfwd(upd_p upd);
873 private uint32_t upd_pxlrev(upd_p upd);
874 #define upd_pxlget(UPD) (*UPD->pxlget)(UPD)
875
876 private void *upd_cast(const void *);
877
878 /* ------------------------------------------------------------------- */
879 /* Macros to deal with the Parameter-Memory */
880 /* ------------------------------------------------------------------- */
881
882 /**
883 Usually the creation of copies of external parameters is not necessary,
884 at least with gs-versions > 4.03. But uniprint writes to the parameters
885 in some cases or creates some by itself, thus to get a unified interface
886 all parameter-data are copied and thus it is legal to manipulate them.
887
888 Here are several Macros, named "UPD_MM_*" to deal with that.
889 */
890
891 /** UPD_MM_GET_ARRAY allocates & initializes an array of values */
892 #define UPD_MM_GET_ARRAY(mem, Which,Nelts) \
893 Which = NULL; \
894 if(0 < (Nelts)) { \
895 byte *tmp = gs_malloc(mem, Nelts,sizeof(Which[0]),"uniprint/params");\
896 if(tmp) { \
897 memset(tmp,0,(Nelts)*sizeof(Which[0])); \
898 Which = (void *) tmp; \
899 } else { \
900 return_error(gs_error_VMerror); \
901 } \
902 }
903
904 /** UPD_MM_DEL_ARRAY frees an array of values */
905 #define UPD_MM_DEL_ARRAY(mem, Which,Nelts,Delete) \
906 if(Which && 0 < (Nelts)) { \
907 uint ii; \
908 for(ii = 0; (Nelts) > ii; ++ii) Delete(mem, Which[ii]); \
909 gs_free(mem, upd_cast(Which),Nelts,sizeof(Which[0]),"uniprint/params");\
910 } \
911 Which = 0
912
913 /** UPD_MM_DEL_VALUE deletes a value, does nothing */
914 #define UPD_MM_DEL_VALUE(mem, Which) /* */
915
916 /** UPD_MM_DEL_PARAM deletes a single gs-array-parameter */
917 #define UPD_MM_DEL_PARAM(mem, Which) { \
918 if(Which.data && Which.size) \
919 gs_free(mem, upd_cast(Which.data),Which.size,sizeof(Which.data[0]),\
920 "uniprint/params"); \
921 }
922
923 /** UPD_MM_DEL_APARAM deletes a nested gs-array-parameter */
924 #define UPD_MM_DEL_APARAM(mem, Which) { \
925 if(Which.data && Which.size) { \
926 uint iii; \
927 for(iii = 0; iii < Which.size; ++iii) \
928 UPD_MM_DEL_PARAM(mem, Which.data[iii]); \
929 gs_free(mem, upd_cast(Which.data),Which.size,sizeof(Which.data[0]),\
930 "uniprint/params"); \
931 } \
932 }
933
934 /** UPD_MM_CPY_ARRAY creates a new copy of an array of values */
935 #define UPD_MM_CPY_ARRAY(mem, To,From,Nelts,Copy) \
936 UPD_MM_GET_ARRAY(mem, To,Nelts); \
937 if(To && From) { \
938 uint ii; \
939 for(ii = 0; (Nelts) > ii; ++ii) Copy(mem, To[ii],From[ii]);\
940 }
941
942 /** UPD_MM_CPY_VALUE Copies a simple Value */
943 #define UPD_MM_CPY_VALUE(mem,To,From) To = From
944
945 #define UPD_MM_CPY_VALUE_3(mem,To,From) To = From
946
947 /** UPD_MM_CPY_PARAM Creates a copy of a gs-parameter */
948 #define UPD_MM_CPY_PARAM(mem, To, From) \
949 if(From.data && From.size) { \
950 UPD_MM_GET_ARRAY(mem, To.data,From.size); \
951 if(To.data) { \
952 To.size = From.size; \
953 memcpy(upd_cast(To.data),From.data,To.size*sizeof(To.data[0]));\
954 } \
955 }
956
957 /** UPD_MM_CPY_APARAM Creates a copy of a nested gs-parameter */
958 #define UPD_MM_CPY_APARAM(mem, To,From) \
959 if(From.data && From.size) { \
960 UPD_MM_GET_ARRAY(mem, To.data,From.size); \
961 if(To.data) { \
962 gs_param_string *tmp2 = (gs_param_string *) upd_cast(To.data);\
963 uint iii; \
964 To.size = From.size; \
965 for(iii = 0; To.size > iii; ++iii) \
966 UPD_MM_CPY_PARAM(mem, tmp2[iii],From.data[iii]); \
967 } \
968 }
969
970 /* ------------------------------------------------------------------- */
971 /* UPD-Initialized-Data */
972 /* ------------------------------------------------------------------- */
973
974 /** Version-String */
975
976 static const char rcsid[] = "$Revision: 1.16 $";
977
978 /** Default-Transfer-curve */
979
980 static const float upd_data_xfer[2] = { 0.0, 1.0 };
981
982 /*@ > */
983
984 /* ------------------------------------------------------------------- */
985 /* upd_cast: keeps some compilers more happy [dangerous] */
986 /* ------------------------------------------------------------------- */
987
988 private void *
upd_cast(const void * data)989 upd_cast(const void *data)
990 {
991 return (void *) data;
992 }
993
994 /* ------------------------------------------------------------------- */
995 /* upd_signal_handler: Catch interrupts */
996 /* ------------------------------------------------------------------- */
997
998 #if UPD_SIGNAL
999 static upd_p sigupd = NULL;
1000 private void
upd_signal_handler(int sig)1001 upd_signal_handler(int sig)
1002 {
1003 if(sigupd) sigupd->flags |= B_ABORT;
1004 }
1005 #endif
1006
1007
1008 /* ------------------------------------------------------------------- */
1009 /* upd_print_page: The main workhorse */
1010 /* ------------------------------------------------------------------- */
1011
1012 /**
1013 Function: upd_print_page
1014
1015 This is the top-level printing routine. It works through this
1016 steps:
1017
1018 1. Once for each generated file, the "device-open-sequence" is written.
1019 2. The "page-begin-sequence" is written.
1020
1021 3. The data are generated and written:
1022 3.1: Data are converted into a "printer-family"-specific format.
1023 This step includes the halftoning, if selected.
1024 3.2: Data are written with a printer-specific function.
1025 There is not much code-compression inside theese functions,
1026 since i observed to improvments in print-speed. Other
1027 drivers do a better job in this.
1028
1029 4. The "page-end-sequence" is written.
1030 5. If a one-page-per-file mode is selected, the "device-close-sequence"
1031 is added to the output. For multi-page files, this writing is
1032 performed in "upd_close", the drivers close-function.
1033
1034 The routine is quite short, since all the allocation and checking
1035 occur in upd_open and upd_putparams. The only test, that upd_print_page
1036 does, is the verification wether the device is in a sane state. This
1037 must be done here, since during the initialisation, the device is
1038 usually opened several times, before obtaining a valid state.
1039 */
1040
1041 private int
upd_print_page(gx_device_printer * pdev,FILE * out)1042 upd_print_page(gx_device_printer *pdev, FILE *out)
1043 {
1044 upd_device *const udev = (upd_device *) pdev;
1045 const upd_p upd = udev->upd;
1046 const int *const ints = upd ? upd->ints : NULL;
1047 int error,need,yfill;
1048
1049 #if UPD_SIGNAL /* variables required for signal-handling only */
1050 void (*oldint )(int) = NULL;
1051 void (*oldterm)(int) = NULL;
1052 upd_p oldupd = sigupd;
1053 #endif /* variables required for signal-handling only */
1054
1055 /*
1056 * Refuse to work, if not explicitly enabled during open
1057 * (some/lot of allocated memory is required)
1058 */
1059 if(!upd || B_OK4GO != (upd->flags & (B_OK4GO | B_ERROR))) {
1060 #if UPD_MESSAGES & (UPD_M_ERROR | UPD_M_TOPCALLS)
1061 errprintf("CALL-REJECTED upd_print_page(0x%05lx,0x%05lx)\n",
1062 (long) udev,(long) out);
1063 #endif
1064 return gs_error_undefined;
1065 }
1066
1067 #if UPD_MESSAGES & UPD_M_TOPCALLS
1068 errprintf("CALL: upd_print_page(0x%05lx,0x%05lx)\n",
1069 (long) udev,(long) out);
1070 #endif
1071
1072 #if UPD_SIGNAL /* Setup of signal-handling */
1073 sigupd = upd;
1074 oldint = signal(SIGINT, upd_signal_handler);
1075 oldterm = signal(SIGTERM,upd_signal_handler);
1076 #endif /* Setup of signal-handling */
1077
1078 /*
1079 * If the OutputFile was just opened, transfer the Open-Sequence to it.
1080 */
1081 if(!(upd->flags & B_OPEN)) {
1082
1083 if(0 < upd->strings[S_OPEN].size)
1084 fwrite(upd->strings[S_OPEN].data,1,upd->strings[S_OPEN].size,out);
1085 upd->flags |= B_OPEN;
1086 }
1087 /*
1088 * Always write the the Page-begin-sequence
1089 */
1090 if(0 < upd->strings[S_BEGIN].size)
1091 fwrite(upd->strings[S_BEGIN].data,1,upd->strings[S_BEGIN].size,out);
1092 /*
1093 * Establish page-variables
1094 */
1095
1096 /* Positions */
1097 upd->xprinter = 0;
1098 upd->yscan = 0; /* Position we are processing */
1099 upd->yprinter = 0; /* Actual Printer-Positions */
1100 upd->yscnbuf = 0; /* Next free scnbuf-Line */
1101
1102 /* Rendering & Writing Setup, if available */
1103 if(upd->start_render) (*upd->start_render)(upd);
1104 if(upd->start_writer) (*upd->start_writer)(upd,out);
1105
1106 /* How many scanlines do we need ? */
1107 need = ints[I_NYPASS] * ints[I_PINS2WRITE];
1108 if(0 >= need) need = 1;
1109
1110 /* The Weave-counters */
1111 upd->ipass = 0;
1112 upd->ixpass = 0;
1113 upd->icomp = -1; /* Enforces initial selection */
1114 upd->lf = -1; /* Enforces initial selection */
1115 /*
1116 * Main Loop
1117 */
1118 while(upd->pheight > upd->yscan) { /* Main-Loop */
1119
1120 /*
1121 * Load as much data into the scan-buffer as possible
1122 * (this is done in scan-sequence, the printing not necessarily.)
1123 */
1124 if(ints[I_BEGSKIP] > upd->yscan) yfill = 0;
1125 else yfill = upd->yscan - ints[I_BEGSKIP];
1126
1127 for(yfill += upd->nscnbuf; upd->yscnbuf < yfill; upd->yscnbuf++) {
1128
1129 if(upd->gsheight > upd->yscnbuf) {
1130
1131 if(0 > (*dev_proc(udev,get_bits))((gx_device *) udev,
1132 upd->yscnbuf,upd->gsbuf,&upd->gsscan)) {
1133 #if UPD_MESSAGES & UPD_M_WARNING
1134 errprintf("get_bits aborted with error, yscnbuf = %4d\n",
1135 upd->yscnbuf);
1136 #endif
1137 break;
1138 }
1139 } else {
1140
1141 memset(upd->gsscan = upd->gsbuf,0,upd->ngsbuf);
1142
1143 }
1144
1145 if(0 > (*upd->render)(upd)) {
1146 #if UPD_MESSAGES & UPD_M_WARNING
1147 errprintf("Rendering aborted with error, yscnbuf = %4d\n",
1148 upd->yscnbuf);
1149 #endif
1150 break;
1151 }
1152
1153 }
1154 /*
1155 * Did the buffering loop take an error exit ?
1156 */
1157 if((upd->yscnbuf ^ yfill) & upd->scnmsk) break;
1158 /*
1159 * Print as much as possible
1160 */
1161 while((upd->yscan - ints[I_BEGSKIP] + need) < upd->yscnbuf) {
1162
1163 /* first write the scan(s) */
1164 (*upd->writer)(upd,out);
1165
1166 /* Check for termination */
1167 if(upd->yscan >= upd->pheight) break;
1168 if(upd->flags & B_ABORT ) {
1169 #if UPD_MESSAGES & UPD_M_WARNING
1170 errprintf("Printing aborted upon interrupt, yscan = %4d\n",
1171 upd->yscan);
1172 #endif
1173 break;
1174 }
1175 }
1176 /*
1177 * Did the print-Loop take an error exit ?
1178 */
1179 if((upd->yscan - ints[I_BEGSKIP] + need) < upd->yscnbuf) break;
1180 } /* Main-Loop */
1181
1182 /*
1183 * If we aborted for some reason, use the dedicated sequence
1184 */
1185
1186 if((upd->pheight > upd->yscan) &&
1187 (0 < upd->strings[S_ABORT].size)) { /* Only This! */
1188 fwrite(upd->strings[S_ABORT].data,1,upd->strings[S_ABORT].size,out);
1189
1190 upd->flags &= ~B_OPEN; /* Inhibit Close-Sequence ! */
1191 /*
1192 * If there is no special sequence, or we came to normal end,
1193 * write the normal sequence, if any
1194 */
1195
1196 } else if(0 < upd->strings[S_END].size) {
1197 fwrite(upd->strings[S_END].data,1,upd->strings[S_END].size,out);
1198 }
1199 /*
1200 * If necessary, write the close-sequence
1201 */
1202 if((NULL != udev->fname ) && strchr(udev->fname,'%')) {
1203
1204 if(0 < upd->strings[S_CLOSE].size)
1205 fwrite(upd->strings[S_CLOSE].data,1,upd->strings[S_CLOSE].size,out);
1206
1207 upd->flags &= ~B_OPEN;
1208 }
1209
1210 /*
1211 * clean up, and return status
1212 */
1213
1214 fflush(out); /* just to prepare for ferror */
1215
1216 if(upd->pheight > upd->yscan) error = gs_error_interrupt;
1217 else if(ferror(out)) error = gs_error_ioerror;
1218 else error = 0;
1219
1220 #if UPD_MESSAGES & UPD_M_TOPCALLS
1221 errprintf("RETURN: %d = upd_print_page(0x%05lx,0x%05lx)\n",
1222 error,(long) udev,(long)out);
1223 #endif
1224
1225 #if UPD_SIGNAL /* Restore Interrupt-state */
1226 sigupd = oldupd;
1227 (void) signal(SIGINT ,oldint);
1228 (void) signal(SIGTERM,oldterm);
1229 #endif /* Restore Interrupt-state */
1230
1231 return error;
1232 }
1233
1234 /* ------------------------------------------------------------------- */
1235 /* upd_open: Initialize everything for printing */
1236 /* ------------------------------------------------------------------- */
1237 /**
1238 "upd_open" is -through the specified table of procedures- called instead
1239 of the normal open-procedures for printer-devices, that performs quite
1240 a complex job. Thus it is necessary to call this `superclass-open�
1241 here.
1242
1243 Besides that, this routine does quite a complex job too, in initializes
1244 everything required to print a page. This might be time-consuming, the
1245 alternative would be "upd_print_page", but i often print 100 pages or
1246 more, but i never experienced more than 5-6 open-calls.
1247 */
1248
1249 private int
upd_open(gx_device * pdev)1250 upd_open(gx_device *pdev)
1251 {
1252 upd_device *const udev = (upd_device *) pdev;
1253 const upd_p upd = udev->upd;
1254 int error;
1255
1256 #if UPD_MESSAGES & UPD_M_TOPCALLS
1257 errprintf("CALL: upd_open(0x%05lx)\n",(long) pdev);
1258 #endif
1259
1260 /** enforce the UPD-Margins */
1261
1262 if((NULL != upd) &&
1263 (NULL != upd->float_a[FA_MARGINS].data) &&
1264 (4 == upd->float_a[FA_MARGINS].size) ) {
1265 static float m[4];
1266 m[1] = upd->float_a[FA_MARGINS].data[1] / 72.0;
1267 m[3] = upd->float_a[FA_MARGINS].data[3] / 72.0;
1268 if(B_YFLIP & upd->flags) {
1269 m[0] = upd->float_a[FA_MARGINS].data[2] / 72.0;
1270 m[2] = upd->float_a[FA_MARGINS].data[0] / 72.0;
1271 } else {
1272 m[0] = upd->float_a[FA_MARGINS].data[0] / 72.0;
1273 m[2] = upd->float_a[FA_MARGINS].data[2] / 72.0;
1274 }
1275 gx_device_set_margins((gx_device *) udev, m, true);
1276 }
1277
1278 /** call the super-class open **/
1279 error = gdev_prn_open(pdev);
1280
1281 /** invoke the subroutines, if an upd is present. */
1282
1283 if(upd) {
1284
1285 upd->flags &= ~B_OK4GO;
1286
1287 /**
1288 The following initializations are run, even in case of an error in
1289 the super-class open, just to bring our upd into a sane state.
1290 */
1291 if(0 > error) upd->flags |= B_ERROR;
1292
1293 if(gs_error_VMerror == upd_open_map(udev)) error = gs_error_VMerror;
1294
1295 /**
1296 The following piece of code is here for demonstration-purposes:
1297 It determines the size of the printed image and allocates the
1298 buffer for the raw raster-data
1299 */
1300 upd->gswidth = udev->width -
1301 (int)((dev_l_margin(udev)+dev_r_margin(udev))*udev->x_pixels_per_inch);
1302
1303 upd->gsheight = udev->height -
1304 (int)((dev_t_margin(udev)+dev_b_margin(udev))*udev->y_pixels_per_inch);
1305
1306 upd->ngsbuf = 0; /* Ensure sane values */
1307 upd->gsbuf = NULL; /* Ensure sane values */
1308
1309 if(B_MAP & upd->flags) { /* Only if prerequisites were met */
1310 uint want = gx_device_raster(pdev,true);
1311 upd->gsbuf = gs_malloc(pdev->memory, want,1,"upd/gsbuf");
1312
1313 if(upd->gsbuf) {
1314 upd->ngsbuf = want;
1315 upd->flags |= B_BUF; /* Signal Success */
1316 } else {
1317 error = gs_error_VMerror; /* Signal Error */
1318 upd->flags |= B_ERROR;
1319 }
1320
1321 } /* Only if prerequisites were met */
1322
1323 upd_open_render(udev); /* First subloop in printing */
1324
1325 if(gs_error_VMerror == upd_open_writer(udev)) error = gs_error_VMerror;
1326
1327 udev->upd->pdwidth = udev->width;
1328 udev->upd->pdheight = udev->height;
1329
1330 #if UPD_MESSAGES & UPD_M_SETUP
1331 if((upd->flags & (B_OK4GO | B_ERROR)) == B_OK4GO) {
1332 int i,j,l,ln,lv;
1333 errprintf("\nupd->flags = 0x%05lx\n",(unsigned long)upd->flags);
1334 errprintf( "upd->pdwidth = %5d\n",upd->pdwidth);
1335 errprintf( "upd->pdheight = %5d\n",upd->pdheight);
1336 errprintf( "upd->ngsbuf = %5u\n",upd->ngsbuf);
1337 errprintf( "upd->gswidth = %5d\n",upd->gswidth);
1338 errprintf( "upd->gsheight = %5d\n",upd->gsheight);
1339 errprintf( "upd->rwidth = %5d\n",upd->rwidth);
1340 errprintf( "upd->pwidth = %5d\n",upd->pwidth);
1341 errprintf( "upd->pheight = %5d\n",upd->pheight);
1342 errprintf( "upd->nvalbuf = %5u\n",upd->nvalbuf);
1343 errprintf( "upd->nscnbuf = %5d\n",upd->nscnbuf);
1344 errprintf( "upd->ncomp = %5d\n",upd->ncomp);
1345 errprintf( "upd->ocomp = %5d\n",upd->ocomp);
1346 errprintf( "upd->nbytes = %5d\n",upd->nbytes);
1347 errprintf( "upd->nlimits = %5d\n",upd->nlimits);
1348 errprintf( "upd->scnmsk = %5d\n",upd->scnmsk);
1349 errprintf( "upd->noutbuf = %5u\n",upd->noutbuf);
1350 errprintf( "upd->ixpass = %5d\n",upd->ixpass);
1351 errprintf( "upd->ipass = %5d\n",upd->ipass);
1352 errprintf( "upd->icomp = %5d\n",upd->icomp);
1353 errprintf( "upd->lf = %5d\n",upd->lf);
1354 errprintf( "upd->xprinter = %5d\n",upd->xprinter);
1355 errprintf( "upd->yscan = %5d\n",upd->yscan);
1356 errprintf( "upd->yprinter = %5d\n",upd->yprinter);
1357 errprintf( "upd->yscnbuf = %5d\n",upd->yscnbuf);
1358
1359 ln = 13;
1360 lv = 5;
1361 for(i = 0; countof(upd_choice) > i; ++i) {
1362 if(!upd_choice[i]) continue;
1363 l = strlen(upd_choice[i][0]);
1364 if(ln < l) ln = l;
1365 for(j = 1; upd_choice[i][j]; ++j) {
1366 l = strlen(upd_choice[i][j]);
1367 if(lv < l) lv = l;
1368 }
1369 }
1370
1371 for(i = 0; countof(upd_flags) > i; ++i) {
1372 if(upd_flags[i]) {
1373 l = strlen(upd_flags[i]);
1374 if(ln < l) ln = l;
1375 }
1376 }
1377
1378 for(i = 0; countof(upd_ints) > i; ++i) {
1379 if(upd_ints[i]) {
1380 l = strlen(upd_ints[i]);
1381 if(ln < l) ln = l;
1382 }
1383 }
1384
1385 for(i = 0; countof(upd_int_a) > i; ++i) {
1386 if(upd_int_a[i]) {
1387 l = strlen(upd_int_a[i]);
1388 if(ln < l) ln = l;
1389 }
1390 }
1391
1392 for(i = 0; countof(upd_strings) > i; ++i) {
1393 if(upd_strings[i]) {
1394 l = strlen(upd_strings[i]);
1395 if(ln < l) ln = l;
1396 }
1397 }
1398
1399 for(i = 0; countof(upd_string_a) > i; ++i) {
1400 if(upd_string_a[i]) {
1401 l = strlen(upd_string_a[i]);
1402 if(ln < l) ln = l;
1403 }
1404 }
1405
1406 for(i = 0; countof(upd_float_a) > i; ++i) {
1407 if(upd_float_a[i]) {
1408 l = strlen(upd_float_a[i]);
1409 if(ln < l) ln = l;
1410 }
1411 }
1412
1413 for(i = 0; countof(upd_choice) > i; ++i) {
1414 if(upd_choice[i]) {
1415 errprintf("%*s = %-*s (%2d)\n",ln,upd_choice[i][0],
1416 lv,upd_choice[i][upd->choice[i]],upd->choice[i]);
1417 } else {
1418 errprintf("%*s[%2d] = %2d\n",ln-4,"upd_choice",i,
1419 upd->choice[i]);
1420 }
1421 }
1422
1423 for(i = 0; countof(upd_flags) > i; ++i) {
1424 if(upd_flags[i]) {
1425 errprintf("%*s = %s\n",ln,upd_flags[i],
1426 ((uint32_t) 1 << i) & upd->flags ? "true" : "false");
1427 } else {
1428 errprintf("%*s[%2d] = %s\n",ln-4,"upd_flags",i,
1429 ((uint32_t) 1 << i) & upd->flags ? "true" : "false");
1430
1431 }
1432 }
1433
1434 for(i = 0; countof(upd_ints) > i; ++i) {
1435 if(upd_ints[i]) {
1436 errprintf("%*s = %5d\n",ln,upd_ints[i],upd->ints[i]);
1437 } else {
1438 errprintf("%*s[%2d] = %5d\n",ln-4,"upd_ints",i,upd->ints[i]);
1439 }
1440 }
1441
1442 }
1443
1444
1445 errprintf("\n%sready to print\n\n",
1446 B_OK4GO != (upd->flags & (B_OK4GO | B_ERROR)) ?
1447 "NOT " : "");
1448 #endif
1449
1450 }
1451
1452 #if UPD_MESSAGES & UPD_M_TOPCALLS
1453 errprintf("RETURN: %d = upd_open(0x%05lx)\n",
1454 error,(long) pdev);
1455 #endif
1456
1457 return error;
1458 }
1459
1460 /* ------------------------------------------------------------------- */
1461 /* upd_close: Release everything allocated in upd_open */
1462 /* ------------------------------------------------------------------- */
1463
1464 private int
upd_close(gx_device * pdev)1465 upd_close(gx_device *pdev)
1466 {
1467 upd_device *const udev = (upd_device *) pdev;
1468 const upd_p upd = udev->upd;
1469 int error = 0;
1470 int code;
1471
1472 #if UPD_MESSAGES & UPD_M_TOPCALLS
1473 errprintf("CALL: upd_close(0x%05lx)\n",(long)pdev);
1474 #endif
1475
1476 /** If necessary, write the close-sequence **/
1477
1478 if( upd && (( B_OPEN | B_OK4GO) ==
1479 ((B_OPEN | B_OK4GO | B_ERROR) & upd->flags))) {
1480
1481 if(udev->file && upd->strings && 0 < upd->strings[S_CLOSE].size)
1482 fwrite(upd->strings[S_CLOSE].data,1,
1483 upd->strings[S_CLOSE].size,udev->file);
1484
1485 upd->flags &= ~B_OPEN;
1486 }
1487
1488 /** Then release the open-allocated memory */
1489 if(upd) {
1490
1491 upd_close_writer(udev);
1492
1493 if(upd->gsbuf)
1494 gs_free(pdev->memory, upd->gsbuf,upd->ngsbuf,1,"uniprint/gsbuf");
1495 upd->gsbuf = NULL;
1496 upd->ngsbuf = 0;
1497 upd->flags &= ~B_BUF;
1498
1499 upd_close_render(udev);
1500 upd_close_map(udev);
1501
1502 UPD_MM_DEL_ARRAY(pdev->memory, upd->choice, countof(upd_choice), UPD_MM_DEL_VALUE);
1503 UPD_MM_DEL_ARRAY(pdev->memory, upd->ints, countof(upd_ints), UPD_MM_DEL_VALUE);
1504 UPD_MM_DEL_ARRAY(pdev->memory, upd->int_a, countof(upd_int_a), UPD_MM_DEL_PARAM);
1505 UPD_MM_DEL_ARRAY(pdev->memory, upd->strings, countof(upd_strings), UPD_MM_DEL_PARAM);
1506 UPD_MM_DEL_ARRAY(pdev->memory, upd->string_a,countof(upd_string_a),UPD_MM_DEL_APARAM);
1507 UPD_MM_DEL_ARRAY(pdev->memory, upd->float_a, countof(upd_float_a), UPD_MM_DEL_PARAM);
1508
1509 gs_free(pdev->memory, upd,sizeof(upd[0]),1,"uniprint");
1510
1511 udev->upd = NULL;
1512 }
1513
1514 /** Then call the superclass close **/
1515 code = gdev_prn_close(pdev);
1516 error = error > code ? code : error;
1517
1518
1519 #if UPD_MESSAGES & UPD_M_TOPCALLS
1520 errprintf("RETURN: %d = upd_close(0x%05lx)\n",
1521 error,(long) pdev);
1522 #endif
1523
1524 return error;
1525 }
1526
1527 /* ------------------------------------------------------------------- */
1528 /* upd_get_params: Export Parameters to the Interpreter */
1529 /* ------------------------------------------------------------------- */
1530
1531 #if UPD_MESSAGES & UPD_M_TOPCALLS
1532 #define UPD_EXIT_GET(Err,Dev,List) \
1533 if(0 > Err) { \
1534 errprintf("RETURN-%d: %d upd_get_params(0x%05lx,0x%05lx)\n", \
1535 __LINE__,Err,(long) Dev,(long) List); \
1536 return_error(Err); \
1537 }
1538 #else
1539 #define UPD_EXIT_GET(Err,Dev,List) if(0 > Err) return_error(Err);
1540 #endif
1541
1542 private int
upd_get_params(gx_device * pdev,gs_param_list * plist)1543 upd_get_params(gx_device *pdev, gs_param_list *plist)
1544 {
1545 upd_device *const udev = (upd_device *) pdev;
1546 const upd_p upd = udev->upd;
1547 int error,i;
1548
1549 #if UPD_MESSAGES & UPD_M_TOPCALLS
1550 errprintf("CALL: upd_get_params(0x%05lx,0x%05lx)\n",
1551 (long) udev,(long) plist);
1552 #endif
1553
1554 /** Call the SuperClass-get_params at the beginning */
1555 error = gdev_prn_get_params((gx_device *)udev,plist);
1556 UPD_EXIT_GET(error,udev,plist);
1557
1558 /** Export the version */
1559 if(upd_version) { /* Version-Export enabled */
1560 udev->upd_version.data = (const byte *) rcsid;
1561 udev->upd_version.size = strlen(rcsid);
1562 udev->upd_version.persistent = true;
1563 error = param_write_string(plist,upd_version,&udev->upd_version);
1564 UPD_EXIT_GET(error,udev,plist);
1565 } /* Version-Export enabled */
1566
1567 /** Export the Named choices */
1568 for(i = 0; i < countof(upd_choice); ++i) {
1569 if(!upd_choice[i]) continue; /* Choice-Export disabled */
1570 if(upd && upd->choice && upd->choice[i]) {
1571 gs_param_string name;
1572 name.data = (const byte *) upd_choice[i][upd->choice[i]];
1573 name.size = strlen((const char *) name.data);
1574 name.persistent = true;
1575 error = param_write_name(plist,upd_choice[i][0],&name);
1576 } else {
1577 error = param_write_null(plist,upd_choice[i][0]);
1578 }
1579 UPD_EXIT_GET(error,udev,plist);
1580 }
1581
1582 /** Export the flags (bool) */
1583 for(i = 0; i < countof(upd_flags); ++i) {
1584 if(!upd_flags[i]) continue; /* Flag-Export disabled */
1585 if(upd) {
1586 bool value = upd->flags & ((uint32_t) 1 << i);
1587 error = param_write_bool(plist,upd_flags[i],&value);
1588 } else {
1589 error = param_write_null(plist,upd_flags[i]);
1590 }
1591 UPD_EXIT_GET(error,udev,plist);
1592 }
1593
1594 /** Export the ints */
1595 for(i = 0; i < countof(upd_ints); ++i) {
1596 if(!upd_ints[i]) continue; /* int-Export disabled */
1597 if(upd && upd->ints && upd->ints[i]) {
1598 int value = upd->ints[i];
1599 error = param_write_int( plist,upd_ints[i],&value);
1600 } else {
1601 error = param_write_null(plist,upd_ints[i]);
1602 }
1603 UPD_EXIT_GET(error,udev,plist);
1604 }
1605
1606 /** Export the int-arrays */
1607 for(i = 0; i < countof(upd_int_a); ++i) {
1608 if(!upd_int_a[i]) continue; /* int-Array-Export disabled */
1609 if(upd && upd->int_a && upd->int_a[i].size) {
1610 error = param_write_int_array( plist,upd_int_a[i],(upd->int_a+i));
1611 } else {
1612 error = param_write_null(plist,upd_int_a[i]);
1613 }
1614 UPD_EXIT_GET(error,udev,plist);
1615 }
1616
1617 /** Export the strings */
1618 for(i = 0; i < countof(upd_strings); ++i) {
1619 if(!upd_strings[i]) continue; /* String-Export disabled */
1620 if(upd && upd->strings && upd->strings[i].size) {
1621 error = param_write_string( plist,upd_strings[i],(upd->strings+i));
1622 } else {
1623 error = param_write_null(plist,upd_strings[i]);
1624 }
1625 UPD_EXIT_GET(error,udev,plist);
1626 }
1627
1628 /** Export the string-Arrays */
1629 for(i = 0; i < countof(upd_string_a); ++i) {
1630 if(!upd_string_a[i]) continue; /* String-Array-Export disabled */
1631 if(upd && upd->string_a && upd->string_a[i].size) {
1632 error =
1633 param_write_string_array( plist,upd_string_a[i],(upd->string_a+i));
1634 } else {
1635 error = param_write_null(plist,upd_string_a[i]);
1636 }
1637 UPD_EXIT_GET(error,udev,plist);
1638 }
1639
1640 /** Export the float-Arrays */
1641 for(i = 0; i < countof(upd_float_a); ++i) {
1642 if(!upd_float_a[i]) continue; /* Float-Array-Export disabled */
1643 if(upd && upd->float_a && upd->float_a[i].size) {
1644 error =
1645 param_write_float_array( plist,upd_float_a[i],(upd->float_a+i));
1646 } else {
1647 error = param_write_null(plist,upd_float_a[i]);
1648 }
1649 UPD_EXIT_GET(error,udev,plist);
1650 }
1651
1652 #if UPD_MESSAGES & UPD_M_TOPCALLS
1653 errprintf("RETURN: %d = upd_get_params(0x%05lx,0x%05lx)\n",
1654 error,(long) udev,(long) plist);
1655 #endif
1656
1657 return error;
1658 }
1659
1660 #undef UPD_EXIT_GET
1661
1662 /* ------------------------------------------------------------------- */
1663 /* upd_put_params: Load Parameters into the device-structure */
1664 /* ------------------------------------------------------------------- */
1665
1666 private int
upd_put_params(gx_device * pdev,gs_param_list * plist)1667 upd_put_params(gx_device *pdev, gs_param_list *plist)
1668 {
1669 upd_device *const udev = (upd_device *) pdev;
1670 upd_p upd = udev->upd;
1671 int error = 0, code,i;
1672
1673 float MarginsHWResolution[2],Margins[2];
1674 gx_device_color_info color_info;
1675 uint32_t flags = 0;
1676 int *choice = NULL;
1677 int *ints = NULL;
1678 gs_param_int_array *int_a = NULL;
1679 gs_param_string *strings = NULL;
1680 gs_param_string_array *string_a = NULL;
1681 gs_param_float_array *float_a = NULL, mfa;
1682
1683 /**
1684 Error is used for two purposes: either it holds a negative error
1685 code or it is used as a bitfield, that tells, which parameters
1686 were actually loaded. If any of the important parameters changed
1687 upd_put_params closes the device, since the real parameter-evaluation
1688 is carried out by upd_open.
1689 */
1690
1691 #define UPD_PUT_FLAGS 0x0002
1692 #define UPD_PUT_CHOICE 0x0004
1693 #define UPD_PUT_INTS 0x0008
1694 #define UPD_PUT_INT_A 0x0010
1695 #define UPD_PUT_STRINGS 0x0020
1696 #define UPD_PUT_STRING_A 0x0040
1697 #define UPD_PUT_FLOAT_A 0x0080
1698 #define UPD_PUT_CHANGEDSIZE 0x0100
1699
1700 #if UPD_MESSAGES & UPD_M_TOPCALLS
1701 errprintf("CALL: upd_put_params(0x%05lx,0x%05lx)\n",
1702 (long)udev,(long)plist);
1703 #endif
1704
1705
1706 /**
1707 I consider the following part of upd_put_params a bad-nasty-hack-hack
1708 and i am uncertain, wether it really works in the intended way. I provide it
1709 just for the case someone is performing nasty-parameter-changes on the
1710 active device, especially switching the OutputFile. If this happens in
1711 a situation, where data were written to the file, but the termination
1712 sequence is required, the driver does it now. (If you want to know, why
1713 i am writing bad-nasty-hack-hack, visit http://www.zark.com )
1714 */
1715 if(upd && (B_OPEN & udev->upd->flags) && (NULL != udev->file)) {
1716
1717 gs_param_string fname = { NULL, 0, false };
1718
1719 code = param_read_string(plist,"OutputFile",&fname);
1720 if((1 != code) && (0 != code)) {
1721 code = param_read_null(plist,"OutputFile");
1722 if(0 == code) {
1723 fname.data = (const byte *) "";
1724 fname.size = 0;
1725 }
1726 }
1727
1728 if((0 == code) &&
1729 strncmp((const char *)fname.data,udev->fname,fname.size)) {
1730 if(upd->strings && 0 < udev->upd->strings[S_CLOSE].size)
1731 fwrite(upd->strings[S_CLOSE].data,1,
1732 upd->strings[S_CLOSE].size,udev->file);
1733
1734 upd->flags &= ~B_OPEN;
1735 }
1736 }
1737 /* Done with the bad-nasty-hack-hack */
1738
1739 /**
1740 The next thing "upd_put_params" does, is a little strange too. It imports
1741 a readonly-parameter, the version-string. I do not know wether it is still
1742 required, but some versions of GHOSTSCRIPT disliked it very much, if an
1743 existing parameter was not touched by the put-operation.
1744
1745 On the other hand it is the right time to show the basic-outline of the
1746 parameter-importing flow. Basically the proper "param_read"-procedure
1747 is called. If it indicated, that the parameter was present, but of the
1748 wrong type, a read for the null-type is attempted, which is by convention
1749 somehow an reset to default. This sequence is applied to all the parameters
1750 and in case of the array-parameters, a succesful null-read is marked by
1751 setting data and size to 0.
1752 */
1753 #if UPD_MESSAGES & UPD_M_SETUP
1754 #define UPD_PARAM_READ(Param_read,Name,Object) \
1755 code = Param_read(plist,Name,&Object); \
1756 if(0 > code) { \
1757 code = param_read_null(plist,Name); \
1758 if(0 == code) memset(&Object,0,sizeof(Object));\
1759 } \
1760 if(!code) errprintf( \
1761 "upd_put_params: retrieved parameter \"%s\"\n",\
1762 Name); \
1763 if(0 > code) { \
1764 param_signal_error(plist,Name,code); \
1765 if(error > code) error = code; \
1766 }
1767 #else
1768 #define UPD_PARAM_READ(Param_read,Name,Object) \
1769 code = Param_read(plist,Name,&Object); \
1770 if(0 > code) { \
1771 code = param_read_null(plist,Name); \
1772 if(0 == code) memset(&Object,0,sizeof(Object));\
1773 } \
1774 if(0 > code) { \
1775 param_signal_error(plist,Name,code); \
1776 if(error > code) error = code; \
1777 }
1778 #endif
1779
1780 UPD_PARAM_READ(param_read_string,upd_version,udev->upd_version)
1781
1782
1783 /**
1784 upd_put_params begins it's normal work by creating a copy, of
1785 the data, that it might change, except for color_info that might
1786 be changed in the device-structure, all manipulations are carried
1787 out on this copies.
1788 */
1789 MarginsHWResolution[0] = udev->MarginsHWResolution[0];
1790 MarginsHWResolution[1] = udev->MarginsHWResolution[1];
1791 Margins[0] = udev->Margins[0];
1792 Margins[1] = udev->Margins[1];
1793
1794 color_info = udev->color_info;
1795 if(upd) {
1796 flags = upd->flags;
1797 UPD_MM_CPY_ARRAY(udev->memory, choice, upd->choice, countof(upd_choice),
1798 UPD_MM_CPY_VALUE);
1799 UPD_MM_CPY_ARRAY(udev->memory, ints, upd->ints, countof(upd_ints),
1800 UPD_MM_CPY_VALUE);
1801 UPD_MM_CPY_ARRAY(udev->memory, int_a, upd->int_a, countof(upd_int_a),
1802 UPD_MM_CPY_PARAM);
1803 UPD_MM_CPY_ARRAY(udev->memory, strings, upd->strings, countof(upd_strings),
1804 UPD_MM_CPY_PARAM);
1805 UPD_MM_CPY_ARRAY(udev->memory, string_a,upd->string_a,countof(upd_string_a),
1806 UPD_MM_CPY_APARAM);
1807 UPD_MM_CPY_ARRAY(udev->memory, float_a, upd->float_a, countof(upd_float_a),
1808 UPD_MM_CPY_PARAM);
1809 } else {
1810 flags = 0;
1811 UPD_MM_GET_ARRAY(udev->memory, choice, countof(upd_choice));
1812 UPD_MM_GET_ARRAY(udev->memory, ints, countof(upd_ints));
1813 UPD_MM_GET_ARRAY(udev->memory, int_a, countof(upd_int_a));
1814 UPD_MM_GET_ARRAY(udev->memory, strings, countof(upd_strings));
1815 UPD_MM_GET_ARRAY(udev->memory, string_a,countof(upd_string_a));
1816 UPD_MM_GET_ARRAY(udev->memory, float_a, countof(upd_float_a));
1817 }
1818
1819 /** Import the Multiple-Choices */
1820 for(i = 0; countof(upd_choice) > i; ++i) {
1821 gs_param_string value = { NULL, 0, false};
1822 if(!upd_choice[i][0]) continue;
1823 UPD_PARAM_READ(param_read_name,upd_choice[i][0],value);
1824 if(0 == code) {
1825 if(0 <= error) error |= UPD_PUT_CHOICE;
1826 choice[i] = 0;
1827 if(0 < value.size) {
1828 int j;
1829 for(j = 1; upd_choice[i][j]; ++j) {
1830 if((strlen(upd_choice[i][j]) == value.size) &&
1831 (0 == strncmp(upd_choice[i][j],
1832 (const char *) value.data,value.size))) {
1833 choice[i] = j;
1834 break;
1835 }
1836 }
1837 }
1838 }
1839 }
1840
1841 /** Import the Boolean Values */
1842 for(i = 0; countof(upd_flags) > i; ++i) {
1843 uint32_t bit = (uint32_t) 1 << i;
1844 bool flag = flags & bit ? true : false;
1845 if(!upd_flags[i]) continue;
1846 UPD_PARAM_READ(param_read_bool,upd_flags[i],flag);
1847 if(0 == code) {
1848 if(0 <= error) error |= UPD_PUT_FLAGS;
1849 if(flag) flags |= bit;
1850 else flags &= ~bit;
1851 }
1852 }
1853
1854 /** Import the Integer Values */
1855 for(i = 0; countof(upd_ints) > i; ++i) {
1856 int value = ints[i];
1857 if(!upd_ints[i]) continue;
1858 UPD_PARAM_READ(param_read_int,upd_ints[i],value);
1859 if(0 == code) {
1860 if(0 <= error) error |= UPD_PUT_INTS;
1861 ints[i] = value;
1862 }
1863 }
1864
1865 /** Import the Integer Arrays */
1866 for(i = 0; countof(upd_int_a) > i; ++i) {
1867 gs_param_int_array value = int_a[i];
1868 if(!upd_int_a[i]) continue;
1869 UPD_PARAM_READ(param_read_int_array,upd_int_a[i],value);
1870 if(0 == code) {
1871 if(0 <= error) error |= UPD_PUT_INT_A;
1872 UPD_MM_DEL_PARAM(udev->memory, int_a[i]);
1873 if(!value.size) {
1874 value.data = NULL;
1875 int_a[i] = value;
1876 } else {
1877 UPD_MM_CPY_PARAM(udev->memory, int_a[i],value);
1878 }
1879 }
1880 }
1881
1882 /** Import the Strings */
1883 for(i = 0; countof(upd_strings) > i; ++i) {
1884 gs_param_string value = strings[i];
1885 if(!upd_strings[i]) continue;
1886 UPD_PARAM_READ(param_read_string,upd_strings[i],value);
1887 if(0 == code) {
1888 if(0 <= error) error |= UPD_PUT_STRINGS;
1889 UPD_MM_DEL_PARAM(udev->memory, strings[i]);
1890 if(!value.size) {
1891 value.data = NULL;
1892 strings[i] = value;
1893 } else {
1894 UPD_MM_CPY_PARAM(udev->memory, strings[i],value);
1895 }
1896 }
1897 }
1898
1899 /** Import the String Arrays */
1900 for(i = 0; countof(upd_string_a) > i; ++i) {
1901 gs_param_string_array value = string_a[i];
1902 if(!upd_string_a[i]) continue;
1903 UPD_PARAM_READ(param_read_string_array,upd_string_a[i],value);
1904 if(0 == code) {
1905 if(0 <= error) error |= UPD_PUT_STRING_A;
1906 UPD_MM_DEL_APARAM(udev->memory, string_a[i]);
1907 if(!value.size) {
1908 value.data = NULL;
1909 string_a[i] = value;
1910 } else {
1911 UPD_MM_CPY_APARAM(udev->memory, string_a[i],value);
1912 }
1913 }
1914 }
1915
1916 /** Import the Float Arrays */
1917 for(i = 0; countof(upd_float_a) > i; ++i) {
1918 gs_param_float_array value = float_a[i];
1919 if(!upd_float_a[i]) continue;
1920 UPD_PARAM_READ(param_read_float_array,upd_float_a[i],value);
1921 if(0 == code) {
1922 if(0 <= error) error |= UPD_PUT_FLOAT_A;
1923 UPD_MM_DEL_PARAM(udev->memory, float_a[i]);
1924 if(!value.size) {
1925 value.data = NULL;
1926 float_a[i] = value;
1927 } else {
1928 UPD_MM_CPY_PARAM(udev->memory, float_a[i],value);
1929 }
1930 }
1931 }
1932
1933 /**
1934 Prior to the call to the superclass-put_params, the memory-layout and
1935 the color-model needs adjustment. This is performed here, if any parameters
1936 were set.
1937 In addition to that, Resolution & Margin-Parameters are tested & adjusted.
1938 */
1939 if(0 < error) {
1940
1941 int *ip,*ip2,ncomp,nbits;
1942
1943 if(6 > int_a[IA_COLOR_INFO].size) {
1944 UPD_MM_DEL_PARAM(udev->memory, int_a[IA_COLOR_INFO]);
1945 UPD_MM_GET_ARRAY(udev->memory, int_a[IA_COLOR_INFO].data,6);
1946 int_a[IA_COLOR_INFO].size = 6;
1947 }
1948 ip = (int *) upd_cast(int_a[IA_COLOR_INFO].data);
1949
1950 if(0 == ip[0]) { /* Try to obtain num_components */
1951 switch(choice[C_MAPPER]) {
1952 case MAP_GRAY: ip[0] = 1; break;
1953 case MAP_RGBW: ip[0] = 3; break;
1954 case MAP_RGB: ip[0] = 3; break;
1955 case MAP_CMYK: ip[0] = 4; break;
1956 case MAP_CMYKGEN: ip[0] = 4; break;
1957 case MAP_RGBOV: ip[0] = 3; break;
1958 case MAP_RGBNOV: ip[0] = 3; break;
1959 default: ip[0] = color_info.num_components; break;
1960 }
1961 } /* Try to obtain num_components */
1962
1963 switch(choice[C_MAPPER]) {
1964 case MAP_GRAY: ncomp = 1; break;
1965 case MAP_RGBW: ncomp = 4; break;
1966 case MAP_RGB: ncomp = 3; break;
1967 case MAP_CMYK: ncomp = 4; break;
1968 case MAP_CMYKGEN: ncomp = 4; break;
1969 case MAP_RGBOV: ncomp = 4; break;
1970 case MAP_RGBNOV: ncomp = 4; break;
1971 default: ncomp = ip[0]; break;
1972 }
1973 if(UPD_CMAP_MAX < ncomp) ncomp = UPD_CMAP_MAX;
1974
1975 if(ncomp > int_a[IA_COMPBITS].size) { /* Default ComponentBits */
1976 UPD_MM_GET_ARRAY(udev->memory, ip2,ncomp);
1977 nbits = 32 / ncomp;
1978 if(8 < nbits) nbits = 8;
1979 for(i = 0; i < ncomp; ++i) ip2[i] = nbits;
1980 UPD_MM_DEL_PARAM(udev->memory, int_a[IA_COMPBITS]);
1981 int_a[IA_COMPBITS].data = ip2;
1982 int_a[IA_COMPBITS].size = ncomp;
1983 } /* Default ComponentBits */
1984
1985 if(ncomp > int_a[IA_COMPSHIFT].size) { /* Default ComponentShift */
1986 nbits = 0;
1987 for(i = 0; i < ncomp; ++i) nbits += int_a[IA_COMPBITS].data[i];
1988 UPD_MM_GET_ARRAY(udev->memory, ip2,ncomp);
1989 for(i = 0; i < ncomp; ++i) {
1990 ip2[i] = nbits - int_a[IA_COMPBITS].data[i];
1991 nbits -= int_a[IA_COMPBITS].data[i];
1992 }
1993 UPD_MM_DEL_PARAM(udev->memory, int_a[IA_COMPSHIFT]);
1994 int_a[IA_COMPSHIFT].data = ip2;
1995 int_a[IA_COMPSHIFT].size = ncomp;
1996 } /* Default ComponentShift */
1997
1998 if(0 == ip[1]) { /* Try to compute the depth */
1999 nbits = 0;
2000 for(i = 0; i < ncomp; ++i) {
2001 if(nbits < (int_a[IA_COMPBITS].data[i] +
2002 int_a[IA_COMPSHIFT].data[i]))
2003 nbits = int_a[IA_COMPBITS].data[i] +
2004 int_a[IA_COMPSHIFT].data[i];
2005 }
2006 if( 1 >= nbits) nbits = 1;
2007 else if( 2 >= nbits) nbits = 2;
2008 else if( 4 >= nbits) nbits = 4;
2009 else if( 8 >= nbits) nbits = 8;
2010 else if(16 >= nbits) nbits = 16;
2011 else if(24 >= nbits) nbits = 24;
2012 else nbits = 32;
2013
2014 ip[1] = nbits;
2015
2016 } /* Try to compute the depth */
2017
2018 if(0 == ip[2]) { /* Number of Gray-Levels */
2019 nbits = 0;
2020 for(i = 0; i < ncomp; ++i) if(nbits < int_a[IA_COMPBITS].data[i])
2021 nbits = int_a[IA_COMPBITS].data[i];
2022 if(nbits > 8) nbits = 8;
2023 ip[2] = (1 << nbits) - 1;
2024 } /* Number of Gray-Levels */
2025
2026 if(0 == ip[3] && 1 < ip[0]) { /* Number of Colors */
2027 nbits = 0;
2028 for(i = 0; i < ip[0]; ++i) nbits += int_a[IA_COMPBITS].data[i];
2029 if(nbits > 8) nbits = 8;
2030 ip[3] = (1 << nbits) - 1;
2031 } /* Number of Colors */
2032
2033 if(0 == ip[4]) { /* Gray-Ramp */
2034 nbits = 0;
2035 for(i = 0; i < ncomp; ++i) if(nbits < int_a[IA_COMPBITS].data[i])
2036 nbits = int_a[IA_COMPBITS].data[i];
2037 if(2 < nbits) ip[4] = 256;
2038 else ip[4] = 2;
2039 } /* Gray-Ramp */
2040
2041 if(0 == ip[5] && 1 < ip[0]) { /* Color-Ramp */
2042 nbits = 0;
2043 for(i = 0; i < ncomp; ++i) if(nbits < int_a[IA_COMPBITS].data[i])
2044 nbits = int_a[IA_COMPBITS].data[i];
2045 if(2 < nbits) ip[5] = 256;
2046 else ip[5] = 2;
2047 } /* Color-Ramp */
2048
2049 udev->color_info.num_components = ip[0];
2050 udev->color_info.depth = ip[1];
2051 udev->color_info.max_gray = (gx_color_value) ip[2];
2052 udev->color_info.max_color = (gx_color_value) ip[3];
2053 udev->color_info.dither_grays = (gx_color_value) ip[4];
2054 udev->color_info.dither_colors = (gx_color_value) ip[5];
2055
2056 /*
2057 * Now we're dealing with the Resolution- & Margin-Stuff
2058 * (This is close to be a bad-nasty-hack-hack)
2059 */
2060 if((0 == param_read_float_array(plist,"HWResolution",&mfa)) &&
2061 (2 == mfa.size) && (0 != mfa.data)) {
2062 udev->MarginsHWResolution[0] = mfa.data[0];
2063 udev->MarginsHWResolution[1] = mfa.data[1];
2064 } else {
2065 udev->MarginsHWResolution[0] = udev->HWResolution[0];
2066 udev->MarginsHWResolution[1] = udev->HWResolution[1];
2067 }
2068
2069 if((0 == param_read_float_array(plist,".HWMargins",&mfa)) &&
2070 (4 == mfa.size) && (0 != mfa.data)) {
2071 udev->Margins[0] = -mfa.data[0] * udev->MarginsHWResolution[0] / 72.0;
2072 udev->Margins[1] = -mfa.data[3] * udev->MarginsHWResolution[1] / 72.0;
2073 }
2074 } /* Change the color-Info */
2075
2076 /* Call the superclass-put_params now */
2077 code = gdev_prn_put_params((gx_device *)udev,plist);
2078 if(0 > code) error = code;
2079
2080 /**
2081 If the superclass-"put_params" went o.k. too, then the new parameters are
2082 transferred into the device-structure. In the case of "uniprint", this may
2083
2084 1. Close the device, which might fail.
2085 2. Allocate new memory for the upd-specific structure, that might fail too.
2086
2087 */
2088 /* *HGS* recognize a changed device geometry */
2089 if( udev->upd && /* HGS */
2090 ((udev->width != udev->upd->pdwidth) || /* HGS */
2091 (udev->height != udev->upd->pdheight) )) /* HGS */
2092 error |= UPD_PUT_CHANGEDSIZE; /* HGS */
2093
2094 if(0 < error && udev->is_open) {
2095 code = gs_closedevice((gx_device *)udev);
2096 if(0 > code) error = code;
2097 }
2098
2099 if(0 < error) { /* Actually something loaded without error */
2100
2101 if(!(upd = udev->upd)) {
2102 UPD_MM_GET_ARRAY(udev->memory, udev->upd,1);
2103 upd = udev->upd;
2104 } else {
2105 UPD_MM_DEL_ARRAY(udev->memory, upd->choice, countof(upd_choice), UPD_MM_DEL_VALUE);
2106 UPD_MM_DEL_ARRAY(udev->memory, upd->ints, countof(upd_ints), UPD_MM_DEL_VALUE);
2107 UPD_MM_DEL_ARRAY(udev->memory, upd->int_a, countof(upd_int_a), UPD_MM_DEL_PARAM);
2108 UPD_MM_DEL_ARRAY(udev->memory, upd->strings, countof(upd_strings), UPD_MM_DEL_PARAM);
2109 UPD_MM_DEL_ARRAY(udev->memory, upd->string_a,countof(upd_string_a),UPD_MM_DEL_APARAM);
2110 UPD_MM_DEL_ARRAY(udev->memory, upd->float_a, countof(upd_float_a), UPD_MM_DEL_PARAM);
2111 }
2112
2113 upd->choice = choice;
2114 upd->flags = flags;
2115 upd->ints = ints;
2116 upd->int_a = int_a;
2117 upd->strings = strings;
2118 upd->string_a = string_a;
2119 upd->float_a = float_a;
2120
2121 if(0 < error) error = 0;
2122
2123 } else {
2124
2125 udev->Margins[0] = Margins[0];
2126 udev->Margins[1] = Margins[1];
2127 udev->MarginsHWResolution[0] = MarginsHWResolution[0];
2128 udev->MarginsHWResolution[1] = MarginsHWResolution[1];
2129
2130 udev->color_info = color_info;
2131 UPD_MM_DEL_ARRAY(udev->memory, choice, countof(upd_choice), UPD_MM_DEL_VALUE);
2132 UPD_MM_DEL_ARRAY(udev->memory, ints, countof(upd_ints), UPD_MM_DEL_VALUE);
2133 UPD_MM_DEL_ARRAY(udev->memory, int_a, countof(upd_int_a), UPD_MM_DEL_PARAM);
2134 UPD_MM_DEL_ARRAY(udev->memory, strings, countof(upd_strings), UPD_MM_DEL_PARAM);
2135 UPD_MM_DEL_ARRAY(udev->memory, string_a,countof(upd_string_a),UPD_MM_DEL_APARAM);
2136 UPD_MM_DEL_ARRAY(udev->memory, float_a, countof(upd_float_a), UPD_MM_DEL_PARAM);
2137
2138 }
2139
2140 /*
2141 * upd_put_params keeps the Procedures upd to date
2142 */
2143
2144 upd_procs_map(udev);
2145
2146
2147 #if UPD_MESSAGES & UPD_M_TOPCALLS
2148 errprintf("RETURN: %d = upd_put_params(0x%05lx,0x%05lx)\n",
2149 error,(long) udev, (long) plist);
2150 #endif
2151
2152 return error;
2153 }
2154
2155 /* ------------------------------------------------------------------- */
2156 /* upd_cmyk_icolor: KCMY->KCMY-Index Mapping */
2157 /* ------------------------------------------------------------------- */
2158 /**
2159 The next Routines, that follow, are the color-mapping routines.
2160 GHOSTSCRIPT talks about "gx_color_values" and the driver has
2161 to merge the 1, 3 or four values into up to 32 Bits, that means
2162 it is necessary to do some truncation and shifting. For the truncation
2163 "uniprint" uses the internal function "upd_truncate" and "upd_expand"
2164 reverses this in the reverse-mapping procedures.
2165 */
2166
2167 private gx_color_index
upd_cmyk_icolor(gx_device * pdev,const gx_color_value cv[])2168 upd_cmyk_icolor(gx_device *pdev, const gx_color_value cv[])
2169 {
2170 const upd_p upd = ((upd_device *)pdev)->upd;
2171 gx_color_index rv;
2172 gx_color_value c, m, y, k;
2173 c = cv[0]; m = cv[1]; y = cv[2]; k = cv[3];
2174
2175 /**
2176 All 4-Component-Modi have to deal with the Problem, that a value
2177 with all bits set can be produced, which is treated as an error-return
2178 from the mapping-functions. But with RGBW or KCMY, there is a neat
2179 trick: Grayscale are transferred as RGB/CMY=0 and holding Data only
2180 in the W- or K-Component.
2181 */
2182
2183 if((c == m) && (m == y)) {
2184
2185 rv = upd_truncate(upd,0,(gx_color_value)(c > k ? c : k));
2186
2187 } else {
2188
2189 rv = upd_truncate(upd,0,k) | upd_truncate(upd,1,c)
2190 | upd_truncate(upd,2,m) | upd_truncate(upd,3,y);
2191
2192
2193 /* It might still become a "gx_no_color_value" due to truncation, thus: */
2194
2195 if(rv == gx_no_color_index) rv ^= 1;
2196 }
2197
2198
2199 #if UPD_MESSAGES & UPD_M_MAPCALLS
2200 errprintf(
2201 "cmyk_icolor: (%5.1f,%5.1f,%5.1f,%5.1f) : (%5.1f,%5.1f,%5.1f,%5.1f) : 0x%0*lx\n",
2202 255.0 * (double) c / (double) gx_max_color_value,
2203 255.0 * (double) m / (double) gx_max_color_value,
2204 255.0 * (double) y / (double) gx_max_color_value,
2205 255.0 * (double) k / (double) gx_max_color_value,
2206 255.0 * (double) ((rv >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2207 / (double) upd->cmap[1].bitmsk,
2208 255.0 * (double) ((rv >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2209 / (double) upd->cmap[2].bitmsk,
2210 255.0 * (double) ((rv >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2211 / (double) upd->cmap[3].bitmsk,
2212 255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2213 / (double) upd->cmap[0].bitmsk,
2214 (pdev->color_info.depth + 3)>>2,rv);
2215 #endif
2216
2217 return rv;
2218 }
2219
2220 /* ------------------------------------------------------------------- */
2221 /* upd_icolor_rgb: Stored KCMY back to a RGB */
2222 /* ------------------------------------------------------------------- */
2223
2224 private int
upd_icolor_rgb(gx_device * pdev,gx_color_index color,gx_color_value prgb[3])2225 upd_icolor_rgb(gx_device *pdev, gx_color_index color, gx_color_value prgb[3])
2226 {
2227 const upd_p upd = ((upd_device *)pdev)->upd;
2228 gx_color_value c,m,y,k;
2229
2230 /*
2231 * Expand to the Component-Values
2232 */
2233 k = upd_expand(upd,0,color);
2234 c = upd_expand(upd,1,color);
2235 m = upd_expand(upd,2,color);
2236 y = upd_expand(upd,3,color);
2237
2238 /*
2239 * Then Invert and subtract K from the colors
2240 */
2241 prgb[0] = gx_max_color_value - c;
2242 if(prgb[0] > k) prgb[0] -= k;
2243 else prgb[0] = 0;
2244
2245 prgb[1] = gx_max_color_value - m;
2246 if(prgb[1] > k) prgb[1] -= k;
2247 else prgb[1] = 0;
2248
2249 prgb[2] = gx_max_color_value - y;
2250 if(prgb[2] > k) prgb[2] -= k;
2251 else prgb[2] = 0;
2252
2253
2254 #if UPD_MESSAGES & UPD_M_MAPCALLS
2255 errprintf(
2256 "icolor_rgb: 0x%0*lx -> (%5.1f,%5.1f,%5.1f,%5.1f) -> (%5.1f,%5.1f,%5.1f,%5.1f) -> (%5.1f,%5.1f,%5.1f)\n",
2257 (pdev->color_info.depth + 3)>>2,color,
2258 255.0 * (double) ((color >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2259 / (double) upd->cmap[1].bitmsk,
2260 255.0 * (double) ((color >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2261 / (double) upd->cmap[2].bitmsk,
2262 255.0 * (double) ((color >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2263 / (double) upd->cmap[3].bitmsk,
2264 255.0 * (double) ((color >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2265 / (double) upd->cmap[0].bitmsk,
2266 255.0 * (double) c / (double) gx_max_color_value,
2267 255.0 * (double) m / (double) gx_max_color_value,
2268 255.0 * (double) y / (double) gx_max_color_value,
2269 255.0 * (double) k / (double) gx_max_color_value,
2270 255.0 * (double) prgb[0] / (double) gx_max_color_value,
2271 255.0 * (double) prgb[1] / (double) gx_max_color_value,
2272 255.0 * (double) prgb[2] / (double) gx_max_color_value);
2273 #endif
2274
2275 return 0;
2276 }
2277
2278 /* ------------------------------------------------------------------- */
2279 /* upd_rgb_1color: Grayscale->Grayscale-index-Mapping */
2280 /* ------------------------------------------------------------------- */
2281
2282 private gx_color_index
upd_rgb_1color(gx_device * pdev,const gx_color_value cv[])2283 upd_rgb_1color(gx_device *pdev, const gx_color_value cv[])
2284 {
2285 const upd_p upd = ((upd_device *)pdev)->upd;
2286 gx_color_index rv;
2287 gx_color_value g;
2288
2289 g = cv[0];
2290 rv = upd_truncate(upd,0,g);
2291
2292 #if UPD_MESSAGES & UPD_M_MAPCALLS
2293 errprintf(
2294 "rgb_1color: (%5.1f) : (%5.1f) : 0x%0*lx\n",
2295 255.0 * (double) g / (double) gx_max_color_value,
2296 255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2297 / (double) upd->cmap[0].bitmsk,
2298 (pdev->color_info.depth + 3)>>2,rv);
2299 #endif
2300
2301 return rv;
2302 }
2303
2304 /* ------------------------------------------------------------------- */
2305 /* upd_1color_rgb: reversal of the above */
2306 /* ------------------------------------------------------------------- */
2307
2308 private int
upd_1color_rgb(gx_device * pdev,gx_color_index color,gx_color_value cv[1])2309 upd_1color_rgb(gx_device *pdev, gx_color_index color, gx_color_value cv[1])
2310 {
2311 const upd_p upd = ((upd_device *)pdev)->upd;
2312 /*
2313 * Actual task: expand to full range of gx_color_value
2314 */
2315 cv[0] = upd_expand(upd,0,color);
2316
2317 #if UPD_MESSAGES & UPD_M_MAPCALLS
2318 errprintf("1color_rgb: 0x%0*lx -> %5.1f -> (%5.1f,%5.1f,%5.1f)\n",
2319 (pdev->color_info.depth + 3)>>2,color,
2320 255.0 * (double) ((color >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2321 / (double) upd->cmap[0].bitmsk,
2322 255.0 * (double) prgb[0] / (double) gx_max_color_value,
2323 255.0 * (double) prgb[0] / (double) gx_max_color_value,
2324 255.0 * (double) prgb[0] / (double) gx_max_color_value);
2325 #endif
2326
2327 return 0;
2328 }
2329
2330 /* ------------------------------------------------------------------- */
2331 /* upd_rgb_3color: component-wise RGB->RGB-Mapping */
2332 /* ------------------------------------------------------------------- */
2333
2334 private gx_color_index
upd_rgb_3color(gx_device * pdev,const gx_color_value cv[])2335 upd_rgb_3color(gx_device *pdev, const gx_color_value cv[])
2336 {
2337 const upd_p upd = ((upd_device *)pdev)->upd;
2338 gx_color_index rv;
2339 gx_color_value r, g, b;
2340 r = cv[0]; g = cv[1]; b = cv[2];
2341
2342 rv = upd_truncate(upd,0,r) | upd_truncate(upd,1,g) | upd_truncate(upd,2,b);
2343 if(rv == gx_no_color_index) rv ^= 1;
2344
2345 #if UPD_MESSAGES & UPD_M_MAPCALLS
2346 errprintf(
2347 "rgb_3color: (%5.1f,%5.1f,%5.1f) : (%5.1f,%5.1f,%5.1f) : 0x%0*lx\n",
2348 255.0 * (double) r / (double) gx_max_color_value,
2349 255.0 * (double) g / (double) gx_max_color_value,
2350 255.0 * (double) b / (double) gx_max_color_value,
2351 255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2352 / (double) upd->cmap[0].bitmsk,
2353 255.0 * (double) ((rv >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2354 / (double) upd->cmap[1].bitmsk,
2355 255.0 * (double) ((rv >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2356 / (double) upd->cmap[2].bitmsk,
2357 (pdev->color_info.depth + 3)>>2,rv);
2358 #endif
2359
2360 return rv;
2361 }
2362
2363 /* ------------------------------------------------------------------- */
2364 /* upd_3color_rgb: reversal of the above */
2365 /* ------------------------------------------------------------------- */
2366
2367 private int
upd_3color_rgb(gx_device * pdev,gx_color_index color,gx_color_value prgb[3])2368 upd_3color_rgb(gx_device *pdev, gx_color_index color, gx_color_value prgb[3])
2369 {
2370 const upd_p upd = ((upd_device *)pdev)->upd;
2371
2372 prgb[0] = upd_expand(upd,0,color);
2373 prgb[1] = upd_expand(upd,1,color);
2374 prgb[2] = upd_expand(upd,2,color);
2375
2376 #if UPD_MESSAGES & UPD_M_MAPCALLS
2377 errprintf(
2378 "3color_rgb: 0x%0*lx -> (%5.1f,%5.1f,%5.1f) -> (%5.1f,%5.1f,%5.1f)\n",
2379 (pdev->color_info.depth + 3)>>2,color,
2380 255.0 * (double) ((color >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2381 / (double) upd->cmap[0].bitmsk,
2382 255.0 * (double) ((color >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2383 / (double) upd->cmap[1].bitmsk,
2384 255.0 * (double) ((color >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2385 / (double) upd->cmap[2].bitmsk,
2386
2387 255.0 * (double) prgb[0] / (double) gx_max_color_value,
2388 255.0 * (double) prgb[1] / (double) gx_max_color_value,
2389 255.0 * (double) prgb[2] / (double) gx_max_color_value);
2390 #endif
2391
2392 return 0;
2393 }
2394
2395 /* ------------------------------------------------------------------- */
2396 /* upd_rgb_4color: Create an WRGB-Index from RGB */
2397 /* ------------------------------------------------------------------- */
2398
2399 private gx_color_index
upd_rgb_4color(gx_device * pdev,const gx_color_value cv[])2400 upd_rgb_4color(gx_device *pdev, const gx_color_value cv[])
2401 {
2402 const upd_p upd = ((upd_device *)pdev)->upd;
2403 gx_color_index rv;
2404 gx_color_value r, g, b;
2405
2406 r = cv[0]; g = cv[1]; b = cv[2];
2407
2408 if((r == g) && (g == b)) {
2409
2410 rv = upd_truncate(upd,0,r);
2411
2412 } else {
2413
2414 gx_color_value w = g < r ? g : r; w = w < b ? w : b; /* Minimum */
2415
2416 rv = upd_truncate(upd,0,w) | upd_truncate(upd,1,r) |
2417 upd_truncate(upd,2,g) | upd_truncate(upd,3,b);
2418
2419 /* It might still become a "gx_no_color_value" due to truncation, thus: */
2420
2421 if(rv == gx_no_color_index) rv ^= 1;
2422 }
2423
2424 #if UPD_MESSAGES & UPD_M_MAPCALLS
2425 errprintf(
2426 "rgb_4color: (%5.1f,%5.1f,%5.1f) : (%5.1f,%5.1f,%5.1f,%5.1f) : 0x%0*lx\n",
2427 255.0 * (double) r / (double) gx_max_color_value,
2428 255.0 * (double) g / (double) gx_max_color_value,
2429 255.0 * (double) b / (double) gx_max_color_value,
2430 255.0 * (double) ((rv >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2431 / (double) upd->cmap[1].bitmsk,
2432 255.0 * (double) ((rv >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2433 / (double) upd->cmap[2].bitmsk,
2434 255.0 * (double) ((rv >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2435 / (double) upd->cmap[3].bitmsk,
2436 255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2437 / (double) upd->cmap[0].bitmsk,
2438 (pdev->color_info.depth + 3)>>2,rv);
2439 #endif
2440
2441 return rv;
2442 }
2443
2444 /* ------------------------------------------------------------------- */
2445 /* upd_4color_rgb: Stored WRGB-Index back to a RGB */
2446 /* ------------------------------------------------------------------- */
2447
2448 private int
upd_4color_rgb(gx_device * pdev,gx_color_index color,gx_color_value prgb[3])2449 upd_4color_rgb(gx_device *pdev, gx_color_index color, gx_color_value prgb[3])
2450 {
2451 const upd_p upd = ((upd_device *)pdev)->upd;
2452
2453 /*
2454 * Expand to the Component-Values
2455 */
2456 prgb[0] = upd_expand(upd,1,color);
2457 prgb[1] = upd_expand(upd,2,color);
2458 prgb[2] = upd_expand(upd,3,color);
2459
2460 /* Revert our Grayscale-Trick: */
2461 if(!(prgb[0] || prgb[1] || prgb[2]))
2462 prgb[0] = prgb[1] = prgb[2] = upd_expand(upd,0,color);
2463
2464
2465 #if UPD_MESSAGES & UPD_M_MAPCALLS
2466 errprintf(
2467 "4color_rgb: 0x%0*lx -> (%5.1f,%5.1f,%5.1f,%5.1f) -> (%5.1f,%5.1f,%5.1f)\n",
2468 (pdev->color_info.depth + 3)>>2,color,
2469 255.0 * (double) ((color >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2470 / (double) upd->cmap[1].bitmsk,
2471 255.0 * (double) ((color >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2472 / (double) upd->cmap[2].bitmsk,
2473 255.0 * (double) ((color >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2474 / (double) upd->cmap[3].bitmsk,
2475 255.0 * (double) ((color >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2476 / (double) upd->cmap[0].bitmsk,
2477 255.0 * (double) prgb[0] / (double) gx_max_color_value,
2478 255.0 * (double) prgb[1] / (double) gx_max_color_value,
2479 255.0 * (double) prgb[2] / (double) gx_max_color_value);
2480 #endif
2481
2482 return 0;
2483 }
2484
2485 /* ------------------------------------------------------------------- */
2486 /* upd_cmyk_kcolor: KCMY->KCMY-Index Mapping with Black Generation */
2487 /* ------------------------------------------------------------------- */
2488
2489 private gx_color_index
upd_cmyk_kcolor(gx_device * pdev,const gx_color_value cv[])2490 upd_cmyk_kcolor(gx_device *pdev, const gx_color_value cv[])
2491 {
2492 const upd_p upd = ((upd_device *)pdev)->upd;
2493 gx_color_index rv;
2494 gx_color_value black;
2495
2496 gx_color_value c, m, y, k;
2497 c = cv[0]; m = cv[1]; y = cv[2]; k = cv[3];
2498
2499 if((c == m) && (m == y)) {
2500
2501 black = c > k ? c : k;
2502 rv = upd_truncate(upd,0,black);
2503
2504 } else {
2505
2506 if(k && !(c | m | y)) {
2507 black = k;
2508 } else {
2509 black = c < m ? c : m;
2510 black = black < y ? black : y;
2511 }
2512
2513 rv = upd_truncate(upd,0,black) | upd_truncate(upd,1,c)
2514 | upd_truncate(upd,2,m) | upd_truncate(upd,3,y);
2515
2516 /* It might still become a "gx_no_color_value" due to truncation, thus: */
2517
2518 if(rv == gx_no_color_index) rv ^= 1;
2519 }
2520
2521
2522 #if UPD_MESSAGES & UPD_M_MAPCALLS
2523 errprintf(
2524 "cmyk_kcolor: (%5.1f,%5.1f,%5.1f,%5.1f) : (%5.1f,%5.1f,%5.1f,%5.1f) : 0x%0*lx\n",
2525 255.0 * (double) c / (double) gx_max_color_value,
2526 255.0 * (double) m / (double) gx_max_color_value,
2527 255.0 * (double) y / (double) gx_max_color_value,
2528 255.0 * (double) k / (double) gx_max_color_value,
2529 255.0 * (double) ((rv >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2530 / (double) upd->cmap[1].bitmsk,
2531 255.0 * (double) ((rv >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2532 / (double) upd->cmap[2].bitmsk,
2533 255.0 * (double) ((rv >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2534 / (double) upd->cmap[3].bitmsk,
2535 255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2536 / (double) upd->cmap[0].bitmsk,
2537 (pdev->color_info.depth + 3)>>2,rv);
2538 #endif
2539
2540 return rv;
2541 }
2542
2543 /* ------------------------------------------------------------------- */
2544 /* upd_kcolor_rgb: Stored CMY+generated K back to a RGB */
2545 /* ------------------------------------------------------------------- */
2546
2547 private int
upd_kcolor_rgb(gx_device * pdev,gx_color_index color,gx_color_value prgb[3])2548 upd_kcolor_rgb(gx_device *pdev, gx_color_index color, gx_color_value prgb[3])
2549 {
2550 const upd_p upd = ((upd_device *)pdev)->upd;
2551 gx_color_value c,m,y,k;
2552
2553 /*
2554 * Expand to the Component-Values
2555 */
2556 k = upd_expand(upd,0,color);
2557 c = upd_expand(upd,1,color);
2558 m = upd_expand(upd,2,color);
2559 y = upd_expand(upd,3,color);
2560
2561 /*
2562 * Check for plain Gray-Values
2563 */
2564 if(!(c | m | y )) {
2565
2566 prgb[2] = prgb[1] = prgb[0] = gx_max_color_value - k;
2567
2568 } else {
2569 prgb[0] = gx_max_color_value - c;
2570 prgb[1] = gx_max_color_value - m;
2571 prgb[2] = gx_max_color_value - y;
2572 }
2573
2574 #if UPD_MESSAGES & UPD_M_MAPCALLS
2575 errprintf(
2576 "kcolor_rgb: 0x%0*lx -> (%5.1f,%5.1f,%5.1f,%5.1f) -> (%5.1f,%5.1f,%5.1f,%5.1f) -> (%5.1f,%5.1f,%5.1f)\n",
2577 (pdev->color_info.depth + 3)>>2,color,
2578 255.0 * (double) ((color >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2579 / (double) upd->cmap[1].bitmsk,
2580 255.0 * (double) ((color >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2581 / (double) upd->cmap[2].bitmsk,
2582 255.0 * (double) ((color >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2583 / (double) upd->cmap[3].bitmsk,
2584 255.0 * (double) ((color >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2585 / (double) upd->cmap[0].bitmsk,
2586 255.0 * (double) c / (double) gx_max_color_value,
2587 255.0 * (double) m / (double) gx_max_color_value,
2588 255.0 * (double) y / (double) gx_max_color_value,
2589 255.0 * (double) k / (double) gx_max_color_value,
2590 255.0 * (double) prgb[0] / (double) gx_max_color_value,
2591 255.0 * (double) prgb[1] / (double) gx_max_color_value,
2592 255.0 * (double) prgb[2] / (double) gx_max_color_value);
2593 #endif
2594
2595 return 0;
2596 }
2597
2598 /* ------------------------------------------------------------------- */
2599 /* upd_rgb_ovcolor: Create an KCMY-Index from RGB */
2600 /* ------------------------------------------------------------------- */
2601
2602 private gx_color_index
upd_rgb_ovcolor(gx_device * pdev,const gx_color_value cv[])2603 upd_rgb_ovcolor(gx_device *pdev, const gx_color_value cv[])
2604 {
2605 const upd_p upd = ((upd_device *)pdev)->upd;
2606 gx_color_index rv;
2607 gx_color_value c,m,y,black;
2608 gx_color_value r, g, b;
2609 r = cv[0]; g = cv[1]; b = cv[2];
2610 if((r == g) && (g == b)) {
2611
2612 black = gx_max_color_value - r;
2613 rv = upd_truncate(upd,0,black);
2614 c = m = y = 0;
2615
2616 } else {
2617
2618 c = gx_max_color_value - r;
2619 m = gx_max_color_value - g;
2620 y = gx_max_color_value - b;
2621
2622 black = c < m ? c : m;
2623 black = black < y ? black : y;
2624
2625 if(black != gx_max_color_value) {
2626 float tmp,d;
2627
2628 d = (float)(gx_max_color_value - black);
2629
2630 tmp = (float) (c-black) / d;
2631 if( 0.0 > tmp) tmp = 0.0;
2632 else if( 1.0 < tmp) tmp = 1.0;
2633 c = (gx_color_value)(tmp * gx_max_color_value + 0.499);
2634
2635 tmp = (float) (m-black) / d;
2636 if( 0.0 > tmp) tmp = 0.0;
2637 else if( 1.0 < tmp) tmp = 1.0;
2638 m = (gx_color_value)(tmp * gx_max_color_value + 0.499);
2639
2640 tmp = (float) (y-black) / d;
2641 if( 0.0 > tmp) tmp = 0.0;
2642 else if( 1.0 < tmp) tmp = 1.0;
2643 y = (gx_color_value)(tmp * gx_max_color_value + 0.499);
2644
2645 } else {
2646
2647 c = m = y = gx_max_color_value;
2648
2649 }
2650
2651 rv = upd_truncate(upd,0,black) | upd_truncate(upd,1,c) |
2652 upd_truncate(upd,2,m) | upd_truncate(upd,3,y);
2653
2654 /* It might still become a "gx_no_color_value" due to truncation, thus: */
2655
2656 if(rv == gx_no_color_index) rv ^= 1;
2657 }
2658
2659 #if UPD_MESSAGES & UPD_M_MAPCALLS
2660 errprintf(
2661 "rgb_ovcolor: (%5.1f,%5.1f,%5.1f) : (%5.1f,%5.1f,%5.1f,%5.1f) : 0x%0*lx\n",
2662 255.0 * (double) r / (double) gx_max_color_value,
2663 255.0 * (double) g / (double) gx_max_color_value,
2664 255.0 * (double) b / (double) gx_max_color_value,
2665 255.0 * (double) ((rv >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2666 / (double) upd->cmap[1].bitmsk,
2667 255.0 * (double) ((rv >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2668 / (double) upd->cmap[2].bitmsk,
2669 255.0 * (double) ((rv >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2670 / (double) upd->cmap[3].bitmsk,
2671 255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2672 / (double) upd->cmap[0].bitmsk,
2673 (pdev->color_info.depth + 3)>>2,rv);
2674 #endif
2675
2676 return rv;
2677 }
2678
2679 /* ------------------------------------------------------------------- */
2680 /* upd_rgb_novcolor: Create an KCMY-Index from RGB */
2681 /* ------------------------------------------------------------------- */
2682
2683 private gx_color_index
upd_rgb_novcolor(gx_device * pdev,const gx_color_value cv[])2684 upd_rgb_novcolor(gx_device *pdev, const gx_color_value cv[])
2685 {
2686 const upd_p upd = ((upd_device *)pdev)->upd;
2687 gx_color_index rv;
2688 gx_color_value c,m,y,black;
2689 gx_color_value r, g, b;
2690 r = cv[0]; g = cv[1]; b = cv[2];
2691
2692 if((r == g) && (g == b)) {
2693
2694 black = gx_max_color_value - r;
2695 rv = upd_truncate(upd,0,black);
2696 c = m = y = 0;
2697
2698 } else {
2699
2700 c = gx_max_color_value - r;
2701 m = gx_max_color_value - g;
2702 y = gx_max_color_value - b;
2703
2704 black = c < m ? c : m;
2705 black = black < y ? black : y;
2706 c = c - black;
2707 m = m - black;
2708 y = y - black;
2709
2710 rv = upd_truncate(upd,0,black) | upd_truncate(upd,1,c) |
2711 upd_truncate(upd,2,m) | upd_truncate(upd,3,y);
2712
2713 /* It might still become a "gx_no_color_value" due to truncation, thus: */
2714
2715 if(rv == gx_no_color_index) rv ^= 1;
2716 }
2717
2718 #if UPD_MESSAGES & UPD_M_MAPCALLS
2719 errprintf(
2720 "rgb_ovcolor: (%5.1f,%5.1f,%5.1f) : (%5.1f,%5.1f,%5.1f,%5.1f) : 0x%0*lx\n",
2721 255.0 * (double) r / (double) gx_max_color_value,
2722 255.0 * (double) g / (double) gx_max_color_value,
2723 255.0 * (double) b / (double) gx_max_color_value,
2724 255.0 * (double) ((rv >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2725 / (double) upd->cmap[1].bitmsk,
2726 255.0 * (double) ((rv >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2727 / (double) upd->cmap[2].bitmsk,
2728 255.0 * (double) ((rv >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2729 / (double) upd->cmap[3].bitmsk,
2730 255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2731 / (double) upd->cmap[0].bitmsk,
2732 (pdev->color_info.depth + 3)>>2,rv);
2733 #endif
2734
2735 return rv;
2736 }
2737
2738 /* ------------------------------------------------------------------- */
2739 /* NOTE: Beyond this point only "uniprint"-special-items. */
2740 /* ------------------------------------------------------------------- */
2741
2742 /* ------------------------------------------------------------------- */
2743 /* Truncate a gx_color_value to the desired number of bits. */
2744 /* ------------------------------------------------------------------- */
2745
2746 private uint32_t
upd_truncate(upd_pc upd,int i,gx_color_value v)2747 upd_truncate(upd_pc upd,int i,gx_color_value v) {
2748 const updcmap_pc cmap = upd->cmap + i;
2749 int32_t s; /* step size */
2750 gx_color_value *p; /* value-pointer */
2751
2752 if(0 == cmap->bits) { /* trivial case */
2753
2754 v = 0;
2755
2756 } else if(gx_color_value_bits > cmap->bits) { /* really truncate ? */
2757
2758 p = cmap->code + ((cmap->bitmsk + 1) >> 1);
2759 s = ((cmap->bitmsk + 1) >> 2);
2760 /*
2761 * Perform search in monotonic code-array
2762 */
2763 while(s > 0) {
2764 if(v > *p) { /* we're below */
2765 p += s;
2766 } else if(v < p[-1]) { /* we're ahead for sure */
2767 p -= s;
2768 } else {
2769 /* years ago, i knew what this was good for */
2770 if((v-p[-1]) < (p[0]-v)) p -= 1;
2771 break;
2772 }
2773 s >>= 1;
2774 }
2775 if((v-p[-1]) < (p[0]-v)) p -= 1;
2776 v = p - cmap->code;
2777 }
2778
2779 if(!cmap->rise) v = cmap->bitmsk - v; /* Again reverse, if necessary */
2780
2781 return ((uint32_t) v) << cmap->bitshf;
2782 }
2783
2784 /* ------------------------------------------------------------------- */
2785 /* upd_open_map: install the color-mapping */
2786 /* ------------------------------------------------------------------- */
2787
2788 private int
upd_open_map(upd_device * udev)2789 upd_open_map(upd_device *udev)
2790 {
2791 const upd_p upd = udev->upd;
2792 int imap;
2793
2794 /** _always_ initialize crucial Values! */
2795 for(imap = 0; UPD_CMAP_MAX > imap; ++imap) upd->cmap[imap].code = NULL;
2796 upd->ncomp = 0;
2797
2798 /** There should not be an error yet */
2799 if(B_ERROR & upd->flags) imap = 0;
2800
2801 /** Establish the xfer-Indices */
2802 if(imap) {
2803 for(imap = 0; UPD_CMAP_MAX > imap; ++imap) {
2804 upd->cmap[imap].xfer = -1;
2805 upd->cmap[imap].bits = 0;
2806 }
2807 switch(upd->choice[C_MAPPER]) {
2808 case MAP_GRAY:
2809 upd->cmap[0].xfer = FA_WXFER;
2810 break;
2811 case MAP_RGBW:
2812 upd->cmap[0].xfer = FA_WXFER;
2813 upd->cmap[1].xfer = FA_RXFER;
2814 upd->cmap[2].xfer = FA_GXFER;
2815 upd->cmap[3].xfer = FA_BXFER;
2816 break;
2817 case MAP_RGB:
2818 upd->cmap[0].xfer = FA_RXFER;
2819 upd->cmap[1].xfer = FA_GXFER;
2820 upd->cmap[2].xfer = FA_BXFER;
2821 break;
2822 case MAP_CMYK:
2823 upd->cmap[0].xfer = FA_KXFER;
2824 upd->cmap[1].xfer = FA_CXFER;
2825 upd->cmap[2].xfer = FA_MXFER;
2826 upd->cmap[3].xfer = FA_YXFER;
2827 break;
2828 case MAP_CMYKGEN:
2829 upd->cmap[0].xfer = FA_KXFER;
2830 upd->cmap[1].xfer = FA_CXFER;
2831 upd->cmap[2].xfer = FA_MXFER;
2832 upd->cmap[3].xfer = FA_YXFER;
2833 break;
2834 case MAP_RGBOV:
2835 upd->cmap[0].xfer = FA_KXFER;
2836 upd->cmap[1].xfer = FA_CXFER;
2837 upd->cmap[2].xfer = FA_MXFER;
2838 upd->cmap[3].xfer = FA_YXFER;
2839 break;
2840 case MAP_RGBNOV:
2841 upd->cmap[0].xfer = FA_KXFER;
2842 upd->cmap[1].xfer = FA_CXFER;
2843 upd->cmap[2].xfer = FA_MXFER;
2844 upd->cmap[3].xfer = FA_YXFER;
2845 break;
2846 default:
2847 #if UPD_MESSAGES & UPD_M_WARNING
2848 if(upd_choice[C_MAPPER][0])
2849 errprintf(
2850 "upd_open_map: unsupported %s=%d\n",
2851 upd_choice[C_MAPPER][0],upd->choice[C_MAPPER]);
2852 else
2853 errprintf(
2854 "upd_open_map: unsupported choce[%d]=%d\n",
2855 C_MAPPER,upd->choice[C_MAPPER]);
2856 #endif
2857 imap = 0;
2858 break;
2859 }
2860 }
2861
2862
2863 /** The bit number sould be positive & fit into the storage */
2864
2865 if(imap) { /* Check number of Bits & Shifts */
2866
2867 #if UPD_MESSAGES & UPD_M_WARNING
2868 uint32_t used = 0,bitmsk;
2869 #endif
2870 bool success = true;
2871
2872 for(imap = 0; UPD_CMAP_MAX > imap; ++imap) {
2873 if(0 > upd->cmap[imap].xfer) continue;
2874
2875 if((0 > upd->int_a[IA_COMPBITS].data[imap]) ||
2876 (gx_color_value_bits < upd->int_a[IA_COMPBITS].data[imap]) ||
2877 (0 > upd->int_a[IA_COMPSHIFT].data[imap]) ||
2878 (upd->int_a[IA_COMPBITS].data[imap] >
2879 (udev->color_info.depth - upd->int_a[IA_COMPSHIFT].data[imap]))) {
2880 #if UPD_MESSAGES & UPD_M_WARNING
2881 errprintf(
2882 "upd_open_map: %d Bits << %d is illegal for %d. Component\n",
2883 upd->int_a[IA_COMPBITS].data[imap],
2884 upd->int_a[IA_COMPSHIFT].data[imap],imap+1);
2885 #endif
2886
2887 success = false;
2888
2889
2890 } else {
2891
2892 int n;
2893 const float *now;
2894 float last;
2895
2896 if((NULL == upd->float_a[upd->cmap[imap].xfer].data) ||
2897 (2 > upd->float_a[upd->cmap[imap].xfer].size) ) {
2898 float *fp;
2899 UPD_MM_DEL_PARAM(udev->memory, upd->float_a[upd->cmap[imap].xfer]);
2900 UPD_MM_GET_ARRAY(udev->memory, fp,2);
2901 fp[0] = 0.0;
2902 fp[1] = 1.0;
2903 upd->float_a[upd->cmap[imap].xfer].data = fp;
2904 upd->float_a[upd->cmap[imap].xfer].size = 2;
2905 }
2906 n = upd->float_a[upd->cmap[imap].xfer].size-1;
2907 now = upd->float_a[upd->cmap[imap].xfer].data;
2908 last = now[n];
2909
2910 if( *now < last) { /* Rising */
2911 last = *now++;
2912 while(n--) {
2913 if(last >= *now) break;
2914 last = *now++;
2915 }
2916 } else if(*now > last) { /* Falling */
2917 last = *now++;
2918 while(n--) {
2919 if(last <= *now) break;
2920 last = *now++;
2921 }
2922 } /* Monotony-check */
2923
2924 if(0 <= n) {
2925 #if UPD_MESSAGES & UPD_M_WARNING
2926 errprintf(
2927 "upd_open_map: %d. Component has non monoton Xfer\n",imap+1);
2928 #endif
2929 success = false;
2930
2931 } else {
2932
2933 #if UPD_MESSAGES & UPD_M_WARNING
2934
2935 bitmsk = ((uint32_t) 1 << upd->int_a[IA_COMPBITS].data[imap]) -1;
2936 bitmsk <<= upd->int_a[IA_COMPSHIFT].data[imap];
2937
2938 if(used & bitmsk) errprintf(
2939 "upd_open_map: %d. Component overlaps with others\n",imap+1);
2940
2941 used |= bitmsk;
2942 #endif
2943 }
2944 }
2945 }
2946
2947 if(!success) imap = 0;
2948
2949 } /* Check number of Bits */
2950
2951 /** Do the allocation */
2952
2953 if(imap) {
2954
2955 for(imap = 0; UPD_CMAP_MAX > imap; ++imap) {
2956 if(0 > upd->cmap[imap].xfer) continue;
2957
2958 upd->cmap[imap].bits = upd->int_a[IA_COMPBITS].data[imap];
2959 upd->cmap[imap].bitshf = upd->int_a[IA_COMPSHIFT].data[imap];
2960 upd->cmap[imap].bitmsk = 1;
2961 upd->cmap[imap].bitmsk <<= upd->cmap[imap].bits;
2962 upd->cmap[imap].bitmsk -= 1;
2963 upd->cmap[imap].rise =
2964 upd->float_a[upd->cmap[imap].xfer].data[0] <
2965 upd->float_a[upd->cmap[imap].xfer].data[
2966 upd->float_a[upd->cmap[imap].xfer].size-1] ?
2967 true : false;
2968 upd->cmap[imap].code = gs_malloc(udev->memory, upd->cmap[imap].bitmsk+1,
2969 sizeof(upd->cmap[imap].code[0]),"upd/code");
2970 if(!upd->cmap[imap].code) break;
2971 }
2972
2973 if(UPD_CMAP_MAX > imap) {
2974
2975 imap = 0;
2976
2977 #if UPD_MESSAGES & UPD_M_ERROR
2978 errprintf("upd_open_map: could not allocate code-arrays\n");
2979 # endif
2980
2981 }
2982 }
2983
2984 /** then fill the code-arrays */
2985
2986 if(imap) {
2987 /*
2988 * Try making things easier: (than with stcolor)
2989 * normalize values to 0.0/1.0-Range
2990 * X-Axis: Color-Values (implied)
2991 * Y-Values: Indices (given)
2992 */
2993
2994 for(imap = 0; UPD_CMAP_MAX > imap; ++imap) {
2995
2996 const updcmap_p cmap = upd->cmap + imap;
2997 uint32_t ly,iy;
2998 float ystep,xstep,fx,fy;
2999
3000 /* Variables & Macro for Range-Normalization */
3001 double offset,scale;
3002 #define XFVAL(I) ((upd->float_a[cmap->xfer].data[I]-offset)*scale)
3003
3004 if(0 > cmap->xfer) continue;
3005
3006 cmap->code[cmap->bitmsk] = gx_max_color_value;
3007
3008 if(!cmap->bits) continue;
3009
3010 offset = upd->float_a[cmap->xfer].data[0];
3011 if( 0.0 > offset) offset = 0.0;
3012 else if(1.0 < offset) offset = 1.0;
3013
3014 scale = upd->float_a[cmap->xfer].data[upd->float_a[cmap->xfer].size-1];
3015 if( 0.0 > scale ) scale = 0.0;
3016 else if(1.0 < scale ) scale = 1.0;
3017
3018 if(scale != offset) scale = 1.0 / (scale - offset);
3019 else scale = 0.0;
3020
3021 /* interpolate */
3022 ystep = (float) 1.0 / (float) cmap->bitmsk;
3023 xstep = (float) 1.0 / (float)(upd->float_a[cmap->xfer].size - 1);
3024
3025 iy = 0;
3026 for(ly = 0; ly <= cmap->bitmsk; ++ly) {
3027
3028 fy = ystep * ly; /* Target-Value */
3029
3030 while(((iy+2) < upd->float_a[cmap->xfer].size) &&
3031 (fy > XFVAL(iy+1))) ++iy;
3032
3033 fx = iy + (fy - XFVAL(iy))/(XFVAL(iy+1) - XFVAL(iy));
3034
3035 fx *= xstep * gx_max_color_value;
3036
3037 fx = fx < 0.0 ? 0.0 :
3038 (fx > gx_max_color_value ? gx_max_color_value : fx);
3039
3040 cmap->code[ly] = (gx_color_value)fx;
3041 if((fx - cmap->code[ly]) >= 0.5) cmap->code[ly] += 1;
3042 }
3043
3044 #undef XFVAL
3045
3046 }
3047 }
3048
3049 /** If we're ok, massage upd->ncomp */
3050
3051 if(imap) {
3052 switch(upd->choice[C_MAPPER]) {
3053 case MAP_GRAY:
3054 if(1 > imap) imap = 0;
3055 upd->ncomp = 1;
3056 break;
3057 case MAP_RGBW: /* RGB->RGBW */
3058 if(4 > imap) imap = 0;
3059 upd->ncomp = 4;
3060 break;
3061 case MAP_RGB: /* Plain RGB */
3062 if(3 > imap) imap = 0;
3063 upd->ncomp = 3;
3064 break;
3065 case MAP_CMYK: /* Plain KCMY */
3066 if(4 > imap) imap = 0;
3067 upd->ncomp = 4;
3068 break;
3069 case MAP_CMYKGEN: /* KCMY with black-generation */
3070 if(4 > imap) imap = 0;
3071 upd->ncomp = 4;
3072 break;
3073 case MAP_RGBOV: /* RGB->KCMY with black-generation */
3074 if(4 > imap) imap = 0;
3075 upd->ncomp = 4;
3076 break;
3077 case MAP_RGBNOV: /* RGB->KCMY with black-generation */
3078 if(4 > imap) imap = 0;
3079 upd->ncomp = 4;
3080 break;
3081
3082 default:
3083 imap = 0;
3084 #if UPD_MESSAGES & UPD_M_WARNING
3085 errprintf(
3086 "upd_open: Mapping %d unknown\n",upd->choice[C_MAPPER]);
3087 #endif
3088
3089 break;
3090 }
3091 }
3092
3093
3094 /** If unsuccesful, install the default routines */
3095
3096 if(!imap) {
3097 upd_close_map(udev);
3098 } else {
3099 upd->flags |= B_MAP;
3100 upd_procs_map(udev);
3101 }
3102
3103 return imap ? 1 : -1;
3104 }
3105
3106 /* ------------------------------------------------------------------- */
3107 /* upd_procs_map: (de-) install the color-mapping-procedures */
3108 /* ------------------------------------------------------------------- */
3109
3110 private int
upd_procs_map(upd_device * udev)3111 upd_procs_map(upd_device *udev)
3112 {
3113 int imap;
3114
3115 if( udev->upd &&
3116 (udev->upd->flags & B_MAP)) imap = udev->upd->choice[C_MAPPER];
3117 else imap = 0;
3118
3119 switch(imap) {
3120 case MAP_GRAY: /* Grayscale -> Grayscale */
3121 set_dev_proc(udev,encode_color, upd_rgb_1color);
3122 set_dev_proc(udev,decode_color, upd_1color_rgb);
3123 set_dev_proc(udev,map_rgb_color, upd_rgb_1color);
3124 set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3125 set_dev_proc(udev,map_color_rgb, upd_1color_rgb);
3126 break;
3127 case MAP_RGBW: /* RGB->RGBW */
3128 set_dev_proc(udev,encode_color, upd_rgb_4color);
3129 set_dev_proc(udev,decode_color, upd_4color_rgb);
3130 set_dev_proc(udev,map_rgb_color, upd_rgb_4color);
3131 set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3132 set_dev_proc(udev,map_color_rgb, upd_4color_rgb);
3133 break;
3134 case MAP_RGB: /* Plain RGB */
3135 set_dev_proc(udev,encode_color, upd_rgb_3color);
3136 set_dev_proc(udev,decode_color, upd_3color_rgb);
3137 set_dev_proc(udev,map_rgb_color, upd_rgb_3color);
3138 set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3139 set_dev_proc(udev,map_color_rgb, upd_3color_rgb);
3140 break;
3141 case MAP_CMYK: /* Plain KCMY */
3142 set_dev_proc(udev,encode_color, upd_cmyk_icolor);
3143 set_dev_proc(udev,decode_color, upd_icolor_rgb);
3144 set_dev_proc(udev,map_rgb_color, gx_default_map_rgb_color);
3145 set_dev_proc(udev,map_cmyk_color,upd_cmyk_icolor);
3146 set_dev_proc(udev,map_color_rgb, upd_icolor_rgb);
3147 break;
3148 case MAP_CMYKGEN: /* KCMY with black-generation */
3149 set_dev_proc(udev,encode_color, upd_cmyk_kcolor);
3150 set_dev_proc(udev,decode_color, upd_kcolor_rgb);
3151 set_dev_proc(udev,map_rgb_color, gx_default_map_rgb_color);
3152 set_dev_proc(udev,map_cmyk_color,upd_cmyk_kcolor);
3153 set_dev_proc(udev,map_color_rgb, upd_kcolor_rgb);
3154 break;
3155 case MAP_RGBOV: /* RGB -> KCMY with BG and UCR for CMYK-Output */
3156 set_dev_proc(udev,encode_color, upd_rgb_ovcolor);
3157 set_dev_proc(udev,decode_color, upd_ovcolor_rgb);
3158 set_dev_proc(udev,map_rgb_color, upd_rgb_ovcolor);
3159 set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3160 set_dev_proc(udev,map_color_rgb, upd_ovcolor_rgb);
3161 break;
3162 case MAP_RGBNOV: /* RGB -> KCMY with BG and UCR for CMY+K-Output */
3163 set_dev_proc(udev,encode_color, upd_rgb_novcolor);
3164 set_dev_proc(udev,decode_color, upd_novcolor_rgb);
3165 set_dev_proc(udev,map_rgb_color, upd_rgb_novcolor);
3166 set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3167 set_dev_proc(udev,map_color_rgb, upd_novcolor_rgb);
3168 break;
3169
3170 default:
3171 set_dev_proc(udev,encode_color, gx_default_map_rgb_color);
3172 set_dev_proc(udev,decode_color, gx_default_map_color_rgb);
3173 set_dev_proc(udev,map_rgb_color, gx_default_map_rgb_color);
3174 set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3175 set_dev_proc(udev,map_color_rgb, gx_default_map_color_rgb);
3176 break;
3177 }
3178 return 0;
3179
3180 }
3181
3182 /* ------------------------------------------------------------------- */
3183 /* upd_close_map: remove color mapping */
3184 /* ------------------------------------------------------------------- */
3185
3186 private int
upd_close_map(upd_device * udev)3187 upd_close_map(upd_device *udev)
3188 {
3189 const upd_p upd = udev->upd;
3190 int imap;
3191
3192 if(upd) {
3193
3194 for(imap = 0; UPD_CMAP_MAX > imap; ++imap) {
3195
3196 if(upd->cmap[imap].code)
3197 gs_free(udev->memory, upd->cmap[imap].code,sizeof(upd->cmap[imap].code[0]),
3198 upd->cmap[imap].bitmsk+1,"upd/code");
3199 upd->cmap[imap].code = NULL;
3200
3201 upd->cmap[imap].bitmsk = 0;
3202 upd->cmap[imap].bitshf = 0;
3203 upd->cmap[imap].bits = 0;
3204 upd->cmap[imap].rise = false;
3205 }
3206 upd->flags &= ~B_MAP;
3207 }
3208
3209 upd_procs_map(udev);
3210
3211 return 0;
3212 }
3213
3214 /* ------------------------------------------------------------------- */
3215 /* Functions for the rendering of data */
3216 /* ------------------------------------------------------------------- */
3217
3218 /**
3219 Inside the main-upd-type are a "valbuf" and some unidentified
3220 pointers. This stuff is used in conjunction with the rendering,
3221 which is the process of converting gx_color_indices into something
3222 suitable for the device.
3223
3224 */
3225
3226 /* ------------------------------------------------------------------- */
3227 /* upd_open_render: Initialize rendering */
3228 /* ------------------------------------------------------------------- */
3229
3230 private void
upd_open_render(upd_device * udev)3231 upd_open_render(upd_device *udev)
3232 {
3233 const upd_p upd = udev->upd;
3234 int icomp;
3235
3236 /** Reset everything related to rendering */
3237 upd->flags &= ~B_RENDER;
3238 upd->valbuf = NULL;
3239 upd->nvalbuf = 0;
3240 upd->render = NULL;
3241 upd->start_render = NULL;
3242 for(icomp = 0; UPD_VALPTR_MAX > icomp; ++icomp) upd->valptr[icomp] = NULL;
3243
3244 if( (B_BUF | B_MAP) ==
3245 ((B_BUF | B_MAP | B_ERROR) & upd->flags)) {
3246
3247 /** Establish the renderingwidth in upd */
3248 upd->rwidth = upd->gswidth;
3249 if((0 < upd->ints[I_PWIDTH]) &&
3250 (upd->gswidth > upd->ints[I_PWIDTH]) )
3251 upd->rwidth = upd->ints[I_PWIDTH];
3252
3253 /** Call the Render-specific Open-Function */
3254 switch(upd->choice[C_RENDER]) {
3255 case RND_FSCOMP:
3256 upd_open_fscomp(udev);
3257 break;
3258 case RND_FSCMYK:
3259 upd_open_fscmyk(udev);
3260 break;
3261 case RND_FSCMY_K:
3262 upd_open_fscmy_k(udev);
3263 break;
3264 default:
3265 #if UPD_MESSAGES & UPD_M_WARNING
3266 errprintf("upd_open_render: Unknown rendering type %d\n",
3267 upd->choice[C_RENDER]);
3268 #endif
3269 break;
3270 }
3271 }
3272
3273 if(B_RENDER != ((B_ERROR | B_RENDER) & upd->flags))
3274 upd_close_render(udev);
3275
3276 return;
3277 }
3278
3279
3280 /* ------------------------------------------------------------------- */
3281 /* upd_close_render: Deinitialize rendering */
3282 /* ------------------------------------------------------------------- */
3283
3284 private void
upd_close_render(upd_device * udev)3285 upd_close_render(upd_device *udev)
3286 {
3287 const upd_p upd = udev->upd;
3288
3289 if(upd) {
3290 int icomp;
3291
3292 if((upd->render == upd_fscomp) ||
3293 (upd->render == upd_fscmyk) ) upd_close_fscomp(udev);
3294
3295 if((0 < upd->nvalbuf) && upd->valbuf)
3296 gs_free(udev->memory, upd->valbuf,upd->nvalbuf,sizeof(upd->valbuf[0]),"upd/valbuf");
3297 upd->valbuf = NULL;
3298 upd->nvalbuf = 0;
3299
3300 upd->flags &= ~B_RENDER;
3301 upd->render = NULL;
3302 upd->start_render = NULL;
3303 for(icomp = 0; UPD_VALPTR_MAX > icomp; ++icomp) upd->valptr[icomp] = NULL;
3304
3305 }
3306 return;
3307 }
3308
3309 /* ------------------------------------------------------------------- */
3310 /* upd_open_fscomp: Initialize Component-Floyd-Steinberg */
3311 /* ------------------------------------------------------------------- */
3312 #if UPD_MESSAGES & UPD_M_FSBUF
3313 static int32_t fs_emin[UPD_VALPTR_MAX],fs_emax[UPD_VALPTR_MAX];
3314 #endif
3315 private void
upd_open_fscomp(upd_device * udev)3316 upd_open_fscomp(upd_device *udev)
3317 {
3318 const upd_p upd = udev->upd;
3319 int icomp,order[UPD_CMAP_MAX];
3320
3321 #if UPD_MESSAGES & UPD_M_FSBUF
3322 for(icomp = 0; UPD_VALPTR_MAX < icomp; ++icomp)
3323 fs_emin[icomp] = fs_emax[icomp] = 0;
3324 #endif
3325
3326 icomp = upd->ncomp;
3327
3328 if((0 >= icomp) ||
3329 (UPD_VALPTR_MAX < icomp) ||
3330 (UPD_CMAP_MAX < icomp) ) icomp = 0;
3331
3332 /**
3333 This Version of the FS-algorithm works on the mapped components, but
3334 the printing-order might be different from the order dictated by the
3335 mapping-routines. The optional COMPORDER-Array is used for that. The
3336 initial test checks it's integrity.
3337 */
3338 if(icomp) {
3339 if(upd->ncomp <= upd->int_a[IA_COMPORDER].size) { /* Reordering */
3340 bool success = true;
3341 for(icomp = 0; upd->ncomp > icomp; ++icomp) {
3342 order[icomp] = upd->int_a[IA_COMPORDER].data[icomp];
3343 if((0 > order[icomp]) ||
3344 (UPD_CMAP_MAX <= order[icomp]) ) {
3345 success = false;
3346 #if UPD_MESSAGES & UPD_M_WARNING
3347 errprintf(
3348 "upd_open_fscomp: %d is illegal component-index\n",
3349 order[icomp]);
3350 #endif
3351 }
3352 }
3353 if(!success) icomp = 0;
3354 } else { /* Default-Ordering */
3355 for(icomp = 0; UPD_CMAP_MAX > icomp; ++icomp) order[icomp] = icomp;
3356 } /* Ordering defined */
3357 }
3358
3359 /**
3360 If anything was ok. up to now, memory get's allocated.
3361 */
3362 if(icomp) {
3363
3364 for(icomp = 0; upd->ncomp > icomp; ++icomp) {
3365 upd->valptr[icomp] = gs_malloc(udev->memory, 1,sizeof(updcomp_t),"upd/fscomp");
3366 if(NULL == upd->valptr[icomp]) {
3367 #if UPD_MESSAGES & UPD_M_ERROR
3368 errprintf(
3369 "upd_open_fscomp: could not allocate %d. updcomp\n",
3370 icomp);
3371 #endif
3372 icomp = 0;
3373 break;
3374 }
3375 }
3376 }
3377
3378 if(icomp) {
3379 uint need;
3380
3381 need = (2 + upd->rwidth) * upd->ncomp;
3382 upd->valbuf = gs_malloc(udev->memory, need,sizeof(upd->valbuf[0]),"upd/valbuf");
3383
3384 if(upd->valbuf) {
3385 upd->nvalbuf = need;
3386 memset(upd->valbuf,0,need*sizeof(upd->valbuf[0]));
3387 } else {
3388 #if UPD_MESSAGES & UPD_M_ERROR
3389 errprintf(
3390 "upd_open_fscomp: could not allocate %u words for valbuf\n",need);
3391 #endif
3392 icomp = 0;
3393 }
3394 }
3395
3396 /* Still happy? then compute component-values */
3397
3398 if(icomp) {
3399 for(icomp = 0; upd->ncomp > icomp; ++icomp) {
3400
3401 const updcomp_p comp = upd->valptr[icomp];
3402 const int32_t nsteps = upd->cmap[order[icomp]].bitmsk;
3403 float ymin,ymax;
3404 int32_t highmod,highval;
3405 int i;
3406
3407 comp->threshold = nsteps;
3408 comp->spotsize = nsteps;
3409 comp->offset = 0;
3410 comp->scale = 1;
3411 comp->cmap = order[icomp];
3412 upd->cmap[comp->cmap].comp = icomp;
3413 comp->bits = upd->cmap[comp->cmap].bits;
3414 comp->bitshf = upd->cmap[comp->cmap].bitshf;
3415 comp->bitmsk = upd->cmap[comp->cmap].bitmsk;
3416
3417 if(!nsteps) continue; /* A 0-Bit component is legal! */
3418
3419 if(upd->cmap[comp->cmap].rise) {
3420 ymin = upd->float_a[upd->cmap[comp->cmap].xfer].data[0];
3421 ymax = upd->float_a[upd->cmap[comp->cmap].xfer].data[
3422 upd->float_a[upd->cmap[comp->cmap].xfer].size-1];
3423 } else {
3424 ymax = upd->float_a[upd->cmap[comp->cmap].xfer].data[0];
3425 ymin = upd->float_a[upd->cmap[comp->cmap].xfer].data[
3426 upd->float_a[upd->cmap[comp->cmap].xfer].size-1];
3427 }
3428
3429 if(0.0 > ymin) {
3430 ymin = 0.0;
3431 if(0.0 > ymax) ymax = 1.0 / (float) (nsteps+1);
3432 }
3433 if(1.0 < ymax) ymax = 1.0;
3434
3435 comp->spotsize = ((int32_t) 1 << 28) - 1;
3436
3437 for(i = 0; i < 32; ++i) { /* Attempt Ideal */
3438
3439 highval = (int32_t)((ymax-ymin) * (double) comp->spotsize + 0.5);
3440
3441 if(!(highmod = highval % nsteps)) break; /* Gotcha */
3442
3443 highval += nsteps - highmod;
3444 comp->spotsize = (int32_t)((double) highval / (ymax-ymin) + 0.5);
3445
3446 if(!(comp->spotsize % 2)) comp->spotsize++;
3447
3448 } /* Attempt Ideal */
3449
3450 comp->offset = (int32_t)(ymin * (double) comp->spotsize + (double) 0.5);
3451 comp->scale = highval / nsteps;
3452 comp->threshold = comp->spotsize / 2;
3453
3454 #if UPD_MESSAGES & UPD_M_SETUP
3455 errprintf(
3456 "Values for %d. Component after %d iterations\n",comp->cmap+1,i);
3457 errprintf(
3458 "steps: %10ld, Bits: %d\n",(long) comp->bitmsk,comp->bits);
3459 errprintf(
3460 "xfer: %10d Points, %s\n",
3461 upd->float_a[upd->cmap[comp->cmap].xfer].size,
3462 upd->cmap[comp->cmap].rise ? "rising" : "falling");
3463 errprintf(
3464 "offset: %10d 0x%08x\n",comp->offset,comp->offset);
3465 errprintf(
3466 "scale: %10d 0x%08x\n",comp->scale,comp->scale);
3467 errprintf(
3468 "threshold: %10d 0x%08x\n",comp->threshold,comp->threshold);
3469 errprintf(
3470 "spotsize: %10d 0x%08x\n",comp->spotsize,comp->spotsize);
3471 #endif
3472 }
3473 }
3474 /**
3475 Optional Random Initialization of the value-Buffer
3476 */
3477 if(icomp && !(B_FSZERO & upd->flags)) {
3478 for(icomp = 0; icomp < upd->ncomp; ++icomp) {
3479 const updcomp_p comp = upd->valptr[icomp];
3480 int i;
3481 int32_t lv = INT32_MAX, hv = INT32_MIN, v;
3482 float scale;
3483 for(i = icomp; i < upd->nvalbuf; i += upd->ncomp) {
3484 v = rand();
3485 if(lv > v) lv = v;
3486 if(hv < v) hv = v;
3487 upd->valbuf[i] = v;
3488 }
3489 scale = (float) comp->threshold / (float) (hv - lv);
3490 lv += (int32_t)(comp->threshold / (2*scale));
3491 for(i = icomp; i < upd->nvalbuf; i += upd->ncomp)
3492 upd->valbuf[i] = (int32_t)(scale * (upd->valbuf[i] - lv));
3493 }
3494 }
3495
3496 /**
3497 The render-Routine acts as an indicator, which render-close is to use!
3498 */
3499 upd->render = upd_fscomp;
3500
3501 if(icomp) upd->flags |= B_RENDER;
3502 else upd->flags &= ~B_RENDER;
3503
3504 return;
3505 }
3506
3507 /* ------------------------------------------------------------------- */
3508 /* upd_close_fscomp: Deinitialize Component-Floyd-Steinberg */
3509 /* ------------------------------------------------------------------- */
3510
3511 private void
upd_close_fscomp(upd_device * udev)3512 upd_close_fscomp(upd_device *udev)
3513 {
3514 const upd_p upd = udev->upd;
3515 int icomp;
3516
3517 #if UPD_MESSAGES & UPD_M_FSBUF
3518 if(upd && (upd->flags & B_RENDER)) {
3519
3520 for(icomp = 0; icomp < upd->ncomp; ++icomp) {
3521 updcomp_p comp = upd->valptr[icomp];
3522 if(!comp) continue;
3523 if(!comp->spotsize) continue;
3524 errprintf("%d. Component: %6.3f <= error <= %6.3f\n",
3525 icomp+1,
3526 (double) fs_emin[icomp] / (double) comp->spotsize,
3527 (double) fs_emax[icomp] / (double) comp->spotsize);
3528 }
3529
3530 }
3531 #endif
3532
3533 for(icomp = 0; UPD_VALPTR_MAX > icomp; ++icomp) {
3534 if(!upd->valptr[icomp]) continue;
3535 gs_free(udev->memory, upd->valptr[icomp],1,sizeof(updcomp_t),"upd/fscomp");
3536 upd->valptr[icomp] = NULL;
3537 }
3538 }
3539
3540 /* ------------------------------------------------------------------- */
3541 /* upd_fscomp: Apply Floyd-Steinberg to each component */
3542 /* ------------------------------------------------------------------- */
3543
3544 /**
3545 With UPD_M_FSBUF Max/Min-Values for the Errors are computed
3546 */
3547 #if UPD_MESSAGES & UPD_M_FSBUF
3548 #define FS_M_ROWERR(I) \
3549 if(fs_emin[I] > rowerr[I]) fs_emin[I] = rowerr[I]; \
3550 if(fs_emax[I] < rowerr[I]) fs_emax[I] = rowerr[I];
3551 #else
3552 #define FS_M_ROWERR(I) ;
3553 #endif
3554 /**
3555 FS_GOAL computes the desired Pixel-Value
3556 */
3557 #define FS_GOAL(Raw,I) \
3558 pixel[I] = (int32_t)(Raw) * comp[I]->scale + comp[I]->offset \
3559 + rowerr[I] + colerr[I] - ((colerr[I]+4)>>3); \
3560 if( pixel[I] < 0) pixel[I] = 0; \
3561 else if( pixel[I] > comp[I]->spotsize) pixel[I] = comp[I]->spotsize;
3562
3563 /*
3564 * Distribute the error: prev now next
3565 * X 7/16 Y
3566 * 3/16 5/16 1/16 Y+1
3567 */
3568 #define FS_DIST(I) \
3569 if(!first) rowerr[I-dir] += ((3*pixel[I]+8)>>4); /* 3/16 */ \
3570 rowerr[I ] = ((5*pixel[I] )>>4) /* 5/16 */ \
3571 + (( colerr[I]+4)>>3); /* 1/16 (rest) */ \
3572 colerr[I ] = pixel[I] /* 8/16 (neu) */ \
3573 - ((5*pixel[I] )>>4) \
3574 - ((3*pixel[I]+8)>>4);
3575 /**
3576 S_FSTEP adjusts the Indices (rowerr, bit and iword)
3577 */
3578 #define S_FSTEP \
3579 rowerr += dir; \
3580 first = false; \
3581 if(0 > dir) { /* Reverse */ \
3582 if(!(bit <<= 1)) { bit = 0x01; ibyte--; }\
3583 } else { /* Forward */ \
3584 if(!(bit >>= 1)) { bit = 0x80; ibyte++; }\
3585 } /* Inc/Dec Bit */
3586
3587 private int
upd_fscomp(upd_p upd)3588 upd_fscomp(upd_p upd)
3589 {
3590 const updscan_p scan = upd->scnbuf[upd->yscnbuf & upd->scnmsk];
3591 const updcomp_p *comp = (updcomp_p *) upd->valptr;
3592 int32_t *const pixel = upd->valbuf;
3593 int32_t *const colerr = pixel + upd->ncomp;
3594 int32_t *rowerr = colerr + upd->ncomp;
3595 int pwidth = upd->rwidth;
3596 int dir,ibyte;
3597 int iblack,bblack,pxlset;
3598 uint32_t ci;
3599 byte bit;
3600 bool first = true;
3601 /*
3602 * Erase the component-Data
3603 */
3604 switch(upd->ncomp) {
3605 case 4: memset(scan[3].bytes,0,upd->nbytes);
3606 case 3: memset(scan[2].bytes,0,upd->nbytes);
3607 memset(scan[1].bytes,0,upd->nbytes);
3608 default: memset(scan[0].bytes,0,upd->nbytes);
3609 }
3610 /*
3611 * determine the direction
3612 */
3613 if(upd->flags & B_REVDIR) { /* This one reverse */
3614
3615 if(upd->flags & B_YFLIP) {
3616 dir = upd->ncomp;
3617 bit = 0x80;
3618 ibyte = 0;
3619 } else {
3620 dir = -upd->ncomp;
3621 rowerr += upd->ncomp * (pwidth-1);
3622 bit = 0x80 >> ((pwidth-1) & 7);
3623 ibyte = (pwidth-1) >> 3;
3624 }
3625
3626 if(!(upd->flags & B_FSWHITE)) {
3627 upd_pxlfwd(upd);
3628 while((0 < pwidth) && !upd_pxlget(upd)) pwidth--;
3629 }
3630
3631 upd_pxlrev(upd);
3632
3633 } else { /* This one forward */
3634
3635 if(upd->flags & B_YFLIP) {
3636 dir = -upd->ncomp;
3637 rowerr += upd->ncomp * (pwidth-1);
3638 bit = 0x80 >> ((pwidth-1) & 7);
3639 ibyte = (pwidth-1) >> 3;
3640 } else {
3641 dir = upd->ncomp;
3642 bit = 0x80;
3643 ibyte = 0;
3644 }
3645
3646 if(!(upd->flags & B_FSWHITE)) {
3647 upd_pxlrev(upd);
3648 while((0 < pwidth) && !upd_pxlget(upd)) pwidth--;
3649 }
3650
3651 upd_pxlfwd(upd);
3652
3653 } /* reverse or forward */
3654 /*
3655 * Toggle Direction, if not fixed
3656 */
3657 if(!(upd->flags & B_FIXDIR)) upd->flags ^= B_REVDIR;
3658 /*
3659 * Skip over leading white-space
3660 */
3661 if(!(upd->flags & B_FSWHITE)) {
3662 upd_proc_pxlget((*fun)) = upd->pxlget;
3663 byte *ptr = upd->pxlptr;
3664 while((0 < pwidth) && !upd_pxlget(upd)) {
3665 pwidth--;
3666 fun = upd->pxlget;
3667 ptr = upd->pxlptr;
3668 S_FSTEP
3669 }
3670 upd->pxlget = fun;
3671 upd->pxlptr = ptr;
3672 }
3673 /*
3674 * Set iblack, if black-reduction is active
3675 */
3676 iblack = -1;
3677 bblack = 0;
3678 if((4 == upd->ncomp) && (B_REDUCEK & upd->flags)) {
3679 iblack = upd->cmap[0].comp;
3680 bblack = 1<<iblack;
3681 }
3682 /*
3683 * Process all Pixels
3684 */
3685 first = true;
3686 while(0 < pwidth--) {
3687 /*
3688 * Execute FS-Algorithm for each active component
3689 */
3690 pxlset = 0;
3691 ci = upd_pxlget(upd);
3692 switch(upd->ncomp) {
3693 case 4: FS_M_ROWERR(3)
3694 FS_GOAL(comp[3]->bitmsk & (ci >> comp[3]->bitshf),3)
3695 if(pixel[3] > comp[3]->threshold) { /* "Fire" */
3696 pixel[3] -= comp[3]->spotsize;
3697 scan[3].bytes[ibyte] |= bit;
3698 pxlset |= 8;
3699 } /* "Fire" */
3700 FS_DIST(3)
3701
3702 case 3: FS_M_ROWERR(2)
3703 FS_GOAL(comp[2]->bitmsk & (ci >> comp[2]->bitshf),2)
3704 if(pixel[2] > comp[2]->threshold) { /* "Fire" */
3705 pixel[2] -= comp[2]->spotsize;
3706 scan[2].bytes[ibyte] |= bit;
3707 pxlset |= 4;
3708 } /* "Fire" */
3709 FS_DIST(2)
3710
3711 FS_M_ROWERR(1)
3712 FS_GOAL(comp[1]->bitmsk & (ci >> comp[1]->bitshf),1)
3713 if(pixel[1] > comp[1]->threshold) { /* "Fire" */
3714 pixel[1] -= comp[1]->spotsize;
3715 scan[1].bytes[ibyte] |= bit;
3716 pxlset |= 2;
3717 } /* "Fire" */
3718 FS_DIST(1)
3719
3720 default: FS_M_ROWERR(0)
3721 FS_GOAL(comp[0]->bitmsk & (ci >> comp[0]->bitshf),0)
3722 if(pixel[0] > comp[0]->threshold) { /* "Fire" */
3723 pixel[0] -= comp[0]->spotsize;
3724 scan[0].bytes[ibyte] |= bit;
3725 pxlset |= 1;
3726 } /* "Fire" */
3727 FS_DIST(0)
3728 }
3729 /*
3730 * Black-Reduction
3731 */
3732 if(bblack) {
3733 if(pxlset & bblack) pxlset |= 15;
3734 switch(pxlset) {
3735 case 0:
3736 case 1:
3737 case 2:
3738 case 4:
3739 case 8:
3740 case 3:
3741 case 5:
3742 case 9:
3743 case 6:
3744 case 10:
3745 case 12:
3746 break;
3747 default:
3748 scan[0].bytes[ibyte] &= ~bit;
3749 scan[1].bytes[ibyte] &= ~bit;
3750 scan[2].bytes[ibyte] &= ~bit;
3751 scan[3].bytes[ibyte] &= ~bit;
3752 scan[iblack].bytes[ibyte] |= bit;
3753 break;
3754 }
3755 }
3756 /*
3757 * Adjust rowerr, bit & iword, depending on direction
3758 */
3759 S_FSTEP
3760 }
3761 /*
3762 * Finally call the limits-Routine
3763 */
3764 if(0 < upd->nlimits) upd_limits(upd,true);
3765 return 0;
3766 }
3767
3768 /* ------------------------------------------------------------------- */
3769 /* upd_open_fscmyk: Initialize Component-Floyd-Steinberg */
3770 /* ------------------------------------------------------------------- */
3771
3772 private void
upd_open_fscmyk(upd_device * udev)3773 upd_open_fscmyk(upd_device *udev)
3774 {
3775 const upd_p upd = udev->upd;
3776
3777 upd_open_fscomp(udev);
3778
3779 if((B_RENDER & upd->flags) &&
3780 (4 == upd->ncomp) &&
3781 (8 <= upd->cmap[0].bits) && (24 == upd->cmap[0].bitshf) &&
3782 (8 <= upd->cmap[1].bits) && (16 == upd->cmap[1].bitshf) &&
3783 (8 <= upd->cmap[2].bits) && ( 8 == upd->cmap[2].bitshf) &&
3784 (8 <= upd->cmap[3].bits) && ( 0 == upd->cmap[3].bitshf) ) {
3785 upd->render = upd_fscmyk;
3786 } else {
3787 upd->flags &= ~B_RENDER;
3788 }
3789
3790 }
3791
3792 /* ------------------------------------------------------------------- */
3793 /* upd_fscmyk: 32 Bit, K-CMY-Order Dithering */
3794 /* ------------------------------------------------------------------- */
3795
3796 private int
upd_fscmyk(upd_p upd)3797 upd_fscmyk(upd_p upd)
3798 {
3799 const updscan_p scan = upd->scnbuf[upd->yscnbuf & upd->scnmsk];
3800 int32_t *const pixel = upd->valbuf;
3801 const updcomp_p *comp = (updcomp_p *) upd->valptr;
3802 int32_t *const colerr = pixel + 4;
3803 int32_t *rowerr = colerr + 4;
3804 int32_t pwidth = upd->rwidth;
3805 int dir,ibyte;
3806 byte bit,*data;
3807 bool first = false;
3808 /*
3809 * Erase the component-Data
3810 */
3811 memset(scan[0].bytes,0,upd->nbytes);
3812 memset(scan[1].bytes,0,upd->nbytes);
3813 memset(scan[2].bytes,0,upd->nbytes);
3814 memset(scan[3].bytes,0,upd->nbytes);
3815
3816 /*
3817 * determine the direction
3818 */
3819 if(upd->flags & B_REVDIR) { /* This one reverse */
3820
3821 if(!(upd->flags & B_FSWHITE)) {
3822 data = upd->gsscan;
3823 while(0 < pwidth && !*(uint32_t *)data) pwidth--, data += 4;
3824 if(0 >= pwidth) {
3825 if(0 < upd->nlimits) upd_limits(upd,false);
3826 return 0;
3827 }
3828 }
3829
3830 data = upd->gsscan + 4 * (upd->rwidth-1);
3831
3832 } else { /* This one forward */
3833
3834 if(!(upd->flags & B_FSWHITE)) {
3835 data = upd->gsscan + 4 * (upd->rwidth-1);
3836 while(0 < pwidth && !*(uint32_t *)data) pwidth--, data -= 4;
3837 if(0 >= pwidth) {
3838 if(0 < upd->nlimits) upd_limits(upd,false);
3839 return 0;
3840 }
3841 }
3842
3843 data = upd->gsscan;
3844
3845 } /* reverse or forward */
3846 /*
3847 * Bits depend on FLIP & Direction
3848 */
3849 if(!(B_REVDIR & upd->flags) == !(B_YFLIP & upd->flags)) {
3850 dir = 4;
3851 bit = 0x80;
3852 ibyte = 0;
3853 } else {
3854 dir = -4;
3855 rowerr += 4 * (upd->rwidth-1);
3856 bit = 0x80 >> ((upd->rwidth-1) & 7);
3857 ibyte = (upd->rwidth-1) >> 3;
3858 }
3859
3860 /*
3861 * Toggle Direction, if not fixed
3862 */
3863 if(!(upd->flags & B_FIXDIR)) upd->flags ^= B_REVDIR;
3864 /*
3865 * Skip over leading white-space
3866 */
3867 if(!(upd->flags & B_FSWHITE)) {
3868 while(0 < pwidth && !*((uint32_t *)data)) {
3869 pwidth--;
3870 if(B_YFLIP & upd->flags) data -= dir;
3871 else data += dir;
3872 S_FSTEP
3873 }
3874 }
3875 /*
3876 * Process all Pixels
3877 */
3878 first = true;
3879 while(0 < pwidth--) {
3880 /*
3881 * Compute the Black-Value first
3882 */
3883 FS_M_ROWERR(upd->cmap[0].comp) FS_GOAL(data[0],upd->cmap[0].comp);
3884
3885 /*
3886 * Decide wether this is a color value
3887 */
3888 if(data[1] || data[2] || data[3]) {
3889
3890 FS_M_ROWERR(upd->cmap[1].comp) FS_GOAL(data[1],upd->cmap[1].comp)
3891 FS_M_ROWERR(upd->cmap[2].comp) FS_GOAL(data[2],upd->cmap[2].comp)
3892 FS_M_ROWERR(upd->cmap[3].comp) FS_GOAL(data[3],upd->cmap[3].comp)
3893 /*
3894 * if black fires, then all other components fire logically too
3895 */
3896 if(pixel[upd->cmap[0].comp] > comp[upd->cmap[0].comp]->threshold) {
3897
3898 pixel[0] -= comp[0]->spotsize;
3899 pixel[1] -= comp[1]->spotsize;
3900 pixel[2] -= comp[2]->spotsize;
3901 pixel[3] -= comp[3]->spotsize;
3902 scan[upd->cmap[0].comp].bytes[ibyte] |= bit;
3903
3904 /*
3905 * if black is below threshold, only components with larger data-values
3906 * are allowed to fire
3907 */
3908 } else { /* Restricted firing */
3909
3910 if(( data[0] < data[1]) &&
3911 (pixel[upd->cmap[1].comp] >
3912 comp[upd->cmap[1].comp]->threshold)) { /* "Fire" */
3913 pixel[upd->cmap[1].comp] -= comp[upd->cmap[1].comp]->spotsize;
3914 scan[upd->cmap[1].comp].bytes[ibyte] |= bit;
3915 } /* "Fire" */
3916
3917 if(( data[0] < data[2]) &&
3918 (pixel[upd->cmap[2].comp] >
3919 comp[upd->cmap[2].comp]->threshold)) { /* "Fire" */
3920 pixel[upd->cmap[2].comp] -= comp[upd->cmap[2].comp]->spotsize;
3921 scan[upd->cmap[2].comp].bytes[ibyte] |= bit;
3922 } /* "Fire" */
3923
3924 if(( data[0] < data[3]) &&
3925 (pixel[upd->cmap[3].comp] >
3926 comp[upd->cmap[3].comp]->threshold)) { /* "Fire" */
3927 pixel[upd->cmap[3].comp] -= comp[upd->cmap[3].comp]->spotsize;
3928 scan[upd->cmap[3].comp].bytes[ibyte] |= bit;
3929 } /* "Fire" */
3930
3931 } /* Fire-Mode */
3932
3933 /*
3934 * Handle Color-Errors
3935 */
3936 FS_DIST(upd->cmap[3].comp)
3937 FS_DIST(upd->cmap[2].comp)
3938 FS_DIST(upd->cmap[1].comp)
3939
3940 } else if(pixel[upd->cmap[0].comp] > comp[upd->cmap[0].comp]->threshold) {
3941 scan[upd->cmap[0].comp].bytes[ibyte] |= bit;
3942 pixel[upd->cmap[0].comp] -= comp[upd->cmap[0].comp]->spotsize;
3943 }
3944
3945 FS_DIST(upd->cmap[0].comp)
3946 /*
3947 * Adjust bit & iword, depending on direction
3948 */
3949 S_FSTEP
3950 if(upd->flags & B_YFLIP) data -= dir;
3951 else data += dir;
3952 }
3953 /*
3954 * Finally call the limits-Routine
3955 */
3956 if(0 < upd->nlimits) upd_limits(upd,true);
3957 return 0;
3958 }
3959
3960 /* ------------------------------------------------------------------- */
3961 /* upd_open_fscmy_k: Initialize for CMY_K Printing */
3962 /* ------------------------------------------------------------------- */
3963
3964 private void
upd_open_fscmy_k(upd_device * udev)3965 upd_open_fscmy_k(upd_device *udev)
3966 {
3967 const upd_p upd = udev->upd;
3968
3969 upd_open_fscomp(udev);
3970
3971 if((B_RENDER & upd->flags) &&
3972 (4 == upd->ncomp)) {
3973 upd->render = upd_fscmy_k;
3974 } else {
3975 upd->flags &= ~B_RENDER;
3976 }
3977
3978 }
3979
3980 /* ------------------------------------------------------------------- */
3981 /* upd_fscmy_k: CMY_K rendering */
3982 /* ------------------------------------------------------------------- */
3983
3984 private int
upd_fscmy_k(upd_p upd)3985 upd_fscmy_k(upd_p upd)
3986 {
3987 const updscan_p scan = upd->scnbuf[upd->yscnbuf & upd->scnmsk];
3988 const updcomp_p *comp = (updcomp_p *) upd->valptr;
3989 int32_t *const pixel = upd->valbuf;
3990 int32_t *const colerr = pixel + upd->ncomp;
3991 int32_t *rowerr = colerr + upd->ncomp;
3992 int pwidth = upd->rwidth;
3993 int dir,ibyte;
3994 uint32_t ci;
3995 byte bit;
3996 bool first = true;
3997 /*
3998 * Erase the component-Data
3999 */
4000 memset(scan[3].bytes,0,upd->nbytes);
4001 memset(scan[2].bytes,0,upd->nbytes);
4002 memset(scan[1].bytes,0,upd->nbytes);
4003 memset(scan[0].bytes,0,upd->nbytes);
4004 /*
4005 * determine the direction
4006 */
4007 if(upd->flags & B_REVDIR) { /* This one reverse */
4008
4009 if(upd->flags & B_YFLIP) {
4010 dir = 4;
4011 bit = 0x80;
4012 ibyte = 0;
4013 } else {
4014 dir = -4;
4015 rowerr += 4 * (pwidth-1);
4016 bit = 0x80 >> ((pwidth-1) & 7);
4017 ibyte = (pwidth-1) >> 3;
4018 }
4019
4020 if(!(upd->flags & B_FSWHITE)) {
4021 upd_pxlfwd(upd);
4022 while((0 < pwidth) && !upd_pxlget(upd)) pwidth--;
4023 }
4024
4025 upd_pxlrev(upd);
4026
4027 } else { /* This one forward */
4028
4029 if(upd->flags & B_YFLIP) {
4030 dir = -4;
4031 rowerr += 4 * (pwidth-1);
4032 bit = 0x80 >> ((pwidth-1) & 7);
4033 ibyte = (pwidth-1) >> 3;
4034 } else {
4035 dir = 4;
4036 bit = 0x80;
4037 ibyte = 0;
4038 }
4039
4040 if(!(upd->flags & B_FSWHITE)) {
4041 upd_pxlrev(upd);
4042 while((0 < pwidth) && !upd_pxlget(upd)) pwidth--;
4043 }
4044
4045 upd_pxlfwd(upd);
4046
4047 } /* reverse or forward */
4048 /*
4049 * Toggle Direction, if not fixed
4050 */
4051 if(!(upd->flags & B_FIXDIR)) upd->flags ^= B_REVDIR;
4052 /*
4053 * Skip over leading white-space
4054 */
4055 if(!(upd->flags & B_FSWHITE)) {
4056 upd_proc_pxlget((*fun)) = upd->pxlget;
4057 byte *ptr = upd->pxlptr;
4058 while((0 < pwidth) && !upd_pxlget(upd)) {
4059 pwidth--;
4060 fun = upd->pxlget;
4061 ptr = upd->pxlptr;
4062 S_FSTEP
4063 }
4064 upd->pxlget = fun;
4065 upd->pxlptr = ptr;
4066 }
4067 /*
4068 * Process all Pixels
4069 */
4070 first = true;
4071 while(0 < pwidth--) {
4072
4073 /* get the Pixel-Value */
4074
4075 ci = upd_pxlget(upd);
4076
4077 /* process all components */
4078
4079 FS_M_ROWERR(0) FS_GOAL(comp[0]->bitmsk & (ci >> comp[0]->bitshf),0)
4080 FS_M_ROWERR(1) FS_GOAL(comp[1]->bitmsk & (ci >> comp[1]->bitshf),1)
4081 FS_M_ROWERR(2) FS_GOAL(comp[2]->bitmsk & (ci >> comp[2]->bitshf),2)
4082 FS_M_ROWERR(3) FS_GOAL(comp[3]->bitmsk & (ci >> comp[3]->bitshf),3)
4083
4084 if(pixel[0] > comp[0]->threshold) { /* Black fires */
4085
4086 pixel[0] -= comp[0]->spotsize;
4087 scan[0].bytes[ibyte] |= bit;
4088
4089 } else { /* Colors may fire */
4090
4091 if((pixel[1] <= comp[1]->threshold) ||
4092 (pixel[2] <= comp[2]->threshold) ||
4093 (pixel[3] <= comp[3]->threshold) ) { /* Really a Color */
4094
4095 if(pixel[1] > comp[1]->threshold) {
4096 pixel[1] -= comp[1]->spotsize;
4097 scan[1].bytes[ibyte] |= bit;
4098 }
4099
4100 if(pixel[2] > comp[2]->threshold) {
4101 pixel[2] -= comp[2]->spotsize;
4102 scan[2].bytes[ibyte] |= bit;
4103 }
4104
4105 if(pixel[3] > comp[3]->threshold) {
4106 pixel[3] -= comp[3]->spotsize;
4107 scan[3].bytes[ibyte] |= bit;
4108 }
4109
4110 } else {
4111 pixel[1] -= comp[1]->spotsize;
4112 pixel[2] -= comp[2]->spotsize;
4113 pixel[3] -= comp[3]->spotsize;
4114 scan[0].bytes[ibyte] |= bit;
4115 }
4116 }
4117
4118 FS_DIST(0)
4119 FS_DIST(1)
4120 FS_DIST(2)
4121 FS_DIST(3)
4122
4123 /*
4124 * Adjust rowerr, bit & iword, depending on direction
4125 */
4126 S_FSTEP
4127 }
4128 /*
4129 * Finally call the limits-Routine
4130 */
4131 if(0 < upd->nlimits) upd_limits(upd,true);
4132 return 0;
4133 }
4134
4135 /* ------------------------------------------------------------------- */
4136 /* upd_open_writer: Initialize rendering */
4137 /* ------------------------------------------------------------------- */
4138
4139 private int
upd_open_writer(upd_device * udev)4140 upd_open_writer(upd_device *udev)
4141 {
4142 const upd_p upd = udev->upd;
4143 bool success = true;
4144
4145
4146 /** Reset the crucial values */
4147 upd->start_writer = NULL;
4148 upd->writer = NULL;
4149 upd->scnbuf = NULL;
4150 upd->nscnbuf = 0;
4151 upd->nbytes = 0;
4152 upd->nlimits = 0;
4153 upd->outbuf = NULL;
4154 upd->noutbuf = 0;
4155
4156 /** Rendering should be succesfully initialized */
4157 if(B_RENDER != ((B_RENDER | B_ERROR) & upd->flags))
4158 success = false;
4159
4160 /** Create number of components */
4161 upd->ocomp = upd->ncomp;
4162 if(0 < upd->ints[I_OCOMP]) upd->ocomp = upd->ints[I_OCOMP];
4163
4164 /** Massage some Parameters */
4165 if(success) {
4166
4167 /* Make sure, that Pass & Pin-Numbers are at least 1 */
4168 if(1 > upd->ints[I_NYPASS]) upd->ints[I_NYPASS] = 1;
4169 if(1 > upd->ints[I_NXPASS]) upd->ints[I_NXPASS] = 1;
4170 if(1 > upd->ints[I_PINS2WRITE]) upd->ints[I_PINS2WRITE] = 1;
4171
4172 if((upd->ints[I_NXPASS] * upd->ints[I_NYPASS]) > upd->ints[I_NPASS])
4173 upd->ints[I_NPASS] = upd->ints[I_NXPASS] * upd->ints[I_NYPASS];
4174
4175 /* Create Default noWeave-Feeds */
4176
4177 if(upd->ints[I_NPASS] > upd->int_a[IA_STD_DY].size) {
4178 int ix,iy,*ip;
4179 UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_STD_DY]);
4180 UPD_MM_GET_ARRAY(udev->memory, ip,upd->ints[I_NPASS]);
4181 upd->int_a[IA_STD_DY].data = ip;
4182 upd->int_a[IA_STD_DY].size = upd->ints[I_NPASS];
4183
4184 for(iy = 1; iy < upd->ints[I_NYPASS]; ++iy) {
4185 for(ix = 1; ix < upd->ints[I_NXPASS]; ++ix) *ip++ = 0;
4186 *ip++ = 1;
4187 }
4188 for(ix = 1; ix < upd->ints[I_NXPASS]; ++ix) *ip++ = 0;
4189 *ip = upd->ints[I_NYPASS] * upd->ints[I_PINS2WRITE]
4190 - upd->ints[I_NYPASS] + 1;
4191
4192 upd->ints[I_BEG_Y] = 0;
4193 upd->ints[I_END_Y] = upd->ints[I_PHEIGHT] ?
4194 upd->ints[I_PHEIGHT] : upd->gsheight;
4195 }
4196
4197 /* Adjust BEG_Y */
4198 if(0 >= upd->ints[I_BEG_Y]) {
4199 if(0 < upd->int_a[IA_BEG_DY].size) {
4200 int i,sum = 0;
4201 for(i = 0; i < upd->int_a[IA_BEG_DY].size; ++i)
4202 sum += upd->int_a[IA_BEG_DY].data[i];
4203 upd->ints[I_BEG_Y] = sum;
4204 } else {
4205 upd->ints[I_BEG_Y] = 0;
4206 }
4207 }
4208
4209 /* Adjust END_Y */
4210 /* Arrgh, I knew, why I refused to provide defaults for crucial */
4211 /* parameters in uniprint. But o.k. it's nice for size-changing */
4212 /* PostScript-Code. Nevertheless, it's still not perfect. */
4213
4214 if(0 >= upd->int_a[IA_ENDTOP].size ||
4215 0 >= upd->int_a[IA_END_DY].size ) upd->ints[I_END_Y] =
4216 upd->ints[I_PHEIGHT] ? upd->ints[I_PHEIGHT] : upd->gsheight;
4217
4218 if(0 >= upd->ints[I_END_Y]) upd->ints[I_END_Y] = upd->ints[I_PHEIGHT] ?
4219 upd->ints[I_PHEIGHT] : upd->gsheight;
4220
4221
4222 /* Create Default X-Passes */
4223
4224 if(0 >= upd->int_a[IA_STD_IX].size) {
4225 int ix,i,*ip;
4226 UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_STD_IX]);
4227 UPD_MM_GET_ARRAY(udev->memory, ip,upd->int_a[IA_STD_DY].size);
4228 upd->int_a[IA_STD_IX].data = ip;
4229 upd->int_a[IA_STD_IX].size = upd->int_a[IA_STD_DY].size;
4230
4231 for(i = 0, ix = 0; i < upd->int_a[IA_STD_IX].size; ++i) {
4232 *ip++ = ix++;
4233 if(ix == upd->ints[I_NXPASS]) ix = 0;
4234 }
4235 }
4236
4237 if((0 >= upd->int_a[IA_BEG_IX].size) &&
4238 (0 < upd->int_a[IA_BEG_DY].size) ) {
4239 int ix,i,*ip;
4240 UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_BEG_IX]);
4241 UPD_MM_GET_ARRAY(udev->memory, ip,upd->int_a[IA_BEG_DY].size);
4242 upd->int_a[IA_BEG_IX].data = ip;
4243 upd->int_a[IA_BEG_IX].size = upd->int_a[IA_BEG_DY].size;
4244
4245 for(i = 0, ix = 0; i < upd->int_a[IA_BEG_IX].size; ++i) {
4246 *ip++ = ix++;
4247 if(ix == upd->ints[I_NXPASS]) ix = 0;
4248 }
4249 }
4250
4251 if((0 >= upd->int_a[IA_END_IX].size) &&
4252 (0 < upd->int_a[IA_END_DY].size) ) {
4253 int ix,i,*ip;
4254 UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_END_IX]);
4255 UPD_MM_GET_ARRAY(udev->memory, ip,upd->int_a[IA_END_DY].size);
4256 upd->int_a[IA_END_IX].data = ip;
4257 upd->int_a[IA_END_IX].size = upd->int_a[IA_END_DY].size;
4258
4259 for(i = 0, ix = 0; i < upd->int_a[IA_END_IX].size; ++i) {
4260 *ip++ = ix++;
4261 if(ix == upd->ints[I_NXPASS]) ix = 0;
4262 }
4263 }
4264 }
4265
4266 if(upd->ints[I_NPASS] > upd->int_a[IA_STD_DY].size) {
4267 #if UPD_MESSAGES & UPD_M_WARNING
4268 errprintf(
4269 "upd_open_writer: Only %d instead of %d normal Feeds\n",
4270 (int) upd->int_a[IA_STD_DY].size,upd->ints[I_NPASS]);
4271 #endif
4272 success = false;
4273
4274 } else if(upd->int_a[IA_STD_IX].size < upd->int_a[IA_STD_DY].size) {
4275 #if UPD_MESSAGES & UPD_M_WARNING
4276 errprintf(
4277 "upd_open_writer: Only %d instead of %d normal Xstarts\n",
4278 (int) upd->int_a[IA_STD_IX].size,
4279 (int) upd->int_a[IA_STD_DY].size);
4280 #endif
4281 success = false;
4282 }
4283
4284 /** The sum of Values in STD_DY should equal NYPASS * PINS2WRITE (diagnostic) */
4285
4286 #if UPD_MESSAGES & UPD_M_WARNING
4287 if(success) {
4288 int i,sum = 0;
4289 for(i = 0; upd->ints[I_NPASS] > i; ++i)
4290 sum += upd->int_a[IA_STD_DY].data[i];
4291 if((upd->ints[I_NYPASS]*upd->ints[I_PINS2WRITE]) != sum)
4292 errprintf(
4293 "upd_open_writer: Sum of normal Feeds is %d rather than %d\n",
4294 sum,upd->ints[I_NYPASS]*upd->ints[I_PINS2WRITE]);
4295 }
4296 #endif
4297
4298 if(upd->int_a[IA_BEG_IX].size < upd->int_a[IA_BEG_DY].size) {
4299 #if UPD_MESSAGES & UPD_M_WARNING
4300 errprintf(
4301 "upd_open_writer: Only %d instead of %d initial Xstarts\n",
4302 (int) upd->int_a[IA_BEG_IX].size,
4303 (int) upd->int_a[IA_BEG_DY].size);
4304 #endif
4305 success = false;
4306 }
4307
4308 if(upd->int_a[IA_BEGBOT].size < upd->int_a[IA_BEG_DY].size) {
4309 #if UPD_MESSAGES & UPD_M_WARNING
4310 errprintf(
4311 "upd_open_writer: Only %d instead of %d initial Pins\n",
4312 (int) upd->int_a[IA_BEGBOT].size,
4313 (int) upd->int_a[IA_BEG_DY].size);
4314 #endif
4315 success = false;
4316
4317 } else {
4318
4319 int i;
4320 for(i = 0; i < upd->int_a[IA_BEG_DY].size; ++i)
4321 if((upd->int_a[IA_BEGBOT].data[i] > upd->ints[I_PINS2WRITE]) ||
4322 (upd->int_a[IA_BEGBOT].data[i] < 0 ) ) break;
4323
4324 if(i < upd->int_a[IA_BEG_DY].size) {
4325 #if UPD_MESSAGES & UPD_M_WARNING
4326 errprintf(
4327 "upd_open_writer: Only %d is invalid initial Pins\n",
4328 upd->int_a[IA_BEGBOT].data[i]);
4329 #endif
4330 success = false;
4331 }
4332 }
4333
4334
4335 /** The sum of Values in BEG_DY should equal BEG_Y */
4336
4337 #if UPD_MESSAGES & UPD_M_WARNING
4338 if(success) {
4339 int i,sum = 0;
4340 for(i = 0; upd->int_a[IA_BEG_DY].size > i; ++i)
4341 sum += upd->int_a[IA_BEG_DY].data[i];
4342 if(upd->ints[I_BEG_Y] != sum)
4343 errprintf(
4344 "upd_open_writer: Sum of initial Feeds is %d rather than %d\n",
4345 sum,upd->ints[I_BEG_Y]);
4346 }
4347 #endif
4348
4349 if(upd->int_a[IA_END_IX].size < upd->int_a[IA_END_DY].size) {
4350 #if UPD_MESSAGES & UPD_M_WARNING
4351 errprintf(
4352 "upd_open_writer: Only %d instead of %d final Xstarts\n",
4353 (int) upd->int_a[IA_END_IX].size,
4354 (int) upd->int_a[IA_END_DY].size);
4355 #endif
4356 success = false;
4357 }
4358
4359 if(upd->int_a[IA_ENDTOP].size < upd->int_a[IA_END_DY].size) {
4360 #if UPD_MESSAGES & UPD_M_WARNING
4361 errprintf(
4362 "upd_open_writer: Only %d instead of %d Final Pins\n",
4363 (int) upd->int_a[IA_ENDTOP].size,
4364 (int) upd->int_a[IA_END_DY].size);
4365 #endif
4366 success = false;
4367
4368 } else {
4369
4370 int i;
4371 for(i = 0; i < upd->int_a[IA_END_DY].size; ++i)
4372 if((upd->int_a[IA_ENDTOP].data[i] > upd->ints[I_PINS2WRITE]) ||
4373 (upd->int_a[IA_ENDTOP].data[i] < 0 ) ) break;
4374
4375 if(i < upd->int_a[IA_END_DY].size) {
4376 #if UPD_MESSAGES & UPD_M_WARNING
4377 errprintf(
4378 "upd_open_writer: Only %d is invalid initial Pins\n",
4379 upd->int_a[IA_ENDTOP].data[i]);
4380 #endif
4381 success = false;
4382 }
4383 }
4384
4385 /** SA_SETCOMP must be valid, if present */
4386 if((0 < upd->string_a[SA_SETCOMP].size) &&
4387 (upd->ocomp > upd->string_a[SA_SETCOMP].size)) {
4388 #if UPD_MESSAGES & UPD_M_WARNING
4389 errprintf(
4390 "upd_open_writer: Only %d SETCOMP-Commands (%d required)\n",
4391 (int) upd->string_a[SA_SETCOMP].size,upd->ocomp);
4392 #endif
4393 success = false;
4394 }
4395
4396 /** Determine required number of scan-Buffers */
4397
4398 if(success) { /* Compute nscnbuf */
4399 int32_t want,use;
4400
4401 want = upd->ints[I_NYPASS];
4402 want *= upd->ints[I_PINS2WRITE];
4403
4404 if(upd->ints[I_NSCNBUF] > want) want = upd->ints[I_NSCNBUF];
4405
4406 if(1 > want) want = 1;
4407
4408 for(use = 1; 0 < use; use <<= 1) if(use > want) break;
4409
4410 if(use <= INT_MAX) upd->nscnbuf = upd->ints[I_NSCNBUF] = use;
4411 else success = false;
4412
4413 } /* Compute nscnbuf */
4414
4415 /** Determine number of words in scan-buffers */
4416
4417 if(success) { /* Compute pwidth, scnmsk, nbytes, pheight */
4418
4419 if(0 < upd->ints[I_PWIDTH]) upd->pwidth = upd->ints[I_PWIDTH];
4420 else upd->pwidth = upd->gswidth;
4421
4422 upd->nbytes = (upd->pwidth+CHAR_BIT*sizeof(upd->scnbuf[0]->bytes[0]) - 1)
4423 / (CHAR_BIT*sizeof(upd->scnbuf[0]->bytes[0]));
4424
4425 upd->scnmsk = upd->nscnbuf - 1;
4426
4427 if(0 < upd->ints[I_PHEIGHT]) upd->pheight = upd->ints[I_PHEIGHT];
4428 else upd->pheight = upd->gsheight;
4429
4430 } /* Compute pwidth, scnmsk, nbytes */
4431
4432 /** Call the writer-specific open-function */
4433
4434 if(success) { /* Determine sizes */
4435 switch(upd->choice[C_FORMAT]) {
4436 case FMT_RAS:
4437 if(0 > upd_open_rascomp(udev)) success = false;
4438 break;
4439 case FMT_EPSON:
4440 if(0 > upd_open_wrtescp(udev)) success = false;
4441 break;
4442 case FMT_ESCP2Y:
4443 case FMT_ESCP2XY:
4444 case FMT_ESCNMY: /* (GR) */
4445 if(0 > upd_open_wrtescp2(udev)) success = false;
4446 break;
4447 case FMT_RTL:
4448 if(0 > upd_open_wrtrtl(udev)) success = false;
4449 break;
4450 case FMT_CANON: /* (hr) */
4451 if(0 > upd_open_wrtcanon(udev)) success = false;
4452 break;
4453 default:
4454 success = false;
4455 #if UPD_MESSAGES & UPD_M_WARNING
4456 errprintf("upd_open_writer: Unknown writer-type %d\n",
4457 upd->choice[C_FORMAT]);
4458 #endif
4459 break;
4460 }
4461 } /* Determine sizes*/
4462
4463 /** Allocate the Outputbuffer */
4464 if(success && (0 < upd->noutbuf)) { /* Allocate outbuf */
4465 upd->outbuf = gs_malloc(udev->memory, upd->noutbuf,sizeof(upd->outbuf[0]),"upd/outbuf");
4466 if(!upd->outbuf) success = false;
4467 } /* Allocate outbuf */
4468
4469 /** Allocate the desired scan-buffer-pointers */
4470 if(success) {
4471 upd->scnbuf = gs_malloc(udev->memory, upd->nscnbuf,sizeof(upd->scnbuf[0]),"upd/scnbuf");
4472 if(NULL == upd->scnbuf) {
4473 success = false;
4474 } else {
4475 int ibuf;
4476 for(ibuf = 0; ibuf < upd->nscnbuf; ++ibuf) {
4477 if(success) upd->scnbuf[ibuf] =
4478 gs_malloc(udev->memory, upd->ocomp,sizeof(upd->scnbuf[0][0]),"upd/scnbuf[]");
4479 else upd->scnbuf[ibuf] = NULL;
4480
4481 if(!upd->scnbuf[ibuf]) {
4482 success = false;
4483 } else {
4484 int icomp;
4485 for(icomp = 0; icomp < upd->ocomp; ++icomp) {
4486 if(success) upd->scnbuf[ibuf][icomp].bytes =
4487 gs_malloc(udev->memory, upd->nbytes,sizeof(upd->scnbuf[0][0].bytes[0]),
4488 "upd/bytes");
4489 else upd->scnbuf[ibuf][icomp].bytes = NULL;
4490 if(!upd->scnbuf[ibuf][icomp].bytes) success = false;
4491
4492 if(0 < upd->nlimits) {
4493
4494 upd->scnbuf[ibuf][icomp].xbegin = gs_malloc(udev->memory, upd->nlimits,
4495 sizeof(upd->scnbuf[0][0].xbegin[0]),"upd/xbegin");
4496 if(!upd->scnbuf[ibuf][icomp].xbegin) success = false;
4497
4498 upd->scnbuf[ibuf][icomp].xend = gs_malloc(udev->memory, upd->nlimits,
4499 sizeof(upd->scnbuf[0][0].xend[0]),"upd/xend");
4500 if(!upd->scnbuf[ibuf][icomp].xbegin) success = false;
4501
4502 } else {
4503
4504 upd->scnbuf[ibuf][icomp].xbegin = NULL;
4505 upd->scnbuf[ibuf][icomp].xend = NULL;
4506
4507 }
4508 }
4509 }
4510 }
4511 }
4512 }
4513
4514 if(success) upd->flags |= B_FORMAT;
4515 else upd_close_writer(udev);
4516
4517 return success ? 1 : -1;
4518 }
4519
4520 /* ------------------------------------------------------------------- */
4521 /* upd_close_writer: Deinitialize rendering */
4522 /* ------------------------------------------------------------------- */
4523
4524 private void
upd_close_writer(upd_device * udev)4525 upd_close_writer(upd_device *udev)
4526 {
4527 const upd_p upd = udev->upd;
4528
4529 if(upd) {
4530 int ibuf,icomp;
4531
4532 if((0 < upd->noutbuf) && upd->outbuf)
4533 gs_free(udev->memory, upd->outbuf,upd->noutbuf,sizeof(upd->outbuf[0]),"upd/outbuf");
4534 upd->noutbuf = 0;
4535 upd->outbuf = NULL;
4536
4537 if((0 < upd->nscnbuf) && upd->scnbuf) {
4538 for(ibuf = 0; upd->nscnbuf > ibuf; ++ibuf) {
4539
4540 if(!upd->scnbuf[ibuf]) continue;
4541
4542 for(icomp = 0; icomp < upd->ocomp; ++icomp) {
4543
4544 if((0 < upd->nbytes) && upd->scnbuf[ibuf][icomp].bytes)
4545 gs_free(udev->memory, upd->scnbuf[ibuf][icomp].bytes,upd->nbytes,
4546 sizeof(upd->scnbuf[ibuf][icomp].words[0]),"upd/bytes");
4547 upd->scnbuf[ibuf][icomp].bytes = NULL;
4548
4549 if((0 < upd->nlimits) && upd->scnbuf[ibuf][icomp].xbegin)
4550 gs_free(udev->memory, upd->scnbuf[ibuf][icomp].xbegin,upd->nlimits,
4551 sizeof(upd->scnbuf[ibuf][icomp].xbegin[0]),"upd/xbegin");
4552 upd->scnbuf[ibuf][icomp].xbegin = NULL;
4553
4554 if((0 < upd->nlimits) && upd->scnbuf[ibuf][icomp].xend)
4555 gs_free(udev->memory, upd->scnbuf[ibuf][icomp].xend,upd->nlimits,
4556 sizeof(upd->scnbuf[ibuf][icomp].xend[0]),"upd/xend");
4557 upd->scnbuf[ibuf][icomp].xend = NULL;
4558 }
4559
4560 if(icomp)
4561 gs_free(udev->memory, upd->scnbuf[ibuf],upd->ocomp,sizeof(upd->scnbuf[0][0]),
4562 "upd/scnbuf[]");
4563 upd->scnbuf[ibuf] = NULL;
4564
4565 }
4566 gs_free(udev->memory, upd->scnbuf,upd->nscnbuf,sizeof(upd->scnbuf[0]),"upd/scnbuf");
4567 }
4568
4569
4570 upd->flags &= ~B_FORMAT;
4571 }
4572 }
4573
4574
4575 /* ------------------------------------------------------------------- */
4576 /* upd_limits: Establish passwise limits, after rendering */
4577 /* ------------------------------------------------------------------- */
4578
4579 private void
upd_limits(upd_p upd,bool check)4580 upd_limits(upd_p upd, bool check)
4581 {
4582 updscan_p scans = upd->scnbuf[upd->yscnbuf & upd->scnmsk], scan;
4583 int xs,x,xe,icomp,pass;
4584 byte *bytes,bit;
4585
4586 for(icomp = 0; icomp < upd->ocomp; ++icomp) {
4587 scan = scans + icomp;
4588 for(pass = 0; pass < upd->nlimits; ++pass) {
4589 scan->xbegin[pass] = upd->pwidth;
4590 scan->xend[ pass] = -1;
4591 }
4592 }
4593
4594 if(check) { /* Really check */
4595 for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Check Components */
4596 scan = scans + icomp;
4597 bytes = scan->bytes;
4598
4599 for(xs = 0; xs < upd->nbytes && !bytes[xs]; ++xs);
4600
4601 if(xs < upd->nbytes) { /* Has Data */
4602 for(xe = upd->nbytes; xs < xe && !bytes[xe-1]; --xe);
4603
4604 for(pass = 0; pass < upd->nlimits; ++pass) { /* limit (pass) loop */
4605
4606 x = ((xs<<3)/upd->nlimits)*upd->nlimits + pass;
4607 while((x >> 3) < xs) x += upd->nlimits;
4608
4609 bit = 0x80 >> (x & 7);
4610 while(x < scan->xbegin[pass]) {
4611 if(bytes[x>>3] & bit) scan->xbegin[pass] = x;
4612 x += upd->nlimits;
4613 bit = 0x80 >> (x & 7);
4614 }
4615
4616 x = (((xe<<3)|7)/upd->nlimits)*upd->nlimits + pass;
4617
4618 while((x >> 3) < xe) x += upd->nlimits;
4619 while((x >> 3) > xe) x -= upd->nlimits;
4620
4621 bit = 0x80 >> (xs & 7);
4622 while(x > scan->xend[pass]) {
4623 if(bytes[x>>3] & bit) scan->xend[pass] = x;
4624 x -= upd->nlimits;
4625 bit = 0x80 >> (x & 7);
4626 }
4627
4628 } /* limit (pass) loop */
4629
4630 } /* Has Data */
4631
4632 } /* Check Components */
4633
4634 } /* Really check */
4635
4636 }
4637
4638 /* ------------------------------------------------------------------- */
4639 /* upd_open_rascomp: ncomp * 1Bit Raster-Writer */
4640 /* ------------------------------------------------------------------- */
4641
4642 private int
upd_open_rascomp(upd_device * udev)4643 upd_open_rascomp(upd_device *udev)
4644 {
4645 const upd_p upd = udev->upd;
4646 int32_t noutbuf;
4647 int error = 0;
4648
4649 noutbuf = upd->pwidth;
4650
4651 if(1 < upd->ncomp) noutbuf *= 8; /* ??? upd->ocomp */
4652
4653 noutbuf = ((noutbuf+15)>>4)<<1;
4654
4655 if(INT_MAX >= noutbuf) {
4656 upd->noutbuf = noutbuf;
4657 upd->start_writer = upd_start_rascomp;
4658 upd->writer = upd_rascomp;
4659 } else {
4660 error = -1;
4661 }
4662
4663 return error;
4664 }
4665
4666 /* ------------------------------------------------------------------- */
4667 /* upd_start_rascomp: write appropiate raster-header */
4668 /* ------------------------------------------------------------------- */
4669 #if arch_is_big_endian
4670 #define put32(I32,Out) \
4671 fwrite(&I32,1,4,Out)
4672 #else
4673 #define put32(I32,Out) \
4674 putc(((I32)>>24)&255,Out),\
4675 putc(((I32)>>16)&255,Out),\
4676 putc(((I32)>> 8)&255,Out),\
4677 putc( (I32) &255,Out)
4678 #endif
4679
4680 private int
upd_start_rascomp(upd_p upd,FILE * out)4681 upd_start_rascomp(upd_p upd, FILE *out) {
4682
4683 /** if no begin-sequence externally set */
4684 if(0 == upd->strings[S_BEGIN].size) {
4685 int32_t val;
4686
4687 /** ras_magic */
4688 val = 0x59a66a95;
4689 put32(val,out);
4690
4691 /** ras_width */
4692 val = upd->pwidth;
4693 put32(val,out);
4694
4695 /** ras_height */
4696 val = upd->pheight;
4697 put32(val,out);
4698
4699 /** ras_depth */
4700 if(1 < upd->ncomp) val = 8; /* ??? upd->ocomp */
4701 else val = 1;
4702 put32(val,out);
4703
4704 /** ras_length */
4705 val *= upd->pwidth;
4706 val = ((val+15)>>4)<<1;
4707 val *= upd->pheight;
4708 put32(val,out);
4709
4710 /** ras_type */
4711 val = 1;
4712 put32(val,out);
4713
4714 /** ras_maptype */
4715 val = 1;
4716 put32(val,out);
4717
4718 /** ras_maplength */
4719 val = 3 * (1 << upd->ncomp); /* ??? upd->ocomp */
4720 put32(val,out);
4721
4722 /** R,G,B-Map */
4723 if(1 == upd->ncomp) { /* ??? upd->ocomp */
4724 const updcomp_p comp = upd->valptr[0];
4725
4726 if(upd->cmap[comp->cmap].rise) {
4727 putc((char) 0x00,out); putc((char) 0xff,out);
4728 putc((char) 0x00,out); putc((char) 0xff,out);
4729 putc((char) 0x00,out); putc((char) 0xff,out);
4730 } else {
4731 putc((char) 0xff,out); putc((char) 0x00,out);
4732 putc((char) 0xff,out); putc((char) 0x00,out);
4733 putc((char) 0xff,out); putc((char) 0x00,out);
4734 }
4735
4736 } else if(3 == upd->ncomp) { /* ??? upd->ocomp */
4737 int rgb;
4738
4739 for( rgb = 0; rgb < 3; ++rgb) {
4740 int entry;
4741 for(entry = 0; entry < 8; ++entry) {
4742 byte xval = upd->cmap[rgb].rise ? 0x00 : 0xff;
4743 if(entry & (1<<upd->cmap[rgb].comp)) xval ^= 0xff;
4744 putc(xval,out);
4745 }
4746 }
4747 } else { /* we have 4 components */
4748 int rgb;
4749
4750 for(rgb = 16; 0 <= rgb; rgb -= 8) {
4751 int entry;
4752 for(entry = 0; entry < 16; ++entry) {
4753 uint32_t rgbval = 0;
4754
4755 if(entry & (1<<upd->cmap[0].comp)) {
4756
4757 rgbval = 0xffffff;
4758
4759 } else {
4760
4761 if(entry & (1<<upd->cmap[1].comp)) rgbval |= 0xff0000;
4762 if(entry & (1<<upd->cmap[2].comp)) rgbval |= 0x00ff00;
4763 if(entry & (1<<upd->cmap[3].comp)) rgbval |= 0x0000ff;
4764 }
4765
4766 if(!upd->cmap[1].rise) rgbval ^= 0xff0000;
4767 if(!upd->cmap[2].rise) rgbval ^= 0x00ff00;
4768 if(!upd->cmap[3].rise) rgbval ^= 0x0000ff;
4769
4770 if(!(upd->choice[C_MAPPER] == MAP_RGBW)) rgbval ^= 0xffffff;
4771
4772 putc((rgbval>>rgb)&255,out);
4773 }
4774 }
4775 }
4776 }
4777 memset(upd->outbuf,0,upd->noutbuf);
4778
4779 return 0;
4780 }
4781
4782 /* ------------------------------------------------------------------- */
4783 /* upd_rascomp: assemble & write a scanline */
4784 /* ------------------------------------------------------------------- */
4785 private int
upd_rascomp(upd_p upd,FILE * out)4786 upd_rascomp(upd_p upd, FILE *out) {
4787 updscan_p scan = upd->scnbuf[upd->yscan & upd->scnmsk];
4788 uint bits = upd->pwidth;
4789
4790 if(1 == upd->ncomp) { /* ??? upd->ocomp */
4791 uint nbytes;
4792
4793 nbytes = (bits+7)>>3;
4794 memcpy(upd->outbuf,scan->bytes,nbytes);
4795 if((bits &= 7)) upd->outbuf[nbytes-1] &= ((byte) 0xff) << (8-bits);
4796
4797 } else {
4798
4799 byte *buf = upd->outbuf, bit = 0x80;
4800 int ibyte = 0;
4801
4802 while(0 < bits--) {
4803 byte val = 0;
4804 switch(upd->ncomp) { /* ??? upd->ocomp */
4805 case 4: if(scan[3].bytes[ibyte] & bit) val |= 8;
4806 case 3: if(scan[2].bytes[ibyte] & bit) val |= 4;
4807 if(scan[1].bytes[ibyte] & bit) val |= 2;
4808 case 1: if(scan[0].bytes[ibyte] & bit) val |= 1;
4809 }
4810 *buf++ = val;
4811 if(!(bit >>= 1)) {
4812 bit = 0x80;
4813 ibyte += 1;
4814 }
4815 }
4816 }
4817
4818 fwrite(upd->outbuf,1,upd->noutbuf,out);
4819 upd->yscan += 1;
4820
4821 return 0;
4822 }
4823
4824 /* ------------------------------------------------------------------- */
4825 /* upd_open_wrtescp: ESC/P Writer intended for ESC * m commands */
4826 /* ------------------------------------------------------------------- */
4827
4828 private int
upd_open_wrtescp(upd_device * udev)4829 upd_open_wrtescp(upd_device *udev)
4830 {
4831 const upd_p upd = udev->upd;
4832 int error = 0;
4833
4834 /** Adjust the PageLength, If Requested */
4835 if((B_PAGELENGTH & upd->flags) &&
4836 (0 < upd->strings[S_BEGIN].size)) { /* BOP-Checker */
4837 int i,state = 0,value = 0;
4838 byte *bp = (byte *) upd_cast(upd->strings[S_BEGIN].data);
4839 for(i = 0; i < upd->strings[S_BEGIN].size; ++i) {
4840 switch(state) {
4841 case 0:
4842 if(0x1b == bp[i]) state = 1;
4843 break;
4844 case 1:
4845 if('C' == bp[i]) state = 2;
4846 else state = 0;
4847 break;
4848 case 2:
4849 if(bp[i]) {
4850 value = (int)(0.5 + udev->height * (float) bp[i]
4851 / udev->y_pixels_per_inch);
4852 if( 0 >= value) bp[i] = 1;
4853 else if(128 > value) bp[i] = value;
4854 else bp[i] = 127;
4855 state = 0;
4856 } else {
4857 state = 3;
4858 }
4859 break;
4860 case 3:
4861 value = (int)(0.5 + udev->height / udev->y_pixels_per_inch);
4862 if( 0 >= value) bp[i] = 1;
4863 else if( 22 > value) bp[i] = value;
4864 else bp[i] = 22;
4865 state = 0;
4866 break;
4867 }
4868 }
4869 } /* BOP-Checker */
4870
4871
4872 /** Either SETLF or YMOVE must be set */
4873 if((0 == upd->strings[S_SETLF].size) &&
4874 (0 == upd->strings[S_YMOVE].size) ) {
4875 #if UPD_MESSAGES & UPD_M_WARNING
4876 errprintf(
4877 "ESC/P-Open: Either SETLF- or YMOVE-Command must be present\n");
4878 #endif
4879 error = -1;
4880 }
4881
4882 /** X-Positioning must be set too */
4883 if(((1 < upd->ints[I_XSTEP] ) &&
4884 (0 == upd->strings[S_XSTEP].size) ) ||
4885 ((1 < upd->ints[I_NXPASS] ) &&
4886 (0 == upd->strings[S_XMOVE].size) &&
4887 (0 == upd->strings[S_XSTEP].size) ) ) {
4888 #if UPD_MESSAGES & UPD_M_WARNING
4889 errprintf(
4890 "ESC/P-Open: Missing XSTEP- and/or XMOVE-Command\n");
4891 #endif
4892 error = -1;
4893 }
4894
4895 /** SA_WRITECOMP must be valid */
4896 if(upd->ncomp > upd->string_a[SA_WRITECOMP].size) { /* ??? upd->ocomp */
4897 #if UPD_MESSAGES & UPD_M_WARNING
4898 errprintf(
4899 "ESC/P-Open: WRITECOMP-Commands must be given\n");
4900 #endif
4901 error = -1;
4902 }
4903
4904 /**
4905 If all this is correct, it's time to coumput the size of the output-buffer.
4906 It must hold:
4907 1. Y-Positioning
4908 2. X-Positioning
4909 3. Component-Selection
4910 4. The Raster-Command
4911 5. The Data
4912 */
4913 if(0 <= error) {
4914 int32_t i,noutbuf,need;
4915
4916 if(0 < upd->strings[S_YMOVE].size) {
4917 noutbuf = upd->strings[S_YMOVE].size + 2;
4918 } else {
4919 int nmax = upd->pheight;
4920 if( 1 < upd->ints[I_YSTEP]) nmax /= upd->ints[I_YSTEP];
4921 else if(-1 > upd->ints[I_YSTEP]) nmax *= -upd->ints[I_YSTEP];
4922 noutbuf = 2 * upd->strings[S_SETLF].size + 2;
4923 noutbuf += nmax/255 + 1;
4924 }
4925
4926 if(1 < upd->ints[I_YSTEP])
4927 noutbuf += (upd->ints[I_YSTEP]-1) * upd->strings[S_YSTEP].size;
4928
4929 noutbuf += upd->strings[S_XMOVE].size + 2;
4930
4931 if(1 < upd->ints[I_XSTEP])
4932 noutbuf += (upd->ints[I_XSTEP]-1) * upd->strings[S_XSTEP].size;
4933
4934 if(0 < upd->string_a[SA_SETCOMP].size) {
4935 need = 0;
4936 for(i = 0; i < upd->ocomp; ++i)
4937 if(need < upd->string_a[SA_SETCOMP].data[i].size)
4938 need = upd->string_a[SA_SETCOMP].data[i].size;
4939 noutbuf += need;
4940 }
4941
4942 need = 0;
4943 for(i = 0; i < upd->ocomp; ++i)
4944 if(need < upd->string_a[SA_WRITECOMP].data[i].size)
4945 need = upd->string_a[SA_WRITECOMP].data[i].size;
4946 noutbuf += need + 2;
4947
4948 noutbuf += ((upd->ints[I_PINS2WRITE] + 7) / 8)
4949 * ((upd->pwidth + upd->ints[I_NXPASS] - 1)/upd->ints[I_NXPASS]);
4950
4951 if((0 < noutbuf) && (noutbuf <= INT_MAX)) {
4952 upd->noutbuf = noutbuf;
4953 upd->writer = upd_wrtescp;
4954 upd->nlimits = upd->ints[I_NXPASS];
4955 error = 1;
4956 } else {
4957 error = -1;
4958 #if UPD_MESSAGES & UPD_M_WARNING
4959 errprintf(
4960 "ESC/P-Open: %ld is unreasonable size of Outputbuffer\n",
4961 (long) noutbuf);
4962 #endif
4963 }
4964 }
4965
4966 return error;
4967 }
4968
4969 /* ------------------------------------------------------------------- */
4970 /* upd_wrtescp: Write a pass */
4971 /* ------------------------------------------------------------------- */
4972
4973 private int
upd_wrtescp(upd_p upd,FILE * out)4974 upd_wrtescp(upd_p upd, FILE *out)
4975 {
4976 int pinbot,pin,pintop,xbegin,x,xend,icomp,ybegin,yend,y,ioutbuf,n,ixpass;
4977 byte *obytes,bit;
4978 updscan_p scan;
4979
4980 /** Determine the number of pins to write */
4981
4982 if(upd->yscan < upd->ints[I_BEG_Y]) {
4983 ixpass = upd->int_a[IA_BEG_IX].data[upd->ipass];
4984 pintop = 0;
4985 pinbot = upd->int_a[IA_BEGBOT].data[upd->ipass];
4986 } else if(upd->yscan >= upd->ints[I_END_Y]) {
4987 ixpass = upd->int_a[IA_END_IX].data[upd->ipass];
4988 pinbot = upd->ints[I_PINS2WRITE];
4989 pintop = pinbot - upd->int_a[IA_ENDTOP].data[upd->ipass];
4990 } else {
4991 ixpass = upd->int_a[IA_STD_IX].data[upd->ipass];
4992 pintop = 0;
4993 pinbot = upd->ints[I_PINS2WRITE];
4994 }
4995
4996 ybegin = pintop * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
4997 yend = pinbot * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
4998
4999 /** Determine Width of this scan */
5000
5001 xbegin = upd->pwidth;
5002 xend = -1;
5003
5004 for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Pin-testloop */
5005
5006 if(0 > y) continue; /* Inserted Scanlines */
5007
5008 scan = upd->scnbuf[y & upd->scnmsk];
5009
5010 for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Compwise test */
5011 if(xbegin > scan[icomp].xbegin[ixpass])
5012 xbegin = scan[icomp].xbegin[ixpass];
5013 if(xend < scan[icomp].xend[ ixpass])
5014 xend = scan[icomp].xend[ ixpass];
5015 } /* Compwise test */
5016
5017 } /* Pin-testloop */
5018
5019 if(xbegin <= xend) { /* Some data to write */
5020
5021 ioutbuf = 0;
5022
5023 if(0 == upd->strings[S_XMOVE].size) xbegin = ixpass;
5024
5025 /*
5026 * Adjust the Printers Y-Position
5027 */
5028 if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
5029 if(B_YABS & upd->flags) y = upd->yscan + upd->ints[I_YOFS];
5030 else y = upd->yscan - upd->yprinter;
5031
5032 if( 1 < upd->ints[I_YSTEP]) {
5033 n = y / upd->ints[I_YSTEP]; /* Major-Steps */
5034 y -= n * upd->ints[I_YSTEP]; /* Minor-Steps */
5035 } else if(-1 > upd->ints[I_YSTEP]) {
5036 n = y * -upd->ints[I_YSTEP]; /* May this work? */
5037 y = 0;
5038 } else {
5039 n = y;
5040 y = 0;
5041 }
5042
5043 if(n) { /* Coarse Positioning */
5044 if(0 < upd->strings[S_YMOVE].size) {
5045
5046 memcpy(upd->outbuf+ioutbuf,
5047 upd->strings[S_YMOVE].data,
5048 upd->strings[S_YMOVE].size);
5049 ioutbuf += upd->strings[S_YMOVE].size;
5050
5051 upd->outbuf[ioutbuf++] = n & 0xff;
5052 upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5053
5054 } else {
5055
5056 while(n) {
5057 int n2do = n > 255 ? 255 : n;
5058 if(upd->lf != n2do) {
5059 memcpy(upd->outbuf+ioutbuf,
5060 upd->strings[S_SETLF].data,
5061 upd->strings[S_SETLF].size);
5062 ioutbuf += upd->strings[S_SETLF].size;
5063 upd->outbuf[ioutbuf++] = n2do;
5064 upd->lf = n2do;
5065 }
5066 upd->outbuf[ioutbuf++] = '\n';
5067 n -= n2do;
5068 }
5069 }
5070 } /* Coarse Positioning */
5071
5072 if(0 < upd->strings[S_YSTEP].size) {
5073 while(y--) {
5074 memcpy(upd->outbuf+ioutbuf,
5075 upd->strings[S_YSTEP].data,
5076 upd->strings[S_YSTEP].size);
5077 ioutbuf += upd->strings[S_YSTEP].size;
5078 }
5079 }
5080
5081 upd->yprinter = upd->yscan;
5082 } /* Adjust Y-Position */
5083
5084 /*
5085 * Now write the required components
5086 */
5087 for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Component-Print */
5088 /*
5089 * First check, wether this Component needs printing
5090 */
5091 for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Comp-Test */
5092 if(0 > y) continue;
5093 scan = upd->scnbuf[y & upd->scnmsk]+icomp;
5094 if(0 <= scan->xend[ixpass]) break;
5095 } /* Comp-Test */
5096 if(y >= yend) continue; /* Component not required */
5097 /*
5098 * Select the Component
5099 */
5100 if((0 < upd->string_a[SA_SETCOMP].size) &&
5101 (upd->icomp != icomp ) ) { /* Selection enabled */
5102 upd->icomp = icomp;
5103 if(0 < upd->string_a[SA_SETCOMP].data[icomp].size) {
5104 memcpy(upd->outbuf+ioutbuf,
5105 upd->string_a[SA_SETCOMP].data[icomp].data,
5106 upd->string_a[SA_SETCOMP].data[icomp].size);
5107 ioutbuf += upd->string_a[SA_SETCOMP].data[icomp].size;
5108 }
5109 } /* Selection enabled */
5110 /*
5111 * Establish the X-Position
5112 */
5113 if(xbegin != upd->xprinter) {
5114
5115 if(0 == upd->strings[S_XMOVE].size) {
5116
5117 upd->outbuf[ioutbuf++] = '\r';
5118 upd->xprinter = 0;
5119 n = 0;
5120 x = ixpass;
5121
5122 } else {
5123
5124 if(B_XABS & upd->flags) n = x = xbegin + upd->ints[I_XOFS];
5125 else n = x = xbegin - upd->xprinter;
5126
5127 if( 1 < upd->ints[I_XSTEP]) {
5128 if(0 > n) {
5129 n -= upd->ints[I_XSTEP];
5130 x -= n;
5131 }
5132 if(n) n /= upd->ints[I_XSTEP]; /* Major-Steps */
5133 if(x) x %= upd->ints[I_XSTEP]; /* Minor-Steps */
5134
5135 } else if(-1 > upd->ints[I_XSTEP]) {
5136 n *= -upd->ints[I_XSTEP]; /* May this work? */
5137 x = 0;
5138 }
5139
5140 if(n) { /* Adjust X-Position */
5141
5142 memcpy(upd->outbuf+ioutbuf,
5143 upd->strings[S_XMOVE].data,
5144 upd->strings[S_XMOVE].size);
5145 ioutbuf += upd->strings[S_XMOVE].size;
5146
5147 upd->outbuf[ioutbuf++] = n & 0xff;
5148 upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5149
5150 } /* Adjust X-Position */
5151
5152 }
5153
5154 if(x && 0 < upd->strings[S_XSTEP].size) { /* Fine-Adjust X */
5155 while(x--) {
5156 memcpy(upd->outbuf+ioutbuf,
5157 upd->strings[S_XSTEP].data,
5158 upd->strings[S_XSTEP].size);
5159 ioutbuf += upd->strings[S_XSTEP].size;
5160 }
5161 } /* Fine-Adjust X */
5162 }
5163 upd->xprinter = xend+1;
5164 /*
5165 * Send the Write-Command
5166 */
5167 if(0 < upd->string_a[SA_WRITECOMP].data[icomp].size) {
5168 memcpy(upd->outbuf+ioutbuf,
5169 upd->string_a[SA_WRITECOMP].data[icomp].data,
5170 upd->string_a[SA_WRITECOMP].data[icomp].size);
5171 ioutbuf += upd->string_a[SA_WRITECOMP].data[icomp].size;
5172 }
5173 n = (xend - xbegin) / upd->ints[I_NXPASS] + 1;;
5174 upd->outbuf[ioutbuf++] = n & 255;
5175 upd->outbuf[ioutbuf++] = (n>>8) & 255;
5176 /*
5177 * Clear the data-Part
5178 */
5179 obytes = upd->outbuf+ioutbuf;
5180 n *= (upd->ints[I_PINS2WRITE]+7)>>3;
5181 memset(obytes,0,n);
5182 ioutbuf += n;
5183 /*
5184 * Set the Pixels
5185 */
5186 for(x = xbegin; x <= xend; x += upd->ints[I_NXPASS]) {
5187
5188 bit = 0x80 >> (pintop & 7);
5189 obytes += pintop>>3;
5190
5191 for(pin = pintop, y = ybegin; pin < pinbot;
5192 pin++, y += upd->ints[I_NYPASS]) {
5193 if(0 <= y) {
5194 scan = upd->scnbuf[y & upd->scnmsk]+icomp;
5195 if(scan->bytes[x>>3] & (0x80 >> (x & 7))) *obytes |= bit;
5196 }
5197 if(!(bit >>= 1)) { obytes++; bit = 0x80; }
5198 }
5199
5200 obytes += (upd->ints[I_PINS2WRITE]-pinbot+7)>>3;
5201 }
5202 /*
5203 * Send this Component to the Printer
5204 */
5205 fwrite(upd->outbuf,1,ioutbuf,out);
5206 ioutbuf = 0;
5207 } /* Component-Print */
5208 } /* Some data to write */
5209
5210 /** Advance counters in upd, change modi */
5211
5212 if(upd->yscan < upd->ints[I_BEG_Y]) {
5213 upd->yscan += upd->int_a[IA_BEG_DY].data[upd->ipass++];
5214 if( upd->ints[I_BEG_Y] <= upd->yscan) upd->ipass = 0;
5215 else if(upd->int_a[IA_BEG_DY].size <= upd->ipass) upd->ipass = 0;
5216 } else if(upd->yscan >= upd->ints[I_END_Y]) {
5217 upd->yscan += upd->int_a[IA_END_DY].data[upd->ipass++];
5218 if(upd->int_a[IA_END_DY].size <= upd->ipass) upd->ipass = 0;
5219 } else {
5220 upd->yscan += upd->int_a[IA_STD_DY].data[upd->ipass++];
5221 if(upd->int_a[IA_STD_DY].size <= upd->ipass) upd->ipass = 0;
5222 if(upd->yscan >= upd->ints[I_END_Y]) upd->ipass = 0;
5223 }
5224
5225 return 0;
5226 }
5227
5228 /* ------------------------------------------------------------------- */
5229 /* upd_open_wrtescp2: ESC/P2 Writer intended for ESC . 1 commands */
5230 /* ------------------------------------------------------------------- */
5231
5232 private int
upd_open_wrtescp2(upd_device * udev)5233 upd_open_wrtescp2(upd_device *udev)
5234 {
5235 const upd_p upd = udev->upd;
5236 int error = 0;
5237 float pixels_per_inch = 360.0;
5238
5239 /** Analyze (and optionally adjust) the BOP-Sequence */
5240 if(0 < upd->strings[S_BEGIN].size) { /* BOP-Checker */
5241 int i,state = 0,value = 0;
5242 byte *bp = (byte *) upd_cast(upd->strings[S_BEGIN].data);
5243 for(i = 0; i < upd->strings[S_BEGIN].size; ++i) {
5244 switch(state) {
5245 case 0:
5246 if(0x1b == bp[i]) state = 1;
5247 break;
5248 case 1:
5249 if('(' == bp[i]) state = 2;
5250 else state = 0;
5251 break;
5252 case 2:
5253 switch(bp[i]) {
5254 case 'U': state = 3; break; /* Printer-Resolution */
5255 case 'C': state = 6; break; /* Page-Length */
5256 case 'c': state = 10; break; /* Top/Bottom Margin */
5257 default: state = 0; break;
5258 }
5259 break;
5260 case 3:
5261 if(1 == bp[i]) state = 4;
5262 else state = 0;
5263 break;
5264 case 4:
5265 if(0 == bp[i]) state = 5;
5266 else state = 0;
5267 break;
5268 case 5:
5269 pixels_per_inch = 3600.0 / (float) bp[i];
5270 state = 0;
5271 break;
5272 case 6:
5273 if(2 == bp[i]) state = 7;
5274 else state = 0;
5275 break;
5276 case 7:
5277 if(0 == bp[i]) state = 8;
5278 else state = 0;
5279 break;
5280 case 8:
5281 if(B_PAGELENGTH & upd->flags) {
5282 value = (int)(0.5 + udev->height
5283 * pixels_per_inch / udev->y_pixels_per_inch);
5284 bp[i] = value & 0xff;
5285 }
5286 state = 9;
5287 break;
5288 case 9:
5289 if(B_PAGELENGTH & upd->flags) {
5290 bp[i] = (value>>8) & 0xff;
5291 }
5292 state = 0;
5293 break;
5294 case 10:
5295 if(4 == bp[i]) state = 11;
5296 else state = 0;
5297 break;
5298 case 11:
5299 if(0 == bp[i]) state = 12;
5300 else state = 0;
5301 break;
5302 case 12:
5303 if(B_TOPMARGIN & upd->flags) {
5304 value = (int)(dev_t_margin(udev) * pixels_per_inch);
5305 bp[i] = value & 0xff;
5306 }
5307 state = 13;
5308 break;
5309 case 13:
5310 if(B_TOPMARGIN & upd->flags) {
5311 bp[i] = (value>>8) & 0xff;
5312 }
5313 state = 14;
5314 break;
5315 case 14:
5316 if(B_BOTTOMMARGIN & upd->flags) {
5317 value = (int)(0.5 + udev->height
5318 * pixels_per_inch / udev->y_pixels_per_inch
5319 - dev_b_margin(udev) * pixels_per_inch);
5320 bp[i] = value & 0xff;
5321 }
5322 state = 15;
5323 break;
5324 case 15:
5325 if(B_BOTTOMMARGIN & upd->flags) {
5326 bp[i] = (value>>8) & 0xff;
5327 }
5328 state = 0;
5329 break;
5330 }
5331 }
5332 } /* BOP-Checker */
5333
5334 /** Create Y-Move-Command, if not given */
5335 if(0 == upd->strings[S_YMOVE].size) {
5336 byte *bp;
5337 UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_YMOVE]);
5338 UPD_MM_GET_ARRAY(udev->memory, bp,5);
5339 upd->strings[S_YMOVE].data = bp;
5340 upd->strings[S_YMOVE].size = 5;
5341 *bp++ = 0x1b; /* ESC */
5342 *bp++ = '(';
5343 *bp++ = upd->flags & B_YABS ? 'V' : 'v';
5344 *bp++ = 2;
5345 *bp++ = 0;
5346 }
5347
5348 /** X-Positioning must be set too, sometimes */
5349 if((1 < upd->ints[I_XSTEP]) && (0 == upd->strings[S_XSTEP].size)) {
5350
5351 #if UPD_MESSAGES & UPD_M_WARNING
5352 errprintf(
5353 "ESC/P2-Open: XSTEP-Command required for XSTEP=%d\n",
5354 upd->ints[I_XSTEP]);
5355 #endif
5356 error = -1;
5357
5358 } else if((1 < upd->ints[I_NXPASS] ) &&
5359 (0 == upd->strings[S_XMOVE].size) &&
5360 (0 == upd->strings[S_XSTEP].size) ) {
5361 byte *bp;
5362 int ratio;
5363
5364 ratio = (int)((udev->y_pixels_per_inch + 0.5) / udev->x_pixels_per_inch);
5365
5366 if(0 == upd->ints[I_XSTEP]) { /* Adjust scale-factor too! */
5367 if(ratio > 1) upd->ints[I_XSTEP] = -ratio;
5368 } else { /* Adjust scale-factor too! */
5369 ratio = -upd->ints[I_XSTEP];
5370 }
5371
5372 if(2 == upd->ints[I_NXPASS]) { /* Use a relative Step */
5373
5374 UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_XSTEP]);
5375 UPD_MM_GET_ARRAY(udev->memory, bp,4);
5376 upd->strings[S_XSTEP].size = 4;
5377 upd->strings[S_XSTEP].data = bp;
5378 *bp++ = 0x1b;
5379 *bp++ = '\\';
5380 *bp++ = ratio & 0xff;
5381 *bp++ = (ratio>>8) & 0xff;
5382
5383 } else { /* Use relative or absolute Move */
5384
5385 UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_XMOVE]);
5386 UPD_MM_GET_ARRAY(udev->memory, bp,2);
5387 upd->strings[S_XMOVE].size = 2;
5388 upd->strings[S_XMOVE].data = bp;
5389 *bp++ = 0x1b;
5390 *bp++ = upd->flags & B_XABS ? '$' : '\\';
5391
5392 }
5393 }
5394
5395 /* Check the Nozzle Map parameters and set some defaults */
5396 /* Used a switch construct in case FMT_ESCNMXY is added later */
5397 switch(upd->choice[C_FORMAT]){
5398 case FMT_ESCNMY:
5399 /* RowsPerPass */
5400 if( 0 == upd->ints[I_ROWS] ){
5401 upd->ints[I_ROWS] = 1;
5402 }
5403 /* PatternRepeat */
5404 if( 0 == upd->ints[I_PATRPT] ){
5405 upd->ints[I_PATRPT] = 1;
5406 }
5407 /* RowMask - default is all 1's */
5408 if( upd->ints[I_PATRPT] != upd->int_a[IA_ROWMASK].size ) {
5409 int i, *bp;
5410 UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_ROWMASK]);
5411 UPD_MM_GET_ARRAY(udev->memory, bp,upd->ints[I_PATRPT]);
5412 upd->int_a[IA_ROWMASK].size = upd->ints[I_PATRPT];
5413 upd->int_a[IA_ROWMASK].data = bp;
5414 for (i = 0 ; i < upd->ints[I_PATRPT] ; i++){
5415 *bp++ = 1; /* black */
5416 }
5417 }
5418 /* MaskScanOffset - default is 0-patternRepeat */
5419 if( upd->ints[I_PATRPT] != upd->int_a[IA_SCNOFS].size ) {
5420 int i, *bp;
5421 UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_SCNOFS]);
5422 UPD_MM_GET_ARRAY(udev->memory, bp,upd->ints[I_PATRPT]);
5423 upd->int_a[IA_SCNOFS].size = upd->ints[I_PATRPT];
5424 upd->int_a[IA_SCNOFS].data = bp;
5425 for (i = 0 ; i < upd->ints[I_PATRPT] ; i++){
5426 *bp++ = i;
5427 }
5428 }
5429 break;
5430 case FMT_ESCP2Y:
5431 case FMT_ESCP2XY:
5432 /* Nozzle map parameters are not valid for these formats
5433 so ignore them*/
5434 break;
5435 }
5436
5437
5438 /** If there is neither a writecomp nor a setcomp-command, generate both */
5439 if((0 == upd->string_a[SA_WRITECOMP].size) &&
5440 (0 == upd->string_a[SA_SETCOMP].size ) ) { /* Default-commands */
5441 byte *bp;
5442 gs_param_string *ap;
5443 int i;
5444
5445 if(4 == upd->ocomp) { /* Establish Component-Selection */
5446 UPD_MM_DEL_APARAM(udev->memory, upd->string_a[SA_SETCOMP]);
5447 UPD_MM_GET_ARRAY(udev->memory, ap,4);
5448 upd->string_a[SA_SETCOMP].data = ap;
5449 upd->string_a[SA_SETCOMP].size = 4;
5450 for(i = 0; i < 4; ++i) {
5451 UPD_MM_GET_ARRAY(udev->memory, bp,3);
5452 ap[i].size = 3;
5453 ap[i].data = bp;
5454 *bp++ = 0x1b;
5455 *bp++ = 'r';
5456 switch(((updcomp_p)upd->valptr[i])->cmap) { /* use COMPORDER! */
5457 case 0: *bp++ = 0; break; /* Black */
5458 case 1: *bp++ = 2; break; /* Cyan */
5459 case 2: *bp++ = 1; break; /* Magenta */
5460 case 3: *bp++ = 4; break; /* Yellow */
5461 } /* use COMPORDER! */
5462 }
5463 } /* Establish Component-Selection */
5464
5465 UPD_MM_DEL_APARAM(udev->memory, upd->string_a[SA_WRITECOMP]);
5466 UPD_MM_GET_ARRAY(udev->memory, ap,upd->ocomp);
5467 upd->string_a[SA_WRITECOMP].data = ap;
5468 upd->string_a[SA_WRITECOMP].size = upd->ncomp;
5469 for(i = 0; i < upd->ocomp; ++i) {
5470 UPD_MM_GET_ARRAY(udev->memory, bp,6);
5471 ap[i].size = 6;
5472 ap[i].data = bp;
5473 *bp++ = 0x1b;
5474 *bp++ = '.';
5475 *bp++ = 1; /* RLE */
5476 switch(upd->choice[C_FORMAT]){
5477 case FMT_ESCP2Y:
5478 case FMT_ESCP2XY:
5479 *bp++ = (byte)(3600.0 * upd->ints[I_NYPASS] /
5480 udev->y_pixels_per_inch + 0.5);
5481 *bp++ = (byte)(3600.0 * upd->ints[I_NXPASS] /
5482 udev->x_pixels_per_inch + 0.5);
5483 *bp++ = upd->ints[I_PINS2WRITE];
5484 break;
5485 case FMT_ESCNMY:
5486 /*
5487 *bp++ = 3600.0 / udev->y_pixels_per_inch + 0.5;
5488 *bp++ = 3600.0 / udev->x_pixels_per_inch + 0.5;
5489 */
5490 *bp++ = 10; /* needs to always be this for esc300 */
5491 *bp++ = 10;
5492 *bp++ = upd->ints[I_ROWS];
5493 break;
5494 }
5495 }
5496 } /* Default-commands */
5497
5498 /** SA_WRITECOMP must be valid */
5499 if(upd->ocomp > upd->string_a[SA_WRITECOMP].size) {
5500 #if UPD_MESSAGES & UPD_M_WARNING
5501 errprintf(
5502 "ESC/P2-Open: WRITECOMP-Commands must be given\n");
5503 #endif
5504 error = -1;
5505 }
5506
5507 /** Check Validity of X-Pass */
5508 switch(upd->choice[C_FORMAT]) {
5509 case FMT_ESCP2Y:
5510 if(1 < upd->ints[I_NXPASS]) {
5511 #if UPD_MESSAGES & UPD_M_WARNING
5512 errprintf(
5513 "ESC/P2-Open: FMT_ESCP2Y cannot handle multiple X-Passes\n");
5514 #endif
5515 error = -1;
5516 } else {
5517 upd->writer = upd_wrtescp2;
5518 }
5519 break;
5520 case FMT_ESCP2XY:
5521 upd->writer = upd_wrtescp2x;
5522 upd->nlimits = upd->ints[I_NXPASS];
5523 #if UPD_MESSAGES & UPD_M_WARNING
5524 if(1 == upd->ints[I_NXPASS])
5525 errprintf(
5526 "ESC/P2-Open: FMT_ESCP2XY should not be used with 1X-Pass\n");
5527 #endif
5528 break;
5529 case FMT_ESCNMY:
5530 if(1 < upd->ints[I_NXPASS]) {
5531 #if UPD_MESSAGES & UPD_M_WARNING
5532 errprintf(
5533 "ESC/P2-Open: FMT_ESCNMY cannot handle multiple X-Passes\n");
5534 #endif
5535 error = -1;
5536 } else {
5537 upd->writer = upd_wrtescnm;
5538 }
5539 break;
5540 default:
5541 #if UPD_MESSAGES & UPD_M_WARNING
5542 errprintf(
5543 "ESC/P2-Open: %d is not a ESC/P2-Format\n",
5544 upd->choice[C_FORMAT]);
5545 #endif
5546 error = - 1;
5547 break;
5548 }
5549
5550
5551 /**
5552 If all this is correct, it's time to compute the size of the output-buffer.
5553 It must hold:
5554 1. Y-Positioning
5555 2. X-Positioning
5556 3. Component-Selection
5557 4. The Raster-Command
5558 5. The Data
5559 */
5560 if(0 <= error) {
5561 int32_t i,noutbuf,need;
5562 /* Y-Positioning */
5563 if(0 < upd->strings[S_YMOVE].size) {
5564 noutbuf = upd->strings[S_YMOVE].size + 2;
5565 } else {
5566 int nmax = upd->pheight;
5567 if( 1 < upd->ints[I_YSTEP]) nmax /= upd->ints[I_YSTEP];
5568 else if(-1 > upd->ints[I_YSTEP]) nmax *= -upd->ints[I_YSTEP];
5569 noutbuf = 2 * upd->strings[S_SETLF].size + 2;
5570 noutbuf += nmax/255 + 1;
5571 }
5572
5573 if(1 < upd->ints[I_YSTEP])
5574 noutbuf += (upd->ints[I_YSTEP]-1) * upd->strings[S_YSTEP].size;
5575
5576 /* X-Positioning */
5577 if(0 == upd->strings[S_XMOVE].size) {
5578 noutbuf += 1; /* The CR */
5579 noutbuf += (upd->ints[I_NXPASS]-1) * upd->strings[S_XSTEP].size;
5580 } else {
5581 noutbuf += upd->strings[S_XMOVE].size + 2;
5582
5583 if(1 < upd->ints[I_XSTEP])
5584 noutbuf += (upd->ints[I_XSTEP]-1) * upd->strings[S_XSTEP].size;
5585 }
5586
5587 /* Component-Selection */
5588 if(0 < upd->string_a[SA_SETCOMP].size) {
5589 need = 0;
5590 for(i = 0; i < upd->ocomp; ++i)
5591 if(need < upd->string_a[SA_SETCOMP].data[i].size)
5592 need = upd->string_a[SA_SETCOMP].data[i].size;
5593 noutbuf += need;
5594 }
5595
5596 /* The Raster-Command */
5597 need = 0;
5598 for(i = 0; i < upd->ocomp; ++i)
5599 if(need < upd->string_a[SA_WRITECOMP].data[i].size)
5600 need = upd->string_a[SA_WRITECOMP].data[i].size;
5601 noutbuf += need + 2;
5602
5603 /* The Data */
5604 noutbuf += 2*upd->nbytes + (upd->nbytes + 127) / 128;
5605
5606 upd->noutbuf = noutbuf;
5607 error = 1;
5608 }
5609
5610 return error;
5611 }
5612
5613 /* ------------------------------------------------------------------- */
5614 /* upd_wrtescp2: Write a pass */
5615 /* ------------------------------------------------------------------- */
5616
5617 private int
upd_wrtescp2(upd_p upd,FILE * out)5618 upd_wrtescp2(upd_p upd, FILE *out)
5619 {
5620 int pinbot,pin,pintop,xbegin,x,xend,icomp,ybegin,yend,y,ioutbuf,n;
5621 byte *obytes;
5622 updscan_p scan;
5623
5624 /** Determine the number of pins to write */
5625
5626 if(upd->yscan < upd->ints[I_BEG_Y]) {
5627 pintop = 0;
5628 pinbot = upd->int_a[IA_BEGBOT].data[upd->ipass];
5629 } else if(upd->yscan >= upd->ints[I_END_Y]) {
5630 pinbot = upd->ints[I_PINS2WRITE];
5631 pintop = pinbot - upd->int_a[IA_ENDTOP].data[upd->ipass];
5632 } else {
5633 pintop = 0;
5634 pinbot = upd->ints[I_PINS2WRITE];
5635 }
5636
5637 ybegin = pintop * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
5638 yend = pinbot * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
5639
5640 /** Determine Width of this scan */
5641
5642 xbegin = upd->nbytes;
5643 xend = -1;
5644
5645 for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Pin-testloop */
5646
5647 if(0 > y) continue; /* Inserted Scanlines */
5648
5649 scan = upd->scnbuf[y & upd->scnmsk];
5650
5651 for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Compwise test */
5652 obytes = scan[icomp].bytes;
5653
5654 for(x = 0; x < xbegin && !obytes[x]; x++);
5655 if(x < xbegin) xbegin = x;
5656
5657 if(x < upd->nbytes) {
5658 for(x = upd->nbytes-1; x > xend && !obytes[x]; x--);
5659 if(x > xend) xend = x;
5660 }
5661 } /* Compwise test */
5662
5663 } /* Pin-testloop */
5664
5665 if(xbegin <= xend) { /* Some data to write */
5666
5667 ioutbuf = 0;
5668
5669 if(0 == upd->strings[S_XMOVE].size) xbegin = 0;
5670
5671 /*
5672 * Adjust the Printers Y-Position
5673 */
5674 if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
5675 if(B_YABS & upd->flags) y = upd->yscan + upd->ints[I_YOFS];
5676 else y = upd->yscan - upd->yprinter;
5677
5678 if( 1 < upd->ints[I_YSTEP]) {
5679 n = y / upd->ints[I_YSTEP]; /* Major-Steps */
5680 y -= n * upd->ints[I_YSTEP]; /* Minor-Steps */
5681 } else if(-1 > upd->ints[I_YSTEP]) {
5682 n = y * -upd->ints[I_YSTEP]; /* May this work? */
5683 y = 0;
5684 } else {
5685 n = y;
5686 y = 0;
5687 }
5688
5689 if(n) { /* Coarse Positioning */
5690 memcpy(upd->outbuf+ioutbuf,
5691 upd->strings[S_YMOVE].data,upd->strings[S_YMOVE].size);
5692 ioutbuf += upd->strings[S_YMOVE].size;
5693
5694 upd->outbuf[ioutbuf++] = n & 0xff;
5695 upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5696
5697 } /* Coarse Positioning */
5698
5699 if(0 < upd->strings[S_YSTEP].size) {
5700 while(y--) {
5701 memcpy(upd->outbuf+ioutbuf,
5702 upd->strings[S_YSTEP].data,
5703 upd->strings[S_YSTEP].size);
5704 ioutbuf += upd->strings[S_YSTEP].size;
5705 }
5706 }
5707
5708 upd->yprinter = upd->yscan;
5709 } /* Adjust Y-Position */
5710 /*
5711 * Now write the required components
5712 */
5713 for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Component-Print */
5714 /*
5715 * First check, wether this Component needs printing
5716 */
5717 for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Comp-Test */
5718 if(0 > y) continue;
5719 obytes = upd->scnbuf[y & upd->scnmsk][icomp].bytes;
5720 for(x = xbegin; x <= xend && !obytes[x]; ++x);
5721 if( x <= xend) break;
5722 } /* Comp-Test */
5723 if(y >= yend) continue; /* Component not required */
5724 /*
5725 * Select the Component
5726 */
5727 if((0 < upd->string_a[SA_SETCOMP].size) &&
5728 (upd->icomp != icomp ) ) { /* Selection enabled */
5729 upd->icomp = icomp;
5730 if(0 < upd->string_a[SA_SETCOMP].data[icomp].size) {
5731 memcpy(upd->outbuf+ioutbuf,
5732 upd->string_a[SA_SETCOMP].data[icomp].data,
5733 upd->string_a[SA_SETCOMP].data[icomp].size);
5734 ioutbuf += upd->string_a[SA_SETCOMP].data[icomp].size;
5735 }
5736 } /* Selection enabled */
5737 /*
5738 * Establish the X-Position
5739 */
5740 if(xbegin != upd->xprinter) {
5741
5742 if(0 == upd->strings[S_XMOVE].size) {
5743
5744 upd->outbuf[ioutbuf++] = '\r';
5745 upd->xprinter = 0;
5746 n = 0;
5747 x = 0;
5748
5749 } else {
5750
5751 if(B_XABS & upd->flags) n = x = xbegin + upd->ints[I_XOFS];
5752 else n = x = xbegin - upd->xprinter;
5753
5754 if( 1 < upd->ints[I_XSTEP]) {
5755 if(0 > n) {
5756 n -= upd->ints[I_XSTEP];
5757 x -= n;
5758 }
5759 if(n) n /= upd->ints[I_XSTEP]; /* Major-Steps */
5760 if(x) x %= upd->ints[I_XSTEP]; /* Minor-Steps */
5761
5762 } else if(-1 > upd->ints[I_XSTEP]) {
5763 n *= -upd->ints[I_XSTEP]; /* May this work? */
5764 x = 0;
5765 }
5766
5767 if(n) { /* Adjust X-Position */
5768
5769 memcpy(upd->outbuf+ioutbuf,
5770 upd->strings[S_XMOVE].data,
5771 upd->strings[S_XMOVE].size);
5772 ioutbuf += upd->strings[S_XMOVE].size;
5773
5774 upd->outbuf[ioutbuf++] = n & 0xff;
5775 upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5776
5777 } /* Adjust X-Position */
5778
5779 }
5780
5781 if(x && 0 < upd->strings[S_XSTEP].size) { /* Fine-Adjust X */
5782 while(x--) {
5783 memcpy(upd->outbuf+ioutbuf,
5784 upd->strings[S_XSTEP].data,
5785 upd->strings[S_XSTEP].size);
5786 ioutbuf += upd->strings[S_XSTEP].size;
5787 }
5788 } /* Fine-Adjust X */
5789 }
5790 upd->xprinter = xend+1;
5791
5792 /*
5793 * Send the Write-Command
5794 */
5795 if(0 < upd->string_a[SA_WRITECOMP].data[icomp].size) {
5796 memcpy(upd->outbuf+ioutbuf,
5797 upd->string_a[SA_WRITECOMP].data[icomp].data,
5798 upd->string_a[SA_WRITECOMP].data[icomp].size);
5799 ioutbuf += upd->string_a[SA_WRITECOMP].data[icomp].size;
5800 }
5801 n = xend + 1 - xbegin;
5802 upd->outbuf[ioutbuf++] = (n<<3) & 255;
5803 upd->outbuf[ioutbuf++] = (n>>5) & 255;
5804 /*
5805 * Set the Pixels
5806 */
5807 for(pin = 0; pin < pintop; ++pin) {
5808 ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
5809 fwrite(upd->outbuf,1,ioutbuf,out);
5810 ioutbuf = 0;
5811 }
5812
5813 for(y = ybegin; 0 > y; y += upd->ints[I_NYPASS]) {
5814 ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
5815 fwrite(upd->outbuf,1,ioutbuf,out);
5816 ioutbuf = 0;
5817 }
5818
5819 for(; y < yend; y += upd->ints[I_NYPASS]) {
5820 ioutbuf += upd_rle(upd->outbuf+ioutbuf,
5821 upd->scnbuf[y & upd->scnmsk][icomp].bytes+xbegin,n);
5822 fwrite(upd->outbuf,1,ioutbuf,out);
5823 ioutbuf = 0;
5824 }
5825
5826 for(pin = pinbot; pin < upd->ints[I_PINS2WRITE]; ++pin) {
5827 ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
5828 fwrite(upd->outbuf,1,ioutbuf,out);
5829 ioutbuf = 0;
5830 }
5831 } /* Component-Print */
5832 } /* Some data to write */
5833
5834 /** Advance counters in upd, change modi */
5835 if(upd->yscan < upd->ints[I_BEG_Y]) {
5836 upd->yscan += upd->int_a[IA_BEG_DY].data[upd->ipass++];
5837 if( upd->ints[I_BEG_Y] <= upd->yscan) upd->ipass = 0;
5838 else if(upd->int_a[IA_BEG_DY].size <= upd->ipass) upd->ipass = 0;
5839 } else if(upd->yscan >= upd->ints[I_END_Y]) {
5840 upd->yscan += upd->int_a[IA_END_DY].data[upd->ipass++];
5841 if(upd->int_a[IA_END_DY].size <= upd->ipass) upd->ipass = 0;
5842 } else {
5843 upd->yscan += upd->int_a[IA_STD_DY].data[upd->ipass++];
5844 if(upd->int_a[IA_STD_DY].size <= upd->ipass) upd->ipass = 0;
5845 if(upd->yscan >= upd->ints[I_END_Y]) upd->ipass = 0;
5846 }
5847
5848 return 0;
5849 }
5850
5851 /* ------------------------------------------------------------------- */
5852 /* upd_wrtescnm: Write a pass */
5853 /* ------------------------------------------------------------------- */
5854
5855 /*GR copied from upd_wrtescp2 and modified */
5856
5857 private int
upd_wrtescnm(upd_p upd,FILE * out)5858 upd_wrtescnm(upd_p upd, FILE *out)
5859 {
5860 int pinbot,pin,pintop,xbegin,x,xend,icomp,ybegin,yend,y,ioutbuf,n;
5861 int irow,imask,iyofs;
5862 byte *obytes;
5863 updscan_p scan;
5864
5865 /** Determine the number of pins to write */
5866
5867 if(upd->yscan < upd->ints[I_BEG_Y]) {
5868 pintop = 0;
5869 pinbot = upd->int_a[IA_BEGBOT].data[upd->ipass];
5870 } else if(upd->yscan >= upd->ints[I_END_Y]) {
5871 pinbot = upd->ints[I_PINS2WRITE];
5872 pintop = pinbot - upd->int_a[IA_ENDTOP].data[upd->ipass];
5873 } else {
5874 pintop = 0;
5875 pinbot = upd->ints[I_PINS2WRITE];
5876 }
5877
5878 ybegin = pintop * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
5879 yend = pinbot * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
5880
5881 /** Determine Width of this scan */
5882
5883 xbegin = upd->nbytes;
5884 xend = -1;
5885
5886 for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Pin-testloop */
5887
5888 if(0 > y) continue; /* Inserted Scanlines */
5889
5890 scan = upd->scnbuf[y & upd->scnmsk];
5891
5892 for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Compwise test */
5893 obytes = scan[icomp].bytes;
5894
5895 for(x = 0; x < xbegin && !obytes[x]; x++);
5896 if(x < xbegin) xbegin = x;
5897
5898 if(x < upd->nbytes) {
5899 for(x = upd->nbytes-1; x > xend && !obytes[x]; x--);
5900 if(x > xend) xend = x;
5901 }
5902 } /* Compwise test */
5903 } /* Pin-testloop */
5904
5905 if(xbegin <= xend) { /* Some data to write */
5906
5907 ioutbuf = 0;
5908
5909 if(0 == upd->strings[S_XMOVE].size) xbegin = 0;
5910
5911 /*
5912 * Adjust the Printers Y-Position
5913 */
5914 if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
5915 if(B_YABS & upd->flags) y = upd->yscan + upd->ints[I_YOFS];
5916 else y = upd->yscan - upd->yprinter;
5917
5918 if( 1 < upd->ints[I_YSTEP]) {
5919 n = y / upd->ints[I_YSTEP]; /* Major-Steps */
5920 y -= n * upd->ints[I_YSTEP]; /* Minor-Steps */
5921 } else if(-1 > upd->ints[I_YSTEP]) {
5922 n = y * -upd->ints[I_YSTEP]; /* May this work? */
5923 y = 0;
5924 } else {
5925 n = y;
5926 y = 0;
5927 }
5928
5929 if(n) { /* Coarse Positioning */
5930 memcpy(upd->outbuf+ioutbuf,
5931 upd->strings[S_YMOVE].data,upd->strings[S_YMOVE].size);
5932 ioutbuf += upd->strings[S_YMOVE].size;
5933
5934 upd->outbuf[ioutbuf++] = n & 0xff;
5935 upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5936
5937 } /* Coarse Positioning */
5938
5939 if(0 < upd->strings[S_YSTEP].size) {
5940 while(y--) {
5941 memcpy(upd->outbuf+ioutbuf,
5942 upd->strings[S_YSTEP].data,
5943 upd->strings[S_YSTEP].size);
5944 ioutbuf += upd->strings[S_YSTEP].size;
5945 }
5946 }
5947
5948 upd->yprinter = upd->yscan;
5949 } /* Adjust Y-Position */
5950 /*
5951 * Now write the required components
5952 */
5953
5954 /*
5955 * Select the Component
5956 *
5957 * Always issue an ESC 'r' 0 - don't know why - that
5958 * is just what the windows driver does.
5959 */
5960 icomp=0;
5961 if((0 < upd->string_a[SA_SETCOMP].size) /* &&
5962 (upd->icomp != icomp ) */) { /* Selection enabled */
5963 upd->icomp = icomp;
5964 if(0 < upd->string_a[SA_SETCOMP].data[icomp].size) {
5965 memcpy(upd->outbuf+ioutbuf,
5966 upd->string_a[SA_SETCOMP].data[icomp].data,
5967 upd->string_a[SA_SETCOMP].data[icomp].size);
5968 ioutbuf += upd->string_a[SA_SETCOMP].data[icomp].size;
5969 }
5970 } /* Selection enabled */
5971 /*
5972 * Establish the X-Position
5973 */
5974 if(xbegin != upd->xprinter) {
5975
5976 if(0 == upd->strings[S_XMOVE].size) {
5977
5978 upd->outbuf[ioutbuf++] = '\r';
5979 upd->xprinter = 0;
5980 n = 0;
5981 x = 0;
5982
5983 } else {
5984
5985 if(B_XABS & upd->flags) n = x = xbegin + upd->ints[I_XOFS];
5986 else n = x = xbegin - upd->xprinter;
5987
5988 if( 1 < upd->ints[I_XSTEP]) {
5989 if(0 > n) {
5990 n -= upd->ints[I_XSTEP];
5991 x -= n;
5992 }
5993 if(n) n /= upd->ints[I_XSTEP]; /* Major-Steps */
5994 if(x) x %= upd->ints[I_XSTEP]; /* Minor-Steps */
5995
5996 } else if(-1 > upd->ints[I_XSTEP]) {
5997 n *= -upd->ints[I_XSTEP]; /* May this work? */
5998 x = 0;
5999 }
6000
6001 if(n) { /* Adjust X-Position */
6002
6003 memcpy(upd->outbuf+ioutbuf,
6004 upd->strings[S_XMOVE].data,
6005 upd->strings[S_XMOVE].size);
6006 ioutbuf += upd->strings[S_XMOVE].size;
6007
6008 upd->outbuf[ioutbuf++] = n & 0xff;
6009 upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
6010
6011 } /* Adjust X-Position */
6012
6013 }
6014
6015 if(x && 0 < upd->strings[S_XSTEP].size) { /* Fine-Adjust X */
6016 while(x--) {
6017 memcpy(upd->outbuf+ioutbuf,
6018 upd->strings[S_XSTEP].data,
6019 upd->strings[S_XSTEP].size);
6020 ioutbuf += upd->strings[S_XSTEP].size;
6021 }
6022 } /* Fine-Adjust X */
6023 }
6024 upd->xprinter = xend+1;
6025
6026 /*
6027 * Send the Write-Command - the default is ESC '.' 1
6028 */
6029 if(0 < upd->string_a[SA_WRITECOMP].data[icomp].size) {
6030 memcpy(upd->outbuf+ioutbuf,
6031 upd->string_a[SA_WRITECOMP].data[icomp].data,
6032 upd->string_a[SA_WRITECOMP].data[icomp].size);
6033 ioutbuf += upd->string_a[SA_WRITECOMP].data[icomp].size;
6034 }
6035 n = xend + 1 - xbegin;
6036 upd->outbuf[ioutbuf++] = (n<<3) & 255;
6037 upd->outbuf[ioutbuf++] = (n>>5) & 255;
6038 /*
6039 * Set the Pixels
6040 */
6041 irow=0; /* row counter for output data */
6042
6043 /* pins at the top of the head that don't print */
6044 for(pin = 0; pin < pintop; ++pin) {
6045 int i;
6046 for(i=0 ; i < upd->ints[I_PATRPT]; i++){
6047 if(irow >= upd->ints[I_ROWS]) break;
6048 ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6049 fwrite(upd->outbuf,1,ioutbuf,out);
6050 irow++;
6051 ioutbuf = 0;
6052 }
6053 }
6054
6055 /* I'm not really sure what this does */
6056 /* it looks like we're filling in empty rows */
6057 for(y = ybegin; 0 > y; y += upd->ints[I_NYPASS]) {
6058
6059 int i;
6060 for(i=0 ; i < upd->ints[I_PATRPT]; i++){
6061 if(irow >= upd->ints[I_ROWS]) break;
6062 ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6063 fwrite(upd->outbuf,1,ioutbuf,out);
6064 ioutbuf = 0;
6065 irow++;
6066 }
6067 }
6068
6069 for(; y < yend; y += upd->ints[I_NYPASS]) {
6070
6071 int i,masklen=upd->ints[I_PATRPT],yinc=0;
6072
6073 for(i=0 ; (i < upd->ints[I_PATRPT]); i++){
6074 if(irow >= upd->ints[I_ROWS]) break;
6075 imask = irow%masklen;
6076 icomp = upd->int_a[IA_ROWMASK].data[imask];
6077 if(icomp == 0) {
6078 ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6079 } else {
6080 --icomp;
6081 iyofs = upd->int_a[IA_SCNOFS].data[imask];
6082 ioutbuf += upd_rle(upd->outbuf+ioutbuf,
6083 upd->scnbuf[(y+iyofs) & upd->scnmsk][icomp].bytes+xbegin,n);
6084 yinc+=upd->ints[I_NYPASS];
6085 }
6086 fwrite(upd->outbuf,1,ioutbuf,out);
6087 ioutbuf = 0;
6088 irow++;
6089 }
6090
6091 if (upd->ints[I_NYPASS] < upd->ints[I_PATRPT]) {
6092 y+=yinc;
6093 if (y > 0)
6094 y-=upd->ints[I_NYPASS];
6095 }
6096 }
6097
6098 /* I think this is the pins at the bottom of the head that don't print */
6099 for(pin = pinbot; pin < upd->ints[I_PINS2WRITE]; ++pin) {
6100 int i;
6101 for(i=0 ; i < upd->ints[I_PATRPT]; i++){
6102 if(irow >= upd->ints[I_ROWS]) break;
6103 ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6104 fwrite(upd->outbuf,1,ioutbuf,out);
6105 ioutbuf = 0;
6106 irow++;
6107 }
6108 }
6109
6110 /* pad empty rows that haven't been filled yet*/
6111 if (irow < upd->ints[I_ROWS]) {
6112 for( ; irow < upd->ints[I_ROWS]; irow++){
6113 ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6114 fwrite(upd->outbuf,1,ioutbuf,out);
6115 ioutbuf = 0;
6116 }
6117 }
6118
6119 } /* Some data to write */
6120
6121 /** Advance counters in upd, change modi */
6122 if(upd->yscan < upd->ints[I_BEG_Y]) {
6123 upd->yscan += upd->int_a[IA_BEG_DY].data[upd->ipass++];
6124 if( upd->ints[I_BEG_Y] <= upd->yscan) upd->ipass = 0;
6125 else if(upd->int_a[IA_BEG_DY].size <= upd->ipass) upd->ipass = 0;
6126 } else if(upd->yscan >= upd->ints[I_END_Y]) {
6127 upd->yscan += upd->int_a[IA_END_DY].data[upd->ipass++];
6128 if(upd->int_a[IA_END_DY].size <= upd->ipass) upd->ipass = 0;
6129 } else {
6130 upd->yscan += upd->int_a[IA_STD_DY].data[upd->ipass++];
6131 if(upd->int_a[IA_STD_DY].size <= upd->ipass) upd->ipass = 0;
6132 if(upd->yscan >= upd->ints[I_END_Y]) upd->ipass = 0;
6133 }
6134
6135 return 0;
6136 }
6137
6138
6139 /* ------------------------------------------------------------------- */
6140 /* upd_wrtescp2x: Write an ESC/P2-pass with X-Weaving */
6141 /* ------------------------------------------------------------------- */
6142
6143 private int
upd_wrtescp2x(upd_p upd,FILE * out)6144 upd_wrtescp2x(upd_p upd, FILE *out)
6145 {
6146 int pinbot,pin,pintop,xbegin,x,xend,icomp,ybegin,yend,y,ioutbuf,n,ixpass;
6147 byte *obytes,bit;
6148 updscan_p scan;
6149
6150 /** Determine the number of pins to write */
6151
6152 if(upd->yscan < upd->ints[I_BEG_Y]) {
6153 ixpass = upd->int_a[IA_BEG_IX].data[upd->ipass];
6154 pintop = 0;
6155 pinbot = upd->int_a[IA_BEGBOT].data[upd->ipass];
6156 } else if(upd->yscan >= upd->ints[I_END_Y]) {
6157 ixpass = upd->int_a[IA_END_IX].data[upd->ipass];
6158 pinbot = upd->ints[I_PINS2WRITE];
6159 pintop = pinbot - upd->int_a[IA_ENDTOP].data[upd->ipass];
6160 } else {
6161 ixpass = upd->int_a[IA_STD_IX].data[upd->ipass];
6162 pintop = 0;
6163 pinbot = upd->ints[I_PINS2WRITE];
6164 }
6165
6166 ybegin = pintop * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
6167 yend = pinbot * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
6168
6169 /** Determine Width of this scan */
6170
6171 xbegin = upd->pwidth;
6172 xend = -1;
6173
6174 for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Pin-testloop */
6175
6176 if(0 > y) continue; /* Inserted Scanlines */
6177
6178 scan = upd->scnbuf[y & upd->scnmsk];
6179
6180 for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Compwise test */
6181 if(xbegin > scan[icomp].xbegin[ixpass])
6182 xbegin = scan[icomp].xbegin[ixpass];
6183 if(xend < scan[icomp].xend[ ixpass])
6184 xend = scan[icomp].xend[ ixpass];
6185 } /* Compwise test */
6186
6187 } /* Pin-testloop */
6188
6189 if(xbegin <= xend) { /* Some data to write */
6190
6191 ioutbuf = upd->nbytes;
6192
6193 if(0 == upd->strings[S_XMOVE].size) xbegin = ixpass;
6194
6195 /*
6196 * Adjust the Printers Y-Position
6197 */
6198 if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
6199 if(B_YABS & upd->flags) y = upd->yscan + upd->ints[I_YOFS];
6200 else y = upd->yscan - upd->yprinter;
6201
6202 if( 1 < upd->ints[I_YSTEP]) {
6203 n = y / upd->ints[I_YSTEP]; /* Major-Steps */
6204 y -= n * upd->ints[I_YSTEP]; /* Minor-Steps */
6205 } else if(-1 > upd->ints[I_YSTEP]) {
6206 n = y * -upd->ints[I_YSTEP]; /* May this work? */
6207 y = 0;
6208 } else {
6209 n = y;
6210 y = 0;
6211 }
6212
6213 if(n) { /* Coarse Positioning */
6214 memcpy(upd->outbuf+ioutbuf,
6215 upd->strings[S_YMOVE].data,upd->strings[S_YMOVE].size);
6216 ioutbuf += upd->strings[S_YMOVE].size;
6217
6218 upd->outbuf[ioutbuf++] = n & 0xff;
6219 upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
6220
6221 } /* Coarse Positioning */
6222
6223 if(0 < upd->strings[S_YSTEP].size) {
6224 while(y--) {
6225 memcpy(upd->outbuf+ioutbuf,
6226 upd->strings[S_YSTEP].data,
6227 upd->strings[S_YSTEP].size);
6228 ioutbuf += upd->strings[S_YSTEP].size;
6229 }
6230 }
6231
6232 upd->yprinter = upd->yscan;
6233 } /* Adjust Y-Position */
6234
6235 /*
6236 * Now write the required components
6237 */
6238 for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Component-Print */
6239 /*
6240 * First check, wether this Component needs printing
6241 */
6242 for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Comp-Test */
6243 if(0 > y) continue;
6244 scan = upd->scnbuf[y & upd->scnmsk]+icomp;
6245 if(0 <= scan->xend[ixpass]) break;
6246 } /* Comp-Test */
6247 if(y >= yend) continue; /* Component not required */
6248 /*
6249 * Select the Component
6250 */
6251 if((0 < upd->string_a[SA_SETCOMP].size) &&
6252 (upd->icomp != icomp ) ) { /* Selection enabled */
6253 upd->icomp = icomp;
6254 if(0 < upd->string_a[SA_SETCOMP].data[icomp].size) {
6255 memcpy(upd->outbuf+ioutbuf,
6256 upd->string_a[SA_SETCOMP].data[icomp].data,
6257 upd->string_a[SA_SETCOMP].data[icomp].size);
6258 ioutbuf += upd->string_a[SA_SETCOMP].data[icomp].size;
6259 }
6260 } /* Selection enabled */
6261 /*
6262 * Establish the X-Position
6263 */
6264 if(xbegin != upd->xprinter) {
6265
6266 if(0 == upd->strings[S_XMOVE].size) {
6267
6268 upd->outbuf[ioutbuf++] = '\r';
6269 upd->xprinter = 0;
6270 n = 0;
6271 x = ixpass;
6272
6273 } else {
6274
6275 if(B_XABS & upd->flags) n = x = xbegin + upd->ints[I_XOFS];
6276 else n = x = xbegin - upd->xprinter;
6277
6278 if( 1 < upd->ints[I_XSTEP]) {
6279 if(0 > n) {
6280 n -= upd->ints[I_XSTEP];
6281 x -= n;
6282 }
6283 if(n) n /= upd->ints[I_XSTEP]; /* Major-Steps */
6284 if(x) x %= upd->ints[I_XSTEP]; /* Minor-Steps */
6285
6286 } else if(-1 > upd->ints[I_XSTEP]) {
6287 n *= -upd->ints[I_XSTEP]; /* May this work? */
6288 x = 0;
6289 }
6290
6291 if(n) { /* Adjust X-Position */
6292
6293 memcpy(upd->outbuf+ioutbuf,
6294 upd->strings[S_XMOVE].data,
6295 upd->strings[S_XMOVE].size);
6296 ioutbuf += upd->strings[S_XMOVE].size;
6297
6298 upd->outbuf[ioutbuf++] = n & 0xff;
6299 upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
6300
6301 } /* Adjust X-Position */
6302
6303 }
6304
6305 if(x && 0 < upd->strings[S_XSTEP].size) { /* Fine-Adjust X */
6306 while(x--) {
6307 memcpy(upd->outbuf+ioutbuf,
6308 upd->strings[S_XSTEP].data,
6309 upd->strings[S_XSTEP].size);
6310 ioutbuf += upd->strings[S_XSTEP].size;
6311 }
6312 } /* Fine-Adjust X */
6313 }
6314 upd->xprinter = xend+1;
6315
6316 /*
6317 * Send the Write-Command
6318 */
6319 if(0 < upd->string_a[SA_WRITECOMP].data[icomp].size) {
6320 memcpy(upd->outbuf+ioutbuf,
6321 upd->string_a[SA_WRITECOMP].data[icomp].data,
6322 upd->string_a[SA_WRITECOMP].data[icomp].size);
6323 ioutbuf += upd->string_a[SA_WRITECOMP].data[icomp].size;
6324 }
6325 n = ((xend - xbegin) / upd->ints[I_NXPASS] + 8) & ~7;
6326 upd->outbuf[ioutbuf++] = n & 255;
6327 upd->outbuf[ioutbuf++] = (n>>8) & 255;
6328 n >>= 3;
6329 /*
6330 * Set the Pixels
6331 */
6332 for(pin = 0; pin < pintop; ++pin) {
6333 ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6334 fwrite(upd->outbuf+upd->nbytes,1,ioutbuf-upd->nbytes,out);
6335 ioutbuf = upd->nbytes;
6336 }
6337
6338 for(y = ybegin; 0 > y; y += upd->ints[I_NYPASS]) {
6339 ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6340 fwrite(upd->outbuf+upd->nbytes,1,ioutbuf-upd->nbytes,out);
6341 ioutbuf = upd->nbytes;
6342 }
6343
6344 for(; y < yend; y += upd->ints[I_NYPASS]) {
6345 byte * ibytes = upd->scnbuf[y & upd->scnmsk][icomp].bytes;
6346 obytes = upd->outbuf;
6347 memset(obytes,0,upd->nbytes);
6348 bit = 0x80;
6349 for(x = xbegin; x <= xend; x += upd->ints[I_NXPASS]) {
6350 if(ibytes[x>>3] & (0x80 >> (x & 7))) *obytes |= bit;
6351 if(!(bit >>= 1)) { obytes++; bit = 0x80; }
6352 }
6353 ioutbuf += upd_rle(upd->outbuf+ioutbuf,upd->outbuf,n);
6354 fwrite(upd->outbuf+upd->nbytes,1,ioutbuf-upd->nbytes,out);
6355 ioutbuf = upd->nbytes;
6356 }
6357
6358 for(pin = pinbot; pin < upd->ints[I_PINS2WRITE]; ++pin) {
6359 ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6360 fwrite(upd->outbuf+upd->nbytes,1,ioutbuf-upd->nbytes,out);
6361 ioutbuf = upd->nbytes;
6362 }
6363 } /* Component-Print */
6364 } /* Some data to write */
6365
6366 /** Advance counters in upd, change modi */
6367
6368 if(upd->yscan < upd->ints[I_BEG_Y]) {
6369 upd->yscan += upd->int_a[IA_BEG_DY].data[upd->ipass++];
6370 if( upd->ints[I_BEG_Y] <= upd->yscan) upd->ipass = 0;
6371 else if(upd->int_a[IA_BEG_DY].size <= upd->ipass) upd->ipass = 0;
6372 } else if(upd->yscan >= upd->ints[I_END_Y]) {
6373 upd->yscan += upd->int_a[IA_END_DY].data[upd->ipass++];
6374 if(upd->int_a[IA_END_DY].size <= upd->ipass) upd->ipass = 0;
6375 } else {
6376 upd->yscan += upd->int_a[IA_STD_DY].data[upd->ipass++];
6377 if(upd->int_a[IA_STD_DY].size <= upd->ipass) upd->ipass = 0;
6378 if(upd->yscan >= upd->ints[I_END_Y]) upd->ipass = 0;
6379 }
6380
6381 return 0;
6382 }
6383
6384 /* ------------------------------------------------------------------- */
6385 /* upd_rle: The Runlength-Compressor */
6386 /* ------------------------------------------------------------------- */
6387
6388 private int
upd_rle(byte * out,const byte * in,int nbytes)6389 upd_rle(byte *out,const byte *in,int nbytes)
6390 {
6391
6392 int used = 0;
6393 int crun,cdata;
6394 byte run;
6395
6396 if(in != NULL) { /* Data present */
6397
6398 crun = 1;
6399
6400 while(nbytes > 0) { /* something to compress */
6401
6402 run = in[0];
6403
6404 while((nbytes > crun) && (run == in[crun])) if(++crun == 128) break;
6405
6406 if((crun > 2) || (crun == nbytes)) { /* use this run */
6407
6408 *out++ = (257 - crun) & 0xff; *out++ = run; used += 2;
6409
6410 nbytes -= crun; in += crun;
6411 crun = 1;
6412
6413 } else { /* ignore this run */
6414
6415 for(cdata = crun; (nbytes > cdata) && (crun < 4);) {
6416 if(run == in[cdata]) crun += 1;
6417 else run = in[cdata], crun = 1;
6418 if(++cdata == 128) break;
6419 }
6420
6421 if(crun < 3) crun = 0; /* ignore trailing run */
6422 else cdata -= crun;
6423
6424 *out++ = cdata-1; used++;
6425 memcpy(out,in,cdata); used += cdata; out += cdata;
6426
6427 nbytes -= cdata; in += cdata;
6428
6429 } /* use/ignore run */
6430
6431 } /* something to compress */
6432
6433 } else { /* Empty scans to fill bands */
6434
6435 while(nbytes > 0) {
6436 crun = nbytes > 128 ? 128 : nbytes;
6437 nbytes -= crun;
6438 *out++ = (257 - crun) & 0xff;
6439 *out++ = 0;
6440 used += 2;
6441 }
6442 } /* Data present or empty */
6443 return used;
6444 }
6445
6446 /* ------------------------------------------------------------------- */
6447 /* upd_open_wrtrtl: Basic HP-RTL Writer */
6448 /* ------------------------------------------------------------------- */
6449
6450 private int
upd_open_wrtrtl(upd_device * udev)6451 upd_open_wrtrtl(upd_device *udev)
6452 {
6453 const upd_p upd = udev->upd;
6454 int error = 0;
6455
6456 /** Adjust the Raster-Width */
6457
6458 if(0 < upd->strings[S_BEGIN].size) { /* BOP-Checker */
6459
6460 int i,j,state;
6461 char cv[24];
6462 byte *bp;
6463 uint ncv,nbp;
6464
6465 j = -1;
6466 state = 0;
6467 for(i = 0; i < upd->strings[S_BEGIN].size; ++i) {
6468 const int c = upd->strings[S_BEGIN].data[i];
6469
6470 switch(state) {
6471 /* ----- any character */
6472 case 0:
6473 if( c == 0x1b) state = 1; /* ESC */
6474 break;
6475
6476 /* ----- last was ESC */
6477 case 1:
6478 if( c == 0x2a) state = 2; /* ESC * */
6479 else if( c == 0x25) state = 5; /* ESC % */
6480 else state = 0;
6481 break;
6482
6483 /* ----- got ESC * */
6484 case 2:
6485 j = i; /* This character is not part of the replaced text */
6486 if( c == 0x72) state = 3; /* ESC * r */
6487 else if( c == 0x74) state = 4; /* ESC * t */
6488 else state = 0;
6489 break;
6490
6491 /* ----- got ESC * r */
6492 /* Pagewidth and Pagelength might be replaced */
6493 case 3:
6494
6495 if( (B_PAGEWIDTH & upd->flags) &&
6496 ((c == 0x73) || (c == 0x53)) ) { /* esc * r # S */
6497
6498 sprintf(cv,"%d",upd->pwidth);
6499 ncv = strlen(cv);
6500
6501 nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6502 UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6503
6504 if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6505 memcpy(bp+j+1, cv,ncv);
6506 memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6507 upd->strings[S_BEGIN].size-i);
6508 i = j+1+ncv;
6509 UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6510 upd->strings[S_BEGIN].data = bp;
6511 upd->strings[S_BEGIN].size = nbp;
6512
6513 } else if((B_PAGELENGTH & upd->flags) &&
6514 ((c == 0x74) || (c == 0x54)) ) { /* esc * r # T */
6515
6516 sprintf(cv,"%d",upd->pheight);
6517 ncv = strlen(cv);
6518
6519 nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6520 UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6521
6522 if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6523 memcpy(bp+j+1, cv,ncv);
6524 memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6525 upd->strings[S_BEGIN].size-i);
6526 i = j+1+ncv;
6527 UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6528 upd->strings[S_BEGIN].data = bp;
6529 upd->strings[S_BEGIN].size = nbp;
6530
6531 }
6532
6533 if( (0x40 < c) && (c < 0x5b)) state = 0; /* Term. cmd. */
6534 else if(!((0x2f < c) && (c < 0x3a))) j = i; /* Non-Number */
6535
6536 break;
6537
6538 /* ----- got ESC * t */
6539 /* Resolution might be replaced */
6540 case 4: /* esc * t */
6541
6542 if( (B_RESOLUTION & upd->flags) &&
6543 ((c == 0x72) || (c == 0x52)) ) { /* esc * t # R */
6544
6545 sprintf(cv,"%d",(int)
6546 ((udev->y_pixels_per_inch < udev->x_pixels_per_inch ?
6547 udev->x_pixels_per_inch : udev->y_pixels_per_inch)
6548 +0.5));
6549 ncv = strlen(cv);
6550
6551 nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6552 UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6553
6554 if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6555 memcpy(bp+j+1, cv,ncv);
6556 memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6557 upd->strings[S_BEGIN].size-i);
6558 i = j+1+ncv;
6559 UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6560 upd->strings[S_BEGIN].data = bp;
6561 upd->strings[S_BEGIN].size = nbp;
6562
6563 }
6564
6565 if( (0x40 < c) && (c < 0x5b)) state = 0; /* Term. cmd. */
6566 else if(!((0x2f < c) && (c < 0x3a))) j = i; /* Non-Number */
6567
6568 break;
6569
6570 case 5: /* ESC % - 1 2 3 4 5 X */
6571 if( c == 0x2d) state = 6; /* ESC % - */
6572 else state = 0;
6573 break;
6574
6575 case 6: /* ESC % - 1 2 3 4 5 X */
6576 if( c == 0x31) state = 7; /* ESC % - 1 */
6577 else state = 0;
6578 break;
6579
6580 case 7: /* ESC % - 1 2 3 4 5 X */
6581 if( c == 0x32) state = 8; /* ESC % - 1 2 */
6582 else state = 0;
6583 break;
6584
6585 case 8: /* ESC % - 1 2 3 4 5 X */
6586 if( c == 0x33) state = 9; /* ESC % - 1 2 3 */
6587 else state = 0;
6588 break;
6589
6590 case 9: /* ESC % - 1 2 3 4 5 X */
6591 if( c == 0x34) state = 10; /* ESC % - 1 2 3 4 */
6592 else state = 0;
6593 break;
6594
6595 case 10: /* ESC % - 1 2 3 4 5 X */
6596 if( c == 0x35) state = 11; /* ESC % - 1 2 3 4 5 */
6597 else state = 0;
6598 break;
6599
6600 case 11: /* ESC % - 1 2 3 4 5 X */
6601 if( c == 0x58) state = 12; /* ESC % - 1 2 3 4 5 X */
6602 else state = 0;
6603 break;
6604
6605 case 12: /* PJL-BOL: @ P J L ws */
6606 if( c == 0x40) state = 13; /* @ */
6607 else state = 0;
6608 break;
6609
6610 case 13: /* PJL-BOL @ P J L ws */
6611 if( c == 0x50) state = 14; /* @ P */
6612 else state = 0;
6613 break;
6614
6615 case 14: /* PJL-BOL @ P J L ws */
6616 if( c == 0x4a) state = 15; /* @ P J */
6617 else state = 0;
6618 break;
6619
6620 case 15: /* PJL-BOL @ P J L ws */
6621 if( c == 0x4c) state = 16; /* @ P J L */
6622 else state = 0;
6623 break;
6624
6625 case 16: /* PJL-BOL @ P J L ws */
6626 if((c == 0x20) || (c == 0x09)) state = 19; /* @ P J L ws */
6627 else if( c == 0x0d ) state = 17;
6628 else if( c == 0x0a ) state = 12;
6629 else state = 0; /* PJL-Error */
6630 break;
6631
6632 case 17: /* PJL-EOL */
6633 if( c == 0x0a) state = 12; /* Next PJL-Command */
6634 else state = 0; /* PJL-Error */
6635 break;
6636
6637 case 18: /* PJL-Eatup: Expect Newline */
6638 if( c == 0x0a) state = 12;
6639 break;
6640
6641 case 19: /* Begin of PJL-Command */
6642 if( (c == 0x53) || (c == 0x73)) state = 20; /* S E T*/
6643 else if( c == 0x0a ) state = 12; /* BOL */
6644 else if( c == 0x0d ) state = 17;
6645 break;
6646
6647 case 20: /* PJL-Set: S E T */
6648 if( (c == 0x45) || (c == 0x65)) state = 21; /* S E */
6649 else if( c == 0x0a ) state = 12; /* BOL */
6650 else state = 18;
6651 break;
6652
6653 case 21: /* PJL-Set: S E T */
6654 if( (c == 0x54) || (c == 0x74)) state = 22; /* S E T */
6655 else if( c == 0x0a ) state = 12; /* BOL */
6656 else state = 18;
6657 break;
6658
6659 case 22: /* PJL-Set: S E T ws */
6660 if( (c == 0x20) || (c == 0x09)) state = 23; /* S E T ws */
6661 else if( c == 0x0a ) state = 12; /* BOL */
6662 else state = 18;
6663 break;
6664
6665 case 23: /* PJL-Set: S E T ws */
6666 if( (c == 0x50) || (c == 0x70)) state = 24; /* set paper... */
6667 else if((c == 0x52) || (c == 0x72)) state = 41; /* set resolution */
6668 else if( c == 0x0a ) state = 12; /* BOL */
6669 else state = 18;
6670 break;
6671
6672 case 24: /* PJL-Set: set paper... */
6673 if( (c == 0x41) || (c == 0x61)) state = 25; /* set pa */
6674 else if( c == 0x0a ) state = 12; /* BOL */
6675 else state = 18;
6676 break;
6677
6678 case 25: /* PJL-Set: set paper... */
6679 if( (c == 0x50) || (c == 0x70)) state = 26; /* set pap */
6680 else if( c == 0x0a ) state = 12; /* BOL */
6681 else state = 18;
6682 break;
6683
6684 case 26: /* PJL-Set: set paper... */
6685 if( (c == 0x45) || (c == 0x65)) state = 27; /* set pape */
6686 else if( c == 0x0a ) state = 12; /* BOL */
6687 else state = 18;
6688 break;
6689
6690 case 27: /* PJL-Set: set paper... */
6691 if( (c == 0x52) || (c == 0x72)) state = 28; /* set paper */
6692 else if( c == 0x0a ) state = 12; /* BOL */
6693 else state = 18;
6694 break;
6695
6696 case 28: /* PJL-Set: set paper? */
6697 if( (c == 0x4c) || (c == 0x6c)) state = 29; /* set paperlength */
6698 else if((c == 0x57) || (c == 0x77)) state = 36; /* set paperwidth */
6699 else if( c == 0x0a ) state = 12; /* BOL */
6700 else state = 18;
6701 break;
6702
6703 case 29: /* PJL: set paperlength */
6704 if( (c == 0x45) || (c == 0x65)) state = 30; /* set paperle */
6705 else if( c == 0x0a ) state = 12; /* BOL */
6706 else state = 18;
6707 break;
6708
6709 case 30: /* PJL: set paperlength */
6710 if( (c == 0x4e) || (c == 0x6e)) state = 31; /* set paperlen */
6711 else if( c == 0x0a ) state = 12; /* BOL */
6712 else state = 18;
6713 break;
6714
6715 case 31: /* PJL: set paperlength */
6716 if( (c == 0x47) || (c == 0x67)) state = 32; /* set paperleng */
6717 else if( c == 0x0a ) state = 12; /* BOL */
6718 else state = 18;
6719 break;
6720
6721 case 32: /* PJL: set paperlength */
6722 if( (c == 0x54) || (c == 0x74)) state = 33; /* set paperlengt */
6723 else if( c == 0x0a ) state = 12; /* BOL */
6724 else state = 18;
6725 break;
6726
6727 case 33: /* PJL: set paperlength */
6728 if( (c == 0x48) || (c == 0x68)) state = 34; /* set paperlength */
6729 else if( c == 0x0a ) state = 12; /* BOL */
6730 else state = 18;
6731 break;
6732
6733 case 34: /* PJL: set paperlength */
6734 j = i; /* This character is not part of the replaced text */
6735 if( c == 0x3d ) state = 51; /* set paperlength */
6736 else if( c == 0x0a ) state = 12; /* BOL */
6737 else if((c != 0x20) && (c != 0x09)) state = 18;
6738 break;
6739
6740 case 51: /* PJL: set paperlength = ws */
6741 if( c == 0x0a) state = 12;
6742 else if((c == 0x20) || (c == 0x09)) j = i;
6743 else if(( 0x30 > c) || ( c > 0x39)) state = 18;
6744 else state = 35;
6745 break;
6746
6747 case 35: /* PJL: set paperlength */
6748 if((0x30 > c) || (c > 0x39)) { /* End of number */
6749
6750 if(B_PAGELENGTH & upd->flags) { /* insert new number */
6751
6752 sprintf(cv,"%d",(int)
6753 (720.0 * udev->height / udev->y_pixels_per_inch + 0.5));
6754 ncv = strlen(cv);
6755
6756 nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6757 UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6758
6759 if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6760 memcpy(bp+j+1, cv,ncv);
6761 memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6762 upd->strings[S_BEGIN].size-i);
6763 i = j+1+ncv;
6764 UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6765 upd->strings[S_BEGIN].data = bp;
6766 upd->strings[S_BEGIN].size = nbp;
6767 } /* insert new number */
6768
6769 if( c == 0x0a ) state = 12;
6770 else state = 18;
6771 }
6772 break;
6773
6774 case 36: /* PJL: set paperwidth */
6775 if( (c == 0x49) || (c == 0x69)) state = 37; /* set paperwi */
6776 else if( c == 0x0a ) state = 12; /* BOL */
6777 else state = 18;
6778 break;
6779
6780 case 37: /* PJL: set paperwidth */
6781 if( (c == 0x44) || (c == 0x64)) state = 38; /* set paperwid */
6782 else if( c == 0x0a ) state = 12; /* BOL */
6783 else state = 18;
6784 break;
6785
6786 case 38: /* PJL: set paperwidth */
6787 if( (c == 0x54) || (c == 0x74)) state = 39; /* set paperwidt */
6788 else if( c == 0x0a ) state = 12; /* BOL */
6789 else state = 18;
6790 break;
6791
6792 case 39: /* PJL: set paperwidth */
6793 if( (c == 0x48) || (c == 0x68)) state = 52; /* set paperwidth */
6794 else if( c == 0x0a ) state = 12; /* BOL */
6795 else state = 18;
6796 break;
6797
6798 case 52: /* PJL: set paperwidth */
6799 j = i; /* This character is not part of the replaced text */
6800 if( c == 0x3d ) state = 53; /* set paperwidth */
6801 else if( c == 0x0a ) state = 12; /* BOL */
6802 else if((c != 0x20) && (c != 0x09)) state = 18;
6803 break;
6804
6805 case 53: /* PJL: set paperwidth = ws */
6806 if( c == 0x0a) state = 12;
6807 else if((c == 0x20) || (c == 0x09)) j = i;
6808 else if(( 0x30 > c) || ( c > 0x39)) state = 18;
6809 else state = 40;
6810 break;
6811
6812 case 40: /* PJL: set paperlength */
6813 if((0x30 > c) || (c > 0x39)) { /* End of number */
6814
6815 if(B_PAGEWIDTH & upd->flags) { /* insert new number */
6816
6817 sprintf(cv,"%d",(int)
6818 (720.0 * udev->width / udev->x_pixels_per_inch + 0.5));
6819 ncv = strlen(cv);
6820
6821 nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6822 UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6823
6824 if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6825 memcpy(bp+j+1, cv,ncv);
6826 memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6827 upd->strings[S_BEGIN].size-i);
6828 i = j+1+ncv;
6829 UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6830 upd->strings[S_BEGIN].data = bp;
6831 upd->strings[S_BEGIN].size = nbp;
6832 } /* insert new number */
6833
6834 if( c == 0x0a ) state = 12;
6835 else state = 18;
6836 }
6837 break;
6838
6839 case 41: /* PJL: set resolution */
6840 if( (c == 0x45) || (c == 0x65)) state = 42; /* set re */
6841 else if( c == 0x0a ) state = 12; /* BOL */
6842 else state = 18;
6843 break;
6844
6845 case 42: /* PJL: set resolution */
6846 if( (c == 0x53) || (c == 0x73)) state = 43; /* set res */
6847 else if( c == 0x0a ) state = 12; /* BOL */
6848 else state = 18;
6849 break;
6850
6851 case 43: /* PJL: set resolution */
6852 if( (c == 0x4f) || (c == 0x6f)) state = 44; /* set reso */
6853 else if( c == 0x0a ) state = 12; /* BOL */
6854 else state = 18;
6855 break;
6856
6857 case 44: /* PJL: set resolution */
6858 if( (c == 0x4c) || (c == 0x6c)) state = 45; /* set resol */
6859 else if( c == 0x0a ) state = 12; /* BOL */
6860 else state = 18;
6861 break;
6862
6863 case 45: /* PJL: set resolution */
6864 if( (c == 0x55) || (c == 0x75)) state = 46; /* set resolu */
6865 else if( c == 0x0a ) state = 12; /* BOL */
6866 else state = 18;
6867 break;
6868
6869 case 46: /* PJL: set resolution */
6870 if( (c == 0x54) || (c == 0x74)) state = 47; /* set resolut */
6871 else if( c == 0x0a ) state = 12; /* BOL */
6872 else state = 18;
6873 break;
6874
6875 case 47: /* PJL: set resolution */
6876 if( (c == 0x49) || (c == 0x69)) state = 48; /* set resoluti */
6877 else if( c == 0x0a ) state = 12; /* BOL */
6878 else state = 18;
6879 break;
6880
6881 case 48: /* PJL: set resolution */
6882 if( (c == 0x4f) || (c == 0x6f)) state = 49; /* set resolutio */
6883 else if( c == 0x0a ) state = 12; /* BOL */
6884 else state = 18;
6885 break;
6886
6887 case 49: /* PJL: set resolution */
6888 if( (c == 0x4e) || (c == 0x6e)) state = 54; /* set resolution */
6889 else if( c == 0x0a ) state = 12; /* BOL */
6890 else state = 18;
6891 break;
6892
6893 case 54: /* PJL: set resolution */
6894 j = i; /* This character is not part of the replaced text */
6895 if( c == 0x3d ) state = 55; /* set resolution */
6896 else if( c == 0x0a ) state = 12; /* BOL */
6897 else if((c != 0x20) && (c != 0x09)) state = 18;
6898 break;
6899
6900 case 55: /* PJL: set resolution = ws */
6901 if( c == 0x0a) state = 12;
6902 else if((c == 0x20) || (c == 0x09)) j = i;
6903 else if(( 0x30 > c) || ( c > 0x39)) state = 18;
6904 else state = 50;
6905 break;
6906
6907 case 50: /* PJL: set resolution */
6908 if((0x30 > c) || (c > 0x39)) { /* End of number */
6909
6910 if(B_RESOLUTION & upd->flags) { /* insert new number */
6911
6912 sprintf(cv,"%d",(int)
6913 ((udev->y_pixels_per_inch < udev->x_pixels_per_inch ?
6914 udev->x_pixels_per_inch : udev->y_pixels_per_inch)
6915 +0.5));
6916 ncv = strlen(cv);
6917
6918 nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6919 UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6920
6921 if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6922 memcpy(bp+j+1, cv,ncv);
6923 memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6924 upd->strings[S_BEGIN].size-i);
6925 i = j+1+ncv;
6926 UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6927 upd->strings[S_BEGIN].data = bp;
6928 upd->strings[S_BEGIN].size = nbp;
6929 } /* insert new number */
6930
6931 if( c == 0x0a ) state = 12;
6932 else state = 18;
6933 }
6934 break;
6935
6936 default:
6937 #if UPD_MESSAGES & UPD_M_ERROR
6938 errprintf("UNIPRINT-Coding error, wrrtl, state = %d\n",state);
6939 #endif
6940 state = 0;
6941 break;
6942 }
6943 }
6944 } /* BOP-Checker */
6945
6946 /** SA_WRITECOMP must be valid */
6947 if(upd->ocomp > upd->string_a[SA_WRITECOMP].size) {
6948 #if UPD_MESSAGES & UPD_M_WARNING
6949 errprintf(
6950 "PCL-Open: WRITECOMP-Commands must be given\n");
6951 #endif
6952 error = -1;
6953 }
6954
6955 /**
6956 If all this is correct, it's time to compute the size of the output-buffer.
6957 It must hold:
6958 1. Y-Positioning
6959 2. Component-Data
6960 */
6961 if(0 <= error) {
6962 int32_t ny,noutbuf;
6963 char tmp[16];
6964
6965 if(0 < upd->strings[S_YMOVE].size) {
6966 sprintf(tmp,"%d",upd->pheight);
6967 ny = upd->strings[S_YMOVE].size + strlen(tmp);
6968 } else {
6969 ny = 1 + upd->string_a[SA_WRITECOMP].data[upd->ocomp-1].size;
6970 ny *= upd->pheight;
6971 }
6972
6973 noutbuf = upd->nbytes + (upd->nbytes + 127) / 128;
6974
6975 if(ny > noutbuf) noutbuf = ny;
6976 noutbuf += 16;
6977
6978 if((0 < noutbuf) && (noutbuf <= INT_MAX)) {
6979 upd->noutbuf = noutbuf;
6980 upd->writer = upd_wrtrtl;
6981 error = 1;
6982 } else {
6983 error = -1;
6984 #if UPD_MESSAGES & UPD_M_WARNING
6985 errprintf(
6986 "PCL-Open: %ld is unreasonable size of Outputbuffer\n",
6987 (long) noutbuf);
6988 #endif
6989 }
6990 }
6991
6992 return error;
6993 }
6994
6995 /* ------------------------------------------------------------------- */
6996 /* upd_wrtrtl: Write a pass */
6997 /* ------------------------------------------------------------------- */
6998
6999 private int
upd_wrtrtl(upd_p upd,FILE * out)7000 upd_wrtrtl(upd_p upd, FILE *out)
7001 {
7002 const updscan_p scan = upd->scnbuf[upd->yscan & upd->scnmsk];
7003
7004 int x,xend,icomp,ioutbuf;
7005 byte *data;
7006
7007 /** Determine Width of this scan */
7008
7009 xend = -1;
7010 for(icomp = 0; icomp < upd->ocomp; ++icomp) {
7011
7012 data = scan[icomp].bytes;
7013
7014 for(x = upd->nbytes-1; 0 <= x; --x) if(data[x]) break;
7015 if(x > xend) xend = x;
7016 }
7017
7018 if(0 <= xend) { /* Some data to write */
7019
7020 ioutbuf = 0;
7021 xend += 1;
7022 /*
7023 * Adjust the Printers Y-Position
7024 */
7025 if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
7026 if(1 < upd->strings[S_YMOVE].size) {
7027 sprintf((char *)upd->outbuf+ioutbuf,
7028 (const char *) upd->strings[S_YMOVE].data,
7029 upd->yscan - upd->yprinter);
7030 ioutbuf += strlen((char *)upd->outbuf+ioutbuf);
7031 } else {
7032 while(upd->yscan > upd->yprinter) {
7033 for(icomp = 0; icomp < upd->ocomp; ++icomp) {
7034 sprintf((char *)upd->outbuf+ioutbuf,
7035 (const char *) upd->string_a[SA_WRITECOMP].data[icomp].data,0);
7036 ioutbuf += strlen((char *)upd->outbuf+ioutbuf);
7037 }
7038 fwrite(upd->outbuf,1,ioutbuf,out);
7039 ioutbuf = 0;
7040 upd->yprinter += 1;
7041 }
7042 }
7043 upd->yprinter = upd->yscan;
7044 fwrite(upd->outbuf,1,ioutbuf,out);
7045 ioutbuf = 0;
7046 } /* Adjust Y-Position */
7047 /*
7048 * Now write the all! components
7049 */
7050 for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Component-Print */
7051 data = scan[icomp].bytes;
7052 for(x = 0; x <= xend; ++x) if(data[x]) break;
7053 if(x <= xend) {
7054 ioutbuf = upd_rle(upd->outbuf,scan[icomp].bytes,xend);
7055 fprintf(out,
7056 (const char *)upd->string_a[SA_WRITECOMP].data[icomp].data,ioutbuf);
7057 fwrite(upd->outbuf,1,ioutbuf,out);
7058 } else {
7059 fprintf(out,
7060 (const char *)upd->string_a[SA_WRITECOMP].data[icomp].data,0);
7061 }
7062 }
7063
7064 upd->yprinter += 1;
7065
7066 } /* Some data to write */
7067
7068 /** Advance scan by one */
7069
7070 upd->yscan += 1;
7071
7072 return 0;
7073 }
7074
7075 /* ------------------------------------------------------------------- */
7076 /* upd_open_wrtcanon: Basic Canon Extended Mode Writer (hr) */
7077 /* ------------------------------------------------------------------- */
7078
7079 private int
upd_open_wrtcanon(upd_device * udev)7080 upd_open_wrtcanon(upd_device *udev)
7081 {
7082 const upd_p upd = udev->upd;
7083 int error = 0;
7084
7085 /* max length of one printer line */
7086 upd->noutbuf = upd->nbytes + (upd->nbytes + 127) / 128;
7087 upd->writer = upd_wrtcanon;
7088 error = 1;
7089
7090 return error;
7091 }
7092
7093 /* ------------------------------------------------------------------- */
7094 /* upd_wrtcanon: Write a pass (hr) */
7095 /* ------------------------------------------------------------------- */
7096
7097 #define LOW(b) ((b)&0xFF)
7098 #define HIGH(b) ((b)>>8)
7099 #define ESC 0x1B
7100 #define CR 0x0D
7101
7102 private int
upd_wrtcanon(upd_p upd,FILE * out)7103 upd_wrtcanon(upd_p upd, FILE *out)
7104 {
7105 const updscan_p scan = upd->scnbuf[upd->yscan & upd->scnmsk];
7106
7107 int x, xend, icomp, ioutbuf, step, ioutbuf1;
7108 byte *data;
7109
7110
7111 /* Check length of the printable date */
7112 xend = -1;
7113 for(icomp = 0; icomp < upd->ocomp; ++icomp) {
7114 data = scan[icomp].bytes;
7115
7116 for(x = upd->nbytes-1; 0 <= x; --x) if(data[x]) break;
7117
7118 if(x > xend) xend = x;
7119 }
7120
7121 /* If some date to print */
7122 if(0 <= xend) { /* Some data to write */
7123 ioutbuf = 0;
7124 xend += 1;
7125
7126 /* Perform vertical tab */
7127 if(upd->yscan != upd->yprinter) {
7128 step = upd->yscan - upd->yprinter;
7129
7130 fputc(ESC, out);
7131 fputc('(', out);
7132 fputc('e', out);
7133 fputc(2, out);
7134 fputc(0, out);
7135 fputc(HIGH(step), out);
7136 fputc(LOW(step), out);
7137
7138 upd->yprinter = upd->yscan;
7139 }
7140
7141 for(icomp = 0; icomp < upd->ocomp; ++icomp) {
7142
7143 /* Are there date to print for the selected color component */
7144 data = scan[icomp].bytes;
7145 for(x = 0; x <= xend; ++x) if(data[x]) break;
7146
7147 /* Compressing of the scan line */
7148 if(x <= xend) {
7149 ioutbuf = upd_rle(upd->outbuf, scan[icomp].bytes, xend);
7150 } else {
7151 ioutbuf = 0;
7152 }
7153
7154 ioutbuf1 = ioutbuf + 1;
7155
7156 /* prints the scan line */
7157 fputc(ESC, out);
7158 fputc('(', out);
7159 fputc('A', out);
7160 fputc(LOW(ioutbuf1), out);
7161 fputc(HIGH(ioutbuf1), out);
7162 switch(upd->ocomp) {
7163 case 1: fputc('K',out); break;
7164 case 3:
7165 case 4: fputc("YMCK"[icomp],out); break;
7166 /*
7167 * Please Note:
7168 * the validity of the NCOMP-setting should be checked
7169 * in the put_params-routine, thus the default-case is
7170 * just a matter of coding-style.
7171 */
7172 default: fputc('K',out); break;
7173 }
7174
7175 fwrite(upd->outbuf, 1, ioutbuf, out);
7176
7177 fputc(CR, out);
7178 }
7179
7180 /* Printer advances one raster line */
7181 fputc(ESC, out);
7182 fputc('(', out);
7183 fputc('e', out);
7184 fputc(2, out);
7185 fputc(0, out);
7186 fputc(HIGH(1), out);
7187 fputc(LOW(1), out);
7188
7189 upd->yprinter += 1;
7190
7191 }
7192
7193 /* Advance scan by one */
7194 upd->yscan += 1;
7195
7196 return 0;
7197 }
7198
7199
7200
7201 /* ------------------------------------------------------------------- */
7202 /* All the Pixel-Get Routines */
7203 /* ------------------------------------------------------------------- */
7204
7205 /* That bunch of Pixel-Get Routines */
7206
7207 private upd_proc_pxlget(upd_pxlgetnix); /* A Dummy */
7208
7209 private upd_proc_pxlget(upd_pxlget1f1); /* 1 Bit Forward */
7210 private upd_proc_pxlget(upd_pxlget1f2);
7211 private upd_proc_pxlget(upd_pxlget1f3);
7212 private upd_proc_pxlget(upd_pxlget1f4);
7213 private upd_proc_pxlget(upd_pxlget1f5);
7214 private upd_proc_pxlget(upd_pxlget1f6);
7215 private upd_proc_pxlget(upd_pxlget1f7);
7216 private upd_proc_pxlget(upd_pxlget1f8);
7217
7218 private upd_proc_pxlget(upd_pxlget1r1); /* 1 Bit Reverse */
7219 private upd_proc_pxlget(upd_pxlget1r2);
7220 private upd_proc_pxlget(upd_pxlget1r3);
7221 private upd_proc_pxlget(upd_pxlget1r4);
7222 private upd_proc_pxlget(upd_pxlget1r5);
7223 private upd_proc_pxlget(upd_pxlget1r6);
7224 private upd_proc_pxlget(upd_pxlget1r7);
7225 private upd_proc_pxlget(upd_pxlget1r8);
7226
7227 private upd_proc_pxlget(upd_pxlget2f1); /* 2 Bit Forward */
7228 private upd_proc_pxlget(upd_pxlget2f2);
7229 private upd_proc_pxlget(upd_pxlget2f3);
7230 private upd_proc_pxlget(upd_pxlget2f4);
7231
7232 private upd_proc_pxlget(upd_pxlget2r1); /* 2 Bit Reverse */
7233 private upd_proc_pxlget(upd_pxlget2r2);
7234 private upd_proc_pxlget(upd_pxlget2r3);
7235 private upd_proc_pxlget(upd_pxlget2r4);
7236
7237 private upd_proc_pxlget(upd_pxlget4f1); /* 4 Bit Forward */
7238 private upd_proc_pxlget(upd_pxlget4f2);
7239
7240 private upd_proc_pxlget(upd_pxlget4r1); /* 4 Bit Reverse */
7241 private upd_proc_pxlget(upd_pxlget4r2);
7242
7243 private upd_proc_pxlget(upd_pxlget8f); /* 8 Bit Forward */
7244 private upd_proc_pxlget(upd_pxlget8r); /* 8 Bit Reverse */
7245
7246 private upd_proc_pxlget(upd_pxlget16f); /* 16 Bit Forward */
7247 private upd_proc_pxlget(upd_pxlget16r); /* 16Bit Reverse */
7248
7249 private upd_proc_pxlget(upd_pxlget24f); /* 24 Bit Forward */
7250 private upd_proc_pxlget(upd_pxlget24r); /* 24 Bit Reverse */
7251
7252 private upd_proc_pxlget(upd_pxlget32f); /* 32 Bit Forward */
7253 private upd_proc_pxlget(upd_pxlget32r); /* 32 Bit Reverse */
7254
7255 /* Initialize Forward-Run */
7256
7257 private uint32_t
upd_pxlfwd(upd_p upd)7258 upd_pxlfwd(upd_p upd)
7259 {
7260 if(!(upd->pxlptr = upd->gsscan)) {
7261
7262 upd->pxlget = upd_pxlgetnix;
7263
7264 } else {
7265 switch(upd->int_a[IA_COLOR_INFO].data[1]) {
7266 case 1: upd->pxlget = upd_pxlget1f1; break;
7267 case 2: upd->pxlget = upd_pxlget2f1; break;
7268 case 4: upd->pxlget = upd_pxlget4f1; break;
7269 case 8: upd->pxlget = upd_pxlget8f; break;
7270 case 16: upd->pxlget = upd_pxlget16f; break;
7271 case 24: upd->pxlget = upd_pxlget24f; break;
7272 case 32: upd->pxlget = upd_pxlget32f; break;
7273 default:
7274 #if UPD_MESSAGES & UPD_M_ERROR
7275 errprintf("upd_pxlfwd: unsupported depth (%d)\n",
7276 upd->int_a[IA_COLOR_INFO].data[1]);
7277 #endif
7278 upd->pxlget = upd_pxlgetnix;
7279 break;
7280 }
7281 }
7282 return (uint32_t) 0;
7283 }
7284
7285 /* 1 Bit Forward */
7286
7287 private uint32_t
upd_pxlget1f1(upd_p upd)7288 upd_pxlget1f1(upd_p upd)
7289 {
7290 upd->pxlget = upd_pxlget1f2;
7291 return *upd->pxlptr & 0x80 ? (uint32_t) 1 : (uint32_t) 0;
7292 }
7293
7294 private uint32_t
upd_pxlget1f2(upd_p upd)7295 upd_pxlget1f2(upd_p upd)
7296 {
7297 upd->pxlget = upd_pxlget1f3;
7298 return *upd->pxlptr & 0x40 ? (uint32_t) 1 : (uint32_t) 0;
7299 }
7300
7301 private uint32_t
upd_pxlget1f3(upd_p upd)7302 upd_pxlget1f3(upd_p upd)
7303 {
7304 upd->pxlget = upd_pxlget1f4;
7305 return *upd->pxlptr & 0x20 ? (uint32_t) 1 : (uint32_t) 0;
7306 }
7307
7308 private uint32_t
upd_pxlget1f4(upd_p upd)7309 upd_pxlget1f4(upd_p upd)
7310 {
7311 upd->pxlget = upd_pxlget1f5;
7312 return *upd->pxlptr & 0x10 ? (uint32_t) 1 : (uint32_t) 0;
7313 }
7314
7315 private uint32_t
upd_pxlget1f5(upd_p upd)7316 upd_pxlget1f5(upd_p upd)
7317 {
7318 upd->pxlget = upd_pxlget1f6;
7319 return *upd->pxlptr & 0x08 ? (uint32_t) 1 : (uint32_t) 0;
7320 }
7321
7322 private uint32_t
upd_pxlget1f6(upd_p upd)7323 upd_pxlget1f6(upd_p upd)
7324 {
7325 upd->pxlget = upd_pxlget1f7;
7326 return *upd->pxlptr & 0x04 ? (uint32_t) 1 : (uint32_t) 0;
7327 }
7328
7329 private uint32_t
upd_pxlget1f7(upd_p upd)7330 upd_pxlget1f7(upd_p upd)
7331 {
7332 upd->pxlget = upd_pxlget1f8;
7333 return *upd->pxlptr & 0x02 ? (uint32_t) 1 : (uint32_t) 0;
7334 }
7335
7336 private uint32_t
upd_pxlget1f8(upd_p upd)7337 upd_pxlget1f8(upd_p upd)
7338 {
7339 upd->pxlget = upd_pxlget1f1;
7340 return *upd->pxlptr++ & 0x01 ? (uint32_t) 1 : (uint32_t) 0;
7341 }
7342
7343 /* 2 Bit Forward */
7344
7345 private uint32_t
upd_pxlget2f1(upd_p upd)7346 upd_pxlget2f1(upd_p upd)
7347 {
7348 upd->pxlget = upd_pxlget2f2;
7349 return ((uint32_t) (*upd->pxlptr ) & (uint32_t) 0xC0) >> 6;
7350 }
7351
7352 private uint32_t
upd_pxlget2f2(upd_p upd)7353 upd_pxlget2f2(upd_p upd)
7354 {
7355 upd->pxlget = upd_pxlget2f3;
7356 return ((uint32_t) (*upd->pxlptr ) & (uint32_t) 0x30) >> 4;
7357 }
7358
7359 private uint32_t
upd_pxlget2f3(upd_p upd)7360 upd_pxlget2f3(upd_p upd)
7361 {
7362 upd->pxlget = upd_pxlget2f4;
7363 return ((uint32_t) (*upd->pxlptr ) & (uint32_t) 0x0C) >> 2;
7364 }
7365
7366 private uint32_t
upd_pxlget2f4(upd_p upd)7367 upd_pxlget2f4(upd_p upd)
7368 {
7369 upd->pxlget = upd_pxlget2f1;
7370 return (uint32_t) (*upd->pxlptr++) & (uint32_t) 0x03;
7371 }
7372
7373
7374 /* 4 Bit Forward */
7375 private uint32_t
upd_pxlget4f1(upd_p upd)7376 upd_pxlget4f1(upd_p upd)
7377 {
7378 upd->pxlget = upd_pxlget4f2;
7379 return ((uint32_t) (*upd->pxlptr ) & (uint32_t) 0xF0) >> 4;
7380 }
7381
7382 private uint32_t
upd_pxlget4f2(upd_p upd)7383 upd_pxlget4f2(upd_p upd)
7384 {
7385 upd->pxlget = upd_pxlget4f1;
7386 return (uint32_t) (*upd->pxlptr++) & (uint32_t) 0x0F;
7387 }
7388
7389
7390 /* 8 Bit Forward */
7391 private uint32_t
upd_pxlget8f(upd_p upd)7392 upd_pxlget8f(upd_p upd)
7393 {
7394 return (uint32_t) (*upd->pxlptr++);
7395 }
7396
7397
7398 /* 16 Bit Forward */
7399 private uint32_t
upd_pxlget16f(upd_p upd)7400 upd_pxlget16f(upd_p upd)
7401 {
7402 uint32_t ci = (uint32_t) (*upd->pxlptr++) << 8;
7403 ci |= *upd->pxlptr++;
7404 return ci;
7405 }
7406
7407 /* 24 Bit Forward */
7408 private uint32_t
upd_pxlget24f(upd_p upd)7409 upd_pxlget24f(upd_p upd)
7410 {
7411 uint32_t ci = (uint32_t) (*upd->pxlptr++) << 16;
7412 ci |= (uint32_t) (*upd->pxlptr++) << 8;
7413 ci |= *upd->pxlptr++;
7414 return ci;
7415 }
7416
7417 /* 32 Bit Forward */
7418 private uint32_t
upd_pxlget32f(upd_p upd)7419 upd_pxlget32f(upd_p upd)
7420 {
7421 uint32_t ci = (uint32_t) (*upd->pxlptr++) << 24;
7422 ci |= (uint32_t) (*upd->pxlptr++) << 16;
7423 ci |= (uint32_t) (*upd->pxlptr++) << 8;
7424 ci |= *upd->pxlptr++;
7425 return ci;
7426 }
7427
7428
7429 /* Dummy-Routine */
7430
7431 private uint32_t
upd_pxlgetnix(upd_p upd)7432 upd_pxlgetnix(upd_p upd)
7433 {
7434 return (uint32_t) 0;
7435 }
7436
7437 /* Initialize Reverse-Run */
7438
7439 private uint32_t
upd_pxlrev(upd_p upd)7440 upd_pxlrev(upd_p upd)
7441 {
7442 const uint width = upd->pwidth < upd->gswidth ? upd->pwidth : upd->gswidth;
7443
7444 if(!(upd->pxlptr = upd->gsscan)) {
7445
7446 upd->pxlget = upd_pxlgetnix;
7447
7448 } else {
7449 uint32_t ofs = (uint32_t) upd->int_a[IA_COLOR_INFO].data[1] * (width-1);
7450
7451 upd->pxlptr += ofs>>3;
7452
7453 ofs &= 7;
7454
7455 switch(upd->int_a[IA_COLOR_INFO].data[1]) {
7456 case 1: switch(ofs) {
7457 case 0: upd->pxlget = upd_pxlget1r1; break;
7458 case 1: upd->pxlget = upd_pxlget1r2; break;
7459 case 2: upd->pxlget = upd_pxlget1r3; break;
7460 case 3: upd->pxlget = upd_pxlget1r4; break;
7461 case 4: upd->pxlget = upd_pxlget1r5; break;
7462 case 5: upd->pxlget = upd_pxlget1r6; break;
7463 case 6: upd->pxlget = upd_pxlget1r7; break;
7464 case 7: upd->pxlget = upd_pxlget1r8; break;
7465 } break;
7466 case 2: switch(ofs) {
7467 case 0: upd->pxlget = upd_pxlget2r1; break;
7468 case 2: upd->pxlget = upd_pxlget2r2; break;
7469 case 4: upd->pxlget = upd_pxlget2r3; break;
7470 case 6: upd->pxlget = upd_pxlget2r4; break;
7471 } break;
7472 case 4: switch(ofs) {
7473 case 0: upd->pxlget = upd_pxlget4r1; break;
7474 case 4: upd->pxlget = upd_pxlget4r2; break;
7475 } break;
7476 case 8: upd->pxlget = upd_pxlget8r; break;
7477 case 16:
7478 upd->pxlget = upd_pxlget16r;
7479 upd->pxlptr += 1;
7480 break;
7481 case 24:
7482 upd->pxlget = upd_pxlget24r;
7483 upd->pxlptr += 2;
7484 break;
7485 case 32:
7486 upd->pxlget = upd_pxlget32r;
7487 upd->pxlptr += 3;
7488 break;
7489 default:
7490 #if UPD_MESSAGES & UPD_M_ERROR
7491 errprintf("upd_pxlrev: unsupported depth (%d)\n",
7492 upd->int_a[IA_COLOR_INFO].data[1]);
7493 #endif
7494 upd->pxlget = upd_pxlgetnix;
7495 break;
7496 }
7497 }
7498 return (uint32_t) 0;
7499 }
7500
7501 /* 1 Bit Reverse */
7502
7503 private uint32_t
upd_pxlget1r1(upd_p upd)7504 upd_pxlget1r1(upd_p upd)
7505 {
7506 upd->pxlget = upd_pxlget1r8;
7507 return *upd->pxlptr-- & 0x80 ? (uint32_t) 1 : (uint32_t) 0;
7508 }
7509
7510 private uint32_t
upd_pxlget1r2(upd_p upd)7511 upd_pxlget1r2(upd_p upd)
7512 {
7513 upd->pxlget = upd_pxlget1r1;
7514 return *upd->pxlptr & 0x40 ? (uint32_t) 1 : (uint32_t) 0;
7515 }
7516
7517 private uint32_t
upd_pxlget1r3(upd_p upd)7518 upd_pxlget1r3(upd_p upd)
7519 {
7520 upd->pxlget = upd_pxlget1r2;
7521 return *upd->pxlptr & 0x20 ? (uint32_t) 1 : (uint32_t) 0;
7522 }
7523
7524 private uint32_t
upd_pxlget1r4(upd_p upd)7525 upd_pxlget1r4(upd_p upd)
7526 {
7527 upd->pxlget = upd_pxlget1r3;
7528 return *upd->pxlptr & 0x10 ? (uint32_t) 1 : (uint32_t) 0;
7529 }
7530
7531 private uint32_t
upd_pxlget1r5(upd_p upd)7532 upd_pxlget1r5(upd_p upd)
7533 {
7534 upd->pxlget = upd_pxlget1r4;
7535 return *upd->pxlptr & 0x08 ? (uint32_t) 1 : (uint32_t) 0;
7536 }
7537
7538 private uint32_t
upd_pxlget1r6(upd_p upd)7539 upd_pxlget1r6(upd_p upd)
7540 {
7541 upd->pxlget = upd_pxlget1r5;
7542 return *upd->pxlptr & 0x04 ? (uint32_t) 1 : (uint32_t) 0;
7543 }
7544
7545 private uint32_t
upd_pxlget1r7(upd_p upd)7546 upd_pxlget1r7(upd_p upd)
7547 {
7548 upd->pxlget = upd_pxlget1r6;
7549 return *upd->pxlptr & 0x02 ? (uint32_t) 1 : (uint32_t) 0;
7550 }
7551
7552 private uint32_t
upd_pxlget1r8(upd_p upd)7553 upd_pxlget1r8(upd_p upd)
7554 {
7555 upd->pxlget = upd_pxlget1r7;
7556 return *upd->pxlptr & 0x01 ? (uint32_t) 1 : (uint32_t) 0;
7557 }
7558
7559 /* 2 Bit Reverse */
7560
7561 private uint32_t
upd_pxlget2r1(upd_p upd)7562 upd_pxlget2r1(upd_p upd)
7563 {
7564 upd->pxlget = upd_pxlget2r4;
7565 return ((uint32_t) (*upd->pxlptr--) & (uint32_t) 0xC0) >> 6;
7566 }
7567
7568 private uint32_t
upd_pxlget2r2(upd_p upd)7569 upd_pxlget2r2(upd_p upd)
7570 {
7571 upd->pxlget = upd_pxlget2r1;
7572 return ((uint32_t) (*upd->pxlptr ) & (uint32_t) 0x30) >> 4;
7573 }
7574
7575 private uint32_t
upd_pxlget2r3(upd_p upd)7576 upd_pxlget2r3(upd_p upd)
7577 {
7578 upd->pxlget = upd_pxlget2r2;
7579 return ((uint32_t) (*upd->pxlptr ) & (uint32_t) 0x0C) >> 2;
7580 }
7581
7582 private uint32_t
upd_pxlget2r4(upd_p upd)7583 upd_pxlget2r4(upd_p upd)
7584 {
7585 upd->pxlget = upd_pxlget2r3;
7586 return (uint32_t) (*upd->pxlptr ) & (uint32_t) 0x03;
7587 }
7588
7589 /* 4 Bit Reverse */
7590
7591 private uint32_t
upd_pxlget4r1(upd_p upd)7592 upd_pxlget4r1(upd_p upd)
7593 {
7594 upd->pxlget = upd_pxlget4r2;
7595 return ((uint32_t) (*upd->pxlptr--) & (uint32_t) 0xF0) >> 4;
7596 }
7597
7598 private uint32_t
upd_pxlget4r2(upd_p upd)7599 upd_pxlget4r2(upd_p upd)
7600 {
7601 upd->pxlget = upd_pxlget4r1;
7602 return (uint32_t) (*upd->pxlptr ) & (uint32_t) 0x0F;
7603 }
7604
7605
7606 /* 8 Bit Reverse */
7607 private uint32_t
upd_pxlget8r(upd_p upd)7608 upd_pxlget8r(upd_p upd)
7609 {
7610 return (uint32_t) (*upd->pxlptr--);
7611 }
7612
7613
7614 /* 16 Bit Reverse */
7615 private uint32_t
upd_pxlget16r(upd_p upd)7616 upd_pxlget16r(upd_p upd)
7617 {
7618 uint32_t ci = *upd->pxlptr--;
7619 ci |= (uint32_t) (*upd->pxlptr--) << 8;
7620 return ci;
7621 }
7622
7623 /* 24 Bit Reverse */
7624 private uint32_t
upd_pxlget24r(upd_p upd)7625 upd_pxlget24r(upd_p upd)
7626 {
7627 uint32_t ci = *upd->pxlptr--;
7628 ci |= (uint32_t) (*upd->pxlptr--) << 8;
7629 ci |= (uint32_t) (*upd->pxlptr--) << 16;
7630 return ci;
7631 }
7632
7633 /* 32 Bit Reverse */
7634 private uint32_t
upd_pxlget32r(upd_p upd)7635 upd_pxlget32r(upd_p upd)
7636 {
7637 uint32_t ci = *upd->pxlptr--;
7638 ci |= (uint32_t) (*upd->pxlptr--) << 8;
7639 ci |= (uint32_t) (*upd->pxlptr--) << 16;
7640 ci |= (uint32_t) (*upd->pxlptr--) << 24;
7641 return ci;
7642 }
7643