1
/* Copyright (C) 2001-2012 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied,
8
modified or distributed except as expressly authorized under the terms
9
of the license contained in the file LICENSE in this distribution.
11
Refer to licensing information at http://www.artifex.com or contact
12
Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
13
CA 94903, U.S.A., +1(415)492-9861, for further information.
17
/* gdevupd.c Revision: 1.88 */
18
/* "uniprint" -- Ugly Printer Driver by Gunther Hess (ghess@elmos.de) */
21
23-Mar-1997 - 1.43: First published version
22
24-Mar-1997 - 1.44: gs4.03 compatible version on the web
23
31-Mar-1997 - 1.53: First Version inside gs-fileset (limited)
24
28-Apr-1997 - 1.54: Version intended for public gs-release
25
4-May-1997 - 1.55: Deactivated an accidentially active Debug-Option
26
14-Jun-1997 - 1.56: Bug-Workaround for White on White Printing (gs5.0)
27
17-Jun-1997 - 1.57: More reasonable Fix for the above Bug
29
7-Jul-1997 - 1.68: NULL-Param-BUG, HR's BJC, Pwidth/-height BUG, YFlip
30
25-Jul-1997 - 1.69: Bug-Fix: incomplete Change of PHEIGHT-Treatment
31
4-Aug-1997 - 1.70: Arrgh: still incomplete Change of PHEIGHT-Treatment
32
17-AUG-1997 - 1.71: Fix of BSD-sprintf bug. (returns char * there)
34
28-Sep-1997 - 1.77: Fixed the byte<>char and casted-lvalue Problems
36
12-Mar-1998 - 1.80: Some PJL-Functions, Map-Bug-Fix (by Wonder-Wolfgang)
37
21-Oct-1998 - 1.81: Added RGB2CMY[_]K Modi (Eric Domenjoud)
39
27-Feb-2000 - 1.84: CMYKgenerate with forced K-Control [distributed]
40
2-Apr-2000 - Unofficial modifications for Epson Stylus Color 300. GR
41
5-Apr-2000 - GR fixed last row not filled bug in wrtescnm
42
7-May-2000 - 1.85: Always BOP/EOP-Massaging for RTL-Output (Dan Coby)
44
7-May-2000 - 1.87: integrated stc300-code by Glenn Ramsey
45
" - 1.88: reduced "cast discards `const'" warnings to 1
49
/* Canon BJC 610 additions from (hr)
50
Helmut Riegler <helmut-riegler@net4you.co.at>
52
The BJC-4000 can be supported very easily, only by creating the right .upp
53
parameter file. If you have this printer and you are willing to do this,
54
contact me, I'll give you the technical details (ESC codes).
57
/* Epson Stylus Color 300 (FMT_ESCNMY) additions 2-Apr-2000.
58
Glenn Ramsey <glennr@es.co.nz>
61
/* ------------------------------------------------------------------- */
62
/* Compile-Time-Options */
63
/* ------------------------------------------------------------------- */
66
There are two compile-time options for this driver:
67
1. UPD_SIGNAL enables interrupt detection, that aborts printing and
68
2. UPD_MESSAGES controls the amount of messages generated by the driver
73
#define UPD_SIGNAL 1 /** Activated, if undefined, on UNIX-Systems */
75
#define UPD_SIGNAL 0 /** Inactive on others, by default */
76
#endif /* ?__unix__ */
77
#endif /* UPD_SIGNAL */
80
#define UPD_MESSAGES UPD_M_ERROR /** Error-messages only, if not defined */
81
#endif /* UPD_MESSAGES */
83
/* ------------------------------------------------------------------- */
84
/* Required Header-Files */
85
/* ------------------------------------------------------------------- */
89
#ifndef hess_test_INCLUDED /* A private test-Option */
91
#include "gdevprn.h" /** Printer-superclass header */
92
#include "gsparam.h" /** For the Parameter-Handling (optional) */
94
#include <stdlib.h> /** for rand */
95
#include <limits.h> /** for INT_MIN */
96
#include <ctype.h> /** for isupper */
98
#endif /* hess_test_INCLUDED A private test-Option */
101
#include <signal.h> /** Only included, if UPD_SIGNAL is active (true) */
102
#endif /* UPD_SIGNAL */
104
/* ------------------------------------------------------------------- */
105
/* Device-Structure (including an additional Structure-Pointer-Type) */
106
/* ------------------------------------------------------------------- */
108
typedef struct upd_s upd_t,*upd_p; /** Type & Pointer of device-specifics */
109
typedef const upd_t *upd_pc; /** Pointer to constant device-specfics */
111
typedef struct upd_device_s { /** The driver must typedef ... */
112
gx_device_common; /** common fields for all devices */
113
gx_prn_device_common; /** common fields for printing-devices */
114
gs_param_string upd_version; /** Source-Code Version */
115
upd_p upd; /** uniprint-specific extension */
116
} upd_device; /** some type usually <name>_device> */
118
/* ------------------------------------------------------------------- */
119
/* Major Driver-Functions */
120
/* ------------------------------------------------------------------- */
122
static dev_proc_print_page(upd_print_page); /** print a page (required) */
124
static dev_proc_open_device(upd_open); /** device-initialization (opt) */
125
static dev_proc_close_device(upd_close); /** device-release (opt) */
127
static dev_proc_get_params(upd_get_params); /** export parameters (opt) */
128
static dev_proc_put_params(upd_put_params); /** import parameters (opt) */
131
A `normal' Device-Driver wil only implement one of the following pairs
132
of functions for the colormapping. But "uniprint" is something special and
133
it really provides all four reasonable pairs and in addition to that
134
a fifth set of functions, that delivers better FS-Results with KCMY.
136
The first pair is for the mapping into a single stored component, that
137
usually represents a grayscale. But nevertheless GHOSTSCRIPT deals with
138
RGB-Values, but promises to deal with R==G==B-Values when asking to map.
140
The second pair deals with RGB-Values.
143
static dev_proc_encode_color( upd_rgb_1color); /** Gray-Gray->Index */
144
static dev_proc_decode_color( upd_1color_rgb); /** Gray-Index->Gray */
146
static dev_proc_encode_color( upd_rgb_3color); /** RGB->RGB-Index */
147
static dev_proc_decode_color( upd_3color_rgb); /** RGB-Index->RGB */
150
The third pair maps RGB-Values into four components, which one might
151
expect to be KCMY-Values, but they are not: "uniprint" considers this four
152
Values as White+RGB Values!
155
static dev_proc_encode_color( upd_rgb_4color); /** RGB->WRGB-Index */
156
static dev_proc_decode_color(upd_4color_rgb); /** WRGB-Index->RGB */
159
The fourth pair deals with KCMY-Values. The Mapping-Function
160
is of a different type, due to the additional argument, but the
161
inverse-Function is of the same type, and expects RGB-Values to be
162
deliverd into the receiving 3-Component-Array!
165
static dev_proc_encode_color(upd_cmyk_icolor); /** KCMY->KCMY-Index */
166
static dev_proc_decode_color( upd_icolor_rgb); /** KCMY->RGB-Index */
169
The difference between the icolor-pair and the kcolor-pair is the enforced
170
black-generation in the forward-mapping. that is taken into account by the
174
static dev_proc_encode_color(upd_cmyk_kcolor); /** adds black generation */
175
static dev_proc_decode_color( upd_kcolor_rgb); /** watches black-gen */
178
"ovcolor" is CMYK with Black-Generation and Undercolor-Removal, which
179
is suitable for overprinting:
180
CMY' = (CMY-K')/(1-K')
185
static dev_proc_encode_color(upd_rgb_ovcolor); /** RGB->CMYK-Index */
186
#define upd_ovcolor_rgb upd_icolor_rgb /** CMYK-Index->RGB */
189
"novcolor" is CMYK with Black-Generation and Undercolor-Removal, which
190
is suitable for CMY / K - Printing:
196
static dev_proc_encode_color(upd_rgb_novcolor); /** RGB->CMYK-Index */
197
#define upd_novcolor_rgb upd_icolor_rgb /** CMYK-Index->RGB */
200
For the sake of efficiency there is that bunch of functions and they
201
perform no validity checks, thus it has to be assured that they are
202
only active, if there is a valid device-structure for then.
203
upd_procs_map performs this task.
206
static int upd_procs_map( upd_device *udev);
208
/* ------------------------------------------------------------------- */
209
/* Prototype of the Device-Structure (the only thing exported!) */
210
/* ------------------------------------------------------------------- */
213
"uniprint" needs a procedure-table of its own, since it provides several
214
optional procedures. Simpler-Drivers (e.g. non-color-drivers) may use
215
prn_std_procs instead of defining their own procedure-table.
218
#define upd_set_dev_proc(dev, p, proc) \
219
((dev)->std_procs.p = (dev)->orig_procs.p = (proc))
221
static gx_device_procs upd_procs = { /** Table of procedures */
222
upd_open, /** open-function, upd-special */
223
gx_default_get_initial_matrix, /** retrieve matrix */
224
gx_default_sync_output, /** sync display */
225
gdev_prn_output_page, /** superclass-print (calls back) */
226
upd_close, /** close-function, upd-special */
227
gx_default_map_rgb_color, /** RGB-mapping */
228
gx_default_map_color_rgb, /** reverse mapping */
229
NULL, /** fill_rectangle */
230
NULL, /** tile_rectangle */
231
NULL, /** copy_mono */
232
NULL, /** copy_color */
233
NULL, /** draw_line */
234
gx_default_get_bits, /** reads scanlines, e.g. for the driver */
235
upd_get_params, /** Export parameters, upd-special */
236
upd_put_params, /** Import parameters, upd-special */
237
gx_default_map_cmyk_color /** KCMY-mapping */
241
The prototype-instance of the device-structure _must_ have the name
242
"gs_uniprint_device", where "uniprint" is the external name of the driver.
243
This notice is bluntly copied from drivers.txt, which a potential
244
driver-author should carefully read.
246
Just to mention: this prototype is quite similar to the one, that
247
"prn_device" produces and it identifies "uniprint" as a monochrome 1Bit
248
device to GHOSTSCRIPT. But during the lifetime of a driver-instance
251
This is the end of the part of declarations, that are common for
252
color-drivers. The next sections address "uniprint"-specific data-types
253
and the reader might directly skip to the section titled
255
upd_print_page: The main workhorse
258
upd_device far_data gs_uniprint_device = { /** */
259
prn_device_body(upd_device, upd_procs, /** The Type and Procedures */
260
"uniprint", /** External name of the Device */
261
DEFAULT_WIDTH_10THS, /** X-Size (1/10") */
262
DEFAULT_HEIGHT_10THS, /** Y-Size (1/10") */
263
72, 72, /** X,Y-DpI */
264
0.0, 0.0, 0.0, 0.0, /** L,B,R,T-Margin */
265
1, /** color_info.num_components 1/3/4 */
266
1, /** color_info.depth 1/2/4/8/16/24/32 */
267
1, /** color_info.max_gray # of distinct gray levels -1 (255/1) */
268
0, /** color_info.max_color # of distinct color levels -1 (255/1/0)*/
269
2, /** color_info.dither_grays size of gray ramp for dithering (256/2) */
270
0, /** color_info.dither_colors size of color cube ditto (256/2/0) */
271
upd_print_page), /** Print-procedure */
272
{ NULL, 0, true }, /** Driver-Version */
273
NULL /** upd-field: Initially none */
276
/* ------------------------------------------------------------------- */
277
/* UPD-Data- and Prototypes */
278
/* ------------------------------------------------------------------- */
281
/* ------------------------------------------------------------------- */
282
/* External names of the UPD-Parameters */
283
/* ------------------------------------------------------------------- */
287
"uniprint" supports a hole bunch of external parameters. This Parameters
288
fall into the following categories:
290
0. special-string the upd_version, readonly upd_version
291
1. choice name-indices, stored in upd->choice
292
2. boolean single bits, stored in upd->flags
293
3. integers single numbers, stored in upd->ints
294
4. integer-Arrays arrays of numbers, stored in upd->int_a
295
5. string device-commands, stored in upd->strings
296
6. string-Arrays arrayed device-commands, stored in upd->string_a
297
7. float-Arrays arrays of floats, stored in upd->float_a
299
Currently there is no need for single floats, but they may be introduced in
300
future versions. Since "uniprint" somtimes manipulates the contents of the
301
array-variables it dynamically allocates storage for all this parameters.
303
The following sections defines the names for this parameters in the order,
304
they are stored within the mentioned dynamic fields of the upd-structure.
305
A NULL-name means that the corresponding parameter is not externally visible.
306
Besides the name, there is always a symbolic index #defined, that MUST match
307
the Index-Number of the name.
311
static const char *const upd_version = "upVersion"; /** Readonly Version */
313
/** Names for the multiple-choice-Parameters
315
Currently there are three Parameters, that are handled as named choices.
316
For each of them, there is an array of constant strings that consists of
318
1. the Parameter-Name
319
2. - n-1 the available choices.
320
n. A terminating NULL
323
static const char *const upd_mapper[] = { "upColorModel",
324
#define MAP_GRAY 1 /** Monochrome & Grayscale Devices */
325
"DeviceGray", /** Monochrome & Grayscale Devices */
326
#define MAP_RGBW 2 /** RGB with White-Generation */
327
"DeviceRGBW", /** RGB with White-Generation */
328
#define MAP_RGB 3 /** RGB-Mapping */
329
"DeviceRGB", /** RGB-Mapping */
330
#define MAP_CMYK 4 /** CMYK-Mapping */
331
"DeviceCMYK", /** CMYK-Mapping */
332
#define MAP_CMYKGEN 5 /** CMYK-Mapping with Black-Generation */
333
"DeviceCMYKgenerate", /** CMYK-Mapping with Black-Generation */
334
#define MAP_RGBOV 6 /** RGB->CMYK with BG and UCR for CMYK */
335
"DeviceRGB2CMYK", /** RGB->CMYK with BG and UCR for CMYK */
336
#define MAP_RGBNOV 7 /** RGB->CMYK with BG and UCR for CMY + K */
337
"DeviceRGB2CMY_K", /** RGB->CMYK with BG and UCR for CMY + K */
341
static const char *const upd_render[] = { "upRendering",
342
#define RND_FSCOMP 1 /** Componentwise Floyd-Steinberg */
343
"ErrorDiffusion", /** Componentwise Floyd-Steinberg */
344
#define RND_FSCMYK 2 /** CMYK-specialized 32Bit Floyd-Steinberg */
345
"FSCMYK32", /** CMYK-specialized 32Bit Floyd-Steinberg */
346
#define RND_FSCMY_K 3 /** CMY_K Rendering */
351
static const char *const upd_format[] = { "upOutputFormat",
352
#define FMT_RAS 1 /** Generates SUN-Rasterfiles */
353
"SunRaster", /** Generates SUN-Rasterfiles */
354
#define FMT_EPSON 2 /** Generates X+Y-Weaved ESC/P-Output */
355
"Epson", /** Generates X+Y-Weaved ESC/P-Output */
356
#define FMT_ESCP2Y 3 /** Generates Y-Weaved ESC/P2-Output */
357
"EscP2", /** Generates Y-Weaved ESC/P2-Output */
358
#define FMT_ESCP2XY 4 /** Generates X+Y-Weaved ESC/P2-Output */
359
"EscP2XY", /** Generates X+Y-Weaved ESC/P2-Output */
360
#define FMT_RTL 5 /** Generates HP-PCL/RTL-Output */
361
"Pcl", /** Generates HP-PCL/RTL-Output */
362
#define FMT_CANON 6 /** Generates Output for Canon extended mode (hr) */
363
"Canon", /** Generates Output for Canon extended mode (hr) */
364
#define FMT_ESCNMY 7 /** Generates Output for Epson Stylus Color 300 (GR) */
365
"EscNozzleMap", /** Generates Output for Epson Stylus Color 300 (GR) */
369
static const char *const *const upd_choice[] = {
370
#define C_MAPPER 0 /** the selected Mapper */
372
#define C_RENDER 1 /** the selected Rendering */
374
#define C_FORMAT 2 /** the selected Choice */
378
/** Names for the flags (bool)
381
static const char *const upd_flags[] = { /** */
382
#define B_REVDIR ((uint32_t) 1<<0) /** FS-Dir-Flag */
383
"upFSReverseDirection", /** FS-Dir-Flag */
384
#define B_FIXDIR ((uint32_t) 1<<1) /** Do not alter FS-direction */
385
"upFSFixedDirection", /** Do not alter FS-direction */
386
#define B_FSWHITE ((uint32_t) 1<<2) /** Process white in FS */
387
"upFSProcessWhiteSpace", /** Process white in FS */
388
#define B_FSZERO ((uint32_t) 1<<3) /** Zero FS-Initialization */
389
"upFSZeroInit", /** Zero FS-Initialization */
391
#define B_PAGEWIDTH ((uint32_t) 1<<4) /** Adjust Width in BOP */
392
"upAdjustPageWidthCommand", /** Adjust Page-Width in BOP */
393
#define B_PAGELENGTH ((uint32_t) 1<<5) /** Adjust Length in BOP */
394
"upAdjustPageLengthCommand", /** Adjust Page-Length in BOP */
395
#define B_TOPMARGIN ((uint32_t) 1<<6) /** Adjust Top-Margin in BOP */
396
"upAdjustTopMarginCommand", /** Adjust Top-Margin in BOP */
397
#define B_BOTTOMMARGIN ((uint32_t) 1<<7) /** Adjust Bottom-Margin in BOP */
398
"upAdjustBottomMarginCommand", /** Adjust Bottom-Margin in BOP */
399
#define B_RESOLUTION ((uint32_t) 1<<8) /** Adjust Resolution in BOP */
400
"upAdjustResolutionCommand", /** Adjust Resolution in BOP */
401
#define B_MEDIASIZE ((uint32_t) 1<<9) /** Adjust Mediasize in BOP */
402
"upAdjustMediaSize", /** Adjust Mediasize in BOP */
404
#define B_XABS ((uint32_t) 1<<10) /** Use Absolute X-Values */
405
"upFormatXabsolute", /** Use Absolute X-Values */
406
#define B_YABS ((uint32_t) 1<<11) /** Use Absolute Y-Values */
407
"upFormatYabsolute", /** Use Absolute Y-Values */
409
#define B_MAP ((uint32_t) 1<<12) /** Mapping Initialized */
410
"upColorModelInitialized", /** Mapping Initialized */
411
#define B_BUF ((uint32_t) 1<<13) /** Raster-Buffer Initialized */
412
"upRasterBufferInitialized", /** Raster-Buffer Initialized */
413
#define B_RENDER ((uint32_t) 1<<14) /** Rendering Initialized */
414
"upRenderingInitialized", /** Rendering Initialized */
415
#define B_FORMAT ((uint32_t) 1<<15) /** Formatter Initialized */
416
"upOutputFormatInitialized", /** Formatter Initialized */
417
#define B_ABORT ((uint32_t) 1<<16) /** Abort on Interrupt */
418
"upOutputAborted", /** Abort on Interrupt */
419
#define B_ERROR ((uint32_t) 1<<17) /** Severe Error detected */
420
"upErrorDetected", /** Severe Error detected */
422
#define B_OPEN ((uint32_t) 1<<18) /** Open-Command written */
423
"upWroteData", /** Open-Command written */
425
#define B_YFLIP ((uint32_t) 1<<19) /** Mirrored printing (hr) */
426
"upYFlip", /** Mirrored printing (hr) */
428
#define B_REDUCEK ((uint32_t) 1<<20) /** CMY->Black Reduction */
433
/** B_OK4GO: Bits required to execute the print-loop */
435
#define B_OK4GO (B_MAP | B_BUF | B_RENDER | B_FORMAT)
437
/** Names for the ints
440
static const char *const upd_ints[] = {
441
#define I_PWIDTH 0 /** Output-Width */
443
#define I_PHEIGHT 1 /** Output-Height */
445
#define I_OCOMP 2 /** Output-Components */
446
"upOutputComponents",
447
#define I_NSCNBUF 3 /** Output-Buffers */
449
#define I_XSTEP 4 /** Unit-Step */
450
"upOutputXStep", /* > 0 -> divide Raster-X, < 0 muliply Raster-X */
451
#define I_XOFS 5 /** abs. X-Offset */
453
#define I_YSTEP 6 /** Unit-Step */
454
"upOutputYStep", /* > 0 -> divide Raster-Y, < 0 muliply Raster-Y */
455
#define I_YOFS 7 /** abs. Y-Offset */
457
#define I_PINS2WRITE 8 /** Number of Pins */
460
#define I_NXPASS 9 /** X-Passes */
462
#define I_NYPASS 10 /** Y-Passes */
464
#define I_NPASS 11 /** Total # Passes */
466
#define I_BEG_Y 12 /** Start of normal Weaving */
467
"upWeaveInitialScan",
468
#define I_END_Y 13 /** End of normal Weaving */
470
#define I_BEGSKIP 14 /** A Scan-Offset */
472
#define I_ROWS 15 /** Output rows per pass */
473
"upNozzleMapRowsPerPass",
474
#define I_PATRPT 16 /** mask pattern repeat interval */
475
"upNozzleMapPatternRepeat"
478
/** Names for the Integer-Arrays
481
static const char *const upd_int_a[] = { /** */
482
#define IA_COLOR_INFO 0 /** external color_info */
483
"upColorInfo", /** external color_info */
485
#define IA_COMPBITS 1 /** Bits stored per Component */
486
"upComponentBits", /** Bits stored per Component */
487
#define IA_COMPSHIFT 2 /** Shift for the stored Bits */
488
"upComponentShift", /** Shift for the stored Bits */
489
#define IA_COMPORDER 3 /** Order of Output-Components */
490
"upOutputComponentOrder", /** Order of Output-Components */
492
#define IA_STD_DY 4 /** Standard-Weave Feeds */
493
"upWeaveYFeeds", /** Standard-Weave Feeds */
494
#define IA_STD_IX 5 /** Standard-Weave X-Passes */
495
"upWeaveXStarts", /** Standard-Weave X-Start */
496
#define IA_BEG_DY 6 /** Initial-Weave Feeds */
497
"upWeaveInitialYFeeds", /** Initial-Weave Feeds */
498
#define IA_BEG_IX 7 /** Initial-Weave X-Start */
499
"upWeaveInitialXStarts", /** Initial-Weave X-Start */
500
#define IA_BEGBOT 8 /** Initial-Weave #Pins */
501
"upWeaveInitialPins", /** Initial-Weave #Pins */
502
#define IA_END_DY 9 /** Final-Weave Feeds */
503
"upWeaveFinalYFeeds", /** Final-Weave Feeds */
504
#define IA_END_IX 10 /** Final-Weave X-Start */
505
"upWeaveFinalXStarts", /** Final-Weave X-Start */
506
#define IA_ENDTOP 11 /** Final-Weave #Pins */
507
"upWeaveFinalPins", /** Final-Weave #Pins */
508
#define IA_ROWMASK 12 /** The nozzle to row map */
509
"upNozzleMapRowMask",
510
#define IA_SCNOFS 13 /** Mask to scan map */
511
"upNozzleMapMaskScanOffset"
514
/** Names of the String-Parameters
517
static const char *const upd_strings[] = { /** */
518
#define S_MODEL 0 /** Name of the Printer-Model */
519
"upModel", /** Name of the Printer-Model */
520
#define S_OPEN 1 /** Printer-Begin-Job */
521
"upBeginJobCommand", /** Printer-Begin-Job */
522
#define S_CLOSE 2 /** Printer-End-Job */
523
"upEndJobCommand", /** Printer-End-Job */
524
#define S_BEGIN 3 /** Printer-Begin-Page */
525
"upBeginPageCommand", /** Printer-Begin-Page */
526
#define S_END 4 /** Printer-End-Page */
527
"upEndPageCommand", /** Printer-End-Page */
528
#define S_ABORT 5 /** Printer-Abort-Command */
529
"upAbortCommand", /** Printer-Abort-Command */
531
#define S_XMOVE 6 /** X-Positioning-Command */
532
"upXMoveCommand", /** X-Positioning-Command */
533
#define S_XSTEP 7 /** X-Step Command (1<I_XSTEP) */
534
"upXStepCommand", /** X-Step Command (1<I_XSTEP) */
535
#define S_SETLF 8 /** Set-Linefeed-Command */
536
"upSetLineFeedCommand", /** Set-Linefeed-Command */
537
#define S_YMOVE 9 /** Y-Positioning-Command */
538
"upYMoveCommand", /** Y-Positioning-Command */
539
#define S_YSTEP 10 /** Y-Step Command (1<I_YSTEP) */
540
"upYStepCommand" /** Y-Step Command (1<I_YSTEP) */
543
/** Names for the String-Arrays
546
static const char *const upd_string_a[] = { /** */
547
#define SA_SETCOMP 0 /** Select Components */
548
"upSelectComponentCommands", /** Select Components */
549
#define SA_WRITECOMP 1 /** Write Component Comands */
550
"upWriteComponentCommands" /** Write Component Commands */
553
/** Names for the float-Arrays
555
static const char *const upd_float_a[] = { /** */
556
#define FA_WXFER 0 /** White-Transfer */
557
"upWhiteTransfer", /** White-Transfer */
558
#define FA_RXFER 1 /** Red-Transfer */
559
"upRedTransfer", /** Red-Transfer */
560
#define FA_GXFER 2 /** Green-Transfer */
561
"upGreenTransfer", /** Green-Transfer */
562
#define FA_BXFER 3 /** Blue-Transfer */
563
"upBlueTransfer", /** Blue-Transfer */
564
#define FA_KXFER 4 /** Black-Transfer */
565
"upBlackTransfer", /** Black-Transfer */
566
#define FA_CXFER 5 /** Cyan-Transfer */
567
"upCyanTransfer", /** Cyan-Transfer */
568
#define FA_MXFER 6 /** Magenta-Transfer */
569
"upMagentaTransfer", /** Magenta-Transfer */
570
#define FA_YXFER 7 /** Yellow-Transfer */
571
"upYellowTransfer", /** Yellow-Transfer */
572
#define FA_MARGINS 8 /** private Margins */
573
"upMargins", /** private Margins */
574
#define FA_MAP 9 /** Color-Map */
575
"upColorMap" /** Color-Map */
578
/* ------------------------------------------------------------------- */
579
/* UPD-specific datatypes */
580
/* ------------------------------------------------------------------- */
583
int32_t and uint32_t are 32Bit-Integer-Types used in the
584
Floyd-Steinberg Algorithm and instead of gx_color_index. The
585
8-Byte long's on some 64Bit-Machines are apparently useless,
586
since gdevprn.c does (currently) support only 32-Bit Rasterdata.
593
#if arch_log2_sizeof_int < 2 /* int is too small */
594
#define INT32_MIN LONG_MIN
595
#define INT32_MAX LONG_MAX
596
#define UINT32_MAX ULONG_MAX
597
#else /* int is sufficient */
598
#define INT32_MIN INT_MIN
599
#define INT32_MAX INT_MAX
600
#define UINT32_MAX UINT_MAX
601
#endif /* use int or long ? */
604
"updcmap" is used by the color-mapping functions of the driver.
605
there are four cmaps in the "uniprint"-structure, one for each component.
606
To be exact, it's not "4" but rather "UPD_CMAP_MAX", which is a synonym.
609
typedef struct updcmap_s { /** */
610
gx_color_value *code; /** Values related to codes */
611
uint32_t bitmsk; /** Mask, right justified */
612
int bitshf; /** Shift to right-justify */
613
int xfer; /** Index to the Xfer-Array */
614
int bits; /** # of Bits */
615
int comp; /** Output-Number */
616
bool rise; /* Rising/Falling Curve */
617
} updcmap_t, *updcmap_p; /** */
618
typedef const updcmap_t *updcmap_pc;
621
"updcomp" holds similar informations, but is used for the rendering
624
typedef struct updcomp_s { /* Parameters for Floyd-Steinberg */
625
int32_t offset; /* Offset added to scaled values */
626
int32_t scale; /* Scale for the raw values */
627
int32_t threshold; /* Val must be larger than this to fire */
628
int32_t spotsize; /* subtracted from Val when fired */
629
uint32_t bitmsk; /* Mask */
630
int bitshf; /* shift */
631
int bits; /* # of Bits */
632
int cmap; /* Index for the Parameter-name */
633
} updcomp_t, *updcomp_p; /* Parameters for Floyd-Steinberg */
635
/** updscan is the Element of the scan-buffer. */
637
typedef struct updscan_s { /* Single Scanline (1 Bit/Pixel) */
638
byte *bytes; /* Buffer used w. 32-Bit Words */
639
int *xbegin; /* 1st Pixel set (or nbytes<<3 if none) */
640
int *xend; /* last Pixel set (or -1, if none) */
641
} updscan_t, *updscan_p; /* Single Scanline (1 Bit/Pixel) */
643
/** Main upd-Structure ***/
645
#define UPD_CMAP_MAX 4 /** Number of Colormaps provided */
646
#define UPD_VALPTR_MAX 32 /** Number of valbuf-Pointers */
648
#define upd_proc_pxlget(name) uint32_t name(upd_p upd)
649
#define upd_proc_render(name) int name(upd_p upd)
650
#define upd_proc_writer(name) int name(upd_p upd,FILE *out)
652
struct upd_s { /* All upd-specific data */
654
int *choice; /** Named-Choices */
655
int *ints; /** Integers */
656
gs_param_int_array *int_a; /** Integer-Arrays */
657
gs_param_string *strings; /** Strings */
658
gs_param_string_array *string_a; /** String-Arrays */
659
gs_param_float_array *float_a; /** Float-Arrays */
661
updcmap_t cmap[UPD_CMAP_MAX]; /** Mapping-Data */
663
byte *gsbuf; /* Storage for GS-Rasterdata */
664
byte *gsscan; /* Begin of GS-Rasterdata */
666
byte *pxlptr; /* Source for pxlget */
667
upd_proc_pxlget( (*pxlget)); /* The Pixel-Reader */
668
upd_proc_render( (*render)); /* Actual Rendering */
669
upd_proc_writer( (*writer));
671
updscan_p *scnbuf; /* Output-Values */
672
int32_t *valbuf; /* Floyd-Steinberg-Buffer */
673
void *valptr[UPD_VALPTR_MAX];
675
byte *outbuf; /* Output-Buffer */
676
upd_proc_render( (*start_render)); /* Setup for rendering */
677
upd_proc_writer( (*start_writer)); /* Setup for writilg */
679
uint32_t flags; /** Some flags */
680
int pdwidth; /** pdev-width upon open */
681
int pdheight; /** pdev-height upon open */
683
uint ngsbuf; /* Size of gsbuf */
684
int gswidth; /* Width in GS-Pixels */
685
int gsheight; /* Height in GS-Pixels */
687
int rwidth; /* Rendering-Width */
689
int pwidth; /* Printing-Width */
690
int pheight; /* # scanlines printed */
692
int ncomp; /* # Components in gsbuf */
693
int nmap; /* # Entries in color-map */
695
uint nvalbuf; /* Size of valbuf */
696
int nscnbuf; /* Number of entries in scnbuf. */
698
int ocomp; /* # Components written */
699
int nbytes; /* Size of scnbuf[][].words */
700
int nlimits; /* Size of scnbuf[][].xbegin/end */
701
int scnmsk; /* Size of scanbuf - 1 */
702
uint noutbuf; /* Size of the Output-Buffer */
704
int ixpass; /* Current X-pass (0 ... nxpass-1) */
705
int ipass; /* Current pass (0 ... npass-1) */
706
int icomp; /* Selected Component */
707
int lf; /* Selected Line-Space */
709
int xprinter; /* Actual X-Position */
711
int yscan; /* Top-Scan (page-vari) */
712
int yprinter; /* Actual Y-Position (page-vari) */
713
int yscnbuf; /* Y not yet buffered */
714
const gs_memory_t *memory; /* Memory pointer - for errprintf */
715
}; /* All upd-specific data */
717
/* ------------------------------------------------------------------- */
718
/* Various Message-Levels */
719
/* ------------------------------------------------------------------- */
722
UPD_MESSAGES, Is collection of Bits, that controls Messages
725
#define UPD_M_NONE 0x0000 /** No Messages at all */
726
#define UPD_M_ERROR 0x0001 /** Errors */
727
#define UPD_M_WARNING 0x0002 /** Warnings */
728
#define UPD_M_TOPCALLS 0x0004 /** Log Calls to main Functions */
729
#define UPD_M_MAPCALLS 0x0008 /** Log Color-Mapping-Calls */
730
#define UPD_M_SETUP 0x0010 /** Log Setup-Activity */
731
#define UPD_M_FSBUF 0x0020 /** Error-Summary for valbuf */
732
#define UPD_M_FMTVARS 0x0040 /** (GR) Formatting variables */
734
/* ------------------------------------------------------------------- */
735
/* The UPD-Routines */
736
/* ------------------------------------------------------------------- */
739
Besides the main routines required for the color-mapping, that were
740
declared near the beginning, there are some auxillary functions.
741
Most prominent are "upd_open_map" and "upd_close_map", which
742
do the proper actions when opening and closing the device.
745
static int upd_open_map( upd_device *udev);
746
static int upd_close_map(upd_device *udev);
749
But "upd_truncate" and "upd_expand" are also mentionable. They are
750
the actual workhorses for the component-oriented mapping. When mapping
751
the 16Bit Component-Values to the indices, some truncation takes place
752
and this is what "upd_truncate" does, in the most general manner i can
753
think of and with O(log(n)) in time. "upd_expand" is required for the
754
reverse mapping-functions and is a constant-time `algorithm'.
756
static inline uint32_t upd_truncate(upd_pc,int,gx_color_value);
758
/* ------------------------------------------------------------------- */
759
/* Return the gx_color_value for a given component */
760
/* ------------------------------------------------------------------- */
761
static inline gx_color_value
762
upd_expand(upd_pc upd,int i,gx_color_index ci0)
764
const updcmap_pc cmap = upd->cmap + i; /* Writing-Shortcut */
765
uint32_t ci = (uint32_t)((ci0 >> cmap->bitshf) & cmap->bitmsk); /* Extract the component */
767
if(!cmap->rise) ci = cmap->bitmsk - ci; /* Invert, if necessary */
768
/* no Truncation/Expansion on full range */
769
if(gx_color_value_bits > cmap->bits) return cmap->code[ci];
770
else return (gx_color_value) ci;
772
/* That's simple, isn't it? */
775
The next group of internal functions adresses the rendering. Besides
776
the main-functions "upd_open_render" and "upd_close_render", there
777
are groups of up to 3 Functions, for each algorithm available with
778
UPD. Two routines are invoked during open and close and the third
779
is called for each scanline. Actually a fourth function is provided,
780
that is invoked at the beginning of each page to be printed, but the
781
current algorithms do not need it.
783
static void upd_open_render( upd_device *udev);
784
static void upd_close_render( upd_device *udev);
786
static void upd_open_fscomp( upd_device *udev);
787
static int upd_fscomp( upd_p upd);
788
static void upd_close_fscomp( upd_device *udev);
790
static void upd_open_fscmyk( upd_device *udev);
791
static int upd_fscmyk( upd_p upd);
793
static void upd_open_fscmy_k( upd_device *udev);
794
static int upd_fscmy_k( upd_p upd);
797
I hope that the formatting stuff can be kept simple and thus most
798
of the work is done inside the general open and close-functions.
799
During open, there is a call to a format-specific open-function, but
800
this is only for checking and determining the amount of of bytes required
801
for the output-buffer (and limit-values in the scan-buffer).
803
static int upd_open_writer( upd_device *udev);
804
static void upd_close_writer( upd_device *udev);
806
static void upd_signal_handler(int sig);
810
The first format are the uncompressed! SUN-Rasterfiles. The primary intention
811
of this format is testing, but it might turn out to be useful for other
812
purposes, even if the amount of generated data is huge. On the other hand
813
it is a violation of UPD's rules: the start-routine computes the Begin-Page
814
sequence (the Rasterfile header) since it would be a nuisance to provide
815
this code within each (test-)personalization in PostScript.
817
static int upd_open_rascomp( upd_device *udev);
818
static int upd_start_rascomp( upd_p upd, FILE *out);
819
static int upd_rascomp( upd_p upd, FILE *out);
822
The second format is ESC/P, the format introduced with the first Epson
823
impact printers. This format is used by a lot of other printers too.
824
It is also uncompressed. This formatter supports X- and Y-Weaving,
825
which makes it the most sophisticated one inside this driver.
828
static void upd_limits( upd_p upd, bool check);
829
static int upd_open_wrtescp( upd_device *udev);
830
static int upd_wrtescp( upd_p upd, FILE *out);
833
The third format is ESC/P2, the format use by the newer Epson-Printers.
834
It allows runlength-Compression similar to the RTL/PCL-Family of Printers.
835
This formatter does not allow for X-Weaving.
837
The fourth writer is a ESC/P2-Writer, that supports X-Weaving
839
static int upd_rle(byte *out,const byte *in,int nbytes);
840
static int upd_open_wrtescp2( upd_device *udev);
841
static int upd_wrtescp2( upd_p upd, FILE *out);
842
static int upd_wrtescp2x( upd_p upd, FILE *out);
845
The fifth writer is a HP-RTL/PCL-Writer
848
static int upd_open_wrtrtl( upd_device *udev);
849
static int upd_wrtrtl( upd_p upd, FILE *out);
852
The sixth writer is for Canon Extended Mode (currently BJC610) (hr)
855
static int upd_open_wrtcanon( upd_device *udev);
856
static int upd_wrtcanon( upd_p upd, FILE *out);
859
The seventh writer is for ESC P/2 Nozzle Map Mode (currently Stylus Color 300) (GR)
862
static int upd_wrtescnm( upd_p upd, FILE *out);
865
Generalized Pixel Get & Read
867
static uint32_t upd_pxlfwd(upd_p upd);
868
static uint32_t upd_pxlrev(upd_p upd);
869
#define upd_pxlget(UPD) (*UPD->pxlget)(UPD)
871
static void *upd_cast(const void *);
873
/* ------------------------------------------------------------------- */
874
/* Macros to deal with the Parameter-Memory */
875
/* ------------------------------------------------------------------- */
878
Usually the creation of copies of external parameters is not necessary,
879
at least with gs-versions > 4.03. But uniprint writes to the parameters
880
in some cases or creates some by itself, thus to get a unified interface
881
all parameter-data are copied and thus it is legal to manipulate them.
883
Here are several Macros, named "UPD_MM_*" to deal with that.
886
/** UPD_MM_GET_ARRAY allocates & initializes an array of values */
887
#define UPD_MM_GET_ARRAY(mem, Which,Nelts) \
890
byte *tmp = gs_malloc(mem, Nelts,sizeof(Which[0]),"uniprint/params");\
892
memset(tmp,0,(Nelts)*sizeof(Which[0])); \
893
Which = (void *) tmp; \
895
return_error(gs_error_VMerror); \
899
/** UPD_MM_DEL_ARRAY frees an array of values */
900
#define UPD_MM_DEL_ARRAY(mem, Which,Nelts,Delete) \
901
if(Which && 0 < (Nelts)) { \
903
for(ii = 0; (Nelts) > ii; ++ii) Delete(mem, Which[ii]); \
904
gs_free(mem, upd_cast(Which),Nelts,sizeof(Which[0]),"uniprint/params");\
908
/** UPD_MM_DEL_VALUE deletes a value, does nothing */
909
#define UPD_MM_DEL_VALUE(mem, Which) /* */
911
/** UPD_MM_DEL_PARAM deletes a single gs-array-parameter */
912
#define UPD_MM_DEL_PARAM(mem, Which) { \
913
if(Which.data && Which.size) \
914
gs_free(mem, upd_cast(Which.data),Which.size,sizeof(Which.data[0]),\
915
"uniprint/params"); \
918
/** UPD_MM_DEL_APARAM deletes a nested gs-array-parameter */
919
#define UPD_MM_DEL_APARAM(mem, Which) { \
920
if(Which.data && Which.size) { \
922
for(iii = 0; iii < Which.size; ++iii) \
923
UPD_MM_DEL_PARAM(mem, Which.data[iii]); \
924
gs_free(mem, upd_cast(Which.data),Which.size,sizeof(Which.data[0]),\
925
"uniprint/params"); \
929
/** UPD_MM_CPY_ARRAY creates a new copy of an array of values */
930
#define UPD_MM_CPY_ARRAY(mem, To,From,Nelts,Copy) \
931
UPD_MM_GET_ARRAY(mem, To,Nelts); \
934
for(ii = 0; (Nelts) > ii; ++ii) Copy(mem, To[ii],From[ii]);\
937
/** UPD_MM_CPY_VALUE Copies a simple Value */
938
#define UPD_MM_CPY_VALUE(mem,To,From) To = From
940
#define UPD_MM_CPY_VALUE_3(mem,To,From) To = From
942
/** UPD_MM_CPY_PARAM Creates a copy of a gs-parameter */
943
#define UPD_MM_CPY_PARAM(mem, To, From) \
944
if(From.data && From.size) { \
945
UPD_MM_GET_ARRAY(mem, To.data,From.size); \
947
To.size = From.size; \
948
memcpy(upd_cast(To.data),From.data,To.size*sizeof(To.data[0]));\
952
/** UPD_MM_CPY_APARAM Creates a copy of a nested gs-parameter */
953
#define UPD_MM_CPY_APARAM(mem, To,From) \
954
if(From.data && From.size) { \
955
UPD_MM_GET_ARRAY(mem, To.data,From.size); \
957
gs_param_string *tmp2 = (gs_param_string *) upd_cast(To.data);\
959
To.size = From.size; \
960
for(iii = 0; To.size > iii; ++iii) \
961
UPD_MM_CPY_PARAM(mem, tmp2[iii],From.data[iii]); \
965
/* ------------------------------------------------------------------- */
966
/* UPD-Initialized-Data */
967
/* ------------------------------------------------------------------- */
969
/** Version-String */
971
static const char rcsid[] = "$Revision: 5215 $";
973
/** Default-Transfer-curve */
975
static const float upd_data_xfer[2] = { 0.0, 1.0 };
979
/* ------------------------------------------------------------------- */
980
/* upd_cast: keeps some compilers more happy [dangerous] */
981
/* ------------------------------------------------------------------- */
984
upd_cast(const void *data)
986
return (void *) data;
989
/* ------------------------------------------------------------------- */
990
/* upd_signal_handler: Catch interrupts */
991
/* ------------------------------------------------------------------- */
994
static upd_p sigupd = NULL;
996
upd_signal_handler(int sig)
998
if(sigupd) sigupd->flags |= B_ABORT;
1002
/* ------------------------------------------------------------------- */
1003
/* upd_print_page: The main workhorse */
1004
/* ------------------------------------------------------------------- */
1007
Function: upd_print_page
1009
This is the top-level printing routine. It works through this
1012
1. Once for each generated file, the "device-open-sequence" is written.
1013
2. The "page-begin-sequence" is written.
1015
3. The data are generated and written:
1016
3.1: Data are converted into a "printer-family"-specific format.
1017
This step includes the halftoning, if selected.
1018
3.2: Data are written with a printer-specific function.
1019
There is not much code-compression inside theese functions,
1020
since i observed to improvments in print-speed. Other
1021
drivers do a better job in this.
1023
4. The "page-end-sequence" is written.
1024
5. If a one-page-per-file mode is selected, the "device-close-sequence"
1025
is added to the output. For multi-page files, this writing is
1026
performed in "upd_close", the drivers close-function.
1028
The routine is quite short, since all the allocation and checking
1029
occur in upd_open and upd_putparams. The only test, that upd_print_page
1030
does, is the verification wether the device is in a sane state. This
1031
must be done here, since during the initialisation, the device is
1032
usually opened several times, before obtaining a valid state.
1036
upd_print_page(gx_device_printer *pdev, FILE *out)
1038
upd_device *const udev = (upd_device *) pdev;
1039
const upd_p upd = udev->upd;
1040
const int *const ints = upd ? upd->ints : NULL;
1041
int error,need,yfill;
1043
#if UPD_SIGNAL /* variables required for signal-handling only */
1044
void (*oldint )(int) = NULL;
1045
void (*oldterm)(int) = NULL;
1046
upd_p oldupd = sigupd;
1047
#endif /* variables required for signal-handling only */
1050
* Refuse to work, if not explicitly enabled during open
1051
* (some/lot of allocated memory is required)
1053
if(!upd || B_OK4GO != (upd->flags & (B_OK4GO | B_ERROR))) {
1054
#if UPD_MESSAGES & (UPD_M_ERROR | UPD_M_TOPCALLS)
1055
errprintf(pdev->memory, "CALL-REJECTED upd_print_page(0x%05lx,0x%05lx)\n",
1056
(long) udev,(long) out);
1058
return gs_error_undefined;
1061
#if UPD_MESSAGES & UPD_M_TOPCALLS
1062
errprintf(pdev->memory, "CALL: upd_print_page(0x%05lx,0x%05lx)\n",
1063
(long) udev,(long) out);
1066
#if UPD_SIGNAL /* Setup of signal-handling */
1068
oldint = signal(SIGINT, upd_signal_handler);
1069
oldterm = signal(SIGTERM,upd_signal_handler);
1070
#endif /* Setup of signal-handling */
1073
* If the OutputFile was just opened, transfer the Open-Sequence to it.
1075
if(!(upd->flags & B_OPEN)) {
1077
if(0 < upd->strings[S_OPEN].size)
1078
fwrite(upd->strings[S_OPEN].data,1,upd->strings[S_OPEN].size,out);
1079
upd->flags |= B_OPEN;
1082
* Always write the the Page-begin-sequence
1084
if(0 < upd->strings[S_BEGIN].size)
1085
fwrite(upd->strings[S_BEGIN].data,1,upd->strings[S_BEGIN].size,out);
1087
* Establish page-variables
1092
upd->yscan = 0; /* Position we are processing */
1093
upd->yprinter = 0; /* Actual Printer-Positions */
1094
upd->yscnbuf = 0; /* Next free scnbuf-Line */
1096
/* Rendering & Writing Setup, if available */
1097
if(upd->start_render) (*upd->start_render)(upd);
1098
if(upd->start_writer) (*upd->start_writer)(upd,out);
1100
/* How many scanlines do we need ? */
1101
need = ints[I_NYPASS] * ints[I_PINS2WRITE];
1102
if(0 >= need) need = 1;
1104
/* The Weave-counters */
1107
upd->icomp = -1; /* Enforces initial selection */
1108
upd->lf = -1; /* Enforces initial selection */
1112
while(upd->pheight > upd->yscan) { /* Main-Loop */
1115
* Load as much data into the scan-buffer as possible
1116
* (this is done in scan-sequence, the printing not necessarily.)
1118
if(ints[I_BEGSKIP] > upd->yscan) yfill = 0;
1119
else yfill = upd->yscan - ints[I_BEGSKIP];
1121
for(yfill += upd->nscnbuf; upd->yscnbuf < yfill; upd->yscnbuf++) {
1123
if(upd->gsheight > upd->yscnbuf) {
1125
if(0 > (*dev_proc(udev,get_bits))((gx_device *) udev,
1126
upd->yscnbuf,upd->gsbuf,&upd->gsscan)) {
1127
#if UPD_MESSAGES & UPD_M_WARNING
1128
errprintf(udev->memory, "get_bits aborted with error, yscnbuf = %4d\n",
1135
memset(upd->gsscan = upd->gsbuf,0,upd->ngsbuf);
1139
if(0 > (*upd->render)(upd)) {
1140
#if UPD_MESSAGES & UPD_M_WARNING
1141
errprintf(udev->memory, "Rendering aborted with error, yscnbuf = %4d\n",
1149
* Did the buffering loop take an error exit ?
1151
if((upd->yscnbuf ^ yfill) & upd->scnmsk) break;
1153
* Print as much as possible
1155
while((upd->yscan - ints[I_BEGSKIP] + need) < upd->yscnbuf) {
1157
/* first write the scan(s) */
1158
(*upd->writer)(upd,out);
1160
/* Check for termination */
1161
if(upd->yscan >= upd->pheight) break;
1162
if(upd->flags & B_ABORT ) {
1163
#if UPD_MESSAGES & UPD_M_WARNING
1164
errprintf(udev->memory, "Printing aborted upon interrupt, yscan = %4d\n",
1171
* Did the print-Loop take an error exit ?
1173
if((upd->yscan - ints[I_BEGSKIP] + need) < upd->yscnbuf) break;
1177
* If we aborted for some reason, use the dedicated sequence
1180
if((upd->pheight > upd->yscan) &&
1181
(0 < upd->strings[S_ABORT].size)) { /* Only This! */
1182
fwrite(upd->strings[S_ABORT].data,1,upd->strings[S_ABORT].size,out);
1184
upd->flags &= ~B_OPEN; /* Inhibit Close-Sequence ! */
1186
* If there is no special sequence, or we came to normal end,
1187
* write the normal sequence, if any
1190
} else if(0 < upd->strings[S_END].size) {
1191
fwrite(upd->strings[S_END].data,1,upd->strings[S_END].size,out);
1194
* If necessary, write the close-sequence
1197
gs_parsed_file_name_t parsed;
1200
if (NULL != udev->fname &&
1201
0 <= gx_parse_output_file_name(&parsed, &fmt, udev->fname,
1202
strlen(udev->fname), udev->memory) &&
1205
if (0 < upd->strings[S_CLOSE].size)
1206
fwrite(upd->strings[S_CLOSE].data,1,upd->strings[S_CLOSE].size,out);
1207
upd->flags &= ~B_OPEN;
1212
* clean up, and return status
1215
fflush(out); /* just to prepare for ferror */
1217
if(upd->pheight > upd->yscan) error = gs_error_interrupt;
1218
else if(ferror(out)) error = gs_error_ioerror;
1221
#if UPD_MESSAGES & UPD_M_TOPCALLS
1222
errprintf(udev->memory, "RETURN: %d = upd_print_page(0x%05lx,0x%05lx)\n",
1223
error,(long) udev,(long)out);
1226
#if UPD_SIGNAL /* Restore Interrupt-state */
1228
(void) signal(SIGINT ,oldint);
1229
(void) signal(SIGTERM,oldterm);
1230
#endif /* Restore Interrupt-state */
1235
/* ------------------------------------------------------------------- */
1236
/* upd_open: Initialize everything for printing */
1237
/* ------------------------------------------------------------------- */
1239
"upd_open" is -through the specified table of procedures- called instead
1240
of the normal open-procedures for printer-devices, that performs quite
1241
a complex job. Thus it is necessary to call this `superclass-open�
1244
Besides that, this routine does quite a complex job too, in initializes
1245
everything required to print a page. This might be time-consuming, the
1246
alternative would be "upd_print_page", but i often print 100 pages or
1247
more, but i never experienced more than 5-6 open-calls.
1251
upd_open(gx_device *pdev)
1253
upd_device *const udev = (upd_device *) pdev;
1254
const upd_p upd = udev->upd;
1257
#if UPD_MESSAGES & UPD_M_TOPCALLS
1258
errprintf(udev->memory, "CALL: upd_open(0x%05lx)\n",(long) pdev);
1261
/** enforce the UPD-Margins */
1264
(NULL != upd->float_a[FA_MARGINS].data) &&
1265
(4 == upd->float_a[FA_MARGINS].size) ) {
1267
m[1] = upd->float_a[FA_MARGINS].data[1] / 72.0;
1268
m[3] = upd->float_a[FA_MARGINS].data[3] / 72.0;
1269
if(B_YFLIP & upd->flags) {
1270
m[0] = upd->float_a[FA_MARGINS].data[2] / 72.0;
1271
m[2] = upd->float_a[FA_MARGINS].data[0] / 72.0;
1273
m[0] = upd->float_a[FA_MARGINS].data[0] / 72.0;
1274
m[2] = upd->float_a[FA_MARGINS].data[2] / 72.0;
1276
gx_device_set_margins((gx_device *) udev, m, true);
1279
/** call the super-class open **/
1280
error = gdev_prn_open(pdev);
1282
/** invoke the subroutines, if an upd is present. */
1286
upd->flags &= ~B_OK4GO;
1289
The following initializations are run, even in case of an error in
1290
the super-class open, just to bring our upd into a sane state.
1292
if(0 > error) upd->flags |= B_ERROR;
1294
if(gs_error_VMerror == upd_open_map(udev)) error = gs_error_VMerror;
1297
The following piece of code is here for demonstration-purposes:
1298
It determines the size of the printed image and allocates the
1299
buffer for the raw raster-data
1301
upd->gswidth = udev->width -
1302
(int)((dev_l_margin(udev)+dev_r_margin(udev))*udev->x_pixels_per_inch);
1304
upd->gsheight = udev->height -
1305
(int)((dev_t_margin(udev)+dev_b_margin(udev))*udev->y_pixels_per_inch);
1307
upd->ngsbuf = 0; /* Ensure sane values */
1308
upd->gsbuf = NULL; /* Ensure sane values */
1310
if(B_MAP & upd->flags) { /* Only if prerequisites were met */
1311
uint want = gx_device_raster(pdev,true);
1312
upd->gsbuf = gs_malloc(pdev->memory, want,1,"upd/gsbuf");
1316
upd->flags |= B_BUF; /* Signal Success */
1318
error = gs_error_VMerror; /* Signal Error */
1319
upd->flags |= B_ERROR;
1322
} /* Only if prerequisites were met */
1324
upd_open_render(udev); /* First subloop in printing */
1326
if(gs_error_VMerror == upd_open_writer(udev)) error = gs_error_VMerror;
1328
udev->upd->pdwidth = udev->width;
1329
udev->upd->pdheight = udev->height;
1331
#if UPD_MESSAGES & UPD_M_SETUP
1332
if((upd->flags & (B_OK4GO | B_ERROR)) == B_OK4GO) {
1334
errprintf(udev->memory,"\nupd->flags = 0x%05lx\n",(unsigned long)upd->flags);
1335
errprintf(udev->memory, "upd->pdwidth = %5d\n",upd->pdwidth);
1336
errprintf(udev->memory, "upd->pdheight = %5d\n",upd->pdheight);
1337
errprintf(udev->memory, "upd->ngsbuf = %5u\n",upd->ngsbuf);
1338
errprintf(udev->memory, "upd->gswidth = %5d\n",upd->gswidth);
1339
errprintf(udev->memory, "upd->gsheight = %5d\n",upd->gsheight);
1340
errprintf(udev->memory, "upd->rwidth = %5d\n",upd->rwidth);
1341
errprintf(udev->memory, "upd->pwidth = %5d\n",upd->pwidth);
1342
errprintf(udev->memory, "upd->pheight = %5d\n",upd->pheight);
1343
errprintf(udev->memory, "upd->nvalbuf = %5u\n",upd->nvalbuf);
1344
errprintf(udev->memory, "upd->nscnbuf = %5d\n",upd->nscnbuf);
1345
errprintf(udev->memory, "upd->ncomp = %5d\n",upd->ncomp);
1346
errprintf(udev->memory, "upd->ocomp = %5d\n",upd->ocomp);
1347
errprintf(udev->memory, "upd->nbytes = %5d\n",upd->nbytes);
1348
errprintf(udev->memory, "upd->nlimits = %5d\n",upd->nlimits);
1349
errprintf(udev->memory, "upd->scnmsk = %5d\n",upd->scnmsk);
1350
errprintf(udev->memory, "upd->noutbuf = %5u\n",upd->noutbuf);
1351
errprintf(udev->memory, "upd->ixpass = %5d\n",upd->ixpass);
1352
errprintf(udev->memory, "upd->ipass = %5d\n",upd->ipass);
1353
errprintf(udev->memory, "upd->icomp = %5d\n",upd->icomp);
1354
errprintf(udev->memory, "upd->lf = %5d\n",upd->lf);
1355
errprintf(udev->memory, "upd->xprinter = %5d\n",upd->xprinter);
1356
errprintf(udev->memory, "upd->yscan = %5d\n",upd->yscan);
1357
errprintf(udev->memory, "upd->yprinter = %5d\n",upd->yprinter);
1358
errprintf(udev->memory, "upd->yscnbuf = %5d\n",upd->yscnbuf);
1362
for(i = 0; countof(upd_choice) > i; ++i) {
1363
if(!upd_choice[i]) continue;
1364
l = strlen(upd_choice[i][0]);
1366
for(j = 1; upd_choice[i][j]; ++j) {
1367
l = strlen(upd_choice[i][j]);
1372
for(i = 0; countof(upd_flags) > i; ++i) {
1374
l = strlen(upd_flags[i]);
1379
for(i = 0; countof(upd_ints) > i; ++i) {
1381
l = strlen(upd_ints[i]);
1386
for(i = 0; countof(upd_int_a) > i; ++i) {
1388
l = strlen(upd_int_a[i]);
1393
for(i = 0; countof(upd_strings) > i; ++i) {
1394
if(upd_strings[i]) {
1395
l = strlen(upd_strings[i]);
1400
for(i = 0; countof(upd_string_a) > i; ++i) {
1401
if(upd_string_a[i]) {
1402
l = strlen(upd_string_a[i]);
1407
for(i = 0; countof(upd_float_a) > i; ++i) {
1408
if(upd_float_a[i]) {
1409
l = strlen(upd_float_a[i]);
1414
for(i = 0; countof(upd_choice) > i; ++i) {
1416
errprintf(udev->memory,"%*s = %-*s (%2d)\n",ln,upd_choice[i][0],
1417
lv,upd_choice[i][upd->choice[i]],upd->choice[i]);
1419
errprintf(udev->memory,"%*s[%2d] = %2d\n",ln-4,"upd_choice",i,
1424
for(i = 0; countof(upd_flags) > i; ++i) {
1426
errprintf(udev->memory,"%*s = %s\n",ln,upd_flags[i],
1427
((uint32_t) 1 << i) & upd->flags ? "true" : "false");
1429
errprintf(udev->memory,"%*s[%2d] = %s\n",ln-4,"upd_flags",i,
1430
((uint32_t) 1 << i) & upd->flags ? "true" : "false");
1435
for(i = 0; countof(upd_ints) > i; ++i) {
1437
errprintf(udev->memory,"%*s = %5d\n",ln,upd_ints[i],upd->ints[i]);
1439
errprintf(udev->memory,"%*s[%2d] = %5d\n",ln-4,"upd_ints",i,upd->ints[i]);
1445
errprintf(udev->memory,"\n%sready to print\n\n",
1446
B_OK4GO != (upd->flags & (B_OK4GO | B_ERROR)) ?
1452
#if UPD_MESSAGES & UPD_M_TOPCALLS
1453
errprintf(udev->memory,"RETURN: %d = upd_open(0x%05lx)\n",
1460
/* ------------------------------------------------------------------- */
1461
/* upd_close: Release everything allocated in upd_open */
1462
/* ------------------------------------------------------------------- */
1465
upd_close(gx_device *pdev)
1467
upd_device *const udev = (upd_device *) pdev;
1468
const upd_p upd = udev->upd;
1472
#if UPD_MESSAGES & UPD_M_TOPCALLS
1473
errprintf(udev->memory,"CALL: upd_close(0x%05lx)\n",(long)pdev);
1476
/** If necessary, write the close-sequence **/
1478
if( upd && (( B_OPEN | B_OK4GO) ==
1479
((B_OPEN | B_OK4GO | B_ERROR) & upd->flags))) {
1481
if(udev->file && upd->strings && 0 < upd->strings[S_CLOSE].size)
1482
fwrite(upd->strings[S_CLOSE].data,1,
1483
upd->strings[S_CLOSE].size,udev->file);
1485
upd->flags &= ~B_OPEN;
1488
/** Then release the open-allocated memory */
1491
upd_close_writer(udev);
1494
gs_free(pdev->memory, upd->gsbuf,upd->ngsbuf,1,"uniprint/gsbuf");
1497
upd->flags &= ~B_BUF;
1499
upd_close_render(udev);
1500
upd_close_map(udev);
1502
UPD_MM_DEL_ARRAY(pdev->memory, upd->choice, countof(upd_choice), UPD_MM_DEL_VALUE);
1503
UPD_MM_DEL_ARRAY(pdev->memory, upd->ints, countof(upd_ints), UPD_MM_DEL_VALUE);
1504
UPD_MM_DEL_ARRAY(pdev->memory, upd->int_a, countof(upd_int_a), UPD_MM_DEL_PARAM);
1505
UPD_MM_DEL_ARRAY(pdev->memory, upd->strings, countof(upd_strings), UPD_MM_DEL_PARAM);
1506
UPD_MM_DEL_ARRAY(pdev->memory, upd->string_a,countof(upd_string_a),UPD_MM_DEL_APARAM);
1507
UPD_MM_DEL_ARRAY(pdev->memory, upd->float_a, countof(upd_float_a), UPD_MM_DEL_PARAM);
1509
gs_free(pdev->memory, upd,sizeof(upd[0]),1,"uniprint");
1514
/** Then call the superclass close **/
1515
code = gdev_prn_close(pdev);
1516
error = error > code ? code : error;
1518
#if UPD_MESSAGES & UPD_M_TOPCALLS
1519
errprintf(pdev->memory,"RETURN: %d = upd_close(0x%05lx)\n",
1526
/* ------------------------------------------------------------------- */
1527
/* upd_get_params: Export Parameters to the Interpreter */
1528
/* ------------------------------------------------------------------- */
1530
#if UPD_MESSAGES & UPD_M_TOPCALLS
1531
#define UPD_EXIT_GET(Err,Dev,List) \
1533
errprintf(Dev->memory,"RETURN-%d: %d upd_get_params(0x%05lx,0x%05lx)\n", \
1534
__LINE__,Err,(long) Dev,(long) List); \
1535
return_error(Err); \
1538
#define UPD_EXIT_GET(Err,Dev,List) if(0 > Err) return_error(Err);
1542
upd_get_params(gx_device *pdev, gs_param_list *plist)
1544
upd_device *const udev = (upd_device *) pdev;
1545
const upd_p upd = udev->upd;
1548
#if UPD_MESSAGES & UPD_M_TOPCALLS
1549
errprintf(udev->memory,"CALL: upd_get_params(0x%05lx,0x%05lx)\n",
1550
(long) udev,(long) plist);
1553
/** Call the SuperClass-get_params at the beginning */
1554
error = gdev_prn_get_params((gx_device *)udev,plist);
1555
UPD_EXIT_GET(error,udev,plist);
1557
/** Export the version */
1558
if(upd_version) { /* Version-Export enabled */
1559
udev->upd_version.data = (const byte *) rcsid;
1560
udev->upd_version.size = strlen(rcsid);
1561
udev->upd_version.persistent = true;
1562
error = param_write_string(plist,upd_version,&udev->upd_version);
1563
UPD_EXIT_GET(error,udev,plist);
1564
} /* Version-Export enabled */
1566
/** Export the Named choices */
1567
for(i = 0; i < countof(upd_choice); ++i) {
1568
if(!upd_choice[i]) continue; /* Choice-Export disabled */
1569
if(upd && upd->choice && upd->choice[i]) {
1570
gs_param_string name;
1571
name.data = (const byte *) upd_choice[i][upd->choice[i]];
1572
name.size = strlen((const char *) name.data);
1573
name.persistent = true;
1574
error = param_write_name(plist,upd_choice[i][0],&name);
1576
error = param_write_null(plist,upd_choice[i][0]);
1578
UPD_EXIT_GET(error,udev,plist);
1581
/** Export the flags (bool) */
1582
for(i = 0; i < countof(upd_flags); ++i) {
1583
if(!upd_flags[i]) continue; /* Flag-Export disabled */
1585
bool value = upd->flags & ((uint32_t) 1 << i);
1586
error = param_write_bool(plist,upd_flags[i],&value);
1588
error = param_write_null(plist,upd_flags[i]);
1590
UPD_EXIT_GET(error,udev,plist);
1593
/** Export the ints */
1594
for(i = 0; i < countof(upd_ints); ++i) {
1595
if(!upd_ints[i]) continue; /* int-Export disabled */
1596
if(upd && upd->ints && upd->ints[i]) {
1597
int value = upd->ints[i];
1598
error = param_write_int( plist,upd_ints[i],&value);
1600
error = param_write_null(plist,upd_ints[i]);
1602
UPD_EXIT_GET(error,udev,plist);
1605
/** Export the int-arrays */
1606
for(i = 0; i < countof(upd_int_a); ++i) {
1607
if(!upd_int_a[i]) continue; /* int-Array-Export disabled */
1608
if(upd && upd->int_a && upd->int_a[i].size) {
1609
error = param_write_int_array( plist,upd_int_a[i],(upd->int_a+i));
1611
error = param_write_null(plist,upd_int_a[i]);
1613
UPD_EXIT_GET(error,udev,plist);
1616
/** Export the strings */
1617
for(i = 0; i < countof(upd_strings); ++i) {
1618
if(!upd_strings[i]) continue; /* String-Export disabled */
1619
if(upd && upd->strings && upd->strings[i].size) {
1620
error = param_write_string( plist,upd_strings[i],(upd->strings+i));
1622
error = param_write_null(plist,upd_strings[i]);
1624
UPD_EXIT_GET(error,udev,plist);
1627
/** Export the string-Arrays */
1628
for(i = 0; i < countof(upd_string_a); ++i) {
1629
if(!upd_string_a[i]) continue; /* String-Array-Export disabled */
1630
if(upd && upd->string_a && upd->string_a[i].size) {
1632
param_write_string_array( plist,upd_string_a[i],(upd->string_a+i));
1634
error = param_write_null(plist,upd_string_a[i]);
1636
UPD_EXIT_GET(error,udev,plist);
1639
/** Export the float-Arrays */
1640
for(i = 0; i < countof(upd_float_a); ++i) {
1641
if(!upd_float_a[i]) continue; /* Float-Array-Export disabled */
1642
if(upd && upd->float_a && upd->float_a[i].size) {
1644
param_write_float_array( plist,upd_float_a[i],(upd->float_a+i));
1646
error = param_write_null(plist,upd_float_a[i]);
1648
UPD_EXIT_GET(error,udev,plist);
1651
#if UPD_MESSAGES & UPD_M_TOPCALLS
1652
errprintf(udev->memory,"RETURN: %d = upd_get_params(0x%05lx,0x%05lx)\n",
1653
error,(long) udev,(long) plist);
1661
/* ------------------------------------------------------------------- */
1662
/* upd_put_params: Load Parameters into the device-structure */
1663
/* ------------------------------------------------------------------- */
1666
upd_put_params(gx_device *pdev, gs_param_list *plist)
1668
upd_device *const udev = (upd_device *) pdev;
1669
upd_p upd = udev->upd;
1670
int error = 0, code,i;
1672
float MarginsHWResolution[2],Margins[2];
1673
gx_device_color_info color_info;
1677
gs_param_int_array *int_a = NULL;
1678
gs_param_string *strings = NULL;
1679
gs_param_string_array *string_a = NULL;
1680
gs_param_float_array *float_a = NULL, mfa;
1683
Error is used for two purposes: either it holds a negative error
1684
code or it is used as a bitfield, that tells, which parameters
1685
were actually loaded. If any of the important parameters changed
1686
upd_put_params closes the device, since the real parameter-evaluation
1687
is carried out by upd_open.
1690
#define UPD_PUT_FLAGS 0x0002
1691
#define UPD_PUT_CHOICE 0x0004
1692
#define UPD_PUT_INTS 0x0008
1693
#define UPD_PUT_INT_A 0x0010
1694
#define UPD_PUT_STRINGS 0x0020
1695
#define UPD_PUT_STRING_A 0x0040
1696
#define UPD_PUT_FLOAT_A 0x0080
1697
#define UPD_PUT_CHANGEDSIZE 0x0100
1699
#if UPD_MESSAGES & UPD_M_TOPCALLS
1700
errprintf(udev->memory,"CALL: upd_put_params(0x%05lx,0x%05lx)\n",
1701
(long)udev,(long)plist);
1705
I consider the following part of upd_put_params a bad-nasty-hack-hack
1706
and i am uncertain, wether it really works in the intended way. I provide it
1707
just for the case someone is performing nasty-parameter-changes on the
1708
active device, especially switching the OutputFile. If this happens in
1709
a situation, where data were written to the file, but the termination
1710
sequence is required, the driver does it now. (If you want to know, why
1711
i am writing bad-nasty-hack-hack, visit http://www.zark.com )
1713
if(upd && (B_OPEN & udev->upd->flags) && (NULL != udev->file)) {
1715
gs_param_string fname = { NULL, 0, false };
1717
code = param_read_string(plist,"OutputFile",&fname);
1718
if((1 != code) && (0 != code)) {
1719
code = param_read_null(plist,"OutputFile");
1721
fname.data = (const byte *) "";
1727
strncmp((const char *)fname.data,udev->fname,fname.size)) {
1728
if(upd->strings && 0 < udev->upd->strings[S_CLOSE].size)
1729
fwrite(upd->strings[S_CLOSE].data,1,
1730
upd->strings[S_CLOSE].size,udev->file);
1732
upd->flags &= ~B_OPEN;
1735
/* Done with the bad-nasty-hack-hack */
1738
The next thing "upd_put_params" does, is a little strange too. It imports
1739
a readonly-parameter, the version-string. I do not know wether it is still
1740
required, but some versions of GHOSTSCRIPT disliked it very much, if an
1741
existing parameter was not touched by the put-operation.
1743
On the other hand it is the right time to show the basic-outline of the
1744
parameter-importing flow. Basically the proper "param_read"-procedure
1745
is called. If it indicated, that the parameter was present, but of the
1746
wrong type, a read for the null-type is attempted, which is by convention
1747
somehow an reset to default. This sequence is applied to all the parameters
1748
and in case of the array-parameters, a succesful null-read is marked by
1749
setting data and size to 0.
1751
#if UPD_MESSAGES & UPD_M_SETUP
1752
#define UPD_PARAM_READ(Param_read,Name,Object,Mem) \
1753
code = Param_read(plist,Name,&Object); \
1755
code = param_read_null(plist,Name); \
1756
if(0 == code) memset(&Object,0,sizeof(Object));\
1758
if(!code) errprintf(Mem, \
1759
"upd_put_params: retrieved parameter \"%s\"\n",\
1762
param_signal_error(plist,Name,code); \
1763
if(error > code) error = code; \
1766
#define UPD_PARAM_READ(Param_read,Name,Object,Mem) \
1767
code = Param_read(plist,Name,&Object); \
1769
code = param_read_null(plist,Name); \
1770
if(0 == code) memset(&Object,0,sizeof(Object));\
1773
param_signal_error(plist,Name,code); \
1774
if(error > code) error = code; \
1778
UPD_PARAM_READ(param_read_string,upd_version,udev->upd_version,udev->memory)
1781
upd_put_params begins it's normal work by creating a copy, of
1782
the data, that it might change, except for color_info that might
1783
be changed in the device-structure, all manipulations are carried
1786
MarginsHWResolution[0] = udev->MarginsHWResolution[0];
1787
MarginsHWResolution[1] = udev->MarginsHWResolution[1];
1788
Margins[0] = udev->Margins[0];
1789
Margins[1] = udev->Margins[1];
1791
color_info = udev->color_info;
1794
UPD_MM_CPY_ARRAY(udev->memory, choice, upd->choice, countof(upd_choice),
1796
UPD_MM_CPY_ARRAY(udev->memory, ints, upd->ints, countof(upd_ints),
1798
UPD_MM_CPY_ARRAY(udev->memory, int_a, upd->int_a, countof(upd_int_a),
1800
UPD_MM_CPY_ARRAY(udev->memory, strings, upd->strings, countof(upd_strings),
1802
UPD_MM_CPY_ARRAY(udev->memory, string_a,upd->string_a,countof(upd_string_a),
1804
UPD_MM_CPY_ARRAY(udev->memory, float_a, upd->float_a, countof(upd_float_a),
1808
UPD_MM_GET_ARRAY(udev->memory, choice, countof(upd_choice));
1809
UPD_MM_GET_ARRAY(udev->memory, ints, countof(upd_ints));
1810
UPD_MM_GET_ARRAY(udev->memory, int_a, countof(upd_int_a));
1811
UPD_MM_GET_ARRAY(udev->memory, strings, countof(upd_strings));
1812
UPD_MM_GET_ARRAY(udev->memory, string_a,countof(upd_string_a));
1813
UPD_MM_GET_ARRAY(udev->memory, float_a, countof(upd_float_a));
1816
/** Import the Multiple-Choices */
1817
for(i = 0; countof(upd_choice) > i; ++i) {
1818
gs_param_string value = { NULL, 0, false};
1819
if(!upd_choice[i][0]) continue;
1820
UPD_PARAM_READ(param_read_name,upd_choice[i][0],value,udev->memory);
1822
if(0 <= error) error |= UPD_PUT_CHOICE;
1824
if(0 < value.size) {
1826
for(j = 1; upd_choice[i][j]; ++j) {
1827
if((strlen(upd_choice[i][j]) == value.size) &&
1828
(0 == strncmp(upd_choice[i][j],
1829
(const char *) value.data,value.size))) {
1838
/** Import the Boolean Values */
1839
for(i = 0; countof(upd_flags) > i; ++i) {
1840
uint32_t bit = (uint32_t) 1 << i;
1841
bool flag = flags & bit ? true : false;
1842
if(!upd_flags[i]) continue;
1843
UPD_PARAM_READ(param_read_bool,upd_flags[i],flag,udev->memory);
1845
if(0 <= error) error |= UPD_PUT_FLAGS;
1846
if(flag) flags |= bit;
1851
/** Import the Integer Values */
1852
for(i = 0; countof(upd_ints) > i; ++i) {
1853
int value = ints[i];
1854
if(!upd_ints[i]) continue;
1855
UPD_PARAM_READ(param_read_int,upd_ints[i],value,udev->memory);
1857
if(0 <= error) error |= UPD_PUT_INTS;
1862
/** Import the Integer Arrays */
1863
for(i = 0; countof(upd_int_a) > i; ++i) {
1864
gs_param_int_array value = int_a[i];
1865
if(!upd_int_a[i]) continue;
1866
UPD_PARAM_READ(param_read_int_array,upd_int_a[i],value,udev->memory);
1868
if(0 <= error) error |= UPD_PUT_INT_A;
1869
UPD_MM_DEL_PARAM(udev->memory, int_a[i]);
1874
UPD_MM_CPY_PARAM(udev->memory, int_a[i],value);
1879
/** Import the Strings */
1880
for(i = 0; countof(upd_strings) > i; ++i) {
1881
gs_param_string value = strings[i];
1882
if(!upd_strings[i]) continue;
1883
UPD_PARAM_READ(param_read_string,upd_strings[i],value,udev->memory);
1885
if(0 <= error) error |= UPD_PUT_STRINGS;
1886
UPD_MM_DEL_PARAM(udev->memory, strings[i]);
1891
UPD_MM_CPY_PARAM(udev->memory, strings[i],value);
1896
/** Import the String Arrays */
1897
for(i = 0; countof(upd_string_a) > i; ++i) {
1898
gs_param_string_array value = string_a[i];
1899
if(!upd_string_a[i]) continue;
1900
UPD_PARAM_READ(param_read_string_array,upd_string_a[i],value,udev->memory);
1902
if(0 <= error) error |= UPD_PUT_STRING_A;
1903
UPD_MM_DEL_APARAM(udev->memory, string_a[i]);
1906
string_a[i] = value;
1908
UPD_MM_CPY_APARAM(udev->memory, string_a[i],value);
1913
/** Import the Float Arrays */
1914
for(i = 0; countof(upd_float_a) > i; ++i) {
1915
gs_param_float_array value = float_a[i];
1916
if(!upd_float_a[i]) continue;
1917
UPD_PARAM_READ(param_read_float_array,upd_float_a[i],value,udev->memory);
1919
if(0 <= error) error |= UPD_PUT_FLOAT_A;
1920
UPD_MM_DEL_PARAM(udev->memory, float_a[i]);
1925
UPD_MM_CPY_PARAM(udev->memory, float_a[i],value);
1931
Prior to the call to the superclass-put_params, the memory-layout and
1932
the color-model needs adjustment. This is performed here, if any parameters
1934
In addition to that, Resolution & Margin-Parameters are tested & adjusted.
1938
int *ip,*ip2,ncomp,nbits;
1940
if(6 > int_a[IA_COLOR_INFO].size) {
1941
UPD_MM_DEL_PARAM(udev->memory, int_a[IA_COLOR_INFO]);
1942
UPD_MM_GET_ARRAY(udev->memory, int_a[IA_COLOR_INFO].data,6);
1943
int_a[IA_COLOR_INFO].size = 6;
1945
ip = (int *) upd_cast(int_a[IA_COLOR_INFO].data);
1947
if(0 == ip[0]) { /* Try to obtain num_components */
1948
switch(choice[C_MAPPER]) {
1949
case MAP_GRAY: ip[0] = 1; break;
1950
case MAP_RGBW: ip[0] = 3; break;
1951
case MAP_RGB: ip[0] = 3; break;
1952
case MAP_CMYK: ip[0] = 4; break;
1953
case MAP_CMYKGEN: ip[0] = 4; break;
1954
case MAP_RGBOV: ip[0] = 3; break;
1955
case MAP_RGBNOV: ip[0] = 3; break;
1956
default: ip[0] = color_info.num_components; break;
1958
} /* Try to obtain num_components */
1960
switch(choice[C_MAPPER]) {
1961
case MAP_GRAY: ncomp = 1; break;
1962
case MAP_RGBW: ncomp = 4; break;
1963
case MAP_RGB: ncomp = 3; break;
1964
case MAP_CMYK: ncomp = 4; break;
1965
case MAP_CMYKGEN: ncomp = 4; break;
1966
case MAP_RGBOV: ncomp = 4; break;
1967
case MAP_RGBNOV: ncomp = 4; break;
1968
default: ncomp = ip[0]; break;
1970
if(UPD_CMAP_MAX < ncomp) ncomp = UPD_CMAP_MAX;
1972
if(ncomp > int_a[IA_COMPBITS].size) { /* Default ComponentBits */
1973
UPD_MM_GET_ARRAY(udev->memory, ip2,ncomp);
1975
if(8 < nbits) nbits = 8;
1976
for(i = 0; i < ncomp; ++i) ip2[i] = nbits;
1977
UPD_MM_DEL_PARAM(udev->memory, int_a[IA_COMPBITS]);
1978
int_a[IA_COMPBITS].data = ip2;
1979
int_a[IA_COMPBITS].size = ncomp;
1980
} /* Default ComponentBits */
1982
if(ncomp > int_a[IA_COMPSHIFT].size) { /* Default ComponentShift */
1984
for(i = 0; i < ncomp; ++i) nbits += int_a[IA_COMPBITS].data[i];
1985
UPD_MM_GET_ARRAY(udev->memory, ip2,ncomp);
1986
for(i = 0; i < ncomp; ++i) {
1987
ip2[i] = nbits - int_a[IA_COMPBITS].data[i];
1988
nbits -= int_a[IA_COMPBITS].data[i];
1990
UPD_MM_DEL_PARAM(udev->memory, int_a[IA_COMPSHIFT]);
1991
int_a[IA_COMPSHIFT].data = ip2;
1992
int_a[IA_COMPSHIFT].size = ncomp;
1993
} /* Default ComponentShift */
1995
if(0 == ip[1]) { /* Try to compute the depth */
1997
for(i = 0; i < ncomp; ++i) {
1998
if(nbits < (int_a[IA_COMPBITS].data[i] +
1999
int_a[IA_COMPSHIFT].data[i]))
2000
nbits = int_a[IA_COMPBITS].data[i] +
2001
int_a[IA_COMPSHIFT].data[i];
2003
if( 1 >= nbits) nbits = 1;
2004
else if( 2 >= nbits) nbits = 2;
2005
else if( 4 >= nbits) nbits = 4;
2006
else if( 8 >= nbits) nbits = 8;
2007
else if(16 >= nbits) nbits = 16;
2008
else if(24 >= nbits) nbits = 24;
2013
} /* Try to compute the depth */
2015
if(0 == ip[2]) { /* Number of Gray-Levels */
2017
for(i = 0; i < ncomp; ++i) if(nbits < int_a[IA_COMPBITS].data[i])
2018
nbits = int_a[IA_COMPBITS].data[i];
2019
if(nbits > 8) nbits = 8;
2020
ip[2] = (1 << nbits) - 1;
2021
} /* Number of Gray-Levels */
2023
if(0 == ip[3] && 1 < ip[0]) { /* Number of Colors */
2025
for(i = 0; i < ip[0]; ++i) nbits += int_a[IA_COMPBITS].data[i];
2026
if(nbits > 8) nbits = 8;
2027
ip[3] = (1 << nbits) - 1;
2028
} /* Number of Colors */
2030
if(0 == ip[4]) { /* Gray-Ramp */
2032
for(i = 0; i < ncomp; ++i) if(nbits < int_a[IA_COMPBITS].data[i])
2033
nbits = int_a[IA_COMPBITS].data[i];
2034
if(2 < nbits) ip[4] = 256;
2038
if(0 == ip[5] && 1 < ip[0]) { /* Color-Ramp */
2040
for(i = 0; i < ncomp; ++i) if(nbits < int_a[IA_COMPBITS].data[i])
2041
nbits = int_a[IA_COMPBITS].data[i];
2042
if(2 < nbits) ip[5] = 256;
2046
udev->color_info.num_components = ip[0];
2047
udev->color_info.depth = ip[1];
2048
udev->color_info.max_gray = (gx_color_value) ip[2];
2049
udev->color_info.max_color = (gx_color_value) ip[3];
2050
udev->color_info.dither_grays = (gx_color_value) ip[4];
2051
udev->color_info.dither_colors = (gx_color_value) ip[5];
2054
* Now we're dealing with the Resolution- & Margin-Stuff
2055
* (This is close to be a bad-nasty-hack-hack)
2057
if((0 == param_read_float_array(plist,"HWResolution",&mfa)) &&
2058
(2 == mfa.size) && (0 != mfa.data)) {
2059
udev->MarginsHWResolution[0] = mfa.data[0];
2060
udev->MarginsHWResolution[1] = mfa.data[1];
2062
udev->MarginsHWResolution[0] = udev->HWResolution[0];
2063
udev->MarginsHWResolution[1] = udev->HWResolution[1];
2066
if((0 == param_read_float_array(plist,".HWMargins",&mfa)) &&
2067
(4 == mfa.size) && (0 != mfa.data)) {
2068
udev->Margins[0] = -mfa.data[0] * udev->MarginsHWResolution[0] / 72.0;
2069
udev->Margins[1] = -mfa.data[3] * udev->MarginsHWResolution[1] / 72.0;
2071
} /* Change the color-Info */
2073
/* Call the superclass-put_params now */
2074
code = gdev_prn_put_params((gx_device *)udev,plist);
2075
if(0 > code) error = code;
2078
If the superclass-"put_params" went o.k. too, then the new parameters are
2079
transferred into the device-structure. In the case of "uniprint", this may
2081
1. Close the device, which might fail.
2082
2. Allocate new memory for the upd-specific structure, that might fail too.
2085
/* *HGS* recognize a changed device geometry */
2086
if( udev->upd && /* HGS */
2087
((udev->width != udev->upd->pdwidth) || /* HGS */
2088
(udev->height != udev->upd->pdheight) )) /* HGS */
2089
error |= UPD_PUT_CHANGEDSIZE; /* HGS */
2091
if(0 < error && udev->is_open) {
2092
code = gs_closedevice((gx_device *)udev);
2093
if(0 > code) error = code;
2096
if(0 < error) { /* Actually something loaded without error */
2098
if(!(upd = udev->upd)) {
2099
UPD_MM_GET_ARRAY(udev->memory, udev->upd,1);
2102
UPD_MM_DEL_ARRAY(udev->memory, upd->choice, countof(upd_choice), UPD_MM_DEL_VALUE);
2103
UPD_MM_DEL_ARRAY(udev->memory, upd->ints, countof(upd_ints), UPD_MM_DEL_VALUE);
2104
UPD_MM_DEL_ARRAY(udev->memory, upd->int_a, countof(upd_int_a), UPD_MM_DEL_PARAM);
2105
UPD_MM_DEL_ARRAY(udev->memory, upd->strings, countof(upd_strings), UPD_MM_DEL_PARAM);
2106
UPD_MM_DEL_ARRAY(udev->memory, upd->string_a,countof(upd_string_a),UPD_MM_DEL_APARAM);
2107
UPD_MM_DEL_ARRAY(udev->memory, upd->float_a, countof(upd_float_a), UPD_MM_DEL_PARAM);
2110
upd->choice = choice;
2114
upd->strings = strings;
2115
upd->string_a = string_a;
2116
upd->float_a = float_a;
2117
upd->memory = udev->memory;
2119
if(0 < error) error = 0;
2123
udev->Margins[0] = Margins[0];
2124
udev->Margins[1] = Margins[1];
2125
udev->MarginsHWResolution[0] = MarginsHWResolution[0];
2126
udev->MarginsHWResolution[1] = MarginsHWResolution[1];
2128
udev->color_info = color_info;
2129
UPD_MM_DEL_ARRAY(udev->memory, choice, countof(upd_choice), UPD_MM_DEL_VALUE);
2130
UPD_MM_DEL_ARRAY(udev->memory, ints, countof(upd_ints), UPD_MM_DEL_VALUE);
2131
UPD_MM_DEL_ARRAY(udev->memory, int_a, countof(upd_int_a), UPD_MM_DEL_PARAM);
2132
UPD_MM_DEL_ARRAY(udev->memory, strings, countof(upd_strings), UPD_MM_DEL_PARAM);
2133
UPD_MM_DEL_ARRAY(udev->memory, string_a,countof(upd_string_a),UPD_MM_DEL_APARAM);
2134
UPD_MM_DEL_ARRAY(udev->memory, float_a, countof(upd_float_a), UPD_MM_DEL_PARAM);
2139
* upd_put_params keeps the Procedures upd to date
2142
upd_procs_map(udev);
2144
#if UPD_MESSAGES & UPD_M_TOPCALLS
2145
errprintf(udev->memory,"RETURN: %d = upd_put_params(0x%05lx,0x%05lx)\n",
2146
error,(long) udev, (long) plist);
2152
/* ------------------------------------------------------------------- */
2153
/* upd_cmyk_icolor: KCMY->KCMY-Index Mapping */
2154
/* ------------------------------------------------------------------- */
2156
The next Routines, that follow, are the color-mapping routines.
2157
GHOSTSCRIPT talks about "gx_color_values" and the driver has
2158
to merge the 1, 3 or four values into up to 32 Bits, that means
2159
it is necessary to do some truncation and shifting. For the truncation
2160
"uniprint" uses the internal function "upd_truncate" and "upd_expand"
2161
reverses this in the reverse-mapping procedures.
2164
static gx_color_index
2165
upd_cmyk_icolor(gx_device *pdev, const gx_color_value cv[])
2167
const upd_p upd = ((upd_device *)pdev)->upd;
2169
gx_color_value c, m, y, k;
2170
c = cv[0]; m = cv[1]; y = cv[2]; k = cv[3];
2173
All 4-Component-Modi have to deal with the Problem, that a value
2174
with all bits set can be produced, which is treated as an error-return
2175
from the mapping-functions. But with RGBW or KCMY, there is a neat
2176
trick: Grayscale are transferred as RGB/CMY=0 and holding Data only
2177
in the W- or K-Component.
2180
if((c == m) && (m == y)) {
2182
rv = upd_truncate(upd,0,(gx_color_value)(c > k ? c : k));
2186
rv = upd_truncate(upd,0,k) | upd_truncate(upd,1,c)
2187
| upd_truncate(upd,2,m) | upd_truncate(upd,3,y);
2189
/* It might still become a "gx_no_color_value" due to truncation, thus: */
2191
if(rv == gx_no_color_index) rv ^= 1;
2194
#if UPD_MESSAGES & UPD_M_MAPCALLS
2195
errprintf(pdev->memory,
2196
"cmyk_icolor: (%5.1f,%5.1f,%5.1f,%5.1f) : (%5.1f,%5.1f,%5.1f,%5.1f) : 0x%0*lx\n",
2197
255.0 * (double) c / (double) gx_max_color_value,
2198
255.0 * (double) m / (double) gx_max_color_value,
2199
255.0 * (double) y / (double) gx_max_color_value,
2200
255.0 * (double) k / (double) gx_max_color_value,
2201
255.0 * (double) ((rv >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2202
/ (double) upd->cmap[1].bitmsk,
2203
255.0 * (double) ((rv >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2204
/ (double) upd->cmap[2].bitmsk,
2205
255.0 * (double) ((rv >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2206
/ (double) upd->cmap[3].bitmsk,
2207
255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2208
/ (double) upd->cmap[0].bitmsk,
2209
(pdev->color_info.depth + 3)>>2,rv);
2215
/* ------------------------------------------------------------------- */
2216
/* upd_icolor_rgb: Stored KCMY back to a RGB */
2217
/* ------------------------------------------------------------------- */
2220
upd_icolor_rgb(gx_device *pdev, gx_color_index color, gx_color_value prgb[3])
2222
const upd_p upd = ((upd_device *)pdev)->upd;
2223
gx_color_value c,m,y,k;
2226
* Expand to the Component-Values
2228
k = upd_expand(upd,0,color);
2229
c = upd_expand(upd,1,color);
2230
m = upd_expand(upd,2,color);
2231
y = upd_expand(upd,3,color);
2234
* Then Invert and subtract K from the colors
2236
prgb[0] = gx_max_color_value - c;
2237
if(prgb[0] > k) prgb[0] -= k;
2240
prgb[1] = gx_max_color_value - m;
2241
if(prgb[1] > k) prgb[1] -= k;
2244
prgb[2] = gx_max_color_value - y;
2245
if(prgb[2] > k) prgb[2] -= k;
2248
#if UPD_MESSAGES & UPD_M_MAPCALLS
2249
errprintf(pdev->memory,
2250
"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",
2251
(pdev->color_info.depth + 3)>>2,color,
2252
255.0 * (double) ((color >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2253
/ (double) upd->cmap[1].bitmsk,
2254
255.0 * (double) ((color >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2255
/ (double) upd->cmap[2].bitmsk,
2256
255.0 * (double) ((color >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2257
/ (double) upd->cmap[3].bitmsk,
2258
255.0 * (double) ((color >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2259
/ (double) upd->cmap[0].bitmsk,
2260
255.0 * (double) c / (double) gx_max_color_value,
2261
255.0 * (double) m / (double) gx_max_color_value,
2262
255.0 * (double) y / (double) gx_max_color_value,
2263
255.0 * (double) k / (double) gx_max_color_value,
2264
255.0 * (double) prgb[0] / (double) gx_max_color_value,
2265
255.0 * (double) prgb[1] / (double) gx_max_color_value,
2266
255.0 * (double) prgb[2] / (double) gx_max_color_value);
2272
/* ------------------------------------------------------------------- */
2273
/* upd_rgb_1color: Grayscale->Grayscale-index-Mapping */
2274
/* ------------------------------------------------------------------- */
2276
static gx_color_index
2277
upd_rgb_1color(gx_device *pdev, const gx_color_value cv[])
2279
const upd_p upd = ((upd_device *)pdev)->upd;
2284
rv = upd_truncate(upd,0,g);
2286
#if UPD_MESSAGES & UPD_M_MAPCALLS
2287
errprintf(pdev->memory,
2288
"rgb_1color: (%5.1f) : (%5.1f) : 0x%0*lx\n",
2289
255.0 * (double) g / (double) gx_max_color_value,
2290
255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2291
/ (double) upd->cmap[0].bitmsk,
2292
(pdev->color_info.depth + 3)>>2,rv);
2298
/* ------------------------------------------------------------------- */
2299
/* upd_1color_rgb: reversal of the above */
2300
/* ------------------------------------------------------------------- */
2303
upd_1color_rgb(gx_device *pdev, gx_color_index color, gx_color_value cv[1])
2305
const upd_p upd = ((upd_device *)pdev)->upd;
2307
* Actual task: expand to full range of gx_color_value
2309
cv[0] = upd_expand(upd,0,color);
2311
#if UPD_MESSAGES & UPD_M_MAPCALLS
2312
errprintf(pdev->memory,"1color_rgb: 0x%0*lx -> %5.1f -> (%5.1f,%5.1f,%5.1f)\n",
2313
(pdev->color_info.depth + 3)>>2,color,
2314
255.0 * (double) ((color >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2315
/ (double) upd->cmap[0].bitmsk,
2316
255.0 * (double) prgb[0] / (double) gx_max_color_value,
2317
255.0 * (double) prgb[0] / (double) gx_max_color_value,
2318
255.0 * (double) prgb[0] / (double) gx_max_color_value);
2324
/* ------------------------------------------------------------------- */
2325
/* upd_rgb_3color: component-wise RGB->RGB-Mapping */
2326
/* ------------------------------------------------------------------- */
2328
static gx_color_index
2329
upd_rgb_3color(gx_device *pdev, const gx_color_value cv[])
2331
const upd_p upd = ((upd_device *)pdev)->upd;
2333
gx_color_value r, g, b;
2334
r = cv[0]; g = cv[1]; b = cv[2];
2336
rv = upd_truncate(upd,0,r) | upd_truncate(upd,1,g) | upd_truncate(upd,2,b);
2337
if(rv == gx_no_color_index) rv ^= 1;
2339
#if UPD_MESSAGES & UPD_M_MAPCALLS
2340
errprintf(pdev->memory,
2341
"rgb_3color: (%5.1f,%5.1f,%5.1f) : (%5.1f,%5.1f,%5.1f) : 0x%0*lx\n",
2342
255.0 * (double) r / (double) gx_max_color_value,
2343
255.0 * (double) g / (double) gx_max_color_value,
2344
255.0 * (double) b / (double) gx_max_color_value,
2345
255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2346
/ (double) upd->cmap[0].bitmsk,
2347
255.0 * (double) ((rv >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2348
/ (double) upd->cmap[1].bitmsk,
2349
255.0 * (double) ((rv >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2350
/ (double) upd->cmap[2].bitmsk,
2351
(pdev->color_info.depth + 3)>>2,rv);
2357
/* ------------------------------------------------------------------- */
2358
/* upd_3color_rgb: reversal of the above */
2359
/* ------------------------------------------------------------------- */
2362
upd_3color_rgb(gx_device *pdev, gx_color_index color, gx_color_value prgb[3])
2364
const upd_p upd = ((upd_device *)pdev)->upd;
2366
prgb[0] = upd_expand(upd,0,color);
2367
prgb[1] = upd_expand(upd,1,color);
2368
prgb[2] = upd_expand(upd,2,color);
2370
#if UPD_MESSAGES & UPD_M_MAPCALLS
2371
errprintf(pdev->memory,
2372
"3color_rgb: 0x%0*lx -> (%5.1f,%5.1f,%5.1f) -> (%5.1f,%5.1f,%5.1f)\n",
2373
(pdev->color_info.depth + 3)>>2,color,
2374
255.0 * (double) ((color >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2375
/ (double) upd->cmap[0].bitmsk,
2376
255.0 * (double) ((color >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2377
/ (double) upd->cmap[1].bitmsk,
2378
255.0 * (double) ((color >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2379
/ (double) upd->cmap[2].bitmsk,
2381
255.0 * (double) prgb[0] / (double) gx_max_color_value,
2382
255.0 * (double) prgb[1] / (double) gx_max_color_value,
2383
255.0 * (double) prgb[2] / (double) gx_max_color_value);
2389
/* ------------------------------------------------------------------- */
2390
/* upd_rgb_4color: Create an WRGB-Index from RGB */
2391
/* ------------------------------------------------------------------- */
2393
static gx_color_index
2394
upd_rgb_4color(gx_device *pdev, const gx_color_value cv[])
2396
const upd_p upd = ((upd_device *)pdev)->upd;
2398
gx_color_value r, g, b;
2400
r = cv[0]; g = cv[1]; b = cv[2];
2402
if((r == g) && (g == b)) {
2404
rv = upd_truncate(upd,0,r);
2408
gx_color_value w = g < r ? g : r; w = w < b ? w : b; /* Minimum */
2410
rv = upd_truncate(upd,0,w) | upd_truncate(upd,1,r) |
2411
upd_truncate(upd,2,g) | upd_truncate(upd,3,b);
2413
/* It might still become a "gx_no_color_value" due to truncation, thus: */
2415
if(rv == gx_no_color_index) rv ^= 1;
2418
#if UPD_MESSAGES & UPD_M_MAPCALLS
2419
errprintf(pdev->memory,
2420
"rgb_4color: (%5.1f,%5.1f,%5.1f) : (%5.1f,%5.1f,%5.1f,%5.1f) : 0x%0*lx\n",
2421
255.0 * (double) r / (double) gx_max_color_value,
2422
255.0 * (double) g / (double) gx_max_color_value,
2423
255.0 * (double) b / (double) gx_max_color_value,
2424
255.0 * (double) ((rv >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2425
/ (double) upd->cmap[1].bitmsk,
2426
255.0 * (double) ((rv >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2427
/ (double) upd->cmap[2].bitmsk,
2428
255.0 * (double) ((rv >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2429
/ (double) upd->cmap[3].bitmsk,
2430
255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2431
/ (double) upd->cmap[0].bitmsk,
2432
(pdev->color_info.depth + 3)>>2,rv);
2438
/* ------------------------------------------------------------------- */
2439
/* upd_4color_rgb: Stored WRGB-Index back to a RGB */
2440
/* ------------------------------------------------------------------- */
2443
upd_4color_rgb(gx_device *pdev, gx_color_index color, gx_color_value prgb[3])
2445
const upd_p upd = ((upd_device *)pdev)->upd;
2448
* Expand to the Component-Values
2450
prgb[0] = upd_expand(upd,1,color);
2451
prgb[1] = upd_expand(upd,2,color);
2452
prgb[2] = upd_expand(upd,3,color);
2454
/* Revert our Grayscale-Trick: */
2455
if(!(prgb[0] || prgb[1] || prgb[2]))
2456
prgb[0] = prgb[1] = prgb[2] = upd_expand(upd,0,color);
2458
#if UPD_MESSAGES & UPD_M_MAPCALLS
2459
errprintf(pdev->memory,
2460
"4color_rgb: 0x%0*lx -> (%5.1f,%5.1f,%5.1f,%5.1f) -> (%5.1f,%5.1f,%5.1f)\n",
2461
(pdev->color_info.depth + 3)>>2,color,
2462
255.0 * (double) ((color >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2463
/ (double) upd->cmap[1].bitmsk,
2464
255.0 * (double) ((color >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2465
/ (double) upd->cmap[2].bitmsk,
2466
255.0 * (double) ((color >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2467
/ (double) upd->cmap[3].bitmsk,
2468
255.0 * (double) ((color >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2469
/ (double) upd->cmap[0].bitmsk,
2470
255.0 * (double) prgb[0] / (double) gx_max_color_value,
2471
255.0 * (double) prgb[1] / (double) gx_max_color_value,
2472
255.0 * (double) prgb[2] / (double) gx_max_color_value);
2478
/* ------------------------------------------------------------------- */
2479
/* upd_cmyk_kcolor: KCMY->KCMY-Index Mapping with Black Generation */
2480
/* ------------------------------------------------------------------- */
2482
static gx_color_index
2483
upd_cmyk_kcolor(gx_device *pdev, const gx_color_value cv[])
2485
const upd_p upd = ((upd_device *)pdev)->upd;
2487
gx_color_value black;
2489
gx_color_value c, m, y, k;
2490
c = cv[0]; m = cv[1]; y = cv[2]; k = cv[3];
2492
if((c == m) && (m == y)) {
2494
black = c > k ? c : k;
2495
rv = upd_truncate(upd,0,black);
2499
if(k && !(c | m | y)) {
2502
black = c < m ? c : m;
2503
black = black < y ? black : y;
2506
rv = upd_truncate(upd,0,black) | upd_truncate(upd,1,c)
2507
| upd_truncate(upd,2,m) | upd_truncate(upd,3,y);
2509
/* It might still become a "gx_no_color_value" due to truncation, thus: */
2511
if(rv == gx_no_color_index) rv ^= 1;
2514
#if UPD_MESSAGES & UPD_M_MAPCALLS
2515
errprintf(pdev->memory,
2516
"cmyk_kcolor: (%5.1f,%5.1f,%5.1f,%5.1f) : (%5.1f,%5.1f,%5.1f,%5.1f) : 0x%0*lx\n",
2517
255.0 * (double) c / (double) gx_max_color_value,
2518
255.0 * (double) m / (double) gx_max_color_value,
2519
255.0 * (double) y / (double) gx_max_color_value,
2520
255.0 * (double) k / (double) gx_max_color_value,
2521
255.0 * (double) ((rv >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2522
/ (double) upd->cmap[1].bitmsk,
2523
255.0 * (double) ((rv >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2524
/ (double) upd->cmap[2].bitmsk,
2525
255.0 * (double) ((rv >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2526
/ (double) upd->cmap[3].bitmsk,
2527
255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2528
/ (double) upd->cmap[0].bitmsk,
2529
(pdev->color_info.depth + 3)>>2,rv);
2535
/* ------------------------------------------------------------------- */
2536
/* upd_kcolor_rgb: Stored CMY+generated K back to a RGB */
2537
/* ------------------------------------------------------------------- */
2540
upd_kcolor_rgb(gx_device *pdev, gx_color_index color, gx_color_value prgb[3])
2542
const upd_p upd = ((upd_device *)pdev)->upd;
2543
gx_color_value c,m,y,k;
2546
* Expand to the Component-Values
2548
k = upd_expand(upd,0,color);
2549
c = upd_expand(upd,1,color);
2550
m = upd_expand(upd,2,color);
2551
y = upd_expand(upd,3,color);
2554
* Check for plain Gray-Values
2558
prgb[2] = prgb[1] = prgb[0] = gx_max_color_value - k;
2561
prgb[0] = gx_max_color_value - c;
2562
prgb[1] = gx_max_color_value - m;
2563
prgb[2] = gx_max_color_value - y;
2566
#if UPD_MESSAGES & UPD_M_MAPCALLS
2567
errprintf(pdev->memory,
2568
"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",
2569
(pdev->color_info.depth + 3)>>2,color,
2570
255.0 * (double) ((color >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2571
/ (double) upd->cmap[1].bitmsk,
2572
255.0 * (double) ((color >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2573
/ (double) upd->cmap[2].bitmsk,
2574
255.0 * (double) ((color >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2575
/ (double) upd->cmap[3].bitmsk,
2576
255.0 * (double) ((color >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2577
/ (double) upd->cmap[0].bitmsk,
2578
255.0 * (double) c / (double) gx_max_color_value,
2579
255.0 * (double) m / (double) gx_max_color_value,
2580
255.0 * (double) y / (double) gx_max_color_value,
2581
255.0 * (double) k / (double) gx_max_color_value,
2582
255.0 * (double) prgb[0] / (double) gx_max_color_value,
2583
255.0 * (double) prgb[1] / (double) gx_max_color_value,
2584
255.0 * (double) prgb[2] / (double) gx_max_color_value);
2590
/* ------------------------------------------------------------------- */
2591
/* upd_rgb_ovcolor: Create an KCMY-Index from RGB */
2592
/* ------------------------------------------------------------------- */
2594
static gx_color_index
2595
upd_rgb_ovcolor(gx_device *pdev, const gx_color_value cv[])
2597
const upd_p upd = ((upd_device *)pdev)->upd;
2599
gx_color_value c,m,y,black;
2600
gx_color_value r, g, b;
2601
r = cv[0]; g = cv[1]; b = cv[2];
2602
if((r == g) && (g == b)) {
2604
black = gx_max_color_value - r;
2605
rv = upd_truncate(upd,0,black);
2610
c = gx_max_color_value - r;
2611
m = gx_max_color_value - g;
2612
y = gx_max_color_value - b;
2614
black = c < m ? c : m;
2615
black = black < y ? black : y;
2617
if(black != gx_max_color_value) {
2620
d = (float)(gx_max_color_value - black);
2622
tmp = (float) (c-black) / d;
2623
if( 0.0 > tmp) tmp = 0.0;
2624
else if( 1.0 < tmp) tmp = 1.0;
2625
c = (gx_color_value)(tmp * gx_max_color_value + 0.499);
2627
tmp = (float) (m-black) / d;
2628
if( 0.0 > tmp) tmp = 0.0;
2629
else if( 1.0 < tmp) tmp = 1.0;
2630
m = (gx_color_value)(tmp * gx_max_color_value + 0.499);
2632
tmp = (float) (y-black) / d;
2633
if( 0.0 > tmp) tmp = 0.0;
2634
else if( 1.0 < tmp) tmp = 1.0;
2635
y = (gx_color_value)(tmp * gx_max_color_value + 0.499);
2639
c = m = y = gx_max_color_value;
2643
rv = upd_truncate(upd,0,black) | upd_truncate(upd,1,c) |
2644
upd_truncate(upd,2,m) | upd_truncate(upd,3,y);
2646
/* It might still become a "gx_no_color_value" due to truncation, thus: */
2648
if(rv == gx_no_color_index) rv ^= 1;
2651
#if UPD_MESSAGES & UPD_M_MAPCALLS
2652
errprintf(pdev->memory,
2653
"rgb_ovcolor: (%5.1f,%5.1f,%5.1f) : (%5.1f,%5.1f,%5.1f,%5.1f) : 0x%0*lx\n",
2654
255.0 * (double) r / (double) gx_max_color_value,
2655
255.0 * (double) g / (double) gx_max_color_value,
2656
255.0 * (double) b / (double) gx_max_color_value,
2657
255.0 * (double) ((rv >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2658
/ (double) upd->cmap[1].bitmsk,
2659
255.0 * (double) ((rv >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2660
/ (double) upd->cmap[2].bitmsk,
2661
255.0 * (double) ((rv >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2662
/ (double) upd->cmap[3].bitmsk,
2663
255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2664
/ (double) upd->cmap[0].bitmsk,
2665
(pdev->color_info.depth + 3)>>2,rv);
2671
/* ------------------------------------------------------------------- */
2672
/* upd_rgb_novcolor: Create an KCMY-Index from RGB */
2673
/* ------------------------------------------------------------------- */
2675
static gx_color_index
2676
upd_rgb_novcolor(gx_device *pdev, const gx_color_value cv[])
2678
const upd_p upd = ((upd_device *)pdev)->upd;
2680
gx_color_value c,m,y,black;
2681
gx_color_value r, g, b;
2682
r = cv[0]; g = cv[1]; b = cv[2];
2684
if((r == g) && (g == b)) {
2686
black = gx_max_color_value - r;
2687
rv = upd_truncate(upd,0,black);
2692
c = gx_max_color_value - r;
2693
m = gx_max_color_value - g;
2694
y = gx_max_color_value - b;
2696
black = c < m ? c : m;
2697
black = black < y ? black : y;
2702
rv = upd_truncate(upd,0,black) | upd_truncate(upd,1,c) |
2703
upd_truncate(upd,2,m) | upd_truncate(upd,3,y);
2705
/* It might still become a "gx_no_color_value" due to truncation, thus: */
2707
if(rv == gx_no_color_index) rv ^= 1;
2710
#if UPD_MESSAGES & UPD_M_MAPCALLS
2711
errprintf(pdev->memory,
2712
"rgb_ovcolor: (%5.1f,%5.1f,%5.1f) : (%5.1f,%5.1f,%5.1f,%5.1f) : 0x%0*lx\n",
2713
255.0 * (double) r / (double) gx_max_color_value,
2714
255.0 * (double) g / (double) gx_max_color_value,
2715
255.0 * (double) b / (double) gx_max_color_value,
2716
255.0 * (double) ((rv >> upd->cmap[1].bitshf) & upd->cmap[1].bitmsk)
2717
/ (double) upd->cmap[1].bitmsk,
2718
255.0 * (double) ((rv >> upd->cmap[2].bitshf) & upd->cmap[2].bitmsk)
2719
/ (double) upd->cmap[2].bitmsk,
2720
255.0 * (double) ((rv >> upd->cmap[3].bitshf) & upd->cmap[3].bitmsk)
2721
/ (double) upd->cmap[3].bitmsk,
2722
255.0 * (double) ((rv >> upd->cmap[0].bitshf) & upd->cmap[0].bitmsk)
2723
/ (double) upd->cmap[0].bitmsk,
2724
(pdev->color_info.depth + 3)>>2,rv);
2730
/* ------------------------------------------------------------------- */
2731
/* NOTE: Beyond this point only "uniprint"-special-items. */
2732
/* ------------------------------------------------------------------- */
2734
/* ------------------------------------------------------------------- */
2735
/* Truncate a gx_color_value to the desired number of bits. */
2736
/* ------------------------------------------------------------------- */
2739
upd_truncate(upd_pc upd,int i,gx_color_value v) {
2740
const updcmap_pc cmap = upd->cmap + i;
2741
int32_t s; /* step size */
2742
gx_color_value *p; /* value-pointer */
2744
if(0 == cmap->bits) { /* trivial case */
2748
} else if(gx_color_value_bits > cmap->bits) { /* really truncate ? */
2750
p = cmap->code + ((cmap->bitmsk + 1) >> 1);
2751
s = ((cmap->bitmsk + 1) >> 2);
2753
* Perform search in monotonic code-array
2756
if(v > *p) { /* we're below */
2758
} else if(v < p[-1]) { /* we're ahead for sure */
2761
/* years ago, i knew what this was good for */
2762
if((v-p[-1]) < (p[0]-v)) p -= 1;
2767
if((v-p[-1]) < (p[0]-v)) p -= 1;
2771
if(!cmap->rise) v = cmap->bitmsk - v; /* Again reverse, if necessary */
2773
return ((uint32_t) v) << cmap->bitshf;
2776
/* ------------------------------------------------------------------- */
2777
/* upd_open_map: install the color-mapping */
2778
/* ------------------------------------------------------------------- */
2781
upd_open_map(upd_device *udev)
2783
const upd_p upd = udev->upd;
2786
/** _always_ initialize crucial Values! */
2787
for(imap = 0; UPD_CMAP_MAX > imap; ++imap) upd->cmap[imap].code = NULL;
2790
/** There should not be an error yet */
2791
if(B_ERROR & upd->flags) imap = 0;
2793
/** Establish the xfer-Indices */
2795
for(imap = 0; UPD_CMAP_MAX > imap; ++imap) {
2796
upd->cmap[imap].xfer = -1;
2797
upd->cmap[imap].bits = 0;
2799
switch(upd->choice[C_MAPPER]) {
2801
upd->cmap[0].xfer = FA_WXFER;
2804
upd->cmap[0].xfer = FA_WXFER;
2805
upd->cmap[1].xfer = FA_RXFER;
2806
upd->cmap[2].xfer = FA_GXFER;
2807
upd->cmap[3].xfer = FA_BXFER;
2810
upd->cmap[0].xfer = FA_RXFER;
2811
upd->cmap[1].xfer = FA_GXFER;
2812
upd->cmap[2].xfer = FA_BXFER;
2815
upd->cmap[0].xfer = FA_KXFER;
2816
upd->cmap[1].xfer = FA_CXFER;
2817
upd->cmap[2].xfer = FA_MXFER;
2818
upd->cmap[3].xfer = FA_YXFER;
2821
upd->cmap[0].xfer = FA_KXFER;
2822
upd->cmap[1].xfer = FA_CXFER;
2823
upd->cmap[2].xfer = FA_MXFER;
2824
upd->cmap[3].xfer = FA_YXFER;
2827
upd->cmap[0].xfer = FA_KXFER;
2828
upd->cmap[1].xfer = FA_CXFER;
2829
upd->cmap[2].xfer = FA_MXFER;
2830
upd->cmap[3].xfer = FA_YXFER;
2833
upd->cmap[0].xfer = FA_KXFER;
2834
upd->cmap[1].xfer = FA_CXFER;
2835
upd->cmap[2].xfer = FA_MXFER;
2836
upd->cmap[3].xfer = FA_YXFER;
2839
#if UPD_MESSAGES & UPD_M_WARNING
2840
if(upd_choice[C_MAPPER][0])
2841
errprintf(udev->memory,
2842
"upd_open_map: unsupported %s=%d\n",
2843
upd_choice[C_MAPPER][0],upd->choice[C_MAPPER]);
2845
errprintf(udev->memory,
2846
"upd_open_map: unsupported choce[%d]=%d\n",
2847
C_MAPPER,upd->choice[C_MAPPER]);
2854
/** The bit number sould be positive & fit into the storage */
2856
if(imap) { /* Check number of Bits & Shifts */
2858
#if UPD_MESSAGES & UPD_M_WARNING
2859
uint32_t used = 0,bitmsk;
2861
bool success = true;
2863
for(imap = 0; UPD_CMAP_MAX > imap; ++imap) {
2864
if(0 > upd->cmap[imap].xfer) continue;
2866
if((0 > upd->int_a[IA_COMPBITS].data[imap]) ||
2867
(gx_color_value_bits < upd->int_a[IA_COMPBITS].data[imap]) ||
2868
(0 > upd->int_a[IA_COMPSHIFT].data[imap]) ||
2869
(upd->int_a[IA_COMPBITS].data[imap] >
2870
(udev->color_info.depth - upd->int_a[IA_COMPSHIFT].data[imap]))) {
2871
#if UPD_MESSAGES & UPD_M_WARNING
2872
errprintf(udev->memory,
2873
"upd_open_map: %d Bits << %d is illegal for %d. Component\n",
2874
upd->int_a[IA_COMPBITS].data[imap],
2875
upd->int_a[IA_COMPSHIFT].data[imap],imap+1);
2886
if((NULL == upd->float_a[upd->cmap[imap].xfer].data) ||
2887
(2 > upd->float_a[upd->cmap[imap].xfer].size) ) {
2889
UPD_MM_DEL_PARAM(udev->memory, upd->float_a[upd->cmap[imap].xfer]);
2890
UPD_MM_GET_ARRAY(udev->memory, fp,2);
2893
upd->float_a[upd->cmap[imap].xfer].data = fp;
2894
upd->float_a[upd->cmap[imap].xfer].size = 2;
2896
n = upd->float_a[upd->cmap[imap].xfer].size-1;
2897
now = upd->float_a[upd->cmap[imap].xfer].data;
2900
if( *now < last) { /* Rising */
2903
if(last >= *now) break;
2906
} else if(*now > last) { /* Falling */
2909
if(last <= *now) break;
2912
} /* Monotony-check */
2915
#if UPD_MESSAGES & UPD_M_WARNING
2916
errprintf(udev->memory,
2917
"upd_open_map: %d. Component has non monoton Xfer\n",imap+1);
2923
#if UPD_MESSAGES & UPD_M_WARNING
2925
bitmsk = ((uint32_t) 1 << upd->int_a[IA_COMPBITS].data[imap]) -1;
2926
bitmsk <<= upd->int_a[IA_COMPSHIFT].data[imap];
2928
if(used & bitmsk) errprintf(udev->memory,
2929
"upd_open_map: %d. Component overlaps with others\n",imap+1);
2937
if(!success) imap = 0;
2939
} /* Check number of Bits */
2941
/** Do the allocation */
2945
for(imap = 0; UPD_CMAP_MAX > imap; ++imap) {
2946
if(0 > upd->cmap[imap].xfer) continue;
2948
upd->cmap[imap].bits = upd->int_a[IA_COMPBITS].data[imap];
2949
upd->cmap[imap].bitshf = upd->int_a[IA_COMPSHIFT].data[imap];
2950
upd->cmap[imap].bitmsk = 1;
2951
upd->cmap[imap].bitmsk <<= upd->cmap[imap].bits;
2952
upd->cmap[imap].bitmsk -= 1;
2953
upd->cmap[imap].rise =
2954
upd->float_a[upd->cmap[imap].xfer].data[0] <
2955
upd->float_a[upd->cmap[imap].xfer].data[
2956
upd->float_a[upd->cmap[imap].xfer].size-1] ?
2958
upd->cmap[imap].code = gs_malloc(udev->memory, upd->cmap[imap].bitmsk+1,
2959
sizeof(upd->cmap[imap].code[0]),"upd/code");
2960
if(!upd->cmap[imap].code) break;
2963
if(UPD_CMAP_MAX > imap) {
2967
#if UPD_MESSAGES & UPD_M_ERROR
2968
errprintf(udev->memory,
2969
"upd_open_map: could not allocate code-arrays\n");
2975
/** then fill the code-arrays */
2979
* Try making things easier: (than with stcolor)
2980
* normalize values to 0.0/1.0-Range
2981
* X-Axis: Color-Values (implied)
2982
* Y-Values: Indices (given)
2985
for(imap = 0; UPD_CMAP_MAX > imap; ++imap) {
2987
const updcmap_p cmap = upd->cmap + imap;
2989
float ystep,xstep,fx,fy;
2991
/* Variables & Macro for Range-Normalization */
2992
double offset,scale;
2993
#define XFVAL(I) ((upd->float_a[cmap->xfer].data[I]-offset)*scale)
2995
if(0 > cmap->xfer) continue;
2997
cmap->code[cmap->bitmsk] = gx_max_color_value;
2999
if(!cmap->bits) continue;
3001
offset = upd->float_a[cmap->xfer].data[0];
3002
if( 0.0 > offset) offset = 0.0;
3003
else if(1.0 < offset) offset = 1.0;
3005
scale = upd->float_a[cmap->xfer].data[upd->float_a[cmap->xfer].size-1];
3006
if( 0.0 > scale ) scale = 0.0;
3007
else if(1.0 < scale ) scale = 1.0;
3009
if(scale != offset) scale = 1.0 / (scale - offset);
3013
ystep = (float) 1.0 / (float) cmap->bitmsk;
3014
xstep = (float) 1.0 / (float)(upd->float_a[cmap->xfer].size - 1);
3017
for(ly = 0; ly <= cmap->bitmsk; ++ly) {
3019
fy = ystep * ly; /* Target-Value */
3021
while(((iy+2) < upd->float_a[cmap->xfer].size) &&
3022
(fy > XFVAL(iy+1))) ++iy;
3024
fx = iy + (fy - XFVAL(iy))/(XFVAL(iy+1) - XFVAL(iy));
3026
fx *= xstep * gx_max_color_value;
3028
fx = fx < 0.0 ? 0.0 :
3029
(fx > gx_max_color_value ? gx_max_color_value : fx);
3031
cmap->code[ly] = (gx_color_value)fx;
3032
if((fx - cmap->code[ly]) >= 0.5) cmap->code[ly] += 1;
3040
/** If we're ok, massage upd->ncomp */
3043
switch(upd->choice[C_MAPPER]) {
3045
if(1 > imap) imap = 0;
3048
case MAP_RGBW: /* RGB->RGBW */
3049
if(4 > imap) imap = 0;
3052
case MAP_RGB: /* Plain RGB */
3053
if(3 > imap) imap = 0;
3056
case MAP_CMYK: /* Plain KCMY */
3057
if(4 > imap) imap = 0;
3060
case MAP_CMYKGEN: /* KCMY with black-generation */
3061
if(4 > imap) imap = 0;
3064
case MAP_RGBOV: /* RGB->KCMY with black-generation */
3065
if(4 > imap) imap = 0;
3068
case MAP_RGBNOV: /* RGB->KCMY with black-generation */
3069
if(4 > imap) imap = 0;
3075
#if UPD_MESSAGES & UPD_M_WARNING
3076
errprintf(udev->memory,
3077
"upd_open: Mapping %d unknown\n",upd->choice[C_MAPPER]);
3084
/** If unsuccesful, install the default routines */
3087
upd_close_map(udev);
3089
upd->flags |= B_MAP;
3090
upd_procs_map(udev);
3093
return imap ? 1 : -1;
3096
/* ------------------------------------------------------------------- */
3097
/* upd_procs_map: (de-) install the color-mapping-procedures */
3098
/* ------------------------------------------------------------------- */
3101
upd_procs_map(upd_device *udev)
3106
(udev->upd->flags & B_MAP)) imap = udev->upd->choice[C_MAPPER];
3110
case MAP_GRAY: /* Grayscale -> Grayscale */
3111
set_dev_proc(udev,encode_color, upd_rgb_1color);
3112
set_dev_proc(udev,decode_color, upd_1color_rgb);
3113
set_dev_proc(udev,map_rgb_color, upd_rgb_1color);
3114
set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3115
set_dev_proc(udev,map_color_rgb, upd_1color_rgb);
3117
case MAP_RGBW: /* RGB->RGBW */
3118
set_dev_proc(udev,encode_color, upd_rgb_4color);
3119
set_dev_proc(udev,decode_color, upd_4color_rgb);
3120
set_dev_proc(udev,map_rgb_color, upd_rgb_4color);
3121
set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3122
set_dev_proc(udev,map_color_rgb, upd_4color_rgb);
3124
case MAP_RGB: /* Plain RGB */
3125
set_dev_proc(udev,encode_color, upd_rgb_3color);
3126
set_dev_proc(udev,decode_color, upd_3color_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);
3131
case MAP_CMYK: /* Plain KCMY */
3132
set_dev_proc(udev,encode_color, upd_cmyk_icolor);
3133
set_dev_proc(udev,decode_color, upd_icolor_rgb);
3134
set_dev_proc(udev,map_rgb_color, gx_default_map_rgb_color);
3135
set_dev_proc(udev,map_cmyk_color,upd_cmyk_icolor);
3136
set_dev_proc(udev,map_color_rgb, upd_icolor_rgb);
3138
case MAP_CMYKGEN: /* KCMY with black-generation */
3139
set_dev_proc(udev,encode_color, upd_cmyk_kcolor);
3140
set_dev_proc(udev,decode_color, upd_kcolor_rgb);
3141
set_dev_proc(udev,map_rgb_color, gx_default_map_rgb_color);
3142
set_dev_proc(udev,map_cmyk_color,upd_cmyk_kcolor);
3143
set_dev_proc(udev,map_color_rgb, upd_kcolor_rgb);
3145
case MAP_RGBOV: /* RGB -> KCMY with BG and UCR for CMYK-Output */
3146
set_dev_proc(udev,encode_color, upd_rgb_ovcolor);
3147
set_dev_proc(udev,decode_color, upd_ovcolor_rgb);
3148
set_dev_proc(udev,map_rgb_color, upd_rgb_ovcolor);
3149
set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3150
set_dev_proc(udev,map_color_rgb, upd_ovcolor_rgb);
3152
case MAP_RGBNOV: /* RGB -> KCMY with BG and UCR for CMY+K-Output */
3153
set_dev_proc(udev,encode_color, upd_rgb_novcolor);
3154
set_dev_proc(udev,decode_color, upd_novcolor_rgb);
3155
set_dev_proc(udev,map_rgb_color, upd_rgb_novcolor);
3156
set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3157
set_dev_proc(udev,map_color_rgb, upd_novcolor_rgb);
3161
set_dev_proc(udev,encode_color, gx_default_map_rgb_color);
3162
set_dev_proc(udev,decode_color, gx_default_map_color_rgb);
3163
set_dev_proc(udev,map_rgb_color, gx_default_map_rgb_color);
3164
set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3165
set_dev_proc(udev,map_color_rgb, gx_default_map_color_rgb);
3172
/* ------------------------------------------------------------------- */
3173
/* upd_close_map: remove color mapping */
3174
/* ------------------------------------------------------------------- */
3177
upd_close_map(upd_device *udev)
3179
const upd_p upd = udev->upd;
3184
for(imap = 0; UPD_CMAP_MAX > imap; ++imap) {
3186
if(upd->cmap[imap].code)
3187
gs_free(udev->memory, upd->cmap[imap].code,sizeof(upd->cmap[imap].code[0]),
3188
upd->cmap[imap].bitmsk+1,"upd/code");
3189
upd->cmap[imap].code = NULL;
3191
upd->cmap[imap].bitmsk = 0;
3192
upd->cmap[imap].bitshf = 0;
3193
upd->cmap[imap].bits = 0;
3194
upd->cmap[imap].rise = false;
3196
upd->flags &= ~B_MAP;
3199
upd_procs_map(udev);
3204
/* ------------------------------------------------------------------- */
3205
/* Functions for the rendering of data */
3206
/* ------------------------------------------------------------------- */
3209
Inside the main-upd-type are a "valbuf" and some unidentified
3210
pointers. This stuff is used in conjunction with the rendering,
3211
which is the process of converting gx_color_indices into something
3212
suitable for the device.
3216
/* ------------------------------------------------------------------- */
3217
/* upd_open_render: Initialize rendering */
3218
/* ------------------------------------------------------------------- */
3221
upd_open_render(upd_device *udev)
3223
const upd_p upd = udev->upd;
3226
/** Reset everything related to rendering */
3227
upd->flags &= ~B_RENDER;
3231
upd->start_render = NULL;
3232
for(icomp = 0; UPD_VALPTR_MAX > icomp; ++icomp) upd->valptr[icomp] = NULL;
3234
if( (B_BUF | B_MAP) ==
3235
((B_BUF | B_MAP | B_ERROR) & upd->flags)) {
3237
/** Establish the renderingwidth in upd */
3238
upd->rwidth = upd->gswidth;
3239
if((0 < upd->ints[I_PWIDTH]) &&
3240
(upd->gswidth > upd->ints[I_PWIDTH]) )
3241
upd->rwidth = upd->ints[I_PWIDTH];
3243
/** Call the Render-specific Open-Function */
3244
switch(upd->choice[C_RENDER]) {
3246
upd_open_fscomp(udev);
3249
upd_open_fscmyk(udev);
3252
upd_open_fscmy_k(udev);
3255
#if UPD_MESSAGES & UPD_M_WARNING
3256
errprintf(udev->memory, "upd_open_render: Unknown rendering type %d\n",
3257
upd->choice[C_RENDER]);
3263
if(B_RENDER != ((B_ERROR | B_RENDER) & upd->flags))
3264
upd_close_render(udev);
3269
/* ------------------------------------------------------------------- */
3270
/* upd_close_render: Deinitialize rendering */
3271
/* ------------------------------------------------------------------- */
3274
upd_close_render(upd_device *udev)
3276
const upd_p upd = udev->upd;
3281
if((upd->render == upd_fscomp) ||
3282
(upd->render == upd_fscmyk) ) upd_close_fscomp(udev);
3284
if((0 < upd->nvalbuf) && upd->valbuf)
3285
gs_free(udev->memory, upd->valbuf,upd->nvalbuf,sizeof(upd->valbuf[0]),"upd/valbuf");
3289
upd->flags &= ~B_RENDER;
3291
upd->start_render = NULL;
3292
for(icomp = 0; UPD_VALPTR_MAX > icomp; ++icomp) upd->valptr[icomp] = NULL;
3298
/* ------------------------------------------------------------------- */
3299
/* upd_open_fscomp: Initialize Component-Floyd-Steinberg */
3300
/* ------------------------------------------------------------------- */
3301
#if UPD_MESSAGES & UPD_M_FSBUF
3302
static int32_t fs_emin[UPD_VALPTR_MAX],fs_emax[UPD_VALPTR_MAX];
3305
upd_open_fscomp(upd_device *udev)
3307
const upd_p upd = udev->upd;
3308
int icomp,order[UPD_CMAP_MAX];
3310
#if UPD_MESSAGES & UPD_M_FSBUF
3311
for(icomp = 0; UPD_VALPTR_MAX < icomp; ++icomp)
3312
fs_emin[icomp] = fs_emax[icomp] = 0;
3318
(UPD_VALPTR_MAX < icomp) ||
3319
(UPD_CMAP_MAX < icomp) ) icomp = 0;
3322
This Version of the FS-algorithm works on the mapped components, but
3323
the printing-order might be different from the order dictated by the
3324
mapping-routines. The optional COMPORDER-Array is used for that. The
3325
initial test checks it's integrity.
3328
if(upd->ncomp <= upd->int_a[IA_COMPORDER].size) { /* Reordering */
3329
bool success = true;
3330
for(icomp = 0; upd->ncomp > icomp; ++icomp) {
3331
order[icomp] = upd->int_a[IA_COMPORDER].data[icomp];
3332
if((0 > order[icomp]) ||
3333
(UPD_CMAP_MAX <= order[icomp]) ) {
3335
#if UPD_MESSAGES & UPD_M_WARNING
3336
errprintf(udev->memory,
3337
"upd_open_fscomp: %d is illegal component-index\n",
3342
if(!success) icomp = 0;
3343
} else { /* Default-Ordering */
3344
for(icomp = 0; UPD_CMAP_MAX > icomp; ++icomp) order[icomp] = icomp;
3345
} /* Ordering defined */
3349
If anything was ok. up to now, memory get's allocated.
3353
for(icomp = 0; upd->ncomp > icomp; ++icomp) {
3354
upd->valptr[icomp] = gs_malloc(udev->memory, 1,sizeof(updcomp_t),"upd/fscomp");
3355
if(NULL == upd->valptr[icomp]) {
3356
#if UPD_MESSAGES & UPD_M_ERROR
3357
errprintf(udev->memory,
3358
"upd_open_fscomp: could not allocate %d. updcomp\n",
3370
need = (2 + upd->rwidth) * upd->ncomp;
3371
upd->valbuf = gs_malloc(udev->memory, need,sizeof(upd->valbuf[0]),"upd/valbuf");
3374
upd->nvalbuf = need;
3375
memset(upd->valbuf,0,need*sizeof(upd->valbuf[0]));
3377
#if UPD_MESSAGES & UPD_M_ERROR
3378
errprintf(udev->memory,
3379
"upd_open_fscomp: could not allocate %u words for valbuf\n",
3386
/* Still happy? then compute component-values */
3389
for(icomp = 0; upd->ncomp > icomp; ++icomp) {
3391
const updcomp_p comp = upd->valptr[icomp];
3392
const int32_t nsteps = upd->cmap[order[icomp]].bitmsk;
3394
int32_t highmod,highval;
3397
comp->threshold = nsteps;
3398
comp->spotsize = nsteps;
3401
comp->cmap = order[icomp];
3402
upd->cmap[comp->cmap].comp = icomp;
3403
comp->bits = upd->cmap[comp->cmap].bits;
3404
comp->bitshf = upd->cmap[comp->cmap].bitshf;
3405
comp->bitmsk = upd->cmap[comp->cmap].bitmsk;
3407
if(!nsteps) continue; /* A 0-Bit component is legal! */
3409
if(upd->cmap[comp->cmap].rise) {
3410
ymin = upd->float_a[upd->cmap[comp->cmap].xfer].data[0];
3411
ymax = upd->float_a[upd->cmap[comp->cmap].xfer].data[
3412
upd->float_a[upd->cmap[comp->cmap].xfer].size-1];
3414
ymax = upd->float_a[upd->cmap[comp->cmap].xfer].data[0];
3415
ymin = upd->float_a[upd->cmap[comp->cmap].xfer].data[
3416
upd->float_a[upd->cmap[comp->cmap].xfer].size-1];
3421
if(0.0 > ymax) ymax = 1.0 / (float) (nsteps+1);
3423
if(1.0 < ymax) ymax = 1.0;
3425
comp->spotsize = ((int32_t) 1 << 28) - 1;
3427
for(i = 0; i < 32; ++i) { /* Attempt Ideal */
3429
highval = (int32_t)((ymax-ymin) * (double) comp->spotsize + 0.5);
3431
if(!(highmod = highval % nsteps)) break; /* Gotcha */
3433
highval += nsteps - highmod;
3434
comp->spotsize = (int32_t)((double) highval / (ymax-ymin) + 0.5);
3436
if(!(comp->spotsize % 2)) comp->spotsize++;
3438
} /* Attempt Ideal */
3440
comp->offset = (int32_t)(ymin * (double) comp->spotsize + (double) 0.5);
3441
comp->scale = highval / nsteps;
3442
comp->threshold = comp->spotsize / 2;
3444
#if UPD_MESSAGES & UPD_M_SETUP
3445
errprintf(udev->memory,
3446
"Values for %d. Component after %d iterations\n",comp->cmap+1,i);
3447
errprintf(udev->memory,
3448
"steps: %10ld, Bits: %d\n",(long) comp->bitmsk,comp->bits);
3449
errprintf(udev->memory,
3450
"xfer: %10d Points, %s\n",
3451
upd->float_a[upd->cmap[comp->cmap].xfer].size,
3452
upd->cmap[comp->cmap].rise ? "rising" : "falling");
3453
errprintf(udev->memory,
3454
"offset: %10d 0x%08x\n",comp->offset,comp->offset);
3455
errprintf(udev->memory,
3456
"scale: %10d 0x%08x\n",comp->scale,comp->scale);
3457
errprintf(udev->memory,
3458
"threshold: %10d 0x%08x\n",comp->threshold,comp->threshold);
3459
errprintf(udev->memory,
3460
"spotsize: %10d 0x%08x\n",comp->spotsize,comp->spotsize);
3465
Optional Random Initialization of the value-Buffer
3467
if(icomp && !(B_FSZERO & upd->flags)) {
3468
for(icomp = 0; icomp < upd->ncomp; ++icomp) {
3469
const updcomp_p comp = upd->valptr[icomp];
3471
int32_t lv = INT32_MAX, hv = INT32_MIN, v;
3473
for(i = icomp; i < upd->nvalbuf; i += upd->ncomp) {
3479
scale = (float) comp->threshold / (float) (hv - lv);
3480
lv += (int32_t)(comp->threshold / (2*scale));
3481
for(i = icomp; i < upd->nvalbuf; i += upd->ncomp)
3482
upd->valbuf[i] = (int32_t)(scale * (upd->valbuf[i] - lv));
3487
The render-Routine acts as an indicator, which render-close is to use!
3489
upd->render = upd_fscomp;
3491
if(icomp) upd->flags |= B_RENDER;
3492
else upd->flags &= ~B_RENDER;
3497
/* ------------------------------------------------------------------- */
3498
/* upd_close_fscomp: Deinitialize Component-Floyd-Steinberg */
3499
/* ------------------------------------------------------------------- */
3502
upd_close_fscomp(upd_device *udev)
3504
const upd_p upd = udev->upd;
3507
#if UPD_MESSAGES & UPD_M_FSBUF
3508
if(upd && (upd->flags & B_RENDER)) {
3510
for(icomp = 0; icomp < upd->ncomp; ++icomp) {
3511
updcomp_p comp = upd->valptr[icomp];
3513
if(!comp->spotsize) continue;
3514
errprintf(udev->memory,"%d. Component: %6.3f <= error <= %6.3f\n",
3516
(double) fs_emin[icomp] / (double) comp->spotsize,
3517
(double) fs_emax[icomp] / (double) comp->spotsize);
3523
for(icomp = 0; UPD_VALPTR_MAX > icomp; ++icomp) {
3524
if(!upd->valptr[icomp]) continue;
3525
gs_free(udev->memory, upd->valptr[icomp],1,sizeof(updcomp_t),"upd/fscomp");
3526
upd->valptr[icomp] = NULL;
3530
/* ------------------------------------------------------------------- */
3531
/* upd_fscomp: Apply Floyd-Steinberg to each component */
3532
/* ------------------------------------------------------------------- */
3535
With UPD_M_FSBUF Max/Min-Values for the Errors are computed
3537
#if UPD_MESSAGES & UPD_M_FSBUF
3538
#define FS_M_ROWERR(I) \
3539
if(fs_emin[I] > rowerr[I]) fs_emin[I] = rowerr[I]; \
3540
if(fs_emax[I] < rowerr[I]) fs_emax[I] = rowerr[I];
3542
#define FS_M_ROWERR(I) ;
3545
FS_GOAL computes the desired Pixel-Value
3547
#define FS_GOAL(Raw,I) \
3548
pixel[I] = (int32_t)(Raw) * comp[I]->scale + comp[I]->offset \
3549
+ rowerr[I] + colerr[I] - ((colerr[I]+4)>>3); \
3550
if( pixel[I] < 0) pixel[I] = 0; \
3551
else if( pixel[I] > comp[I]->spotsize) pixel[I] = comp[I]->spotsize;
3554
* Distribute the error: prev now next
3556
* 3/16 5/16 1/16 Y+1
3558
#define FS_DIST(I) \
3559
if(!first) rowerr[I-dir] += ((3*pixel[I]+8)>>4); /* 3/16 */ \
3560
rowerr[I ] = ((5*pixel[I] )>>4) /* 5/16 */ \
3561
+ (( colerr[I]+4)>>3); /* 1/16 (rest) */ \
3562
colerr[I ] = pixel[I] /* 8/16 (neu) */ \
3563
- ((5*pixel[I] )>>4) \
3564
- ((3*pixel[I]+8)>>4);
3566
S_FSTEP adjusts the Indices (rowerr, bit and iword)
3571
if(0 > dir) { /* Reverse */ \
3572
if(!(bit <<= 1)) { bit = 0x01; ibyte--; }\
3573
} else { /* Forward */ \
3574
if(!(bit >>= 1)) { bit = 0x80; ibyte++; }\
3578
upd_fscomp(upd_p upd)
3580
const updscan_p scan = upd->scnbuf[upd->yscnbuf & upd->scnmsk];
3581
const updcomp_p *comp = (updcomp_p *) upd->valptr;
3582
int32_t *const pixel = upd->valbuf;
3583
int32_t *const colerr = pixel + upd->ncomp;
3584
int32_t *rowerr = colerr + upd->ncomp;
3585
int pwidth = upd->rwidth;
3587
int iblack,bblack,pxlset;
3592
* Erase the component-Data
3594
switch(upd->ncomp) {
3595
case 4: memset(scan[3].bytes,0,upd->nbytes);
3596
case 3: memset(scan[2].bytes,0,upd->nbytes);
3597
memset(scan[1].bytes,0,upd->nbytes);
3598
default: memset(scan[0].bytes,0,upd->nbytes);
3601
* determine the direction
3603
if(upd->flags & B_REVDIR) { /* This one reverse */
3605
if(upd->flags & B_YFLIP) {
3611
rowerr += upd->ncomp * (pwidth-1);
3612
bit = 0x80 >> ((pwidth-1) & 7);
3613
ibyte = (pwidth-1) >> 3;
3616
if(!(upd->flags & B_FSWHITE)) {
3618
while((0 < pwidth) && !upd_pxlget(upd)) pwidth--;
3623
} else { /* This one forward */
3625
if(upd->flags & B_YFLIP) {
3627
rowerr += upd->ncomp * (pwidth-1);
3628
bit = 0x80 >> ((pwidth-1) & 7);
3629
ibyte = (pwidth-1) >> 3;
3636
if(!(upd->flags & B_FSWHITE)) {
3638
while((0 < pwidth) && !upd_pxlget(upd)) pwidth--;
3643
} /* reverse or forward */
3645
* Toggle Direction, if not fixed
3647
if(!(upd->flags & B_FIXDIR)) upd->flags ^= B_REVDIR;
3649
* Skip over leading white-space
3651
if(!(upd->flags & B_FSWHITE)) {
3652
upd_proc_pxlget((*fun)) = upd->pxlget;
3653
byte *ptr = upd->pxlptr;
3654
while((0 < pwidth) && !upd_pxlget(upd)) {
3664
* Set iblack, if black-reduction is active
3668
if((4 == upd->ncomp) && (B_REDUCEK & upd->flags)) {
3669
iblack = upd->cmap[0].comp;
3673
* Process all Pixels
3676
while(0 < pwidth--) {
3678
* Execute FS-Algorithm for each active component
3681
ci = upd_pxlget(upd);
3682
switch(upd->ncomp) {
3683
case 4: FS_M_ROWERR(3)
3684
FS_GOAL(comp[3]->bitmsk & (ci >> comp[3]->bitshf),3)
3685
if(pixel[3] > comp[3]->threshold) { /* "Fire" */
3686
pixel[3] -= comp[3]->spotsize;
3687
scan[3].bytes[ibyte] |= bit;
3692
case 3: FS_M_ROWERR(2)
3693
FS_GOAL(comp[2]->bitmsk & (ci >> comp[2]->bitshf),2)
3694
if(pixel[2] > comp[2]->threshold) { /* "Fire" */
3695
pixel[2] -= comp[2]->spotsize;
3696
scan[2].bytes[ibyte] |= bit;
3702
FS_GOAL(comp[1]->bitmsk & (ci >> comp[1]->bitshf),1)
3703
if(pixel[1] > comp[1]->threshold) { /* "Fire" */
3704
pixel[1] -= comp[1]->spotsize;
3705
scan[1].bytes[ibyte] |= bit;
3710
default: FS_M_ROWERR(0)
3711
FS_GOAL(comp[0]->bitmsk & (ci >> comp[0]->bitshf),0)
3712
if(pixel[0] > comp[0]->threshold) { /* "Fire" */
3713
pixel[0] -= comp[0]->spotsize;
3714
scan[0].bytes[ibyte] |= bit;
3723
if(pxlset & bblack) pxlset |= 15;
3738
scan[0].bytes[ibyte] &= ~bit;
3739
scan[1].bytes[ibyte] &= ~bit;
3740
scan[2].bytes[ibyte] &= ~bit;
3741
scan[3].bytes[ibyte] &= ~bit;
3742
scan[iblack].bytes[ibyte] |= bit;
3747
* Adjust rowerr, bit & iword, depending on direction
3752
* Finally call the limits-Routine
3754
if(0 < upd->nlimits) upd_limits(upd,true);
3758
/* ------------------------------------------------------------------- */
3759
/* upd_open_fscmyk: Initialize Component-Floyd-Steinberg */
3760
/* ------------------------------------------------------------------- */
3763
upd_open_fscmyk(upd_device *udev)
3765
const upd_p upd = udev->upd;
3767
upd_open_fscomp(udev);
3769
if((B_RENDER & upd->flags) &&
3770
(4 == upd->ncomp) &&
3771
(8 <= upd->cmap[0].bits) && (24 == upd->cmap[0].bitshf) &&
3772
(8 <= upd->cmap[1].bits) && (16 == upd->cmap[1].bitshf) &&
3773
(8 <= upd->cmap[2].bits) && ( 8 == upd->cmap[2].bitshf) &&
3774
(8 <= upd->cmap[3].bits) && ( 0 == upd->cmap[3].bitshf) ) {
3775
upd->render = upd_fscmyk;
3777
upd->flags &= ~B_RENDER;
3782
/* ------------------------------------------------------------------- */
3783
/* upd_fscmyk: 32 Bit, K-CMY-Order Dithering */
3784
/* ------------------------------------------------------------------- */
3787
upd_fscmyk(upd_p upd)
3789
const updscan_p scan = upd->scnbuf[upd->yscnbuf & upd->scnmsk];
3790
int32_t *const pixel = upd->valbuf;
3791
const updcomp_p *comp = (updcomp_p *) upd->valptr;
3792
int32_t *const colerr = pixel + 4;
3793
int32_t *rowerr = colerr + 4;
3794
int32_t pwidth = upd->rwidth;
3799
* Erase the component-Data
3801
memset(scan[0].bytes,0,upd->nbytes);
3802
memset(scan[1].bytes,0,upd->nbytes);
3803
memset(scan[2].bytes,0,upd->nbytes);
3804
memset(scan[3].bytes,0,upd->nbytes);
3807
* determine the direction
3809
if(upd->flags & B_REVDIR) { /* This one reverse */
3811
if(!(upd->flags & B_FSWHITE)) {
3813
while(0 < pwidth && !*(uint32_t *)data) pwidth--, data += 4;
3815
if(0 < upd->nlimits) upd_limits(upd,false);
3820
data = upd->gsscan + 4 * (upd->rwidth-1);
3822
} else { /* This one forward */
3824
if(!(upd->flags & B_FSWHITE)) {
3825
data = upd->gsscan + 4 * (upd->rwidth-1);
3826
while(0 < pwidth && !*(uint32_t *)data) pwidth--, data -= 4;
3828
if(0 < upd->nlimits) upd_limits(upd,false);
3835
} /* reverse or forward */
3837
* Bits depend on FLIP & Direction
3839
if(!(B_REVDIR & upd->flags) == !(B_YFLIP & upd->flags)) {
3845
rowerr += 4 * (upd->rwidth-1);
3846
bit = 0x80 >> ((upd->rwidth-1) & 7);
3847
ibyte = (upd->rwidth-1) >> 3;
3851
* Toggle Direction, if not fixed
3853
if(!(upd->flags & B_FIXDIR)) upd->flags ^= B_REVDIR;
3855
* Skip over leading white-space
3857
if(!(upd->flags & B_FSWHITE)) {
3858
while(0 < pwidth && !*((uint32_t *)data)) {
3860
if(B_YFLIP & upd->flags) data -= dir;
3866
* Process all Pixels
3869
while(0 < pwidth--) {
3871
* Compute the Black-Value first
3873
FS_M_ROWERR(upd->cmap[0].comp) FS_GOAL(data[0],upd->cmap[0].comp);
3876
* Decide wether this is a color value
3878
if(data[1] || data[2] || data[3]) {
3880
FS_M_ROWERR(upd->cmap[1].comp) FS_GOAL(data[1],upd->cmap[1].comp)
3881
FS_M_ROWERR(upd->cmap[2].comp) FS_GOAL(data[2],upd->cmap[2].comp)
3882
FS_M_ROWERR(upd->cmap[3].comp) FS_GOAL(data[3],upd->cmap[3].comp)
3884
* if black fires, then all other components fire logically too
3886
if(pixel[upd->cmap[0].comp] > comp[upd->cmap[0].comp]->threshold) {
3888
pixel[0] -= comp[0]->spotsize;
3889
pixel[1] -= comp[1]->spotsize;
3890
pixel[2] -= comp[2]->spotsize;
3891
pixel[3] -= comp[3]->spotsize;
3892
scan[upd->cmap[0].comp].bytes[ibyte] |= bit;
3895
* if black is below threshold, only components with larger data-values
3896
* are allowed to fire
3898
} else { /* Restricted firing */
3900
if(( data[0] < data[1]) &&
3901
(pixel[upd->cmap[1].comp] >
3902
comp[upd->cmap[1].comp]->threshold)) { /* "Fire" */
3903
pixel[upd->cmap[1].comp] -= comp[upd->cmap[1].comp]->spotsize;
3904
scan[upd->cmap[1].comp].bytes[ibyte] |= bit;
3907
if(( data[0] < data[2]) &&
3908
(pixel[upd->cmap[2].comp] >
3909
comp[upd->cmap[2].comp]->threshold)) { /* "Fire" */
3910
pixel[upd->cmap[2].comp] -= comp[upd->cmap[2].comp]->spotsize;
3911
scan[upd->cmap[2].comp].bytes[ibyte] |= bit;
3914
if(( data[0] < data[3]) &&
3915
(pixel[upd->cmap[3].comp] >
3916
comp[upd->cmap[3].comp]->threshold)) { /* "Fire" */
3917
pixel[upd->cmap[3].comp] -= comp[upd->cmap[3].comp]->spotsize;
3918
scan[upd->cmap[3].comp].bytes[ibyte] |= bit;
3924
* Handle Color-Errors
3926
FS_DIST(upd->cmap[3].comp)
3927
FS_DIST(upd->cmap[2].comp)
3928
FS_DIST(upd->cmap[1].comp)
3930
} else if(pixel[upd->cmap[0].comp] > comp[upd->cmap[0].comp]->threshold) {
3931
scan[upd->cmap[0].comp].bytes[ibyte] |= bit;
3932
pixel[upd->cmap[0].comp] -= comp[upd->cmap[0].comp]->spotsize;
3935
FS_DIST(upd->cmap[0].comp)
3937
* Adjust bit & iword, depending on direction
3940
if(upd->flags & B_YFLIP) data -= dir;
3944
* Finally call the limits-Routine
3946
if(0 < upd->nlimits) upd_limits(upd,true);
3950
/* ------------------------------------------------------------------- */
3951
/* upd_open_fscmy_k: Initialize for CMY_K Printing */
3952
/* ------------------------------------------------------------------- */
3955
upd_open_fscmy_k(upd_device *udev)
3957
const upd_p upd = udev->upd;
3959
upd_open_fscomp(udev);
3961
if((B_RENDER & upd->flags) &&
3962
(4 == upd->ncomp)) {
3963
upd->render = upd_fscmy_k;
3965
upd->flags &= ~B_RENDER;
3970
/* ------------------------------------------------------------------- */
3971
/* upd_fscmy_k: CMY_K rendering */
3972
/* ------------------------------------------------------------------- */
3975
upd_fscmy_k(upd_p upd)
3977
const updscan_p scan = upd->scnbuf[upd->yscnbuf & upd->scnmsk];
3978
const updcomp_p *comp = (updcomp_p *) upd->valptr;
3979
int32_t *const pixel = upd->valbuf;
3980
int32_t *const colerr = pixel + upd->ncomp;
3981
int32_t *rowerr = colerr + upd->ncomp;
3982
int pwidth = upd->rwidth;
3988
* Erase the component-Data
3990
memset(scan[3].bytes,0,upd->nbytes);
3991
memset(scan[2].bytes,0,upd->nbytes);
3992
memset(scan[1].bytes,0,upd->nbytes);
3993
memset(scan[0].bytes,0,upd->nbytes);
3995
* determine the direction
3997
if(upd->flags & B_REVDIR) { /* This one reverse */
3999
if(upd->flags & B_YFLIP) {
4005
rowerr += 4 * (pwidth-1);
4006
bit = 0x80 >> ((pwidth-1) & 7);
4007
ibyte = (pwidth-1) >> 3;
4010
if(!(upd->flags & B_FSWHITE)) {
4012
while((0 < pwidth) && !upd_pxlget(upd)) pwidth--;
4017
} else { /* This one forward */
4019
if(upd->flags & B_YFLIP) {
4021
rowerr += 4 * (pwidth-1);
4022
bit = 0x80 >> ((pwidth-1) & 7);
4023
ibyte = (pwidth-1) >> 3;
4030
if(!(upd->flags & B_FSWHITE)) {
4032
while((0 < pwidth) && !upd_pxlget(upd)) pwidth--;
4037
} /* reverse or forward */
4039
* Toggle Direction, if not fixed
4041
if(!(upd->flags & B_FIXDIR)) upd->flags ^= B_REVDIR;
4043
* Skip over leading white-space
4045
if(!(upd->flags & B_FSWHITE)) {
4046
upd_proc_pxlget((*fun)) = upd->pxlget;
4047
byte *ptr = upd->pxlptr;
4048
while((0 < pwidth) && !upd_pxlget(upd)) {
4058
* Process all Pixels
4061
while(0 < pwidth--) {
4063
/* get the Pixel-Value */
4065
ci = upd_pxlget(upd);
4067
/* process all components */
4069
FS_M_ROWERR(0) FS_GOAL(comp[0]->bitmsk & (ci >> comp[0]->bitshf),0)
4070
FS_M_ROWERR(1) FS_GOAL(comp[1]->bitmsk & (ci >> comp[1]->bitshf),1)
4071
FS_M_ROWERR(2) FS_GOAL(comp[2]->bitmsk & (ci >> comp[2]->bitshf),2)
4072
FS_M_ROWERR(3) FS_GOAL(comp[3]->bitmsk & (ci >> comp[3]->bitshf),3)
4074
if(pixel[0] > comp[0]->threshold) { /* Black fires */
4076
pixel[0] -= comp[0]->spotsize;
4077
scan[0].bytes[ibyte] |= bit;
4079
} else { /* Colors may fire */
4081
if((pixel[1] <= comp[1]->threshold) ||
4082
(pixel[2] <= comp[2]->threshold) ||
4083
(pixel[3] <= comp[3]->threshold) ) { /* Really a Color */
4085
if(pixel[1] > comp[1]->threshold) {
4086
pixel[1] -= comp[1]->spotsize;
4087
scan[1].bytes[ibyte] |= bit;
4090
if(pixel[2] > comp[2]->threshold) {
4091
pixel[2] -= comp[2]->spotsize;
4092
scan[2].bytes[ibyte] |= bit;
4095
if(pixel[3] > comp[3]->threshold) {
4096
pixel[3] -= comp[3]->spotsize;
4097
scan[3].bytes[ibyte] |= bit;
4101
pixel[1] -= comp[1]->spotsize;
4102
pixel[2] -= comp[2]->spotsize;
4103
pixel[3] -= comp[3]->spotsize;
4104
scan[0].bytes[ibyte] |= bit;
4114
* Adjust rowerr, bit & iword, depending on direction
4119
* Finally call the limits-Routine
4121
if(0 < upd->nlimits) upd_limits(upd,true);
4125
/* ------------------------------------------------------------------- */
4126
/* upd_open_writer: Initialize rendering */
4127
/* ------------------------------------------------------------------- */
4130
upd_open_writer(upd_device *udev)
4132
const upd_p upd = udev->upd;
4133
bool success = true;
4135
/** Reset the crucial values */
4136
upd->start_writer = NULL;
4145
/** Rendering should be succesfully initialized */
4146
if(B_RENDER != ((B_RENDER | B_ERROR) & upd->flags))
4149
/** Create number of components */
4150
upd->ocomp = upd->ncomp;
4151
if(0 < upd->ints[I_OCOMP]) upd->ocomp = upd->ints[I_OCOMP];
4153
/** Massage some Parameters */
4156
/* Make sure, that Pass & Pin-Numbers are at least 1 */
4157
if(1 > upd->ints[I_NYPASS]) upd->ints[I_NYPASS] = 1;
4158
if(1 > upd->ints[I_NXPASS]) upd->ints[I_NXPASS] = 1;
4159
if(1 > upd->ints[I_PINS2WRITE]) upd->ints[I_PINS2WRITE] = 1;
4161
if((upd->ints[I_NXPASS] * upd->ints[I_NYPASS]) > upd->ints[I_NPASS])
4162
upd->ints[I_NPASS] = upd->ints[I_NXPASS] * upd->ints[I_NYPASS];
4164
/* Create Default noWeave-Feeds */
4166
if(upd->ints[I_NPASS] > upd->int_a[IA_STD_DY].size) {
4168
UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_STD_DY]);
4169
UPD_MM_GET_ARRAY(udev->memory, ip,upd->ints[I_NPASS]);
4170
upd->int_a[IA_STD_DY].data = ip;
4171
upd->int_a[IA_STD_DY].size = upd->ints[I_NPASS];
4173
for(iy = 1; iy < upd->ints[I_NYPASS]; ++iy) {
4174
for(ix = 1; ix < upd->ints[I_NXPASS]; ++ix) *ip++ = 0;
4177
for(ix = 1; ix < upd->ints[I_NXPASS]; ++ix) *ip++ = 0;
4178
*ip = upd->ints[I_NYPASS] * upd->ints[I_PINS2WRITE]
4179
- upd->ints[I_NYPASS] + 1;
4181
upd->ints[I_BEG_Y] = 0;
4182
upd->ints[I_END_Y] = upd->ints[I_PHEIGHT] ?
4183
upd->ints[I_PHEIGHT] : upd->gsheight;
4187
if(0 >= upd->ints[I_BEG_Y]) {
4188
if(0 < upd->int_a[IA_BEG_DY].size) {
4190
for(i = 0; i < upd->int_a[IA_BEG_DY].size; ++i)
4191
sum += upd->int_a[IA_BEG_DY].data[i];
4192
upd->ints[I_BEG_Y] = sum;
4194
upd->ints[I_BEG_Y] = 0;
4199
/* Arrgh, I knew, why I refused to provide defaults for crucial */
4200
/* parameters in uniprint. But o.k. it's nice for size-changing */
4201
/* PostScript-Code. Nevertheless, it's still not perfect. */
4203
if(0 >= upd->int_a[IA_ENDTOP].size ||
4204
0 >= upd->int_a[IA_END_DY].size ) upd->ints[I_END_Y] =
4205
upd->ints[I_PHEIGHT] ? upd->ints[I_PHEIGHT] : upd->gsheight;
4207
if(0 >= upd->ints[I_END_Y]) upd->ints[I_END_Y] = upd->ints[I_PHEIGHT] ?
4208
upd->ints[I_PHEIGHT] : upd->gsheight;
4210
/* Create Default X-Passes */
4212
if(0 >= upd->int_a[IA_STD_IX].size) {
4214
UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_STD_IX]);
4215
UPD_MM_GET_ARRAY(udev->memory, ip,upd->int_a[IA_STD_DY].size);
4216
upd->int_a[IA_STD_IX].data = ip;
4217
upd->int_a[IA_STD_IX].size = upd->int_a[IA_STD_DY].size;
4219
for(i = 0, ix = 0; i < upd->int_a[IA_STD_IX].size; ++i) {
4221
if(ix == upd->ints[I_NXPASS]) ix = 0;
4225
if((0 >= upd->int_a[IA_BEG_IX].size) &&
4226
(0 < upd->int_a[IA_BEG_DY].size) ) {
4228
UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_BEG_IX]);
4229
UPD_MM_GET_ARRAY(udev->memory, ip,upd->int_a[IA_BEG_DY].size);
4230
upd->int_a[IA_BEG_IX].data = ip;
4231
upd->int_a[IA_BEG_IX].size = upd->int_a[IA_BEG_DY].size;
4233
for(i = 0, ix = 0; i < upd->int_a[IA_BEG_IX].size; ++i) {
4235
if(ix == upd->ints[I_NXPASS]) ix = 0;
4239
if((0 >= upd->int_a[IA_END_IX].size) &&
4240
(0 < upd->int_a[IA_END_DY].size) ) {
4242
UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_END_IX]);
4243
UPD_MM_GET_ARRAY(udev->memory, ip,upd->int_a[IA_END_DY].size);
4244
upd->int_a[IA_END_IX].data = ip;
4245
upd->int_a[IA_END_IX].size = upd->int_a[IA_END_DY].size;
4247
for(i = 0, ix = 0; i < upd->int_a[IA_END_IX].size; ++i) {
4249
if(ix == upd->ints[I_NXPASS]) ix = 0;
4254
if(upd->ints[I_NPASS] > upd->int_a[IA_STD_DY].size) {
4255
#if UPD_MESSAGES & UPD_M_WARNING
4256
errprintf(udev->memory,
4257
"upd_open_writer: Only %d instead of %d normal Feeds\n",
4258
(int) upd->int_a[IA_STD_DY].size,upd->ints[I_NPASS]);
4262
} else if(upd->int_a[IA_STD_IX].size < upd->int_a[IA_STD_DY].size) {
4263
#if UPD_MESSAGES & UPD_M_WARNING
4264
errprintf(udev->memory,
4265
"upd_open_writer: Only %d instead of %d normal Xstarts\n",
4266
(int) upd->int_a[IA_STD_IX].size,
4267
(int) upd->int_a[IA_STD_DY].size);
4272
/** The sum of Values in STD_DY should equal NYPASS * PINS2WRITE (diagnostic) */
4274
#if UPD_MESSAGES & UPD_M_WARNING
4277
for(i = 0; upd->ints[I_NPASS] > i; ++i)
4278
sum += upd->int_a[IA_STD_DY].data[i];
4279
if((upd->ints[I_NYPASS]*upd->ints[I_PINS2WRITE]) != sum)
4280
errprintf(udev->memory,
4281
"upd_open_writer: Sum of normal Feeds is %d rather than %d\n",
4282
sum,upd->ints[I_NYPASS]*upd->ints[I_PINS2WRITE]);
4286
if(upd->int_a[IA_BEG_IX].size < upd->int_a[IA_BEG_DY].size) {
4287
#if UPD_MESSAGES & UPD_M_WARNING
4288
errprintf(udev->memory,
4289
"upd_open_writer: Only %d instead of %d initial Xstarts\n",
4290
(int) upd->int_a[IA_BEG_IX].size,
4291
(int) upd->int_a[IA_BEG_DY].size);
4296
if(upd->int_a[IA_BEGBOT].size < upd->int_a[IA_BEG_DY].size) {
4297
#if UPD_MESSAGES & UPD_M_WARNING
4298
errprintf(udev->memory,
4299
"upd_open_writer: Only %d instead of %d initial Pins\n",
4300
(int) upd->int_a[IA_BEGBOT].size,
4301
(int) upd->int_a[IA_BEG_DY].size);
4308
for(i = 0; i < upd->int_a[IA_BEG_DY].size; ++i)
4309
if((upd->int_a[IA_BEGBOT].data[i] > upd->ints[I_PINS2WRITE]) ||
4310
(upd->int_a[IA_BEGBOT].data[i] < 0 ) ) break;
4312
if(i < upd->int_a[IA_BEG_DY].size) {
4313
#if UPD_MESSAGES & UPD_M_WARNING
4314
errprintf(udev->memory,
4315
"upd_open_writer: Only %d is invalid initial Pins\n",
4316
upd->int_a[IA_BEGBOT].data[i]);
4322
/** The sum of Values in BEG_DY should equal BEG_Y */
4324
#if UPD_MESSAGES & UPD_M_WARNING
4327
for(i = 0; upd->int_a[IA_BEG_DY].size > i; ++i)
4328
sum += upd->int_a[IA_BEG_DY].data[i];
4329
if(upd->ints[I_BEG_Y] != sum)
4330
errprintf(udev->memory,
4331
"upd_open_writer: Sum of initial Feeds is %d rather than %d\n",
4332
sum,upd->ints[I_BEG_Y]);
4336
if(upd->int_a[IA_END_IX].size < upd->int_a[IA_END_DY].size) {
4337
#if UPD_MESSAGES & UPD_M_WARNING
4338
errprintf(udev->memory,
4339
"upd_open_writer: Only %d instead of %d final Xstarts\n",
4340
(int) upd->int_a[IA_END_IX].size,
4341
(int) upd->int_a[IA_END_DY].size);
4346
if(upd->int_a[IA_ENDTOP].size < upd->int_a[IA_END_DY].size) {
4347
#if UPD_MESSAGES & UPD_M_WARNING
4348
errprintf(udev->memory,
4349
"upd_open_writer: Only %d instead of %d Final Pins\n",
4350
(int) upd->int_a[IA_ENDTOP].size,
4351
(int) upd->int_a[IA_END_DY].size);
4358
for(i = 0; i < upd->int_a[IA_END_DY].size; ++i)
4359
if((upd->int_a[IA_ENDTOP].data[i] > upd->ints[I_PINS2WRITE]) ||
4360
(upd->int_a[IA_ENDTOP].data[i] < 0 ) ) break;
4362
if(i < upd->int_a[IA_END_DY].size) {
4363
#if UPD_MESSAGES & UPD_M_WARNING
4364
errprintf(udev->memory,
4365
"upd_open_writer: Only %d is invalid initial Pins\n",
4366
upd->int_a[IA_ENDTOP].data[i]);
4372
/** SA_SETCOMP must be valid, if present */
4373
if((0 < upd->string_a[SA_SETCOMP].size) &&
4374
(upd->ocomp > upd->string_a[SA_SETCOMP].size)) {
4375
#if UPD_MESSAGES & UPD_M_WARNING
4376
errprintf(udev->memory,
4377
"upd_open_writer: Only %d SETCOMP-Commands (%d required)\n",
4378
(int) upd->string_a[SA_SETCOMP].size,upd->ocomp);
4383
/** Determine required number of scan-Buffers */
4385
if(success) { /* Compute nscnbuf */
4388
want = upd->ints[I_NYPASS];
4389
want *= upd->ints[I_PINS2WRITE];
4391
if(upd->ints[I_NSCNBUF] > want) want = upd->ints[I_NSCNBUF];
4393
if(1 > want) want = 1;
4395
for(use = 1; 0 < use; use <<= 1) if(use > want) break;
4397
if(use <= INT_MAX) upd->nscnbuf = upd->ints[I_NSCNBUF] = use;
4398
else success = false;
4400
} /* Compute nscnbuf */
4402
/** Determine number of words in scan-buffers */
4404
if(success) { /* Compute pwidth, scnmsk, nbytes, pheight */
4406
if(0 < upd->ints[I_PWIDTH]) upd->pwidth = upd->ints[I_PWIDTH];
4407
else upd->pwidth = upd->gswidth;
4409
upd->nbytes = (upd->pwidth+CHAR_BIT*sizeof(upd->scnbuf[0]->bytes[0]) - 1)
4410
/ (CHAR_BIT*sizeof(upd->scnbuf[0]->bytes[0]));
4412
upd->scnmsk = upd->nscnbuf - 1;
4414
if(0 < upd->ints[I_PHEIGHT]) upd->pheight = upd->ints[I_PHEIGHT];
4415
else upd->pheight = upd->gsheight;
4417
} /* Compute pwidth, scnmsk, nbytes */
4419
/** Call the writer-specific open-function */
4421
if(success) { /* Determine sizes */
4422
switch(upd->choice[C_FORMAT]) {
4424
if(0 > upd_open_rascomp(udev)) success = false;
4427
if(0 > upd_open_wrtescp(udev)) success = false;
4431
case FMT_ESCNMY: /* (GR) */
4432
if(0 > upd_open_wrtescp2(udev)) success = false;
4435
if(0 > upd_open_wrtrtl(udev)) success = false;
4437
case FMT_CANON: /* (hr) */
4438
if(0 > upd_open_wrtcanon(udev)) success = false;
4442
#if UPD_MESSAGES & UPD_M_WARNING
4443
errprintf(udev->memory,"upd_open_writer: Unknown writer-type %d\n",
4444
upd->choice[C_FORMAT]);
4448
} /* Determine sizes*/
4450
/** Allocate the Outputbuffer */
4451
if(success && (0 < upd->noutbuf)) { /* Allocate outbuf */
4452
upd->outbuf = gs_malloc(udev->memory, upd->noutbuf,sizeof(upd->outbuf[0]),"upd/outbuf");
4453
if(!upd->outbuf) success = false;
4454
} /* Allocate outbuf */
4456
/** Allocate the desired scan-buffer-pointers */
4458
upd->scnbuf = gs_malloc(udev->memory, upd->nscnbuf,sizeof(upd->scnbuf[0]),"upd/scnbuf");
4459
if(NULL == upd->scnbuf) {
4463
for(ibuf = 0; ibuf < upd->nscnbuf; ++ibuf) {
4464
if(success) upd->scnbuf[ibuf] =
4465
gs_malloc(udev->memory, upd->ocomp,sizeof(upd->scnbuf[0][0]),"upd/scnbuf[]");
4466
else upd->scnbuf[ibuf] = NULL;
4468
if(!upd->scnbuf[ibuf]) {
4472
for(icomp = 0; icomp < upd->ocomp; ++icomp) {
4473
if(success) upd->scnbuf[ibuf][icomp].bytes =
4474
gs_malloc(udev->memory, upd->nbytes,sizeof(upd->scnbuf[0][0].bytes[0]),
4476
else upd->scnbuf[ibuf][icomp].bytes = NULL;
4477
if(!upd->scnbuf[ibuf][icomp].bytes) success = false;
4479
if(0 < upd->nlimits) {
4481
upd->scnbuf[ibuf][icomp].xbegin = gs_malloc(udev->memory, upd->nlimits,
4482
sizeof(upd->scnbuf[0][0].xbegin[0]),"upd/xbegin");
4483
if(!upd->scnbuf[ibuf][icomp].xbegin) success = false;
4485
upd->scnbuf[ibuf][icomp].xend = gs_malloc(udev->memory, upd->nlimits,
4486
sizeof(upd->scnbuf[0][0].xend[0]),"upd/xend");
4487
if(!upd->scnbuf[ibuf][icomp].xbegin) success = false;
4491
upd->scnbuf[ibuf][icomp].xbegin = NULL;
4492
upd->scnbuf[ibuf][icomp].xend = NULL;
4501
if(success) upd->flags |= B_FORMAT;
4502
else upd_close_writer(udev);
4504
return success ? 1 : -1;
4507
/* ------------------------------------------------------------------- */
4508
/* upd_close_writer: Deinitialize rendering */
4509
/* ------------------------------------------------------------------- */
4512
upd_close_writer(upd_device *udev)
4514
const upd_p upd = udev->upd;
4519
if((0 < upd->noutbuf) && upd->outbuf)
4520
gs_free(udev->memory, upd->outbuf,upd->noutbuf,sizeof(upd->outbuf[0]),"upd/outbuf");
4524
if((0 < upd->nscnbuf) && upd->scnbuf) {
4525
for(ibuf = 0; upd->nscnbuf > ibuf; ++ibuf) {
4527
if(!upd->scnbuf[ibuf]) continue;
4529
for(icomp = 0; icomp < upd->ocomp; ++icomp) {
4531
if((0 < upd->nbytes) && upd->scnbuf[ibuf][icomp].bytes)
4532
gs_free(udev->memory, upd->scnbuf[ibuf][icomp].bytes,upd->nbytes,
4533
sizeof(upd->scnbuf[ibuf][icomp].words[0]),"upd/bytes");
4534
upd->scnbuf[ibuf][icomp].bytes = NULL;
4536
if((0 < upd->nlimits) && upd->scnbuf[ibuf][icomp].xbegin)
4537
gs_free(udev->memory, upd->scnbuf[ibuf][icomp].xbegin,upd->nlimits,
4538
sizeof(upd->scnbuf[ibuf][icomp].xbegin[0]),"upd/xbegin");
4539
upd->scnbuf[ibuf][icomp].xbegin = NULL;
4541
if((0 < upd->nlimits) && upd->scnbuf[ibuf][icomp].xend)
4542
gs_free(udev->memory, upd->scnbuf[ibuf][icomp].xend,upd->nlimits,
4543
sizeof(upd->scnbuf[ibuf][icomp].xend[0]),"upd/xend");
4544
upd->scnbuf[ibuf][icomp].xend = NULL;
4548
gs_free(udev->memory, upd->scnbuf[ibuf],upd->ocomp,sizeof(upd->scnbuf[0][0]),
4550
upd->scnbuf[ibuf] = NULL;
4553
gs_free(udev->memory, upd->scnbuf,upd->nscnbuf,sizeof(upd->scnbuf[0]),"upd/scnbuf");
4556
upd->flags &= ~B_FORMAT;
4560
/* ------------------------------------------------------------------- */
4561
/* upd_limits: Establish passwise limits, after rendering */
4562
/* ------------------------------------------------------------------- */
4565
upd_limits(upd_p upd, bool check)
4567
updscan_p scans = upd->scnbuf[upd->yscnbuf & upd->scnmsk], scan;
4568
int xs,x,xe,icomp,pass;
4571
for(icomp = 0; icomp < upd->ocomp; ++icomp) {
4572
scan = scans + icomp;
4573
for(pass = 0; pass < upd->nlimits; ++pass) {
4574
scan->xbegin[pass] = upd->pwidth;
4575
scan->xend[ pass] = -1;
4579
if(check) { /* Really check */
4580
for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Check Components */
4581
scan = scans + icomp;
4582
bytes = scan->bytes;
4584
for(xs = 0; xs < upd->nbytes && !bytes[xs]; ++xs);
4586
if(xs < upd->nbytes) { /* Has Data */
4587
for(xe = upd->nbytes; xs < xe && !bytes[xe-1]; --xe);
4589
for(pass = 0; pass < upd->nlimits; ++pass) { /* limit (pass) loop */
4591
x = ((xs<<3)/upd->nlimits)*upd->nlimits + pass;
4592
while((x >> 3) < xs) x += upd->nlimits;
4594
bit = 0x80 >> (x & 7);
4595
while(x < scan->xbegin[pass]) {
4596
if(bytes[x>>3] & bit) scan->xbegin[pass] = x;
4598
bit = 0x80 >> (x & 7);
4601
x = (((xe<<3)|7)/upd->nlimits)*upd->nlimits + pass;
4603
while((x >> 3) < xe) x += upd->nlimits;
4604
while((x >> 3) > xe) x -= upd->nlimits;
4606
bit = 0x80 >> (xs & 7);
4607
while(x > scan->xend[pass]) {
4608
if(bytes[x>>3] & bit) scan->xend[pass] = x;
4610
bit = 0x80 >> (x & 7);
4613
} /* limit (pass) loop */
4617
} /* Check Components */
4619
} /* Really check */
4623
/* ------------------------------------------------------------------- */
4624
/* upd_open_rascomp: ncomp * 1Bit Raster-Writer */
4625
/* ------------------------------------------------------------------- */
4628
upd_open_rascomp(upd_device *udev)
4630
const upd_p upd = udev->upd;
4634
noutbuf = upd->pwidth;
4636
if(1 < upd->ncomp) noutbuf *= 8; /* ??? upd->ocomp */
4638
noutbuf = ((noutbuf+15)>>4)<<1;
4640
if(INT_MAX >= noutbuf) {
4641
upd->noutbuf = noutbuf;
4642
upd->start_writer = upd_start_rascomp;
4643
upd->writer = upd_rascomp;
4651
/* ------------------------------------------------------------------- */
4652
/* upd_start_rascomp: write appropiate raster-header */
4653
/* ------------------------------------------------------------------- */
4654
#if arch_is_big_endian
4655
#define put32(I32,Out) \
4656
fwrite(&I32,1,4,Out)
4658
#define put32(I32,Out) \
4659
putc(((I32)>>24)&255,Out),\
4660
putc(((I32)>>16)&255,Out),\
4661
putc(((I32)>> 8)&255,Out),\
4662
putc( (I32) &255,Out)
4666
upd_start_rascomp(upd_p upd, FILE *out) {
4668
/** if no begin-sequence externally set */
4669
if(0 == upd->strings[S_BEGIN].size) {
4685
if(1 < upd->ncomp) val = 8; /* ??? upd->ocomp */
4691
val = ((val+15)>>4)<<1;
4692
val *= upd->pheight;
4703
/** ras_maplength */
4704
val = 3 * (1 << upd->ncomp); /* ??? upd->ocomp */
4708
if(1 == upd->ncomp) { /* ??? upd->ocomp */
4709
const updcomp_p comp = upd->valptr[0];
4711
if(upd->cmap[comp->cmap].rise) {
4712
putc((char) 0x00,out); putc((char) 0xff,out);
4713
putc((char) 0x00,out); putc((char) 0xff,out);
4714
putc((char) 0x00,out); putc((char) 0xff,out);
4716
putc((char) 0xff,out); putc((char) 0x00,out);
4717
putc((char) 0xff,out); putc((char) 0x00,out);
4718
putc((char) 0xff,out); putc((char) 0x00,out);
4721
} else if(3 == upd->ncomp) { /* ??? upd->ocomp */
4724
for( rgb = 0; rgb < 3; ++rgb) {
4726
for(entry = 0; entry < 8; ++entry) {
4727
byte xval = upd->cmap[rgb].rise ? 0x00 : 0xff;
4728
if(entry & (1<<upd->cmap[rgb].comp)) xval ^= 0xff;
4732
} else { /* we have 4 components */
4735
for(rgb = 16; 0 <= rgb; rgb -= 8) {
4737
for(entry = 0; entry < 16; ++entry) {
4738
uint32_t rgbval = 0;
4740
if(entry & (1<<upd->cmap[0].comp)) {
4746
if(entry & (1<<upd->cmap[1].comp)) rgbval |= 0xff0000;
4747
if(entry & (1<<upd->cmap[2].comp)) rgbval |= 0x00ff00;
4748
if(entry & (1<<upd->cmap[3].comp)) rgbval |= 0x0000ff;
4751
if(!upd->cmap[1].rise) rgbval ^= 0xff0000;
4752
if(!upd->cmap[2].rise) rgbval ^= 0x00ff00;
4753
if(!upd->cmap[3].rise) rgbval ^= 0x0000ff;
4755
if(!(upd->choice[C_MAPPER] == MAP_RGBW)) rgbval ^= 0xffffff;
4757
putc((rgbval>>rgb)&255,out);
4762
memset(upd->outbuf,0,upd->noutbuf);
4767
/* ------------------------------------------------------------------- */
4768
/* upd_rascomp: assemble & write a scanline */
4769
/* ------------------------------------------------------------------- */
4771
upd_rascomp(upd_p upd, FILE *out) {
4772
updscan_p scan = upd->scnbuf[upd->yscan & upd->scnmsk];
4773
uint bits = upd->pwidth;
4775
if(1 == upd->ncomp) { /* ??? upd->ocomp */
4778
nbytes = (bits+7)>>3;
4779
memcpy(upd->outbuf,scan->bytes,nbytes);
4780
if((bits &= 7)) upd->outbuf[nbytes-1] &= ((byte) 0xff) << (8-bits);
4784
byte *buf = upd->outbuf, bit = 0x80;
4789
switch(upd->ncomp) { /* ??? upd->ocomp */
4790
case 4: if(scan[3].bytes[ibyte] & bit) val |= 8;
4791
case 3: if(scan[2].bytes[ibyte] & bit) val |= 4;
4792
if(scan[1].bytes[ibyte] & bit) val |= 2;
4793
case 1: if(scan[0].bytes[ibyte] & bit) val |= 1;
4803
fwrite(upd->outbuf,1,upd->noutbuf,out);
4809
/* ------------------------------------------------------------------- */
4810
/* upd_open_wrtescp: ESC/P Writer intended for ESC * m commands */
4811
/* ------------------------------------------------------------------- */
4814
upd_open_wrtescp(upd_device *udev)
4816
const upd_p upd = udev->upd;
4819
/** Adjust the PageLength, If Requested */
4820
if((B_PAGELENGTH & upd->flags) &&
4821
(0 < upd->strings[S_BEGIN].size)) { /* BOP-Checker */
4822
int i,state = 0,value = 0;
4823
byte *bp = (byte *) upd_cast(upd->strings[S_BEGIN].data);
4824
for(i = 0; i < upd->strings[S_BEGIN].size; ++i) {
4827
if(0x1b == bp[i]) state = 1;
4830
if('C' == bp[i]) state = 2;
4835
value = (int)(0.5 + udev->height * (float) bp[i]
4836
/ udev->y_pixels_per_inch);
4837
if( 0 >= value) bp[i] = 1;
4838
else if(128 > value) bp[i] = value;
4846
value = (int)(0.5 + udev->height / udev->y_pixels_per_inch);
4847
if( 0 >= value) bp[i] = 1;
4848
else if( 22 > value) bp[i] = value;
4856
/** Either SETLF or YMOVE must be set */
4857
if((0 == upd->strings[S_SETLF].size) &&
4858
(0 == upd->strings[S_YMOVE].size) ) {
4859
#if UPD_MESSAGES & UPD_M_WARNING
4860
errprintf(udev->memory,
4861
"ESC/P-Open: Either SETLF- or YMOVE-Command must be present\n");
4866
/** X-Positioning must be set too */
4867
if(((1 < upd->ints[I_XSTEP] ) &&
4868
(0 == upd->strings[S_XSTEP].size) ) ||
4869
((1 < upd->ints[I_NXPASS] ) &&
4870
(0 == upd->strings[S_XMOVE].size) &&
4871
(0 == upd->strings[S_XSTEP].size) ) ) {
4872
#if UPD_MESSAGES & UPD_M_WARNING
4873
errprintf(udev->memory,
4874
"ESC/P-Open: Missing XSTEP- and/or XMOVE-Command\n");
4879
/** SA_WRITECOMP must be valid */
4880
if(upd->ncomp > upd->string_a[SA_WRITECOMP].size) { /* ??? upd->ocomp */
4881
#if UPD_MESSAGES & UPD_M_WARNING
4882
errprintf(udev->memory,
4883
"ESC/P-Open: WRITECOMP-Commands must be given\n");
4889
If all this is correct, it's time to coumput the size of the output-buffer.
4893
3. Component-Selection
4894
4. The Raster-Command
4898
int32_t i,noutbuf,need;
4900
if(0 < upd->strings[S_YMOVE].size) {
4901
noutbuf = upd->strings[S_YMOVE].size + 2;
4903
int nmax = upd->pheight;
4904
if( 1 < upd->ints[I_YSTEP]) nmax /= upd->ints[I_YSTEP];
4905
else if(-1 > upd->ints[I_YSTEP]) nmax *= -upd->ints[I_YSTEP];
4906
noutbuf = 2 * upd->strings[S_SETLF].size + 2;
4907
noutbuf += nmax/255 + 1;
4910
if(1 < upd->ints[I_YSTEP])
4911
noutbuf += (upd->ints[I_YSTEP]-1) * upd->strings[S_YSTEP].size;
4913
noutbuf += upd->strings[S_XMOVE].size + 2;
4915
if(1 < upd->ints[I_XSTEP])
4916
noutbuf += (upd->ints[I_XSTEP]-1) * upd->strings[S_XSTEP].size;
4918
if(0 < upd->string_a[SA_SETCOMP].size) {
4920
for(i = 0; i < upd->ocomp; ++i)
4921
if(need < upd->string_a[SA_SETCOMP].data[i].size)
4922
need = upd->string_a[SA_SETCOMP].data[i].size;
4927
for(i = 0; i < upd->ocomp; ++i)
4928
if(need < upd->string_a[SA_WRITECOMP].data[i].size)
4929
need = upd->string_a[SA_WRITECOMP].data[i].size;
4930
noutbuf += need + 2;
4932
noutbuf += ((upd->ints[I_PINS2WRITE] + 7) / 8)
4933
* ((upd->pwidth + upd->ints[I_NXPASS] - 1)/upd->ints[I_NXPASS]);
4935
if((0 < noutbuf) && (noutbuf <= INT_MAX)) {
4936
upd->noutbuf = noutbuf;
4937
upd->writer = upd_wrtescp;
4938
upd->nlimits = upd->ints[I_NXPASS];
4942
#if UPD_MESSAGES & UPD_M_WARNING
4943
errprintf(udev->memory,
4944
"ESC/P-Open: %ld is unreasonable size of Outputbuffer\n",
4953
/* ------------------------------------------------------------------- */
4954
/* upd_wrtescp: Write a pass */
4955
/* ------------------------------------------------------------------- */
4958
upd_wrtescp(upd_p upd, FILE *out)
4960
int pinbot,pin,pintop,xbegin,x,xend,icomp,ybegin,yend,y,ioutbuf,n,ixpass;
4964
/** Determine the number of pins to write */
4966
if(upd->yscan < upd->ints[I_BEG_Y]) {
4967
ixpass = upd->int_a[IA_BEG_IX].data[upd->ipass];
4969
pinbot = upd->int_a[IA_BEGBOT].data[upd->ipass];
4970
} else if(upd->yscan >= upd->ints[I_END_Y]) {
4971
ixpass = upd->int_a[IA_END_IX].data[upd->ipass];
4972
pinbot = upd->ints[I_PINS2WRITE];
4973
pintop = pinbot - upd->int_a[IA_ENDTOP].data[upd->ipass];
4975
ixpass = upd->int_a[IA_STD_IX].data[upd->ipass];
4977
pinbot = upd->ints[I_PINS2WRITE];
4980
ybegin = pintop * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
4981
yend = pinbot * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
4983
/** Determine Width of this scan */
4985
xbegin = upd->pwidth;
4988
for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Pin-testloop */
4990
if(0 > y) continue; /* Inserted Scanlines */
4992
scan = upd->scnbuf[y & upd->scnmsk];
4994
for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Compwise test */
4995
if(xbegin > scan[icomp].xbegin[ixpass])
4996
xbegin = scan[icomp].xbegin[ixpass];
4997
if(xend < scan[icomp].xend[ ixpass])
4998
xend = scan[icomp].xend[ ixpass];
4999
} /* Compwise test */
5001
} /* Pin-testloop */
5003
if(xbegin <= xend) { /* Some data to write */
5007
if(0 == upd->strings[S_XMOVE].size) xbegin = ixpass;
5010
* Adjust the Printers Y-Position
5012
if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
5013
if(B_YABS & upd->flags) y = upd->yscan + upd->ints[I_YOFS];
5014
else y = upd->yscan - upd->yprinter;
5016
if( 1 < upd->ints[I_YSTEP]) {
5017
n = y / upd->ints[I_YSTEP]; /* Major-Steps */
5018
y -= n * upd->ints[I_YSTEP]; /* Minor-Steps */
5019
} else if(-1 > upd->ints[I_YSTEP]) {
5020
n = y * -upd->ints[I_YSTEP]; /* May this work? */
5027
if(n) { /* Coarse Positioning */
5028
if(0 < upd->strings[S_YMOVE].size) {
5030
memcpy(upd->outbuf+ioutbuf,
5031
upd->strings[S_YMOVE].data,
5032
upd->strings[S_YMOVE].size);
5033
ioutbuf += upd->strings[S_YMOVE].size;
5035
upd->outbuf[ioutbuf++] = n & 0xff;
5036
upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5041
int n2do = n > 255 ? 255 : n;
5042
if(upd->lf != n2do) {
5043
memcpy(upd->outbuf+ioutbuf,
5044
upd->strings[S_SETLF].data,
5045
upd->strings[S_SETLF].size);
5046
ioutbuf += upd->strings[S_SETLF].size;
5047
upd->outbuf[ioutbuf++] = n2do;
5050
upd->outbuf[ioutbuf++] = '\n';
5054
} /* Coarse Positioning */
5056
if(0 < upd->strings[S_YSTEP].size) {
5058
memcpy(upd->outbuf+ioutbuf,
5059
upd->strings[S_YSTEP].data,
5060
upd->strings[S_YSTEP].size);
5061
ioutbuf += upd->strings[S_YSTEP].size;
5065
upd->yprinter = upd->yscan;
5066
} /* Adjust Y-Position */
5069
* Now write the required components
5071
for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Component-Print */
5073
* First check, wether this Component needs printing
5075
for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Comp-Test */
5077
scan = upd->scnbuf[y & upd->scnmsk]+icomp;
5078
if(0 <= scan->xend[ixpass]) break;
5080
if(y >= yend) continue; /* Component not required */
5082
* Select the Component
5084
if((0 < upd->string_a[SA_SETCOMP].size) &&
5085
(upd->icomp != icomp ) ) { /* Selection enabled */
5087
if(0 < upd->string_a[SA_SETCOMP].data[icomp].size) {
5088
memcpy(upd->outbuf+ioutbuf,
5089
upd->string_a[SA_SETCOMP].data[icomp].data,
5090
upd->string_a[SA_SETCOMP].data[icomp].size);
5091
ioutbuf += upd->string_a[SA_SETCOMP].data[icomp].size;
5093
} /* Selection enabled */
5095
* Establish the X-Position
5097
if(xbegin != upd->xprinter) {
5099
if(0 == upd->strings[S_XMOVE].size) {
5101
upd->outbuf[ioutbuf++] = '\r';
5108
if(B_XABS & upd->flags) n = x = xbegin + upd->ints[I_XOFS];
5109
else n = x = xbegin - upd->xprinter;
5111
if( 1 < upd->ints[I_XSTEP]) {
5113
n -= upd->ints[I_XSTEP];
5116
if(n) n /= upd->ints[I_XSTEP]; /* Major-Steps */
5117
if(x) x %= upd->ints[I_XSTEP]; /* Minor-Steps */
5119
} else if(-1 > upd->ints[I_XSTEP]) {
5120
n *= -upd->ints[I_XSTEP]; /* May this work? */
5124
if(n) { /* Adjust X-Position */
5126
memcpy(upd->outbuf+ioutbuf,
5127
upd->strings[S_XMOVE].data,
5128
upd->strings[S_XMOVE].size);
5129
ioutbuf += upd->strings[S_XMOVE].size;
5131
upd->outbuf[ioutbuf++] = n & 0xff;
5132
upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5134
} /* Adjust X-Position */
5138
if(x && 0 < upd->strings[S_XSTEP].size) { /* Fine-Adjust X */
5140
memcpy(upd->outbuf+ioutbuf,
5141
upd->strings[S_XSTEP].data,
5142
upd->strings[S_XSTEP].size);
5143
ioutbuf += upd->strings[S_XSTEP].size;
5145
} /* Fine-Adjust X */
5147
upd->xprinter = xend+1;
5149
* Send the Write-Command
5151
if(0 < upd->string_a[SA_WRITECOMP].data[icomp].size) {
5152
memcpy(upd->outbuf+ioutbuf,
5153
upd->string_a[SA_WRITECOMP].data[icomp].data,
5154
upd->string_a[SA_WRITECOMP].data[icomp].size);
5155
ioutbuf += upd->string_a[SA_WRITECOMP].data[icomp].size;
5157
n = (xend - xbegin) / upd->ints[I_NXPASS] + 1;;
5158
upd->outbuf[ioutbuf++] = n & 255;
5159
upd->outbuf[ioutbuf++] = (n>>8) & 255;
5161
* Clear the data-Part
5163
obytes = upd->outbuf+ioutbuf;
5164
n *= (upd->ints[I_PINS2WRITE]+7)>>3;
5170
for(x = xbegin; x <= xend; x += upd->ints[I_NXPASS]) {
5172
bit = 0x80 >> (pintop & 7);
5173
obytes += pintop>>3;
5175
for(pin = pintop, y = ybegin; pin < pinbot;
5176
pin++, y += upd->ints[I_NYPASS]) {
5178
scan = upd->scnbuf[y & upd->scnmsk]+icomp;
5179
if(scan->bytes[x>>3] & (0x80 >> (x & 7))) *obytes |= bit;
5181
if(!(bit >>= 1)) { obytes++; bit = 0x80; }
5184
obytes += (upd->ints[I_PINS2WRITE]-pinbot+7)>>3;
5187
* Send this Component to the Printer
5189
fwrite(upd->outbuf,1,ioutbuf,out);
5191
} /* Component-Print */
5192
} /* Some data to write */
5194
/** Advance counters in upd, change modi */
5196
if(upd->yscan < upd->ints[I_BEG_Y]) {
5197
upd->yscan += upd->int_a[IA_BEG_DY].data[upd->ipass++];
5198
if( upd->ints[I_BEG_Y] <= upd->yscan) upd->ipass = 0;
5199
else if(upd->int_a[IA_BEG_DY].size <= upd->ipass) upd->ipass = 0;
5200
} else if(upd->yscan >= upd->ints[I_END_Y]) {
5201
upd->yscan += upd->int_a[IA_END_DY].data[upd->ipass++];
5202
if(upd->int_a[IA_END_DY].size <= upd->ipass) upd->ipass = 0;
5204
upd->yscan += upd->int_a[IA_STD_DY].data[upd->ipass++];
5205
if(upd->int_a[IA_STD_DY].size <= upd->ipass) upd->ipass = 0;
5206
if(upd->yscan >= upd->ints[I_END_Y]) upd->ipass = 0;
5212
/* ------------------------------------------------------------------- */
5213
/* upd_open_wrtescp2: ESC/P2 Writer intended for ESC . 1 commands */
5214
/* ------------------------------------------------------------------- */
5217
upd_open_wrtescp2(upd_device *udev)
5219
const upd_p upd = udev->upd;
5221
float pixels_per_inch = 360.0;
5223
/** Analyze (and optionally adjust) the BOP-Sequence */
5224
if(0 < upd->strings[S_BEGIN].size) { /* BOP-Checker */
5225
int i,state = 0,value = 0;
5226
byte *bp = (byte *) upd_cast(upd->strings[S_BEGIN].data);
5227
for(i = 0; i < upd->strings[S_BEGIN].size; ++i) {
5230
if(0x1b == bp[i]) state = 1;
5233
if('(' == bp[i]) state = 2;
5238
case 'U': state = 3; break; /* Printer-Resolution */
5239
case 'C': state = 6; break; /* Page-Length */
5240
case 'c': state = 10; break; /* Top/Bottom Margin */
5241
default: state = 0; break;
5245
if(1 == bp[i]) state = 4;
5249
if(0 == bp[i]) state = 5;
5253
pixels_per_inch = 3600.0 / (float) bp[i];
5257
if(2 == bp[i]) state = 7;
5261
if(0 == bp[i]) state = 8;
5265
if(B_PAGELENGTH & upd->flags) {
5266
value = (int)(0.5 + udev->height
5267
* pixels_per_inch / udev->y_pixels_per_inch);
5268
bp[i] = value & 0xff;
5273
if(B_PAGELENGTH & upd->flags) {
5274
bp[i] = (value>>8) & 0xff;
5279
if(4 == bp[i]) state = 11;
5283
if(0 == bp[i]) state = 12;
5287
if(B_TOPMARGIN & upd->flags) {
5288
value = (int)(dev_t_margin(udev) * pixels_per_inch);
5289
bp[i] = value & 0xff;
5294
if(B_TOPMARGIN & upd->flags) {
5295
bp[i] = (value>>8) & 0xff;
5300
if(B_BOTTOMMARGIN & upd->flags) {
5301
value = (int)(0.5 + udev->height
5302
* pixels_per_inch / udev->y_pixels_per_inch
5303
- dev_b_margin(udev) * pixels_per_inch);
5304
bp[i] = value & 0xff;
5309
if(B_BOTTOMMARGIN & upd->flags) {
5310
bp[i] = (value>>8) & 0xff;
5318
/** Create Y-Move-Command, if not given */
5319
if(0 == upd->strings[S_YMOVE].size) {
5321
UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_YMOVE]);
5322
UPD_MM_GET_ARRAY(udev->memory, bp,5);
5323
upd->strings[S_YMOVE].data = bp;
5324
upd->strings[S_YMOVE].size = 5;
5325
*bp++ = 0x1b; /* ESC */
5327
*bp++ = upd->flags & B_YABS ? 'V' : 'v';
5332
/** X-Positioning must be set too, sometimes */
5333
if((1 < upd->ints[I_XSTEP]) && (0 == upd->strings[S_XSTEP].size)) {
5335
#if UPD_MESSAGES & UPD_M_WARNING
5336
errprintf(udev->memory,
5337
"ESC/P2-Open: XSTEP-Command required for XSTEP=%d\n",
5338
upd->ints[I_XSTEP]);
5342
} else if((1 < upd->ints[I_NXPASS] ) &&
5343
(0 == upd->strings[S_XMOVE].size) &&
5344
(0 == upd->strings[S_XSTEP].size) ) {
5348
ratio = (int)((udev->y_pixels_per_inch + 0.5) / udev->x_pixels_per_inch);
5350
if(0 == upd->ints[I_XSTEP]) { /* Adjust scale-factor too! */
5351
if(ratio > 1) upd->ints[I_XSTEP] = -ratio;
5352
} else { /* Adjust scale-factor too! */
5353
ratio = -upd->ints[I_XSTEP];
5356
if(2 == upd->ints[I_NXPASS]) { /* Use a relative Step */
5358
UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_XSTEP]);
5359
UPD_MM_GET_ARRAY(udev->memory, bp,4);
5360
upd->strings[S_XSTEP].size = 4;
5361
upd->strings[S_XSTEP].data = bp;
5364
*bp++ = ratio & 0xff;
5365
*bp++ = (ratio>>8) & 0xff;
5367
} else { /* Use relative or absolute Move */
5369
UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_XMOVE]);
5370
UPD_MM_GET_ARRAY(udev->memory, bp,2);
5371
upd->strings[S_XMOVE].size = 2;
5372
upd->strings[S_XMOVE].data = bp;
5374
*bp++ = upd->flags & B_XABS ? '$' : '\\';
5379
/* Check the Nozzle Map parameters and set some defaults */
5380
/* Used a switch construct in case FMT_ESCNMXY is added later */
5381
switch(upd->choice[C_FORMAT]){
5384
if( 0 == upd->ints[I_ROWS] ){
5385
upd->ints[I_ROWS] = 1;
5388
if( 0 == upd->ints[I_PATRPT] ){
5389
upd->ints[I_PATRPT] = 1;
5391
/* RowMask - default is all 1's */
5392
if( upd->ints[I_PATRPT] != upd->int_a[IA_ROWMASK].size ) {
5394
UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_ROWMASK]);
5395
UPD_MM_GET_ARRAY(udev->memory, bp,upd->ints[I_PATRPT]);
5396
upd->int_a[IA_ROWMASK].size = upd->ints[I_PATRPT];
5397
upd->int_a[IA_ROWMASK].data = bp;
5398
for (i = 0 ; i < upd->ints[I_PATRPT] ; i++){
5399
*bp++ = 1; /* black */
5402
/* MaskScanOffset - default is 0-patternRepeat */
5403
if( upd->ints[I_PATRPT] != upd->int_a[IA_SCNOFS].size ) {
5405
UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_SCNOFS]);
5406
UPD_MM_GET_ARRAY(udev->memory, bp,upd->ints[I_PATRPT]);
5407
upd->int_a[IA_SCNOFS].size = upd->ints[I_PATRPT];
5408
upd->int_a[IA_SCNOFS].data = bp;
5409
for (i = 0 ; i < upd->ints[I_PATRPT] ; i++){
5416
/* Nozzle map parameters are not valid for these formats
5421
/** If there is neither a writecomp nor a setcomp-command, generate both */
5422
if((0 == upd->string_a[SA_WRITECOMP].size) &&
5423
(0 == upd->string_a[SA_SETCOMP].size ) ) { /* Default-commands */
5425
gs_param_string *ap;
5428
if(4 == upd->ocomp) { /* Establish Component-Selection */
5429
UPD_MM_DEL_APARAM(udev->memory, upd->string_a[SA_SETCOMP]);
5430
UPD_MM_GET_ARRAY(udev->memory, ap,4);
5431
upd->string_a[SA_SETCOMP].data = ap;
5432
upd->string_a[SA_SETCOMP].size = 4;
5433
for(i = 0; i < 4; ++i) {
5434
UPD_MM_GET_ARRAY(udev->memory, bp,3);
5439
switch(((updcomp_p)upd->valptr[i])->cmap) { /* use COMPORDER! */
5440
case 0: *bp++ = 0; break; /* Black */
5441
case 1: *bp++ = 2; break; /* Cyan */
5442
case 2: *bp++ = 1; break; /* Magenta */
5443
case 3: *bp++ = 4; break; /* Yellow */
5444
} /* use COMPORDER! */
5446
} /* Establish Component-Selection */
5448
UPD_MM_DEL_APARAM(udev->memory, upd->string_a[SA_WRITECOMP]);
5449
UPD_MM_GET_ARRAY(udev->memory, ap,upd->ocomp);
5450
upd->string_a[SA_WRITECOMP].data = ap;
5451
upd->string_a[SA_WRITECOMP].size = upd->ncomp;
5452
for(i = 0; i < upd->ocomp; ++i) {
5453
UPD_MM_GET_ARRAY(udev->memory, bp,6);
5458
*bp++ = 1; /* RLE */
5459
switch(upd->choice[C_FORMAT]){
5462
*bp++ = (byte)(3600.0 * upd->ints[I_NYPASS] /
5463
udev->y_pixels_per_inch + 0.5);
5464
*bp++ = (byte)(3600.0 * upd->ints[I_NXPASS] /
5465
udev->x_pixels_per_inch + 0.5);
5466
*bp++ = upd->ints[I_PINS2WRITE];
5470
*bp++ = 3600.0 / udev->y_pixels_per_inch + 0.5;
5471
*bp++ = 3600.0 / udev->x_pixels_per_inch + 0.5;
5473
*bp++ = 10; /* needs to always be this for esc300 */
5475
*bp++ = upd->ints[I_ROWS];
5479
} /* Default-commands */
5481
/** SA_WRITECOMP must be valid */
5482
if(upd->ocomp > upd->string_a[SA_WRITECOMP].size) {
5483
#if UPD_MESSAGES & UPD_M_WARNING
5484
errprintf(udev->memory,
5485
"ESC/P2-Open: WRITECOMP-Commands must be given\n");
5490
/** Check Validity of X-Pass */
5491
switch(upd->choice[C_FORMAT]) {
5493
if(1 < upd->ints[I_NXPASS]) {
5494
#if UPD_MESSAGES & UPD_M_WARNING
5495
errprintf(udev->memory,
5496
"ESC/P2-Open: FMT_ESCP2Y cannot handle multiple X-Passes\n");
5500
upd->writer = upd_wrtescp2;
5504
upd->writer = upd_wrtescp2x;
5505
upd->nlimits = upd->ints[I_NXPASS];
5506
#if UPD_MESSAGES & UPD_M_WARNING
5507
if(1 == upd->ints[I_NXPASS])
5508
errprintf(udev->memory,
5509
"ESC/P2-Open: FMT_ESCP2XY should not be used with 1X-Pass\n");
5513
if(1 < upd->ints[I_NXPASS]) {
5514
#if UPD_MESSAGES & UPD_M_WARNING
5515
errprintf(udev->memory,
5516
"ESC/P2-Open: FMT_ESCNMY cannot handle multiple X-Passes\n");
5520
upd->writer = upd_wrtescnm;
5524
#if UPD_MESSAGES & UPD_M_WARNING
5525
errprintf(udev->memory,
5526
"ESC/P2-Open: %d is not a ESC/P2-Format\n",
5527
upd->choice[C_FORMAT]);
5534
If all this is correct, it's time to compute the size of the output-buffer.
5538
3. Component-Selection
5539
4. The Raster-Command
5543
int32_t i,noutbuf,need;
5545
if(0 < upd->strings[S_YMOVE].size) {
5546
noutbuf = upd->strings[S_YMOVE].size + 2;
5548
int nmax = upd->pheight;
5549
if( 1 < upd->ints[I_YSTEP]) nmax /= upd->ints[I_YSTEP];
5550
else if(-1 > upd->ints[I_YSTEP]) nmax *= -upd->ints[I_YSTEP];
5551
noutbuf = 2 * upd->strings[S_SETLF].size + 2;
5552
noutbuf += nmax/255 + 1;
5555
if(1 < upd->ints[I_YSTEP])
5556
noutbuf += (upd->ints[I_YSTEP]-1) * upd->strings[S_YSTEP].size;
5559
if(0 == upd->strings[S_XMOVE].size) {
5560
noutbuf += 1; /* The CR */
5561
noutbuf += (upd->ints[I_NXPASS]-1) * upd->strings[S_XSTEP].size;
5563
noutbuf += upd->strings[S_XMOVE].size + 2;
5565
if(1 < upd->ints[I_XSTEP])
5566
noutbuf += (upd->ints[I_XSTEP]-1) * upd->strings[S_XSTEP].size;
5569
/* Component-Selection */
5570
if(0 < upd->string_a[SA_SETCOMP].size) {
5572
for(i = 0; i < upd->ocomp; ++i)
5573
if(need < upd->string_a[SA_SETCOMP].data[i].size)
5574
need = upd->string_a[SA_SETCOMP].data[i].size;
5578
/* The Raster-Command */
5580
for(i = 0; i < upd->ocomp; ++i)
5581
if(need < upd->string_a[SA_WRITECOMP].data[i].size)
5582
need = upd->string_a[SA_WRITECOMP].data[i].size;
5583
noutbuf += need + 2;
5586
noutbuf += 2*upd->nbytes + (upd->nbytes + 127) / 128;
5588
upd->noutbuf = noutbuf;
5595
/* ------------------------------------------------------------------- */
5596
/* upd_wrtescp2: Write a pass */
5597
/* ------------------------------------------------------------------- */
5600
upd_wrtescp2(upd_p upd, FILE *out)
5602
int pinbot,pin,pintop,xbegin,x,xend,icomp,ybegin,yend,y,ioutbuf,n;
5606
/** Determine the number of pins to write */
5608
if(upd->yscan < upd->ints[I_BEG_Y]) {
5610
pinbot = upd->int_a[IA_BEGBOT].data[upd->ipass];
5611
} else if(upd->yscan >= upd->ints[I_END_Y]) {
5612
pinbot = upd->ints[I_PINS2WRITE];
5613
pintop = pinbot - upd->int_a[IA_ENDTOP].data[upd->ipass];
5616
pinbot = upd->ints[I_PINS2WRITE];
5619
ybegin = pintop * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
5620
yend = pinbot * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
5622
/** Determine Width of this scan */
5624
xbegin = upd->nbytes;
5627
for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Pin-testloop */
5629
if(0 > y) continue; /* Inserted Scanlines */
5631
scan = upd->scnbuf[y & upd->scnmsk];
5633
for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Compwise test */
5634
obytes = scan[icomp].bytes;
5636
for(x = 0; x < xbegin && !obytes[x]; x++);
5637
if(x < xbegin) xbegin = x;
5639
if(x < upd->nbytes) {
5640
for(x = upd->nbytes-1; x > xend && !obytes[x]; x--);
5641
if(x > xend) xend = x;
5643
} /* Compwise test */
5645
} /* Pin-testloop */
5647
if(xbegin <= xend) { /* Some data to write */
5651
if(0 == upd->strings[S_XMOVE].size) xbegin = 0;
5654
* Adjust the Printers Y-Position
5656
if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
5657
if(B_YABS & upd->flags) y = upd->yscan + upd->ints[I_YOFS];
5658
else y = upd->yscan - upd->yprinter;
5660
if( 1 < upd->ints[I_YSTEP]) {
5661
n = y / upd->ints[I_YSTEP]; /* Major-Steps */
5662
y -= n * upd->ints[I_YSTEP]; /* Minor-Steps */
5663
} else if(-1 > upd->ints[I_YSTEP]) {
5664
n = y * -upd->ints[I_YSTEP]; /* May this work? */
5671
if(n) { /* Coarse Positioning */
5672
memcpy(upd->outbuf+ioutbuf,
5673
upd->strings[S_YMOVE].data,upd->strings[S_YMOVE].size);
5674
ioutbuf += upd->strings[S_YMOVE].size;
5676
upd->outbuf[ioutbuf++] = n & 0xff;
5677
upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5679
} /* Coarse Positioning */
5681
if(0 < upd->strings[S_YSTEP].size) {
5683
memcpy(upd->outbuf+ioutbuf,
5684
upd->strings[S_YSTEP].data,
5685
upd->strings[S_YSTEP].size);
5686
ioutbuf += upd->strings[S_YSTEP].size;
5690
upd->yprinter = upd->yscan;
5691
} /* Adjust Y-Position */
5693
* Now write the required components
5695
for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Component-Print */
5697
* First check, wether this Component needs printing
5699
for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Comp-Test */
5701
obytes = upd->scnbuf[y & upd->scnmsk][icomp].bytes;
5702
for(x = xbegin; x <= xend && !obytes[x]; ++x);
5703
if( x <= xend) break;
5705
if(y >= yend) continue; /* Component not required */
5707
* Select the Component
5709
if((0 < upd->string_a[SA_SETCOMP].size) &&
5710
(upd->icomp != icomp ) ) { /* Selection enabled */
5712
if(0 < upd->string_a[SA_SETCOMP].data[icomp].size) {
5713
memcpy(upd->outbuf+ioutbuf,
5714
upd->string_a[SA_SETCOMP].data[icomp].data,
5715
upd->string_a[SA_SETCOMP].data[icomp].size);
5716
ioutbuf += upd->string_a[SA_SETCOMP].data[icomp].size;
5718
} /* Selection enabled */
5720
* Establish the X-Position
5722
if(xbegin != upd->xprinter) {
5724
if(0 == upd->strings[S_XMOVE].size) {
5726
upd->outbuf[ioutbuf++] = '\r';
5733
if(B_XABS & upd->flags) n = x = xbegin + upd->ints[I_XOFS];
5734
else n = x = xbegin - upd->xprinter;
5736
if( 1 < upd->ints[I_XSTEP]) {
5738
n -= upd->ints[I_XSTEP];
5741
if(n) n /= upd->ints[I_XSTEP]; /* Major-Steps */
5742
if(x) x %= upd->ints[I_XSTEP]; /* Minor-Steps */
5744
} else if(-1 > upd->ints[I_XSTEP]) {
5745
n *= -upd->ints[I_XSTEP]; /* May this work? */
5749
if(n) { /* Adjust X-Position */
5751
memcpy(upd->outbuf+ioutbuf,
5752
upd->strings[S_XMOVE].data,
5753
upd->strings[S_XMOVE].size);
5754
ioutbuf += upd->strings[S_XMOVE].size;
5756
upd->outbuf[ioutbuf++] = n & 0xff;
5757
upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5759
} /* Adjust X-Position */
5763
if(x && 0 < upd->strings[S_XSTEP].size) { /* Fine-Adjust X */
5765
memcpy(upd->outbuf+ioutbuf,
5766
upd->strings[S_XSTEP].data,
5767
upd->strings[S_XSTEP].size);
5768
ioutbuf += upd->strings[S_XSTEP].size;
5770
} /* Fine-Adjust X */
5772
upd->xprinter = xend+1;
5775
* Send the Write-Command
5777
if(0 < upd->string_a[SA_WRITECOMP].data[icomp].size) {
5778
memcpy(upd->outbuf+ioutbuf,
5779
upd->string_a[SA_WRITECOMP].data[icomp].data,
5780
upd->string_a[SA_WRITECOMP].data[icomp].size);
5781
ioutbuf += upd->string_a[SA_WRITECOMP].data[icomp].size;
5783
n = xend + 1 - xbegin;
5784
upd->outbuf[ioutbuf++] = (n<<3) & 255;
5785
upd->outbuf[ioutbuf++] = (n>>5) & 255;
5789
for(pin = 0; pin < pintop; ++pin) {
5790
ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
5791
fwrite(upd->outbuf,1,ioutbuf,out);
5795
for(y = ybegin; 0 > y; y += upd->ints[I_NYPASS]) {
5796
ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
5797
fwrite(upd->outbuf,1,ioutbuf,out);
5801
for(; y < yend; y += upd->ints[I_NYPASS]) {
5802
ioutbuf += upd_rle(upd->outbuf+ioutbuf,
5803
upd->scnbuf[y & upd->scnmsk][icomp].bytes+xbegin,n);
5804
fwrite(upd->outbuf,1,ioutbuf,out);
5808
for(pin = pinbot; pin < upd->ints[I_PINS2WRITE]; ++pin) {
5809
ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
5810
fwrite(upd->outbuf,1,ioutbuf,out);
5813
} /* Component-Print */
5814
} /* Some data to write */
5816
/** Advance counters in upd, change modi */
5817
if(upd->yscan < upd->ints[I_BEG_Y]) {
5818
upd->yscan += upd->int_a[IA_BEG_DY].data[upd->ipass++];
5819
if( upd->ints[I_BEG_Y] <= upd->yscan) upd->ipass = 0;
5820
else if(upd->int_a[IA_BEG_DY].size <= upd->ipass) upd->ipass = 0;
5821
} else if(upd->yscan >= upd->ints[I_END_Y]) {
5822
upd->yscan += upd->int_a[IA_END_DY].data[upd->ipass++];
5823
if(upd->int_a[IA_END_DY].size <= upd->ipass) upd->ipass = 0;
5825
upd->yscan += upd->int_a[IA_STD_DY].data[upd->ipass++];
5826
if(upd->int_a[IA_STD_DY].size <= upd->ipass) upd->ipass = 0;
5827
if(upd->yscan >= upd->ints[I_END_Y]) upd->ipass = 0;
5833
/* ------------------------------------------------------------------- */
5834
/* upd_wrtescnm: Write a pass */
5835
/* ------------------------------------------------------------------- */
5837
/*GR copied from upd_wrtescp2 and modified */
5840
upd_wrtescnm(upd_p upd, FILE *out)
5842
int pinbot,pin,pintop,xbegin,x,xend,icomp,ybegin,yend,y,ioutbuf,n;
5843
int irow,imask,iyofs;
5847
/** Determine the number of pins to write */
5849
if(upd->yscan < upd->ints[I_BEG_Y]) {
5851
pinbot = upd->int_a[IA_BEGBOT].data[upd->ipass];
5852
} else if(upd->yscan >= upd->ints[I_END_Y]) {
5853
pinbot = upd->ints[I_PINS2WRITE];
5854
pintop = pinbot - upd->int_a[IA_ENDTOP].data[upd->ipass];
5857
pinbot = upd->ints[I_PINS2WRITE];
5860
ybegin = pintop * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
5861
yend = pinbot * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
5863
/** Determine Width of this scan */
5865
xbegin = upd->nbytes;
5868
for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Pin-testloop */
5870
if(0 > y) continue; /* Inserted Scanlines */
5872
scan = upd->scnbuf[y & upd->scnmsk];
5874
for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Compwise test */
5875
obytes = scan[icomp].bytes;
5877
for(x = 0; x < xbegin && !obytes[x]; x++);
5878
if(x < xbegin) xbegin = x;
5880
if(x < upd->nbytes) {
5881
for(x = upd->nbytes-1; x > xend && !obytes[x]; x--);
5882
if(x > xend) xend = x;
5884
} /* Compwise test */
5885
} /* Pin-testloop */
5887
if(xbegin <= xend) { /* Some data to write */
5891
if(0 == upd->strings[S_XMOVE].size) xbegin = 0;
5894
* Adjust the Printers Y-Position
5896
if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
5897
if(B_YABS & upd->flags) y = upd->yscan + upd->ints[I_YOFS];
5898
else y = upd->yscan - upd->yprinter;
5900
if( 1 < upd->ints[I_YSTEP]) {
5901
n = y / upd->ints[I_YSTEP]; /* Major-Steps */
5902
y -= n * upd->ints[I_YSTEP]; /* Minor-Steps */
5903
} else if(-1 > upd->ints[I_YSTEP]) {
5904
n = y * -upd->ints[I_YSTEP]; /* May this work? */
5911
if(n) { /* Coarse Positioning */
5912
memcpy(upd->outbuf+ioutbuf,
5913
upd->strings[S_YMOVE].data,upd->strings[S_YMOVE].size);
5914
ioutbuf += upd->strings[S_YMOVE].size;
5916
upd->outbuf[ioutbuf++] = n & 0xff;
5917
upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5919
} /* Coarse Positioning */
5921
if(0 < upd->strings[S_YSTEP].size) {
5923
memcpy(upd->outbuf+ioutbuf,
5924
upd->strings[S_YSTEP].data,
5925
upd->strings[S_YSTEP].size);
5926
ioutbuf += upd->strings[S_YSTEP].size;
5930
upd->yprinter = upd->yscan;
5931
} /* Adjust Y-Position */
5933
* Now write the required components
5937
* Select the Component
5939
* Always issue an ESC 'r' 0 - don't know why - that
5940
* is just what the windows driver does.
5943
if((0 < upd->string_a[SA_SETCOMP].size) /* &&
5944
(upd->icomp != icomp ) */) { /* Selection enabled */
5946
if(0 < upd->string_a[SA_SETCOMP].data[icomp].size) {
5947
memcpy(upd->outbuf+ioutbuf,
5948
upd->string_a[SA_SETCOMP].data[icomp].data,
5949
upd->string_a[SA_SETCOMP].data[icomp].size);
5950
ioutbuf += upd->string_a[SA_SETCOMP].data[icomp].size;
5952
} /* Selection enabled */
5954
* Establish the X-Position
5956
if(xbegin != upd->xprinter) {
5958
if(0 == upd->strings[S_XMOVE].size) {
5960
upd->outbuf[ioutbuf++] = '\r';
5967
if(B_XABS & upd->flags) n = x = xbegin + upd->ints[I_XOFS];
5968
else n = x = xbegin - upd->xprinter;
5970
if( 1 < upd->ints[I_XSTEP]) {
5972
n -= upd->ints[I_XSTEP];
5975
if(n) n /= upd->ints[I_XSTEP]; /* Major-Steps */
5976
if(x) x %= upd->ints[I_XSTEP]; /* Minor-Steps */
5978
} else if(-1 > upd->ints[I_XSTEP]) {
5979
n *= -upd->ints[I_XSTEP]; /* May this work? */
5983
if(n) { /* Adjust X-Position */
5985
memcpy(upd->outbuf+ioutbuf,
5986
upd->strings[S_XMOVE].data,
5987
upd->strings[S_XMOVE].size);
5988
ioutbuf += upd->strings[S_XMOVE].size;
5990
upd->outbuf[ioutbuf++] = n & 0xff;
5991
upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5993
} /* Adjust X-Position */
5997
if(x && 0 < upd->strings[S_XSTEP].size) { /* Fine-Adjust X */
5999
memcpy(upd->outbuf+ioutbuf,
6000
upd->strings[S_XSTEP].data,
6001
upd->strings[S_XSTEP].size);
6002
ioutbuf += upd->strings[S_XSTEP].size;
6004
} /* Fine-Adjust X */
6006
upd->xprinter = xend+1;
6009
* Send the Write-Command - the default is ESC '.' 1
6011
if(0 < upd->string_a[SA_WRITECOMP].data[icomp].size) {
6012
memcpy(upd->outbuf+ioutbuf,
6013
upd->string_a[SA_WRITECOMP].data[icomp].data,
6014
upd->string_a[SA_WRITECOMP].data[icomp].size);
6015
ioutbuf += upd->string_a[SA_WRITECOMP].data[icomp].size;
6017
n = xend + 1 - xbegin;
6018
upd->outbuf[ioutbuf++] = (n<<3) & 255;
6019
upd->outbuf[ioutbuf++] = (n>>5) & 255;
6023
irow=0; /* row counter for output data */
6025
/* pins at the top of the head that don't print */
6026
for(pin = 0; pin < pintop; ++pin) {
6028
for(i=0 ; i < upd->ints[I_PATRPT]; i++){
6029
if(irow >= upd->ints[I_ROWS]) break;
6030
ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6031
fwrite(upd->outbuf,1,ioutbuf,out);
6037
/* I'm not really sure what this does */
6038
/* it looks like we're filling in empty rows */
6039
for(y = ybegin; 0 > y; y += upd->ints[I_NYPASS]) {
6042
for(i=0 ; i < upd->ints[I_PATRPT]; i++){
6043
if(irow >= upd->ints[I_ROWS]) break;
6044
ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6045
fwrite(upd->outbuf,1,ioutbuf,out);
6051
for(; y < yend; y += upd->ints[I_NYPASS]) {
6053
int i,masklen=upd->ints[I_PATRPT],yinc=0;
6055
for(i=0 ; (i < upd->ints[I_PATRPT]); i++){
6056
if(irow >= upd->ints[I_ROWS]) break;
6057
imask = irow%masklen;
6058
icomp = upd->int_a[IA_ROWMASK].data[imask];
6060
ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6063
iyofs = upd->int_a[IA_SCNOFS].data[imask];
6064
ioutbuf += upd_rle(upd->outbuf+ioutbuf,
6065
upd->scnbuf[(y+iyofs) & upd->scnmsk][icomp].bytes+xbegin,n);
6066
yinc+=upd->ints[I_NYPASS];
6068
fwrite(upd->outbuf,1,ioutbuf,out);
6073
if (upd->ints[I_NYPASS] < upd->ints[I_PATRPT]) {
6076
y-=upd->ints[I_NYPASS];
6080
/* I think this is the pins at the bottom of the head that don't print */
6081
for(pin = pinbot; pin < upd->ints[I_PINS2WRITE]; ++pin) {
6083
for(i=0 ; i < upd->ints[I_PATRPT]; i++){
6084
if(irow >= upd->ints[I_ROWS]) break;
6085
ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6086
fwrite(upd->outbuf,1,ioutbuf,out);
6092
/* pad empty rows that haven't been filled yet*/
6093
if (irow < upd->ints[I_ROWS]) {
6094
for( ; irow < upd->ints[I_ROWS]; irow++){
6095
ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6096
fwrite(upd->outbuf,1,ioutbuf,out);
6101
} /* Some data to write */
6103
/** Advance counters in upd, change modi */
6104
if(upd->yscan < upd->ints[I_BEG_Y]) {
6105
upd->yscan += upd->int_a[IA_BEG_DY].data[upd->ipass++];
6106
if( upd->ints[I_BEG_Y] <= upd->yscan) upd->ipass = 0;
6107
else if(upd->int_a[IA_BEG_DY].size <= upd->ipass) upd->ipass = 0;
6108
} else if(upd->yscan >= upd->ints[I_END_Y]) {
6109
upd->yscan += upd->int_a[IA_END_DY].data[upd->ipass++];
6110
if(upd->int_a[IA_END_DY].size <= upd->ipass) upd->ipass = 0;
6112
upd->yscan += upd->int_a[IA_STD_DY].data[upd->ipass++];
6113
if(upd->int_a[IA_STD_DY].size <= upd->ipass) upd->ipass = 0;
6114
if(upd->yscan >= upd->ints[I_END_Y]) upd->ipass = 0;
6120
/* ------------------------------------------------------------------- */
6121
/* upd_wrtescp2x: Write an ESC/P2-pass with X-Weaving */
6122
/* ------------------------------------------------------------------- */
6125
upd_wrtescp2x(upd_p upd, FILE *out)
6127
int pinbot,pin,pintop,xbegin,x,xend,icomp,ybegin,yend,y,ioutbuf,n,ixpass;
6131
/** Determine the number of pins to write */
6133
if(upd->yscan < upd->ints[I_BEG_Y]) {
6134
ixpass = upd->int_a[IA_BEG_IX].data[upd->ipass];
6136
pinbot = upd->int_a[IA_BEGBOT].data[upd->ipass];
6137
} else if(upd->yscan >= upd->ints[I_END_Y]) {
6138
ixpass = upd->int_a[IA_END_IX].data[upd->ipass];
6139
pinbot = upd->ints[I_PINS2WRITE];
6140
pintop = pinbot - upd->int_a[IA_ENDTOP].data[upd->ipass];
6142
ixpass = upd->int_a[IA_STD_IX].data[upd->ipass];
6144
pinbot = upd->ints[I_PINS2WRITE];
6147
ybegin = pintop * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
6148
yend = pinbot * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
6150
/** Determine Width of this scan */
6152
xbegin = upd->pwidth;
6155
for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Pin-testloop */
6157
if(0 > y) continue; /* Inserted Scanlines */
6159
scan = upd->scnbuf[y & upd->scnmsk];
6161
for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Compwise test */
6162
if(xbegin > scan[icomp].xbegin[ixpass])
6163
xbegin = scan[icomp].xbegin[ixpass];
6164
if(xend < scan[icomp].xend[ ixpass])
6165
xend = scan[icomp].xend[ ixpass];
6166
} /* Compwise test */
6168
} /* Pin-testloop */
6170
if(xbegin <= xend) { /* Some data to write */
6172
ioutbuf = upd->nbytes;
6174
if(0 == upd->strings[S_XMOVE].size) xbegin = ixpass;
6177
* Adjust the Printers Y-Position
6179
if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
6180
if(B_YABS & upd->flags) y = upd->yscan + upd->ints[I_YOFS];
6181
else y = upd->yscan - upd->yprinter;
6183
if( 1 < upd->ints[I_YSTEP]) {
6184
n = y / upd->ints[I_YSTEP]; /* Major-Steps */
6185
y -= n * upd->ints[I_YSTEP]; /* Minor-Steps */
6186
} else if(-1 > upd->ints[I_YSTEP]) {
6187
n = y * -upd->ints[I_YSTEP]; /* May this work? */
6194
if(n) { /* Coarse Positioning */
6195
memcpy(upd->outbuf+ioutbuf,
6196
upd->strings[S_YMOVE].data,upd->strings[S_YMOVE].size);
6197
ioutbuf += upd->strings[S_YMOVE].size;
6199
upd->outbuf[ioutbuf++] = n & 0xff;
6200
upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
6202
} /* Coarse Positioning */
6204
if(0 < upd->strings[S_YSTEP].size) {
6206
memcpy(upd->outbuf+ioutbuf,
6207
upd->strings[S_YSTEP].data,
6208
upd->strings[S_YSTEP].size);
6209
ioutbuf += upd->strings[S_YSTEP].size;
6213
upd->yprinter = upd->yscan;
6214
} /* Adjust Y-Position */
6217
* Now write the required components
6219
for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Component-Print */
6221
* First check, wether this Component needs printing
6223
for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Comp-Test */
6225
scan = upd->scnbuf[y & upd->scnmsk]+icomp;
6226
if(0 <= scan->xend[ixpass]) break;
6228
if(y >= yend) continue; /* Component not required */
6230
* Select the Component
6232
if((0 < upd->string_a[SA_SETCOMP].size) &&
6233
(upd->icomp != icomp ) ) { /* Selection enabled */
6235
if(0 < upd->string_a[SA_SETCOMP].data[icomp].size) {
6236
memcpy(upd->outbuf+ioutbuf,
6237
upd->string_a[SA_SETCOMP].data[icomp].data,
6238
upd->string_a[SA_SETCOMP].data[icomp].size);
6239
ioutbuf += upd->string_a[SA_SETCOMP].data[icomp].size;
6241
} /* Selection enabled */
6243
* Establish the X-Position
6245
if(xbegin != upd->xprinter) {
6247
if(0 == upd->strings[S_XMOVE].size) {
6249
upd->outbuf[ioutbuf++] = '\r';
6256
if(B_XABS & upd->flags) n = x = xbegin + upd->ints[I_XOFS];
6257
else n = x = xbegin - upd->xprinter;
6259
if( 1 < upd->ints[I_XSTEP]) {
6261
n -= upd->ints[I_XSTEP];
6264
if(n) n /= upd->ints[I_XSTEP]; /* Major-Steps */
6265
if(x) x %= upd->ints[I_XSTEP]; /* Minor-Steps */
6267
} else if(-1 > upd->ints[I_XSTEP]) {
6268
n *= -upd->ints[I_XSTEP]; /* May this work? */
6272
if(n) { /* Adjust X-Position */
6274
memcpy(upd->outbuf+ioutbuf,
6275
upd->strings[S_XMOVE].data,
6276
upd->strings[S_XMOVE].size);
6277
ioutbuf += upd->strings[S_XMOVE].size;
6279
upd->outbuf[ioutbuf++] = n & 0xff;
6280
upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
6282
} /* Adjust X-Position */
6286
if(x && 0 < upd->strings[S_XSTEP].size) { /* Fine-Adjust X */
6288
memcpy(upd->outbuf+ioutbuf,
6289
upd->strings[S_XSTEP].data,
6290
upd->strings[S_XSTEP].size);
6291
ioutbuf += upd->strings[S_XSTEP].size;
6293
} /* Fine-Adjust X */
6295
upd->xprinter = xend+1;
6298
* Send the Write-Command
6300
if(0 < upd->string_a[SA_WRITECOMP].data[icomp].size) {
6301
memcpy(upd->outbuf+ioutbuf,
6302
upd->string_a[SA_WRITECOMP].data[icomp].data,
6303
upd->string_a[SA_WRITECOMP].data[icomp].size);
6304
ioutbuf += upd->string_a[SA_WRITECOMP].data[icomp].size;
6306
n = ((xend - xbegin) / upd->ints[I_NXPASS] + 8) & ~7;
6307
upd->outbuf[ioutbuf++] = n & 255;
6308
upd->outbuf[ioutbuf++] = (n>>8) & 255;
6313
for(pin = 0; pin < pintop; ++pin) {
6314
ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6315
fwrite(upd->outbuf+upd->nbytes,1,ioutbuf-upd->nbytes,out);
6316
ioutbuf = upd->nbytes;
6319
for(y = ybegin; 0 > y; y += upd->ints[I_NYPASS]) {
6320
ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6321
fwrite(upd->outbuf+upd->nbytes,1,ioutbuf-upd->nbytes,out);
6322
ioutbuf = upd->nbytes;
6325
for(; y < yend; y += upd->ints[I_NYPASS]) {
6326
byte * ibytes = upd->scnbuf[y & upd->scnmsk][icomp].bytes;
6327
obytes = upd->outbuf;
6328
memset(obytes,0,upd->nbytes);
6330
for(x = xbegin; x <= xend; x += upd->ints[I_NXPASS]) {
6331
if(ibytes[x>>3] & (0x80 >> (x & 7))) *obytes |= bit;
6332
if(!(bit >>= 1)) { obytes++; bit = 0x80; }
6334
ioutbuf += upd_rle(upd->outbuf+ioutbuf,upd->outbuf,n);
6335
fwrite(upd->outbuf+upd->nbytes,1,ioutbuf-upd->nbytes,out);
6336
ioutbuf = upd->nbytes;
6339
for(pin = pinbot; pin < upd->ints[I_PINS2WRITE]; ++pin) {
6340
ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6341
fwrite(upd->outbuf+upd->nbytes,1,ioutbuf-upd->nbytes,out);
6342
ioutbuf = upd->nbytes;
6344
} /* Component-Print */
6345
} /* Some data to write */
6347
/** Advance counters in upd, change modi */
6349
if(upd->yscan < upd->ints[I_BEG_Y]) {
6350
upd->yscan += upd->int_a[IA_BEG_DY].data[upd->ipass++];
6351
if( upd->ints[I_BEG_Y] <= upd->yscan) upd->ipass = 0;
6352
else if(upd->int_a[IA_BEG_DY].size <= upd->ipass) upd->ipass = 0;
6353
} else if(upd->yscan >= upd->ints[I_END_Y]) {
6354
upd->yscan += upd->int_a[IA_END_DY].data[upd->ipass++];
6355
if(upd->int_a[IA_END_DY].size <= upd->ipass) upd->ipass = 0;
6357
upd->yscan += upd->int_a[IA_STD_DY].data[upd->ipass++];
6358
if(upd->int_a[IA_STD_DY].size <= upd->ipass) upd->ipass = 0;
6359
if(upd->yscan >= upd->ints[I_END_Y]) upd->ipass = 0;
6365
/* ------------------------------------------------------------------- */
6366
/* upd_rle: The Runlength-Compressor */
6367
/* ------------------------------------------------------------------- */
6370
upd_rle(byte *out,const byte *in,int nbytes)
6377
if(in != NULL) { /* Data present */
6381
while(nbytes > 0) { /* something to compress */
6385
while((nbytes > crun) && (run == in[crun])) if(++crun == 128) break;
6387
if((crun > 2) || (crun == nbytes)) { /* use this run */
6389
*out++ = (257 - crun) & 0xff; *out++ = run; used += 2;
6391
nbytes -= crun; in += crun;
6394
} else { /* ignore this run */
6396
for(cdata = crun; (nbytes > cdata) && (crun < 4);) {
6397
if(run == in[cdata]) crun += 1;
6398
else run = in[cdata], crun = 1;
6399
if(++cdata == 128) break;
6402
if(crun < 3) crun = 0; /* ignore trailing run */
6405
*out++ = cdata-1; used++;
6406
memcpy(out,in,cdata); used += cdata; out += cdata;
6408
nbytes -= cdata; in += cdata;
6410
} /* use/ignore run */
6412
} /* something to compress */
6414
} else { /* Empty scans to fill bands */
6417
crun = nbytes > 128 ? 128 : nbytes;
6419
*out++ = (257 - crun) & 0xff;
6423
} /* Data present or empty */
6427
/* ------------------------------------------------------------------- */
6428
/* upd_open_wrtrtl: Basic HP-RTL Writer */
6429
/* ------------------------------------------------------------------- */
6432
upd_open_wrtrtl(upd_device *udev)
6434
const upd_p upd = udev->upd;
6437
/** Adjust the Raster-Width */
6439
if(0 < upd->strings[S_BEGIN].size) { /* BOP-Checker */
6448
for(i = 0; i < upd->strings[S_BEGIN].size; ++i) {
6449
const int c = upd->strings[S_BEGIN].data[i];
6452
/* ----- any character */
6454
if( c == 0x1b) state = 1; /* ESC */
6457
/* ----- last was ESC */
6459
if( c == 0x2a) state = 2; /* ESC * */
6460
else if( c == 0x25) state = 5; /* ESC % */
6464
/* ----- got ESC * */
6466
j = i; /* This character is not part of the replaced text */
6467
if( c == 0x72) state = 3; /* ESC * r */
6468
else if( c == 0x74) state = 4; /* ESC * t */
6472
/* ----- got ESC * r */
6473
/* Pagewidth and Pagelength might be replaced */
6476
if( (B_PAGEWIDTH & upd->flags) &&
6477
((c == 0x73) || (c == 0x53)) ) { /* esc * r # S */
6479
sprintf(cv,"%d",upd->pwidth);
6482
nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6483
UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6485
if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6486
memcpy(bp+j+1, cv,ncv);
6487
memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6488
upd->strings[S_BEGIN].size-i);
6490
UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6491
upd->strings[S_BEGIN].data = bp;
6492
upd->strings[S_BEGIN].size = nbp;
6494
} else if((B_PAGELENGTH & upd->flags) &&
6495
((c == 0x74) || (c == 0x54)) ) { /* esc * r # T */
6497
sprintf(cv,"%d",upd->pheight);
6500
nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6501
UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6503
if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6504
memcpy(bp+j+1, cv,ncv);
6505
memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6506
upd->strings[S_BEGIN].size-i);
6508
UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6509
upd->strings[S_BEGIN].data = bp;
6510
upd->strings[S_BEGIN].size = nbp;
6514
if( (0x40 < c) && (c < 0x5b)) state = 0; /* Term. cmd. */
6515
else if(!((0x2f < c) && (c < 0x3a))) j = i; /* Non-Number */
6519
/* ----- got ESC * t */
6520
/* Resolution might be replaced */
6521
case 4: /* esc * t */
6523
if( (B_RESOLUTION & upd->flags) &&
6524
((c == 0x72) || (c == 0x52)) ) { /* esc * t # R */
6526
sprintf(cv,"%d",(int)
6527
((udev->y_pixels_per_inch < udev->x_pixels_per_inch ?
6528
udev->x_pixels_per_inch : udev->y_pixels_per_inch)
6532
nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6533
UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6535
if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6536
memcpy(bp+j+1, cv,ncv);
6537
memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6538
upd->strings[S_BEGIN].size-i);
6540
UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6541
upd->strings[S_BEGIN].data = bp;
6542
upd->strings[S_BEGIN].size = nbp;
6546
if( (0x40 < c) && (c < 0x5b)) state = 0; /* Term. cmd. */
6547
else if(!((0x2f < c) && (c < 0x3a))) j = i; /* Non-Number */
6551
case 5: /* ESC % - 1 2 3 4 5 X */
6552
if( c == 0x2d) state = 6; /* ESC % - */
6556
case 6: /* ESC % - 1 2 3 4 5 X */
6557
if( c == 0x31) state = 7; /* ESC % - 1 */
6561
case 7: /* ESC % - 1 2 3 4 5 X */
6562
if( c == 0x32) state = 8; /* ESC % - 1 2 */
6566
case 8: /* ESC % - 1 2 3 4 5 X */
6567
if( c == 0x33) state = 9; /* ESC % - 1 2 3 */
6571
case 9: /* ESC % - 1 2 3 4 5 X */
6572
if( c == 0x34) state = 10; /* ESC % - 1 2 3 4 */
6576
case 10: /* ESC % - 1 2 3 4 5 X */
6577
if( c == 0x35) state = 11; /* ESC % - 1 2 3 4 5 */
6581
case 11: /* ESC % - 1 2 3 4 5 X */
6582
if( c == 0x58) state = 12; /* ESC % - 1 2 3 4 5 X */
6586
case 12: /* PJL-BOL: @ P J L ws */
6587
if( c == 0x40) state = 13; /* @ */
6591
case 13: /* PJL-BOL @ P J L ws */
6592
if( c == 0x50) state = 14; /* @ P */
6596
case 14: /* PJL-BOL @ P J L ws */
6597
if( c == 0x4a) state = 15; /* @ P J */
6601
case 15: /* PJL-BOL @ P J L ws */
6602
if( c == 0x4c) state = 16; /* @ P J L */
6606
case 16: /* PJL-BOL @ P J L ws */
6607
if((c == 0x20) || (c == 0x09)) state = 19; /* @ P J L ws */
6608
else if( c == 0x0d ) state = 17;
6609
else if( c == 0x0a ) state = 12;
6610
else state = 0; /* PJL-Error */
6613
case 17: /* PJL-EOL */
6614
if( c == 0x0a) state = 12; /* Next PJL-Command */
6615
else state = 0; /* PJL-Error */
6618
case 18: /* PJL-Eatup: Expect Newline */
6619
if( c == 0x0a) state = 12;
6622
case 19: /* Begin of PJL-Command */
6623
if( (c == 0x53) || (c == 0x73)) state = 20; /* S E T*/
6624
else if( c == 0x0a ) state = 12; /* BOL */
6625
else if( c == 0x0d ) state = 17;
6628
case 20: /* PJL-Set: S E T */
6629
if( (c == 0x45) || (c == 0x65)) state = 21; /* S E */
6630
else if( c == 0x0a ) state = 12; /* BOL */
6634
case 21: /* PJL-Set: S E T */
6635
if( (c == 0x54) || (c == 0x74)) state = 22; /* S E T */
6636
else if( c == 0x0a ) state = 12; /* BOL */
6640
case 22: /* PJL-Set: S E T ws */
6641
if( (c == 0x20) || (c == 0x09)) state = 23; /* S E T ws */
6642
else if( c == 0x0a ) state = 12; /* BOL */
6646
case 23: /* PJL-Set: S E T ws */
6647
if( (c == 0x50) || (c == 0x70)) state = 24; /* set paper... */
6648
else if((c == 0x52) || (c == 0x72)) state = 41; /* set resolution */
6649
else if( c == 0x0a ) state = 12; /* BOL */
6653
case 24: /* PJL-Set: set paper... */
6654
if( (c == 0x41) || (c == 0x61)) state = 25; /* set pa */
6655
else if( c == 0x0a ) state = 12; /* BOL */
6659
case 25: /* PJL-Set: set paper... */
6660
if( (c == 0x50) || (c == 0x70)) state = 26; /* set pap */
6661
else if( c == 0x0a ) state = 12; /* BOL */
6665
case 26: /* PJL-Set: set paper... */
6666
if( (c == 0x45) || (c == 0x65)) state = 27; /* set pape */
6667
else if( c == 0x0a ) state = 12; /* BOL */
6671
case 27: /* PJL-Set: set paper... */
6672
if( (c == 0x52) || (c == 0x72)) state = 28; /* set paper */
6673
else if( c == 0x0a ) state = 12; /* BOL */
6677
case 28: /* PJL-Set: set paper? */
6678
if( (c == 0x4c) || (c == 0x6c)) state = 29; /* set paperlength */
6679
else if((c == 0x57) || (c == 0x77)) state = 36; /* set paperwidth */
6680
else if( c == 0x0a ) state = 12; /* BOL */
6684
case 29: /* PJL: set paperlength */
6685
if( (c == 0x45) || (c == 0x65)) state = 30; /* set paperle */
6686
else if( c == 0x0a ) state = 12; /* BOL */
6690
case 30: /* PJL: set paperlength */
6691
if( (c == 0x4e) || (c == 0x6e)) state = 31; /* set paperlen */
6692
else if( c == 0x0a ) state = 12; /* BOL */
6696
case 31: /* PJL: set paperlength */
6697
if( (c == 0x47) || (c == 0x67)) state = 32; /* set paperleng */
6698
else if( c == 0x0a ) state = 12; /* BOL */
6702
case 32: /* PJL: set paperlength */
6703
if( (c == 0x54) || (c == 0x74)) state = 33; /* set paperlengt */
6704
else if( c == 0x0a ) state = 12; /* BOL */
6708
case 33: /* PJL: set paperlength */
6709
if( (c == 0x48) || (c == 0x68)) state = 34; /* set paperlength */
6710
else if( c == 0x0a ) state = 12; /* BOL */
6714
case 34: /* PJL: set paperlength */
6715
j = i; /* This character is not part of the replaced text */
6716
if( c == 0x3d ) state = 51; /* set paperlength */
6717
else if( c == 0x0a ) state = 12; /* BOL */
6718
else if((c != 0x20) && (c != 0x09)) state = 18;
6721
case 51: /* PJL: set paperlength = ws */
6722
if( c == 0x0a) state = 12;
6723
else if((c == 0x20) || (c == 0x09)) j = i;
6724
else if(( 0x30 > c) || ( c > 0x39)) state = 18;
6728
case 35: /* PJL: set paperlength */
6729
if((0x30 > c) || (c > 0x39)) { /* End of number */
6731
if(B_PAGELENGTH & upd->flags) { /* insert new number */
6733
sprintf(cv,"%d",(int)
6734
(720.0 * udev->height / udev->y_pixels_per_inch + 0.5));
6737
nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6738
UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6740
if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6741
memcpy(bp+j+1, cv,ncv);
6742
memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6743
upd->strings[S_BEGIN].size-i);
6745
UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6746
upd->strings[S_BEGIN].data = bp;
6747
upd->strings[S_BEGIN].size = nbp;
6748
} /* insert new number */
6750
if( c == 0x0a ) state = 12;
6755
case 36: /* PJL: set paperwidth */
6756
if( (c == 0x49) || (c == 0x69)) state = 37; /* set paperwi */
6757
else if( c == 0x0a ) state = 12; /* BOL */
6761
case 37: /* PJL: set paperwidth */
6762
if( (c == 0x44) || (c == 0x64)) state = 38; /* set paperwid */
6763
else if( c == 0x0a ) state = 12; /* BOL */
6767
case 38: /* PJL: set paperwidth */
6768
if( (c == 0x54) || (c == 0x74)) state = 39; /* set paperwidt */
6769
else if( c == 0x0a ) state = 12; /* BOL */
6773
case 39: /* PJL: set paperwidth */
6774
if( (c == 0x48) || (c == 0x68)) state = 52; /* set paperwidth */
6775
else if( c == 0x0a ) state = 12; /* BOL */
6779
case 52: /* PJL: set paperwidth */
6780
j = i; /* This character is not part of the replaced text */
6781
if( c == 0x3d ) state = 53; /* set paperwidth */
6782
else if( c == 0x0a ) state = 12; /* BOL */
6783
else if((c != 0x20) && (c != 0x09)) state = 18;
6786
case 53: /* PJL: set paperwidth = ws */
6787
if( c == 0x0a) state = 12;
6788
else if((c == 0x20) || (c == 0x09)) j = i;
6789
else if(( 0x30 > c) || ( c > 0x39)) state = 18;
6793
case 40: /* PJL: set paperlength */
6794
if((0x30 > c) || (c > 0x39)) { /* End of number */
6796
if(B_PAGEWIDTH & upd->flags) { /* insert new number */
6798
sprintf(cv,"%d",(int)
6799
(720.0 * udev->width / udev->x_pixels_per_inch + 0.5));
6802
nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6803
UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6805
if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6806
memcpy(bp+j+1, cv,ncv);
6807
memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6808
upd->strings[S_BEGIN].size-i);
6810
UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6811
upd->strings[S_BEGIN].data = bp;
6812
upd->strings[S_BEGIN].size = nbp;
6813
} /* insert new number */
6815
if( c == 0x0a ) state = 12;
6820
case 41: /* PJL: set resolution */
6821
if( (c == 0x45) || (c == 0x65)) state = 42; /* set re */
6822
else if( c == 0x0a ) state = 12; /* BOL */
6826
case 42: /* PJL: set resolution */
6827
if( (c == 0x53) || (c == 0x73)) state = 43; /* set res */
6828
else if( c == 0x0a ) state = 12; /* BOL */
6832
case 43: /* PJL: set resolution */
6833
if( (c == 0x4f) || (c == 0x6f)) state = 44; /* set reso */
6834
else if( c == 0x0a ) state = 12; /* BOL */
6838
case 44: /* PJL: set resolution */
6839
if( (c == 0x4c) || (c == 0x6c)) state = 45; /* set resol */
6840
else if( c == 0x0a ) state = 12; /* BOL */
6844
case 45: /* PJL: set resolution */
6845
if( (c == 0x55) || (c == 0x75)) state = 46; /* set resolu */
6846
else if( c == 0x0a ) state = 12; /* BOL */
6850
case 46: /* PJL: set resolution */
6851
if( (c == 0x54) || (c == 0x74)) state = 47; /* set resolut */
6852
else if( c == 0x0a ) state = 12; /* BOL */
6856
case 47: /* PJL: set resolution */
6857
if( (c == 0x49) || (c == 0x69)) state = 48; /* set resoluti */
6858
else if( c == 0x0a ) state = 12; /* BOL */
6862
case 48: /* PJL: set resolution */
6863
if( (c == 0x4f) || (c == 0x6f)) state = 49; /* set resolutio */
6864
else if( c == 0x0a ) state = 12; /* BOL */
6868
case 49: /* PJL: set resolution */
6869
if( (c == 0x4e) || (c == 0x6e)) state = 54; /* set resolution */
6870
else if( c == 0x0a ) state = 12; /* BOL */
6874
case 54: /* PJL: set resolution */
6875
j = i; /* This character is not part of the replaced text */
6876
if( c == 0x3d ) state = 55; /* set resolution */
6877
else if( c == 0x0a ) state = 12; /* BOL */
6878
else if((c != 0x20) && (c != 0x09)) state = 18;
6881
case 55: /* PJL: set resolution = ws */
6882
if( c == 0x0a) state = 12;
6883
else if((c == 0x20) || (c == 0x09)) j = i;
6884
else if(( 0x30 > c) || ( c > 0x39)) state = 18;
6888
case 50: /* PJL: set resolution */
6889
if((0x30 > c) || (c > 0x39)) { /* End of number */
6891
if(B_RESOLUTION & upd->flags) { /* insert new number */
6893
sprintf(cv,"%d",(int)
6894
((udev->y_pixels_per_inch < udev->x_pixels_per_inch ?
6895
udev->x_pixels_per_inch : udev->y_pixels_per_inch)
6899
nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6900
UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6902
if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6903
memcpy(bp+j+1, cv,ncv);
6904
memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6905
upd->strings[S_BEGIN].size-i);
6907
UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6908
upd->strings[S_BEGIN].data = bp;
6909
upd->strings[S_BEGIN].size = nbp;
6910
} /* insert new number */
6912
if( c == 0x0a ) state = 12;
6918
#if UPD_MESSAGES & UPD_M_ERROR
6919
errprintf(udev->memory,
6920
"UNIPRINT-Coding error, wrrtl, state = %d\n",state);
6928
/** SA_WRITECOMP must be valid */
6929
if(upd->ocomp > upd->string_a[SA_WRITECOMP].size) {
6930
#if UPD_MESSAGES & UPD_M_WARNING
6931
errprintf(udev->memory,
6932
"PCL-Open: WRITECOMP-Commands must be given\n");
6938
If all this is correct, it's time to compute the size of the output-buffer.
6947
if(0 < upd->strings[S_YMOVE].size) {
6948
sprintf(tmp,"%d",upd->pheight);
6949
ny = upd->strings[S_YMOVE].size + strlen(tmp);
6951
ny = 1 + upd->string_a[SA_WRITECOMP].data[upd->ocomp-1].size;
6955
noutbuf = upd->nbytes + (upd->nbytes + 127) / 128;
6957
if(ny > noutbuf) noutbuf = ny;
6960
if((0 < noutbuf) && (noutbuf <= INT_MAX)) {
6961
upd->noutbuf = noutbuf;
6962
upd->writer = upd_wrtrtl;
6966
#if UPD_MESSAGES & UPD_M_WARNING
6967
errprintf(udev->memory,
6968
"PCL-Open: %ld is unreasonable size of Outputbuffer\n",
6977
/* ------------------------------------------------------------------- */
6978
/* upd_wrtrtl: Write a pass */
6979
/* ------------------------------------------------------------------- */
6982
upd_wrtrtl(upd_p upd, FILE *out)
6984
const updscan_p scan = upd->scnbuf[upd->yscan & upd->scnmsk];
6986
int x,xend,icomp,ioutbuf;
6989
/** Determine Width of this scan */
6992
for(icomp = 0; icomp < upd->ocomp; ++icomp) {
6994
data = scan[icomp].bytes;
6996
for(x = upd->nbytes-1; 0 <= x; --x) if(data[x]) break;
6997
if(x > xend) xend = x;
7000
if(0 <= xend) { /* Some data to write */
7005
* Adjust the Printers Y-Position
7007
if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
7008
if(1 < upd->strings[S_YMOVE].size) {
7009
sprintf((char *)upd->outbuf+ioutbuf,
7010
(const char *) upd->strings[S_YMOVE].data,
7011
upd->yscan - upd->yprinter);
7012
ioutbuf += strlen((char *)upd->outbuf+ioutbuf);
7014
while(upd->yscan > upd->yprinter) {
7015
for(icomp = 0; icomp < upd->ocomp; ++icomp) {
7016
sprintf((char *)upd->outbuf+ioutbuf,
7017
(const char *) upd->string_a[SA_WRITECOMP].data[icomp].data,0);
7018
ioutbuf += strlen((char *)upd->outbuf+ioutbuf);
7020
fwrite(upd->outbuf,1,ioutbuf,out);
7025
upd->yprinter = upd->yscan;
7026
fwrite(upd->outbuf,1,ioutbuf,out);
7028
} /* Adjust Y-Position */
7030
* Now write the all! components
7032
for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Component-Print */
7033
data = scan[icomp].bytes;
7034
for(x = 0; x <= xend; ++x) if(data[x]) break;
7036
ioutbuf = upd_rle(upd->outbuf,scan[icomp].bytes,xend);
7038
(const char *)upd->string_a[SA_WRITECOMP].data[icomp].data,ioutbuf);
7039
fwrite(upd->outbuf,1,ioutbuf,out);
7042
(const char *)upd->string_a[SA_WRITECOMP].data[icomp].data,0);
7048
} /* Some data to write */
7050
/** Advance scan by one */
7057
/* ------------------------------------------------------------------- */
7058
/* upd_open_wrtcanon: Basic Canon Extended Mode Writer (hr) */
7059
/* ------------------------------------------------------------------- */
7062
upd_open_wrtcanon(upd_device *udev)
7064
const upd_p upd = udev->upd;
7067
/* max length of one printer line */
7068
upd->noutbuf = upd->nbytes + (upd->nbytes + 127) / 128;
7069
upd->writer = upd_wrtcanon;
7075
/* ------------------------------------------------------------------- */
7076
/* upd_wrtcanon: Write a pass (hr) */
7077
/* ------------------------------------------------------------------- */
7079
#define LOW(b) ((b)&0xFF)
7080
#define HIGH(b) ((b)>>8)
7085
upd_wrtcanon(upd_p upd, FILE *out)
7087
const updscan_p scan = upd->scnbuf[upd->yscan & upd->scnmsk];
7089
int x, xend, icomp, ioutbuf, step, ioutbuf1;
7092
/* Check length of the printable date */
7094
for(icomp = 0; icomp < upd->ocomp; ++icomp) {
7095
data = scan[icomp].bytes;
7097
for(x = upd->nbytes-1; 0 <= x; --x) if(data[x]) break;
7099
if(x > xend) xend = x;
7102
/* If some date to print */
7103
if(0 <= xend) { /* Some data to write */
7107
/* Perform vertical tab */
7108
if(upd->yscan != upd->yprinter) {
7109
step = upd->yscan - upd->yprinter;
7116
fputc(HIGH(step), out);
7117
fputc(LOW(step), out);
7119
upd->yprinter = upd->yscan;
7122
for(icomp = 0; icomp < upd->ocomp; ++icomp) {
7124
/* Are there date to print for the selected color component */
7125
data = scan[icomp].bytes;
7126
for(x = 0; x <= xend; ++x) if(data[x]) break;
7128
/* Compressing of the scan line */
7130
ioutbuf = upd_rle(upd->outbuf, scan[icomp].bytes, xend);
7135
ioutbuf1 = ioutbuf + 1;
7137
/* prints the scan line */
7141
fputc(LOW(ioutbuf1), out);
7142
fputc(HIGH(ioutbuf1), out);
7143
switch(upd->ocomp) {
7144
case 1: fputc('K',out); break;
7146
case 4: fputc("YMCK"[icomp],out); break;
7149
* the validity of the NCOMP-setting should be checked
7150
* in the put_params-routine, thus the default-case is
7151
* just a matter of coding-style.
7153
default: fputc('K',out); break;
7156
fwrite(upd->outbuf, 1, ioutbuf, out);
7161
/* Printer advances one raster line */
7167
fputc(HIGH(1), out);
7174
/* Advance scan by one */
7180
/* ------------------------------------------------------------------- */
7181
/* All the Pixel-Get Routines */
7182
/* ------------------------------------------------------------------- */
7184
/* That bunch of Pixel-Get Routines */
7186
static upd_proc_pxlget(upd_pxlgetnix); /* A Dummy */
7188
static upd_proc_pxlget(upd_pxlget1f1); /* 1 Bit Forward */
7189
static upd_proc_pxlget(upd_pxlget1f2);
7190
static upd_proc_pxlget(upd_pxlget1f3);
7191
static upd_proc_pxlget(upd_pxlget1f4);
7192
static upd_proc_pxlget(upd_pxlget1f5);
7193
static upd_proc_pxlget(upd_pxlget1f6);
7194
static upd_proc_pxlget(upd_pxlget1f7);
7195
static upd_proc_pxlget(upd_pxlget1f8);
7197
static upd_proc_pxlget(upd_pxlget1r1); /* 1 Bit Reverse */
7198
static upd_proc_pxlget(upd_pxlget1r2);
7199
static upd_proc_pxlget(upd_pxlget1r3);
7200
static upd_proc_pxlget(upd_pxlget1r4);
7201
static upd_proc_pxlget(upd_pxlget1r5);
7202
static upd_proc_pxlget(upd_pxlget1r6);
7203
static upd_proc_pxlget(upd_pxlget1r7);
7204
static upd_proc_pxlget(upd_pxlget1r8);
7206
static upd_proc_pxlget(upd_pxlget2f1); /* 2 Bit Forward */
7207
static upd_proc_pxlget(upd_pxlget2f2);
7208
static upd_proc_pxlget(upd_pxlget2f3);
7209
static upd_proc_pxlget(upd_pxlget2f4);
7211
static upd_proc_pxlget(upd_pxlget2r1); /* 2 Bit Reverse */
7212
static upd_proc_pxlget(upd_pxlget2r2);
7213
static upd_proc_pxlget(upd_pxlget2r3);
7214
static upd_proc_pxlget(upd_pxlget2r4);
7216
static upd_proc_pxlget(upd_pxlget4f1); /* 4 Bit Forward */
7217
static upd_proc_pxlget(upd_pxlget4f2);
7219
static upd_proc_pxlget(upd_pxlget4r1); /* 4 Bit Reverse */
7220
static upd_proc_pxlget(upd_pxlget4r2);
7222
static upd_proc_pxlget(upd_pxlget8f); /* 8 Bit Forward */
7223
static upd_proc_pxlget(upd_pxlget8r); /* 8 Bit Reverse */
7225
static upd_proc_pxlget(upd_pxlget16f); /* 16 Bit Forward */
7226
static upd_proc_pxlget(upd_pxlget16r); /* 16Bit Reverse */
7228
static upd_proc_pxlget(upd_pxlget24f); /* 24 Bit Forward */
7229
static upd_proc_pxlget(upd_pxlget24r); /* 24 Bit Reverse */
7231
static upd_proc_pxlget(upd_pxlget32f); /* 32 Bit Forward */
7232
static upd_proc_pxlget(upd_pxlget32r); /* 32 Bit Reverse */
7234
/* Initialize Forward-Run */
7237
upd_pxlfwd(upd_p upd)
7239
if(!(upd->pxlptr = upd->gsscan)) {
7241
upd->pxlget = upd_pxlgetnix;
7244
switch(upd->int_a[IA_COLOR_INFO].data[1]) {
7245
case 1: upd->pxlget = upd_pxlget1f1; break;
7246
case 2: upd->pxlget = upd_pxlget2f1; break;
7247
case 4: upd->pxlget = upd_pxlget4f1; break;
7248
case 8: upd->pxlget = upd_pxlget8f; break;
7249
case 16: upd->pxlget = upd_pxlget16f; break;
7250
case 24: upd->pxlget = upd_pxlget24f; break;
7251
case 32: upd->pxlget = upd_pxlget32f; break;
7253
#if UPD_MESSAGES & UPD_M_ERROR
7254
errprintf(upd->memory, "upd_pxlfwd: unsupported depth (%d)\n",
7255
upd->int_a[IA_COLOR_INFO].data[1]);
7257
upd->pxlget = upd_pxlgetnix;
7261
return (uint32_t) 0;
7267
upd_pxlget1f1(upd_p upd)
7269
upd->pxlget = upd_pxlget1f2;
7270
return *upd->pxlptr & 0x80 ? (uint32_t) 1 : (uint32_t) 0;
7274
upd_pxlget1f2(upd_p upd)
7276
upd->pxlget = upd_pxlget1f3;
7277
return *upd->pxlptr & 0x40 ? (uint32_t) 1 : (uint32_t) 0;
7281
upd_pxlget1f3(upd_p upd)
7283
upd->pxlget = upd_pxlget1f4;
7284
return *upd->pxlptr & 0x20 ? (uint32_t) 1 : (uint32_t) 0;
7288
upd_pxlget1f4(upd_p upd)
7290
upd->pxlget = upd_pxlget1f5;
7291
return *upd->pxlptr & 0x10 ? (uint32_t) 1 : (uint32_t) 0;
7295
upd_pxlget1f5(upd_p upd)
7297
upd->pxlget = upd_pxlget1f6;
7298
return *upd->pxlptr & 0x08 ? (uint32_t) 1 : (uint32_t) 0;
7302
upd_pxlget1f6(upd_p upd)
7304
upd->pxlget = upd_pxlget1f7;
7305
return *upd->pxlptr & 0x04 ? (uint32_t) 1 : (uint32_t) 0;
7309
upd_pxlget1f7(upd_p upd)
7311
upd->pxlget = upd_pxlget1f8;
7312
return *upd->pxlptr & 0x02 ? (uint32_t) 1 : (uint32_t) 0;
7316
upd_pxlget1f8(upd_p upd)
7318
upd->pxlget = upd_pxlget1f1;
7319
return *upd->pxlptr++ & 0x01 ? (uint32_t) 1 : (uint32_t) 0;
7325
upd_pxlget2f1(upd_p upd)
7327
upd->pxlget = upd_pxlget2f2;
7328
return ((uint32_t) (*upd->pxlptr ) & (uint32_t) 0xC0) >> 6;
7332
upd_pxlget2f2(upd_p upd)
7334
upd->pxlget = upd_pxlget2f3;
7335
return ((uint32_t) (*upd->pxlptr ) & (uint32_t) 0x30) >> 4;
7339
upd_pxlget2f3(upd_p upd)
7341
upd->pxlget = upd_pxlget2f4;
7342
return ((uint32_t) (*upd->pxlptr ) & (uint32_t) 0x0C) >> 2;
7346
upd_pxlget2f4(upd_p upd)
7348
upd->pxlget = upd_pxlget2f1;
7349
return (uint32_t) (*upd->pxlptr++) & (uint32_t) 0x03;
7354
upd_pxlget4f1(upd_p upd)
7356
upd->pxlget = upd_pxlget4f2;
7357
return ((uint32_t) (*upd->pxlptr ) & (uint32_t) 0xF0) >> 4;
7361
upd_pxlget4f2(upd_p upd)
7363
upd->pxlget = upd_pxlget4f1;
7364
return (uint32_t) (*upd->pxlptr++) & (uint32_t) 0x0F;
7369
upd_pxlget8f(upd_p upd)
7371
return (uint32_t) (*upd->pxlptr++);
7374
/* 16 Bit Forward */
7376
upd_pxlget16f(upd_p upd)
7378
uint32_t ci = (uint32_t) (*upd->pxlptr++) << 8;
7379
ci |= *upd->pxlptr++;
7383
/* 24 Bit Forward */
7385
upd_pxlget24f(upd_p upd)
7387
uint32_t ci = (uint32_t) (*upd->pxlptr++) << 16;
7388
ci |= (uint32_t) (*upd->pxlptr++) << 8;
7389
ci |= *upd->pxlptr++;
7393
/* 32 Bit Forward */
7395
upd_pxlget32f(upd_p upd)
7397
uint32_t ci = (uint32_t) (*upd->pxlptr++) << 24;
7398
ci |= (uint32_t) (*upd->pxlptr++) << 16;
7399
ci |= (uint32_t) (*upd->pxlptr++) << 8;
7400
ci |= *upd->pxlptr++;
7407
upd_pxlgetnix(upd_p upd)
7409
return (uint32_t) 0;
7412
/* Initialize Reverse-Run */
7415
upd_pxlrev(upd_p upd)
7417
const uint width = upd->pwidth < upd->gswidth ? upd->pwidth : upd->gswidth;
7419
if(!(upd->pxlptr = upd->gsscan)) {
7421
upd->pxlget = upd_pxlgetnix;
7424
uint32_t ofs = (uint32_t) upd->int_a[IA_COLOR_INFO].data[1] * (width-1);
7426
upd->pxlptr += ofs>>3;
7430
switch(upd->int_a[IA_COLOR_INFO].data[1]) {
7431
case 1: switch(ofs) {
7432
case 0: upd->pxlget = upd_pxlget1r1; break;
7433
case 1: upd->pxlget = upd_pxlget1r2; break;
7434
case 2: upd->pxlget = upd_pxlget1r3; break;
7435
case 3: upd->pxlget = upd_pxlget1r4; break;
7436
case 4: upd->pxlget = upd_pxlget1r5; break;
7437
case 5: upd->pxlget = upd_pxlget1r6; break;
7438
case 6: upd->pxlget = upd_pxlget1r7; break;
7439
case 7: upd->pxlget = upd_pxlget1r8; break;
7441
case 2: switch(ofs) {
7442
case 0: upd->pxlget = upd_pxlget2r1; break;
7443
case 2: upd->pxlget = upd_pxlget2r2; break;
7444
case 4: upd->pxlget = upd_pxlget2r3; break;
7445
case 6: upd->pxlget = upd_pxlget2r4; break;
7447
case 4: switch(ofs) {
7448
case 0: upd->pxlget = upd_pxlget4r1; break;
7449
case 4: upd->pxlget = upd_pxlget4r2; break;
7451
case 8: upd->pxlget = upd_pxlget8r; break;
7453
upd->pxlget = upd_pxlget16r;
7457
upd->pxlget = upd_pxlget24r;
7461
upd->pxlget = upd_pxlget32r;
7465
#if UPD_MESSAGES & UPD_M_ERROR
7466
errprintf(upd->memory, "upd_pxlrev: unsupported depth (%d)\n",
7467
upd->int_a[IA_COLOR_INFO].data[1]);
7469
upd->pxlget = upd_pxlgetnix;
7473
return (uint32_t) 0;
7479
upd_pxlget1r1(upd_p upd)
7481
upd->pxlget = upd_pxlget1r8;
7482
return *upd->pxlptr-- & 0x80 ? (uint32_t) 1 : (uint32_t) 0;
7486
upd_pxlget1r2(upd_p upd)
7488
upd->pxlget = upd_pxlget1r1;
7489
return *upd->pxlptr & 0x40 ? (uint32_t) 1 : (uint32_t) 0;
7493
upd_pxlget1r3(upd_p upd)
7495
upd->pxlget = upd_pxlget1r2;
7496
return *upd->pxlptr & 0x20 ? (uint32_t) 1 : (uint32_t) 0;
7500
upd_pxlget1r4(upd_p upd)
7502
upd->pxlget = upd_pxlget1r3;
7503
return *upd->pxlptr & 0x10 ? (uint32_t) 1 : (uint32_t) 0;
7507
upd_pxlget1r5(upd_p upd)
7509
upd->pxlget = upd_pxlget1r4;
7510
return *upd->pxlptr & 0x08 ? (uint32_t) 1 : (uint32_t) 0;
7514
upd_pxlget1r6(upd_p upd)
7516
upd->pxlget = upd_pxlget1r5;
7517
return *upd->pxlptr & 0x04 ? (uint32_t) 1 : (uint32_t) 0;
7521
upd_pxlget1r7(upd_p upd)
7523
upd->pxlget = upd_pxlget1r6;
7524
return *upd->pxlptr & 0x02 ? (uint32_t) 1 : (uint32_t) 0;
7528
upd_pxlget1r8(upd_p upd)
7530
upd->pxlget = upd_pxlget1r7;
7531
return *upd->pxlptr & 0x01 ? (uint32_t) 1 : (uint32_t) 0;
7537
upd_pxlget2r1(upd_p upd)
7539
upd->pxlget = upd_pxlget2r4;
7540
return ((uint32_t) (*upd->pxlptr--) & (uint32_t) 0xC0) >> 6;
7544
upd_pxlget2r2(upd_p upd)
7546
upd->pxlget = upd_pxlget2r1;
7547
return ((uint32_t) (*upd->pxlptr ) & (uint32_t) 0x30) >> 4;
7551
upd_pxlget2r3(upd_p upd)
7553
upd->pxlget = upd_pxlget2r2;
7554
return ((uint32_t) (*upd->pxlptr ) & (uint32_t) 0x0C) >> 2;
7558
upd_pxlget2r4(upd_p upd)
7560
upd->pxlget = upd_pxlget2r3;
7561
return (uint32_t) (*upd->pxlptr ) & (uint32_t) 0x03;
7567
upd_pxlget4r1(upd_p upd)
7569
upd->pxlget = upd_pxlget4r2;
7570
return ((uint32_t) (*upd->pxlptr--) & (uint32_t) 0xF0) >> 4;
7574
upd_pxlget4r2(upd_p upd)
7576
upd->pxlget = upd_pxlget4r1;
7577
return (uint32_t) (*upd->pxlptr ) & (uint32_t) 0x0F;
7582
upd_pxlget8r(upd_p upd)
7584
return (uint32_t) (*upd->pxlptr--);
7587
/* 16 Bit Reverse */
7589
upd_pxlget16r(upd_p upd)
7591
uint32_t ci = *upd->pxlptr--;
7592
ci |= (uint32_t) (*upd->pxlptr--) << 8;
7596
/* 24 Bit Reverse */
7598
upd_pxlget24r(upd_p upd)
7600
uint32_t ci = *upd->pxlptr--;
7601
ci |= (uint32_t) (*upd->pxlptr--) << 8;
7602
ci |= (uint32_t) (*upd->pxlptr--) << 16;
7606
/* 32 Bit Reverse */
7608
upd_pxlget32r(upd_p upd)
7610
uint32_t ci = *upd->pxlptr--;
7611
ci |= (uint32_t) (*upd->pxlptr--) << 8;
7612
ci |= (uint32_t) (*upd->pxlptr--) << 16;
7613
ci |= (uint32_t) (*upd->pxlptr--) << 24;