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