Coverage Report

Created: 2025-06-24 07:01

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