Coverage Report

Created: 2025-08-28 07:06

/src/ghostpdl/devices/gdevupd.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2025 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
            /* Shouldn't happen, but just in case */
3063
0
            if (XFVAL(iy+1) == (float)0.0) {
3064
0
                imap = 0;
3065
0
                break;
3066
0
            }
3067
3068
0
            fx  = iy + (fy - XFVAL(iy))/(XFVAL(iy+1) - XFVAL(iy));
3069
3070
0
            fx *= xstep * gx_max_color_value;
3071
3072
0
            fx  = fx < 0.0 ? 0.0 :
3073
0
                 (fx > gx_max_color_value ? gx_max_color_value : fx);
3074
3075
0
            cmap->code[ly] = (gx_color_value)fx;
3076
0
            if((fx - cmap->code[ly]) >= 0.5) cmap->code[ly] += 1;
3077
0
         }
3078
3079
0
#undef   XFVAL
3080
3081
0
      }
3082
0
   }
3083
3084
/** If we're ok, massage upd->ncomp */
3085
3086
0
   if(imap) {
3087
0
      switch(upd->choice[C_MAPPER]) {
3088
0
         case MAP_GRAY:
3089
0
           if(1 > imap) imap = 0;
3090
0
           upd->ncomp = 1;
3091
0
         break;
3092
0
         case MAP_RGBW: /* RGB->RGBW */
3093
0
           if(4 > imap) imap = 0;
3094
0
           upd->ncomp = 4;
3095
0
         break;
3096
0
         case MAP_RGB: /* Plain RGB */
3097
0
           if(3 > imap) imap = 0;
3098
0
           upd->ncomp = 3;
3099
0
         break;
3100
0
         case MAP_CMYK: /* Plain KCMY */
3101
0
           if(4 > imap) imap = 0;
3102
0
            upd->ncomp = 4;
3103
0
         break;
3104
0
         case MAP_CMYKGEN: /* KCMY with black-generation */
3105
0
           if(4 > imap) imap = 0;
3106
0
           upd->ncomp = 4;
3107
0
         break;
3108
0
         case MAP_RGBOV: /* RGB->KCMY with black-generation */
3109
0
           if(4 > imap) imap = 0;
3110
0
           upd->ncomp = 4;
3111
0
         break;
3112
0
         case MAP_RGBNOV: /* RGB->KCMY with black-generation */
3113
0
           if(4 > imap) imap = 0;
3114
0
           upd->ncomp = 4;
3115
0
         break;
3116
3117
0
         default:
3118
0
           imap = 0;
3119
#if        UPD_MESSAGES & UPD_M_WARNING
3120
              errprintf(udev->memory,
3121
                 "upd_open: Mapping %d unknown\n",upd->choice[C_MAPPER]);
3122
#endif
3123
3124
0
         break;
3125
0
      }
3126
0
   }
3127
3128
/** If unsuccesful, install the default routines */
3129
3130
0
   if(!imap) {
3131
0
      upd_close_map(udev);
3132
0
   } else {
3133
0
      upd->flags |= B_MAP;
3134
0
      upd_procs_map(udev);
3135
0
   }
3136
3137
0
   return imap ? 1 : -1;
3138
0
}
3139
3140
/* ------------------------------------------------------------------- */
3141
/* upd_procs_map: (de-) install the color-mapping-procedures           */
3142
/* ------------------------------------------------------------------- */
3143
3144
static int
3145
upd_procs_map(upd_device *udev)
3146
0
{
3147
0
   int imap;
3148
3149
0
   if( udev->upd &&
3150
0
      (udev->upd->flags & B_MAP)) imap = udev->upd->choice[C_MAPPER];
3151
0
   else                           imap = 0;
3152
3153
0
   switch(imap) {
3154
0
     case MAP_GRAY: /* Grayscale -> Grayscale */
3155
0
       set_dev_proc(udev,encode_color, upd_rgb_1color);
3156
0
       set_dev_proc(udev,decode_color, upd_1color_rgb);
3157
0
       set_dev_proc(udev,map_rgb_color, upd_rgb_1color);
3158
0
       set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3159
0
       set_dev_proc(udev,map_color_rgb, upd_1color_rgb);
3160
0
     break;
3161
0
     case MAP_RGBW: /* RGB->RGBW */
3162
0
       set_dev_proc(udev,encode_color, upd_rgb_4color);
3163
0
       set_dev_proc(udev,decode_color, upd_4color_rgb);
3164
0
       set_dev_proc(udev,map_rgb_color, upd_rgb_4color);
3165
0
       set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3166
0
       set_dev_proc(udev,map_color_rgb, upd_4color_rgb);
3167
0
     break;
3168
0
     case MAP_RGB: /* Plain RGB */
3169
0
       set_dev_proc(udev,encode_color, upd_rgb_3color);
3170
0
       set_dev_proc(udev,decode_color, upd_3color_rgb);
3171
0
       set_dev_proc(udev,map_rgb_color, upd_rgb_3color);
3172
0
       set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3173
0
       set_dev_proc(udev,map_color_rgb, upd_3color_rgb);
3174
0
     break;
3175
0
     case MAP_CMYK: /* Plain KCMY */
3176
0
       set_dev_proc(udev,encode_color, upd_cmyk_icolor);
3177
0
       set_dev_proc(udev,decode_color, upd_icolor_rgb);
3178
0
       set_dev_proc(udev,map_rgb_color, gx_default_map_rgb_color);
3179
0
       set_dev_proc(udev,map_cmyk_color,upd_cmyk_icolor);
3180
0
       set_dev_proc(udev,map_color_rgb, upd_icolor_rgb);
3181
0
     break;
3182
0
     case MAP_CMYKGEN: /* KCMY with black-generation */
3183
0
       set_dev_proc(udev,encode_color, upd_cmyk_kcolor);
3184
0
       set_dev_proc(udev,decode_color, upd_kcolor_rgb);
3185
0
       set_dev_proc(udev,map_rgb_color, gx_default_map_rgb_color);
3186
0
       set_dev_proc(udev,map_cmyk_color,upd_cmyk_kcolor);
3187
0
       set_dev_proc(udev,map_color_rgb, upd_kcolor_rgb);
3188
0
     break;
3189
0
     case MAP_RGBOV: /* RGB -> KCMY with BG and UCR for CMYK-Output */
3190
0
       set_dev_proc(udev,encode_color, upd_rgb_ovcolor);
3191
0
       set_dev_proc(udev,decode_color, upd_ovcolor_rgb);
3192
0
       set_dev_proc(udev,map_rgb_color, upd_rgb_ovcolor);
3193
0
       set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3194
0
       set_dev_proc(udev,map_color_rgb, upd_ovcolor_rgb);
3195
0
     break;
3196
0
     case MAP_RGBNOV: /* RGB -> KCMY with BG and UCR for CMY+K-Output */
3197
0
       set_dev_proc(udev,encode_color, upd_rgb_novcolor);
3198
0
       set_dev_proc(udev,decode_color, upd_novcolor_rgb);
3199
0
       set_dev_proc(udev,map_rgb_color, upd_rgb_novcolor);
3200
0
       set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3201
0
       set_dev_proc(udev,map_color_rgb, upd_novcolor_rgb);
3202
0
     break;
3203
3204
0
     default:
3205
0
       set_dev_proc(udev,encode_color, gx_default_map_rgb_color);
3206
0
       set_dev_proc(udev,decode_color, gx_default_map_color_rgb);
3207
0
       set_dev_proc(udev,map_rgb_color, gx_default_map_rgb_color);
3208
0
       set_dev_proc(udev,map_cmyk_color,gx_default_map_cmyk_color);
3209
0
       set_dev_proc(udev,map_color_rgb, gx_default_map_color_rgb);
3210
0
     break;
3211
0
  }
3212
0
  return 0;
3213
3214
0
}
3215
3216
/* ------------------------------------------------------------------- */
3217
/* upd_close_map: remove color mapping                                 */
3218
/* ------------------------------------------------------------------- */
3219
3220
static int
3221
upd_close_map(upd_device *udev)
3222
0
{
3223
0
   const upd_p      upd   = udev->upd;
3224
0
   int imap;
3225
3226
0
   if(upd) {
3227
3228
0
      for(imap = 0; UPD_CMAP_MAX > imap; ++imap) {
3229
3230
0
         if(upd->cmap[imap].code)
3231
0
            gs_free(udev->memory, upd->cmap[imap].code,sizeof(upd->cmap[imap].code[0]),
3232
0
                upd->cmap[imap].bitmsk+1,"upd/code");
3233
0
         upd->cmap[imap].code   = NULL;
3234
3235
0
         upd->cmap[imap].bitmsk = 0;
3236
0
         upd->cmap[imap].bitshf = 0;
3237
0
         upd->cmap[imap].bits   = 0;
3238
0
         upd->cmap[imap].rise   = false;
3239
0
      }
3240
0
      upd->flags &= ~B_MAP;
3241
0
   }
3242
3243
0
   upd_procs_map(udev);
3244
3245
0
   return 0;
3246
0
}
3247
3248
/* ------------------------------------------------------------------- */
3249
/* Functions for the rendering of data                                 */
3250
/* ------------------------------------------------------------------- */
3251
3252
/**
3253
Inside the main-upd-type are a "valbuf" and some unidentified
3254
pointers. This stuff is used in conjunction with the rendering,
3255
which is the process of converting gx_color_indices into something
3256
suitable for the device.
3257
3258
*/
3259
3260
/* ------------------------------------------------------------------- */
3261
/* upd_open_render: Initialize rendering                               */
3262
/* ------------------------------------------------------------------- */
3263
3264
static void
3265
upd_open_render(upd_device *udev)
3266
0
{
3267
0
   const upd_p upd = udev->upd;
3268
0
   int  icomp;
3269
3270
/** Reset everything related to rendering */
3271
0
   upd->flags       &= ~B_RENDER;
3272
0
   upd->valbuf       = NULL;
3273
0
   upd->nvalbuf      = 0;
3274
0
   upd->render       = NULL;
3275
0
   upd->start_render = NULL;
3276
0
   for(icomp = 0; UPD_VALPTR_MAX > icomp; ++icomp) upd->valptr[icomp] = NULL;
3277
3278
0
   if( (B_BUF | B_MAP) ==
3279
0
      ((B_BUF | B_MAP | B_ERROR) & upd->flags)) {
3280
3281
/** Establish the renderingwidth in upd */
3282
0
      upd->rwidth = upd->gswidth;
3283
0
      if((0            < upd->ints[I_PWIDTH]) &&
3284
0
         (upd->gswidth > upd->ints[I_PWIDTH])   )
3285
0
          upd->rwidth  = upd->ints[I_PWIDTH];
3286
3287
/** Call the Render-specific Open-Function */
3288
0
      switch(upd->choice[C_RENDER]) {
3289
0
         case RND_FSCOMP:
3290
0
            upd_open_fscomp(udev);
3291
0
         break;
3292
0
         case RND_FSCMYK:
3293
0
            upd_open_fscmyk(udev);
3294
0
         break;
3295
0
         case RND_FSCMY_K:
3296
0
            upd_open_fscmy_k(udev);
3297
0
         break;
3298
0
         default:
3299
#if UPD_MESSAGES & UPD_M_WARNING
3300
            errprintf(udev->memory, "upd_open_render: Unknown rendering type %d\n",
3301
                upd->choice[C_RENDER]);
3302
#endif
3303
0
         break;
3304
0
      }
3305
0
   }
3306
3307
0
   if(B_RENDER != ((B_ERROR | B_RENDER) & upd->flags))
3308
0
      upd_close_render(udev);
3309
3310
0
   return;
3311
0
}
3312
3313
/* ------------------------------------------------------------------- */
3314
/* upd_close_render: Deinitialize rendering                            */
3315
/* ------------------------------------------------------------------- */
3316
3317
static void
3318
upd_close_render(upd_device *udev)
3319
0
{
3320
0
   const upd_p upd = udev->upd;
3321
3322
0
   if(upd) {
3323
0
      int icomp;
3324
3325
0
      if((upd->render == upd_fscomp) ||
3326
0
         (upd->render == upd_fscmyk)   )  upd_close_fscomp(udev);
3327
3328
0
      if((0 < upd->nvalbuf) && upd->valbuf)
3329
0
         gs_free(udev->memory, upd->valbuf,upd->nvalbuf,sizeof(upd->valbuf[0]),"upd/valbuf");
3330
0
      upd->valbuf  = NULL;
3331
0
      upd->nvalbuf = 0;
3332
3333
0
      upd->flags       &= ~B_RENDER;
3334
0
      upd->render       = NULL;
3335
0
      upd->start_render = NULL;
3336
0
      for(icomp = 0; UPD_VALPTR_MAX > icomp; ++icomp) upd->valptr[icomp] = NULL;
3337
3338
0
   }
3339
0
   return;
3340
0
}
3341
3342
/* ------------------------------------------------------------------- */
3343
/* upd_open_fscomp: Initialize Component-Floyd-Steinberg               */
3344
/* ------------------------------------------------------------------- */
3345
#if UPD_MESSAGES & UPD_M_FSBUF
3346
static int32_t fs_emin[UPD_VALPTR_MAX],fs_emax[UPD_VALPTR_MAX];
3347
#endif
3348
static void
3349
upd_open_fscomp(upd_device *udev)
3350
0
{
3351
0
   const upd_p upd = udev->upd;
3352
0
   int icomp,order[UPD_CMAP_MAX];
3353
3354
#if UPD_MESSAGES & UPD_M_FSBUF
3355
   for(icomp = 0; UPD_VALPTR_MAX < icomp; ++icomp)
3356
      fs_emin[icomp] = fs_emax[icomp] = 0;
3357
#endif
3358
3359
0
   icomp = upd->ncomp;
3360
3361
0
   if((0              >= icomp) ||
3362
0
      (UPD_VALPTR_MAX <  icomp) ||
3363
0
      (UPD_CMAP_MAX   <  icomp)   ) icomp      = 0;
3364
3365
/**
3366
This Version of the FS-algorithm works on the mapped components, but
3367
the printing-order might be different from the order dictated by the
3368
mapping-routines. The optional COMPORDER-Array is used for that. The
3369
initial test checks it's integrity.
3370
*/
3371
0
   if(icomp) {
3372
0
      if(upd->ncomp <= upd->int_a[IA_COMPORDER].size) { /* Reordering */
3373
0
         bool success = true;
3374
0
         for(icomp = 0; upd->ncomp > icomp; ++icomp) {
3375
0
            order[icomp] = upd->int_a[IA_COMPORDER].data[icomp];
3376
0
            if((0            >  order[icomp]) ||
3377
0
               (UPD_CMAP_MAX <= order[icomp])   ) {
3378
0
               success = false;
3379
#if UPD_MESSAGES & UPD_M_WARNING
3380
                  errprintf(udev->memory,
3381
                   "upd_open_fscomp: %d is illegal component-index\n",
3382
                   order[icomp]);
3383
#endif
3384
0
            }
3385
0
         }
3386
0
         if(!success) icomp = 0;
3387
0
      } else {                                          /* Default-Ordering */
3388
0
         for(icomp = 0; UPD_CMAP_MAX > icomp; ++icomp) order[icomp] = icomp;
3389
0
      }                                                 /* Ordering defined */
3390
0
   }
3391
3392
/**
3393
If anything was ok. up to now, memory get's allocated.
3394
*/
3395
0
   if(icomp) {
3396
3397
0
      for(icomp = 0; upd->ncomp > icomp; ++icomp) {
3398
0
         upd->valptr[icomp] = gs_malloc(udev->memory, 1,sizeof(updcomp_t),"upd/fscomp");
3399
0
         if(NULL == upd->valptr[icomp]) {
3400
0
#if UPD_MESSAGES & UPD_M_ERROR
3401
0
            errprintf(udev->memory,
3402
0
                      "upd_open_fscomp: could not allocate %d. updcomp\n",
3403
0
                      icomp);
3404
0
#endif
3405
0
            icomp = 0;
3406
0
            break;
3407
0
         }
3408
0
      }
3409
0
   }
3410
3411
0
   if(icomp) {
3412
0
      uint need;
3413
3414
0
      need  = (2 + upd->rwidth) * upd->ncomp;
3415
0
      upd->valbuf = gs_malloc(udev->memory, need,sizeof(upd->valbuf[0]),"upd/valbuf");
3416
3417
0
      if(upd->valbuf) {
3418
0
         upd->nvalbuf = need;
3419
0
         memset(upd->valbuf,0,need*sizeof(upd->valbuf[0]));
3420
0
      } else {
3421
0
#if UPD_MESSAGES & UPD_M_ERROR
3422
0
         errprintf(udev->memory,
3423
0
                   "upd_open_fscomp: could not allocate %u words for valbuf\n",
3424
0
                   need);
3425
0
#endif
3426
0
         icomp = 0;
3427
0
      }
3428
0
   }
3429
3430
/* Still happy? then compute component-values */
3431
3432
0
   if(icomp) {
3433
0
      for(icomp = 0; upd->ncomp > icomp; ++icomp) {
3434
3435
0
         const updcomp_p comp   = upd->valptr[icomp];
3436
0
         const int32_t     nsteps = upd->cmap[order[icomp]].bitmsk;
3437
0
         float ymin,ymax;
3438
0
         int32_t highmod,highval;
3439
0
         int i;
3440
3441
0
         comp->threshold = nsteps;
3442
0
         comp->spotsize  = nsteps;
3443
0
         comp->offset    = 0;
3444
0
         comp->scale     = 1;
3445
0
         comp->cmap      = order[icomp];
3446
0
         upd->cmap[comp->cmap].comp = icomp;
3447
0
         comp->bits      = upd->cmap[comp->cmap].bits;
3448
0
         comp->bitshf    = upd->cmap[comp->cmap].bitshf;
3449
0
         comp->bitmsk    = upd->cmap[comp->cmap].bitmsk;
3450
3451
0
         if(!nsteps) continue; /* A 0-Bit component is legal! */
3452
3453
0
         if(upd->cmap[comp->cmap].rise) {
3454
0
            ymin = upd->float_a[upd->cmap[comp->cmap].xfer].data[0];
3455
0
            ymax = upd->float_a[upd->cmap[comp->cmap].xfer].data[
3456
0
                      upd->float_a[upd->cmap[comp->cmap].xfer].size-1];
3457
0
         } else {
3458
0
            ymax = upd->float_a[upd->cmap[comp->cmap].xfer].data[0];
3459
0
            ymin = upd->float_a[upd->cmap[comp->cmap].xfer].data[
3460
0
                      upd->float_a[upd->cmap[comp->cmap].xfer].size-1];
3461
0
         }
3462
3463
0
         if(0.0 > ymin) {
3464
0
            ymin = 0.0;
3465
0
            if(0.0 > ymax) ymax = 1.0 / (float) (nsteps+1);
3466
0
         }
3467
0
         if(1.0 < ymax) ymax = 1.0;
3468
3469
0
         comp->spotsize = ((int32_t) 1 << 28) - 1;
3470
3471
0
         for(i = 0; i < 32; ++i) { /* Attempt Ideal */
3472
3473
0
            highval = (int32_t)((ymax-ymin) * (double) comp->spotsize + 0.5);
3474
3475
0
            if(!(highmod = highval % nsteps)) break; /* Gotcha */
3476
3477
0
            highval += nsteps - highmod;
3478
0
            comp->spotsize = (int32_t)((double) highval / (ymax-ymin) + 0.5);
3479
3480
0
            if(!(comp->spotsize % 2)) comp->spotsize++;
3481
3482
0
         }                         /* Attempt Ideal */
3483
3484
0
         comp->offset    = (int32_t)(ymin * (double) comp->spotsize + (double) 0.5);
3485
0
         comp->scale     = highval / nsteps;
3486
0
         comp->threshold = comp->spotsize / 2;
3487
3488
#if UPD_MESSAGES & UPD_M_SETUP
3489
         errprintf(udev->memory,
3490
             "Values for %d. Component after %d iterations\n",comp->cmap+1,i);
3491
         errprintf(udev->memory,
3492
             "steps:     %10ld, Bits: %d\n",(long) comp->bitmsk,comp->bits);
3493
         errprintf(udev->memory,
3494
             "xfer:      %10d Points, %s\n",
3495
             upd->float_a[upd->cmap[comp->cmap].xfer].size,
3496
             upd->cmap[comp->cmap].rise ? "rising" : "falling");
3497
         errprintf(udev->memory,
3498
             "offset:    %10d 0x%08x\n",comp->offset,comp->offset);
3499
         errprintf(udev->memory,
3500
             "scale:     %10d 0x%08x\n",comp->scale,comp->scale);
3501
         errprintf(udev->memory,
3502
             "threshold: %10d 0x%08x\n",comp->threshold,comp->threshold);
3503
         errprintf(udev->memory,
3504
             "spotsize:  %10d 0x%08x\n",comp->spotsize,comp->spotsize);
3505
#endif
3506
0
      }
3507
0
   }
3508
/**
3509
Optional Random Initialization of the value-Buffer
3510
*/
3511
0
   if(icomp && !(B_FSZERO & upd->flags)) {
3512
0
      for(icomp = 0; icomp < upd->ncomp; ++icomp) {
3513
0
         const updcomp_p comp = upd->valptr[icomp];
3514
0
         int i;
3515
0
         int32_t lv = INT32_MAX, hv = INT32_MIN, v;
3516
0
         float scale;
3517
0
         for(i = icomp; i < upd->nvalbuf; i += upd->ncomp) {
3518
0
            v = rand();
3519
0
            if(lv > v) lv = v;
3520
0
            if(hv < v) hv = v;
3521
0
            upd->valbuf[i] = v;
3522
0
         }
3523
0
         scale = (float) comp->threshold / (float) (hv - lv);
3524
0
         lv   += (int32_t)(comp->threshold / (2*scale));
3525
0
         for(i = icomp; i < upd->nvalbuf; i += upd->ncomp)
3526
0
            upd->valbuf[i] = (int32_t)(scale * (upd->valbuf[i] - lv));
3527
0
      }
3528
0
   }
3529
3530
/**
3531
The render-Routine acts as an indicator, which render-close is to use!
3532
*/
3533
0
   upd->render = upd_fscomp;
3534
3535
0
   if(icomp) upd->flags |=  B_RENDER;
3536
0
   else      upd->flags &= ~B_RENDER;
3537
3538
0
   return;
3539
0
}
3540
3541
/* ------------------------------------------------------------------- */
3542
/* upd_close_fscomp: Deinitialize Component-Floyd-Steinberg            */
3543
/* ------------------------------------------------------------------- */
3544
3545
static void
3546
upd_close_fscomp(upd_device *udev)
3547
0
{
3548
0
   const upd_p upd = udev->upd;
3549
0
   int icomp;
3550
3551
#if UPD_MESSAGES & UPD_M_FSBUF
3552
   if(upd && (upd->flags & B_RENDER)) {
3553
3554
      for(icomp = 0; icomp < upd->ncomp; ++icomp) {
3555
         updcomp_p comp = upd->valptr[icomp];
3556
         if(!comp) continue;
3557
         if(!comp->spotsize) continue;
3558
         errprintf(udev->memory,"%d. Component: %6.3f <= error <= %6.3f\n",
3559
             icomp+1,
3560
             (double) fs_emin[icomp] / (double) comp->spotsize,
3561
             (double) fs_emax[icomp] / (double) comp->spotsize);
3562
      }
3563
3564
   }
3565
#endif
3566
3567
0
   for(icomp = 0; UPD_VALPTR_MAX > icomp; ++icomp) {
3568
0
      if(!upd->valptr[icomp]) continue;
3569
0
      gs_free(udev->memory, upd->valptr[icomp],1,sizeof(updcomp_t),"upd/fscomp");
3570
0
      upd->valptr[icomp] = NULL;
3571
0
   }
3572
0
}
3573
3574
/* ------------------------------------------------------------------- */
3575
/* upd_fscomp: Apply Floyd-Steinberg to each component                 */
3576
/* ------------------------------------------------------------------- */
3577
3578
/**
3579
   With UPD_M_FSBUF Max/Min-Values for the Errors are computed
3580
*/
3581
#if   UPD_MESSAGES & UPD_M_FSBUF
3582
#define FS_M_ROWERR(I)                                        \
3583
           if(fs_emin[I] > rowerr[I]) fs_emin[I] = rowerr[I]; \
3584
           if(fs_emax[I] < rowerr[I]) fs_emax[I] = rowerr[I];
3585
#else
3586
0
#define FS_M_ROWERR(I) ;
3587
#endif
3588
/**
3589
   FS_GOAL computes the desired Pixel-Value
3590
*/
3591
#define FS_GOAL(Raw,I)                                                     \
3592
0
   pixel[I] = (int32_t)(Raw) * comp[I]->scale +    comp[I]->offset           \
3593
0
            + rowerr[I]  + colerr[I] -       ((colerr[I]+4)>>3);           \
3594
0
   if(         pixel[I] < 0)                    pixel[I] = 0;              \
3595
0
   else if(    pixel[I] >    comp[I]->spotsize) pixel[I] = comp[I]->spotsize;
3596
3597
/*
3598
 *    Distribute the error:   prev  now   next
3599
 *                                   X    7/16 Y
3600
 *                            3/16  5/16  1/16 Y+1
3601
 */
3602
#define FS_DIST(I)                                                    \
3603
0
   if(!first) { rowerr[I-dir] += ((3*pixel[I]+8)>>4);} /* 3/16 */        \
3604
0
              rowerr[I    ]  = ((5*pixel[I]  )>>4)  /* 5/16 */        \
3605
0
                             + (( colerr[I]+4)>>3); /* 1/16 (rest) */ \
3606
0
              colerr[I    ]  = pixel[I]             /* 8/16 (neu) */  \
3607
0
                             - ((5*pixel[I]  )>>4)                    \
3608
0
                             - ((3*pixel[I]+8)>>4);
3609
/**
3610
   S_FSTEP   adjusts the Indices (rowerr, bit and iword)
3611
*/
3612
#define S_FSTEP                                \
3613
0
   rowerr += dir;                              \
3614
0
   first   = false;                            \
3615
0
   if(0 > dir) { /* Reverse */                 \
3616
0
      if(!(bit <<= 1)) { bit = 0x01; ibyte--; }\
3617
0
   } else {      /* Forward */                 \
3618
0
      if(!(bit >>= 1)) { bit = 0x80; ibyte++; }\
3619
0
   }             /* Inc/Dec Bit */
3620
3621
static int
3622
upd_fscomp(upd_p upd)
3623
0
{
3624
0
   const updscan_p  scan    = upd->scnbuf[upd->yscnbuf & upd->scnmsk];
3625
0
   const updcomp_p *comp    = (updcomp_p *) upd->valptr;
3626
0
   int32_t *const     pixel  = upd->valbuf;
3627
0
   int32_t *const     colerr = pixel  + upd->ncomp;
3628
0
   int32_t           *rowerr = colerr + upd->ncomp;
3629
0
   int              pwidth = upd->rwidth;
3630
0
   int              dir,ibyte;
3631
0
   int              iblack,bblack,pxlset;
3632
0
   uint32_t       ci;
3633
0
   byte         bit;
3634
0
   bool         first = true;
3635
/*
3636
 * Erase the component-Data
3637
 */
3638
0
   switch(upd->ncomp) {
3639
0
     case 4:  memset(scan[3].bytes,0,upd->nbytes);
3640
         /* fall through */
3641
0
     case 3:  memset(scan[2].bytes,0,upd->nbytes);
3642
0
              memset(scan[1].bytes,0,upd->nbytes);
3643
         /* fall through */
3644
0
     default: memset(scan[0].bytes,0,upd->nbytes);
3645
0
   }
3646
/*
3647
 * determine the direction
3648
 */
3649
0
   if(upd->flags &   B_REVDIR) { /* This one reverse */
3650
3651
0
      if(upd->flags & B_YFLIP) {
3652
0
         dir     = upd->ncomp;
3653
0
         bit     = 0x80;
3654
0
         ibyte   = 0;
3655
0
      } else {
3656
0
         dir     =  -upd->ncomp;
3657
0
         rowerr +=   upd->ncomp * (pwidth-1);
3658
0
         bit     =   0x80 >>     ((pwidth-1) & 7);
3659
0
         ibyte   =                (pwidth-1) >> 3;
3660
0
      }
3661
3662
0
      if(!(upd->flags & B_FSWHITE)) {
3663
0
         upd_pxlfwd(upd);
3664
0
         while((0 < pwidth) && !upd_pxlget(upd)) pwidth--;
3665
0
      }
3666
3667
0
      upd_pxlrev(upd);
3668
3669
0
   } else {                       /* This one forward */
3670
3671
0
      if(upd->flags & B_YFLIP) {
3672
0
         dir     =  -upd->ncomp;
3673
0
         rowerr +=   upd->ncomp * (pwidth-1);
3674
0
         bit     =   0x80 >>     ((pwidth-1) & 7);
3675
0
         ibyte   =                (pwidth-1) >> 3;
3676
0
      } else {
3677
0
         dir     = upd->ncomp;
3678
0
         bit     = 0x80;
3679
0
         ibyte   = 0;
3680
0
      }
3681
3682
0
      if(!(upd->flags & B_FSWHITE)) {
3683
0
         upd_pxlrev(upd);
3684
0
         while((0 < pwidth) && !upd_pxlget(upd)) pwidth--;
3685
0
      }
3686
3687
0
      upd_pxlfwd(upd);
3688
3689
0
   }                              /* reverse or forward */
3690
/*
3691
 * Toggle Direction, if not fixed
3692
 */
3693
0
   if(!(upd->flags & B_FIXDIR)) upd->flags ^= B_REVDIR;
3694
/*
3695
 * Skip over leading white-space
3696
 */
3697
0
   if(!(upd->flags & B_FSWHITE)) {
3698
0
      upd_proc_pxlget((*fun)) = upd->pxlget;
3699
0
      byte             *ptr   = upd->pxlptr;
3700
0
      while((0 < pwidth) && !upd_pxlget(upd)) {
3701
0
         pwidth--;
3702
0
         fun = upd->pxlget;
3703
0
         ptr = upd->pxlptr;
3704
0
         S_FSTEP
3705
0
      }
3706
0
      upd->pxlget = fun;
3707
0
      upd->pxlptr = ptr;
3708
0
   }
3709
/*
3710
 * Set iblack, if black-reduction is active
3711
 */
3712
0
  iblack = -1;
3713
0
  bblack =  0;
3714
0
  if((4 == upd->ncomp) && (B_REDUCEK & upd->flags)) {
3715
0
    iblack = upd->cmap[0].comp;
3716
0
    bblack = 1<<iblack;
3717
0
  }
3718
/*
3719
 * Process all Pixels
3720
 */
3721
0
   first = true;
3722
0
   while(0 < pwidth--) {
3723
/*
3724
 *    Execute FS-Algorithm for each active component
3725
 */
3726
0
      pxlset = 0;
3727
0
      ci = upd_pxlget(upd);
3728
0
      switch(upd->ncomp) {
3729
0
         case 4:  FS_M_ROWERR(3)
3730
0
                  FS_GOAL(comp[3]->bitmsk & (ci >> comp[3]->bitshf),3)
3731
0
                  if(pixel[3] >  comp[3]->threshold) { /* "Fire" */
3732
0
                     pixel[3] -= comp[3]->spotsize;
3733
0
                      scan[3].bytes[ibyte] |= bit;
3734
0
                      pxlset  |= 8;
3735
0
                  }                                    /* "Fire" */
3736
0
                  FS_DIST(3)
3737
                /* fall through */
3738
3739
0
         case 3:  FS_M_ROWERR(2)
3740
0
                  FS_GOAL(comp[2]->bitmsk & (ci >> comp[2]->bitshf),2)
3741
0
                  if(pixel[2] >  comp[2]->threshold) { /* "Fire" */
3742
0
                     pixel[2] -= comp[2]->spotsize;
3743
0
                      scan[2].bytes[ibyte] |= bit;
3744
0
                      pxlset  |= 4;
3745
0
                  }                                    /* "Fire" */
3746
0
                  FS_DIST(2)
3747
3748
0
                  FS_M_ROWERR(1)
3749
0
                  FS_GOAL(comp[1]->bitmsk & (ci >> comp[1]->bitshf),1)
3750
0
                  if(pixel[1] >  comp[1]->threshold) { /* "Fire" */
3751
0
                     pixel[1] -= comp[1]->spotsize;
3752
0
                      scan[1].bytes[ibyte] |= bit;
3753
0
                      pxlset  |= 2;
3754
0
                  }                                    /* "Fire" */
3755
0
                  FS_DIST(1)
3756
                /* fall through */
3757
3758
0
         default: FS_M_ROWERR(0)
3759
0
                  FS_GOAL(comp[0]->bitmsk & (ci >> comp[0]->bitshf),0)
3760
0
                  if(pixel[0] >  comp[0]->threshold) { /* "Fire" */
3761
0
                     pixel[0] -= comp[0]->spotsize;
3762
0
                      scan[0].bytes[ibyte] |= bit;
3763
0
                      pxlset  |= 1;
3764
0
                  }                                    /* "Fire" */
3765
0
                  FS_DIST(0)
3766
0
      }
3767
/*
3768
 *    Black-Reduction
3769
 */
3770
0
      if(bblack) {
3771
0
        if(pxlset & bblack) pxlset |= 15;
3772
0
        switch(pxlset) {
3773
0
          case  0:
3774
0
          case  1:
3775
0
          case  2:
3776
0
          case  4:
3777
0
          case  8:
3778
0
          case  3:
3779
0
          case  5:
3780
0
          case  9:
3781
0
          case  6:
3782
0
          case 10:
3783
0
          case 12:
3784
0
            break;
3785
0
          default:
3786
0
            scan[0].bytes[ibyte]      &= ~bit;
3787
0
            scan[1].bytes[ibyte]      &= ~bit;
3788
0
            scan[2].bytes[ibyte]      &= ~bit;
3789
0
            scan[3].bytes[ibyte]      &= ~bit;
3790
0
            scan[iblack].bytes[ibyte] |=  bit;
3791
0
          break;
3792
0
        }
3793
0
      }
3794
/*
3795
 *    Adjust rowerr, bit & iword, depending on direction
3796
 */
3797
0
      S_FSTEP
3798
0
   }
3799
/*
3800
 * Finally call the limits-Routine
3801
 */
3802
0
   if(0 < upd->nlimits) upd_limits(upd,true);
3803
0
   return 0;
3804
0
}
3805
3806
/* ------------------------------------------------------------------- */
3807
/* upd_open_fscmyk: Initialize Component-Floyd-Steinberg               */
3808
/* ------------------------------------------------------------------- */
3809
3810
static void
3811
upd_open_fscmyk(upd_device *udev)
3812
0
{
3813
0
   const upd_p upd = udev->upd;
3814
3815
0
   upd_open_fscomp(udev);
3816
3817
0
   if((B_RENDER & upd->flags) &&
3818
0
      (4 == upd->ncomp) &&
3819
0
      (8 <= upd->cmap[0].bits) && (24 == upd->cmap[0].bitshf) &&
3820
0
      (8 <= upd->cmap[1].bits) && (16 == upd->cmap[1].bitshf) &&
3821
0
      (8 <= upd->cmap[2].bits) && ( 8 == upd->cmap[2].bitshf) &&
3822
0
      (8 <= upd->cmap[3].bits) && ( 0 == upd->cmap[3].bitshf)   ) {
3823
0
      upd->render = upd_fscmyk;
3824
0
   } else {
3825
0
      upd->flags &= ~B_RENDER;
3826
0
   }
3827
3828
0
}
3829
3830
/* ------------------------------------------------------------------- */
3831
/* upd_fscmyk: 32 Bit, K-CMY-Order Dithering                           */
3832
/* ------------------------------------------------------------------- */
3833
3834
static int
3835
upd_fscmyk(upd_p upd)
3836
0
{
3837
0
   const updscan_p  scan   = upd->scnbuf[upd->yscnbuf & upd->scnmsk];
3838
0
   int32_t *const     pixel  = upd->valbuf;
3839
0
   const updcomp_p *comp   = (updcomp_p *) upd->valptr;
3840
0
   int32_t *const     colerr = pixel  + 4;
3841
0
   int32_t           *rowerr = colerr + 4;
3842
0
   int32_t            pwidth = upd->rwidth;
3843
0
   int              dir,ibyte;
3844
0
   byte             bit,*data;
3845
0
   bool             first = false;
3846
/*
3847
 * Erase the component-Data
3848
 */
3849
0
   memset(scan[0].bytes,0,upd->nbytes);
3850
0
   memset(scan[1].bytes,0,upd->nbytes);
3851
0
   memset(scan[2].bytes,0,upd->nbytes);
3852
0
   memset(scan[3].bytes,0,upd->nbytes);
3853
3854
/*
3855
 * determine the direction
3856
 */
3857
0
   if(upd->flags &   B_REVDIR) { /* This one reverse */
3858
3859
0
      if(!(upd->flags & B_FSWHITE)) {
3860
0
         data = upd->gsscan;
3861
0
         while(0 < pwidth && !*(uint32_t *)data) pwidth--, data += 4;
3862
0
         if(0 >= pwidth) {
3863
0
            if(0 < upd->nlimits) upd_limits(upd,false);
3864
0
            return 0;
3865
0
         }
3866
0
      }
3867
3868
0
      data        = upd->gsscan + 4 * (upd->rwidth-1);
3869
3870
0
   } else {                          /* This one forward */
3871
3872
0
      if(!(upd->flags & B_FSWHITE)) {
3873
0
         data = upd->gsscan + 4 * (upd->rwidth-1);
3874
0
         while(0 < pwidth && !*(uint32_t *)data) pwidth--, data -= 4;
3875
0
         if(0 >= pwidth) {
3876
0
            if(0 < upd->nlimits) upd_limits(upd,false);
3877
0
            return 0;
3878
0
         }
3879
0
      }
3880
3881
0
      data        = upd->gsscan;
3882
3883
0
   }                              /* reverse or forward */
3884
/*
3885
 * Bits depend on FLIP & Direction
3886
 */
3887
0
   if(!(B_REVDIR & upd->flags) == !(B_YFLIP  & upd->flags)) {
3888
0
      dir         = 4;
3889
0
      bit         = 0x80;
3890
0
      ibyte       = 0;
3891
0
   } else {
3892
0
      dir         =  -4;
3893
0
      rowerr     +=   4 *             (upd->rwidth-1);
3894
0
      bit         =   0x80 >>        ((upd->rwidth-1) & 7);
3895
0
      ibyte       =                   (upd->rwidth-1) >> 3;
3896
0
   }
3897
3898
/*
3899
 * Toggle Direction, if not fixed
3900
 */
3901
0
   if(!(upd->flags & B_FIXDIR)) upd->flags ^= B_REVDIR;
3902
/*
3903
 * Skip over leading white-space
3904
 */
3905
0
   if(!(upd->flags & B_FSWHITE)) {
3906
0
      while(0 < pwidth && !*((uint32_t *)data)) {
3907
0
         pwidth--;
3908
0
         if(B_YFLIP  & upd->flags) data -= dir;
3909
0
         else                      data += dir;
3910
0
         S_FSTEP
3911
0
      }
3912
0
   }
3913
/*
3914
 * Process all Pixels
3915
 */
3916
0
   first = true;
3917
0
   while(0 < pwidth--) {
3918
/*
3919
 *    Compute the Black-Value first
3920
 */
3921
0
      FS_M_ROWERR(upd->cmap[0].comp) FS_GOAL(data[0],upd->cmap[0].comp);
3922
3923
/*
3924
 *    Decide wether this is a color value
3925
 */
3926
0
      if(data[1] || data[2] || data[3]) {
3927
3928
0
         FS_M_ROWERR(upd->cmap[1].comp) FS_GOAL(data[1],upd->cmap[1].comp)
3929
0
         FS_M_ROWERR(upd->cmap[2].comp) FS_GOAL(data[2],upd->cmap[2].comp)
3930
0
         FS_M_ROWERR(upd->cmap[3].comp) FS_GOAL(data[3],upd->cmap[3].comp)
3931
/*
3932
 *       if black fires, then all other components fire logically too
3933
 */
3934
0
         if(pixel[upd->cmap[0].comp] > comp[upd->cmap[0].comp]->threshold) {
3935
3936
0
            pixel[0] -= comp[0]->spotsize;
3937
0
            pixel[1] -= comp[1]->spotsize;
3938
0
            pixel[2] -= comp[2]->spotsize;
3939
0
            pixel[3] -= comp[3]->spotsize;
3940
0
            scan[upd->cmap[0].comp].bytes[ibyte] |= bit;
3941
3942
/*
3943
 *       if black is below threshold, only components with larger data-values
3944
 *       are allowed to fire
3945
 */
3946
0
         } else {                                 /* Restricted firing */
3947
3948
0
            if(( data[0] < data[1]) &&
3949
0
               (pixel[upd->cmap[1].comp] >
3950
0
                 comp[upd->cmap[1].comp]->threshold)) { /* "Fire" */
3951
0
                pixel[upd->cmap[1].comp] -= comp[upd->cmap[1].comp]->spotsize;
3952
0
                 scan[upd->cmap[1].comp].bytes[ibyte] |= bit;
3953
0
            }                                           /* "Fire" */
3954
3955
0
            if(( data[0] < data[2]) &&
3956
0
               (pixel[upd->cmap[2].comp] >
3957
0
                 comp[upd->cmap[2].comp]->threshold)) { /* "Fire" */
3958
0
                pixel[upd->cmap[2].comp] -= comp[upd->cmap[2].comp]->spotsize;
3959
0
                 scan[upd->cmap[2].comp].bytes[ibyte] |= bit;
3960
0
            }                                           /* "Fire" */
3961
3962
0
            if(( data[0] < data[3]) &&
3963
0
               (pixel[upd->cmap[3].comp] >
3964
0
                 comp[upd->cmap[3].comp]->threshold)) { /* "Fire" */
3965
0
                pixel[upd->cmap[3].comp] -= comp[upd->cmap[3].comp]->spotsize;
3966
0
                 scan[upd->cmap[3].comp].bytes[ibyte] |= bit;
3967
0
            }                                           /* "Fire" */
3968
3969
0
         }                                        /* Fire-Mode */
3970
3971
/*
3972
 * Handle Color-Errors
3973
 */
3974
0
         FS_DIST(upd->cmap[3].comp)
3975
0
         FS_DIST(upd->cmap[2].comp)
3976
0
         FS_DIST(upd->cmap[1].comp)
3977
3978
0
      } else if(pixel[upd->cmap[0].comp] > comp[upd->cmap[0].comp]->threshold) {
3979
0
                 scan[upd->cmap[0].comp].bytes[ibyte] |= bit;
3980
0
                pixel[upd->cmap[0].comp] -= comp[upd->cmap[0].comp]->spotsize;
3981
0
      }
3982
3983
0
      FS_DIST(upd->cmap[0].comp)
3984
/*
3985
 *    Adjust bit & iword, depending on direction
3986
 */
3987
0
      S_FSTEP
3988
0
      if(upd->flags & B_YFLIP) data -= dir;
3989
0
      else                     data += dir;
3990
0
   }
3991
/*
3992
 * Finally call the limits-Routine
3993
 */
3994
0
   if(0 < upd->nlimits) upd_limits(upd,true);
3995
0
   return 0;
3996
0
}
3997
3998
/* ------------------------------------------------------------------- */
3999
/* upd_open_fscmy_k: Initialize for CMY_K Printing                     */
4000
/* ------------------------------------------------------------------- */
4001
4002
static void
4003
upd_open_fscmy_k(upd_device *udev)
4004
0
{
4005
0
   const upd_p upd = udev->upd;
4006
4007
0
   upd_open_fscomp(udev);
4008
4009
0
   if((B_RENDER & upd->flags) &&
4010
0
      (4 == upd->ncomp)) {
4011
0
      upd->render = upd_fscmy_k;
4012
0
   } else {
4013
0
      upd->flags &= ~B_RENDER;
4014
0
   }
4015
4016
0
}
4017
4018
/* ------------------------------------------------------------------- */
4019
/* upd_fscmy_k: CMY_K rendering                                        */
4020
/* ------------------------------------------------------------------- */
4021
4022
static int
4023
upd_fscmy_k(upd_p upd)
4024
0
{
4025
0
   const updscan_p  scan    = upd->scnbuf[upd->yscnbuf & upd->scnmsk];
4026
0
   const updcomp_p *comp    = (updcomp_p *) upd->valptr;
4027
0
   int32_t *const     pixel  = upd->valbuf;
4028
0
   int32_t *const     colerr = pixel  + upd->ncomp;
4029
0
   int32_t           *rowerr = colerr + upd->ncomp;
4030
0
   int              pwidth = upd->rwidth;
4031
0
   int              dir,ibyte;
4032
0
   uint32_t       ci;
4033
0
   byte         bit;
4034
0
   bool         first = true;
4035
/*
4036
 * Erase the component-Data
4037
 */
4038
0
   memset(scan[3].bytes,0,upd->nbytes);
4039
0
   memset(scan[2].bytes,0,upd->nbytes);
4040
0
   memset(scan[1].bytes,0,upd->nbytes);
4041
0
   memset(scan[0].bytes,0,upd->nbytes);
4042
/*
4043
 * determine the direction
4044
 */
4045
0
   if(upd->flags &   B_REVDIR) { /* This one reverse */
4046
4047
0
      if(upd->flags & B_YFLIP) {
4048
0
         dir     = 4;
4049
0
         bit     = 0x80;
4050
0
         ibyte   = 0;
4051
0
      } else {
4052
0
         dir     =  -4;
4053
0
         rowerr +=   4 * (pwidth-1);
4054
0
         bit     =   0x80 >>     ((pwidth-1) & 7);
4055
0
         ibyte   =                (pwidth-1) >> 3;
4056
0
      }
4057
4058
0
      if(!(upd->flags & B_FSWHITE)) {
4059
0
         upd_pxlfwd(upd);
4060
0
         while((0 < pwidth) && !upd_pxlget(upd)) pwidth--;
4061
0
      }
4062
4063
0
      upd_pxlrev(upd);
4064
4065
0
   } else {                       /* This one forward */
4066
4067
0
      if(upd->flags & B_YFLIP) {
4068
0
         dir     =  -4;
4069
0
         rowerr +=   4          * (pwidth-1);
4070
0
         bit     =   0x80 >>     ((pwidth-1) & 7);
4071
0
         ibyte   =                (pwidth-1) >> 3;
4072
0
      } else {
4073
0
         dir     = 4;
4074
0
         bit     = 0x80;
4075
0
         ibyte   = 0;
4076
0
      }
4077
4078
0
      if(!(upd->flags & B_FSWHITE)) {
4079
0
         upd_pxlrev(upd);
4080
0
         while((0 < pwidth) && !upd_pxlget(upd)) pwidth--;
4081
0
      }
4082
4083
0
      upd_pxlfwd(upd);
4084
4085
0
   }                              /* reverse or forward */
4086
/*
4087
 * Toggle Direction, if not fixed
4088
 */
4089
0
   if(!(upd->flags & B_FIXDIR)) upd->flags ^= B_REVDIR;
4090
/*
4091
 * Skip over leading white-space
4092
 */
4093
0
   if(!(upd->flags & B_FSWHITE)) {
4094
0
      upd_proc_pxlget((*fun)) = upd->pxlget;
4095
0
      byte             *ptr   = upd->pxlptr;
4096
0
      while((0 < pwidth) && !upd_pxlget(upd)) {
4097
0
         pwidth--;
4098
0
         fun = upd->pxlget;
4099
0
         ptr = upd->pxlptr;
4100
0
         S_FSTEP
4101
0
      }
4102
0
      upd->pxlget = fun;
4103
0
      upd->pxlptr = ptr;
4104
0
   }
4105
/*
4106
 * Process all Pixels
4107
 */
4108
0
   first = true;
4109
0
   while(0 < pwidth--) {
4110
4111
/*    get the Pixel-Value */
4112
4113
0
      ci = upd_pxlget(upd);
4114
4115
/*    process all components */
4116
4117
0
      FS_M_ROWERR(0) FS_GOAL(comp[0]->bitmsk & (ci >> comp[0]->bitshf),0)
4118
0
      FS_M_ROWERR(1) FS_GOAL(comp[1]->bitmsk & (ci >> comp[1]->bitshf),1)
4119
0
      FS_M_ROWERR(2) FS_GOAL(comp[2]->bitmsk & (ci >> comp[2]->bitshf),2)
4120
0
      FS_M_ROWERR(3) FS_GOAL(comp[3]->bitmsk & (ci >> comp[3]->bitshf),3)
4121
4122
0
      if(pixel[0] >  comp[0]->threshold) { /* Black fires */
4123
4124
0
        pixel[0]             -= comp[0]->spotsize;
4125
0
        scan[0].bytes[ibyte] |= bit;
4126
4127
0
      } else {                             /* Colors may fire */
4128
4129
0
         if((pixel[1] <= comp[1]->threshold) ||
4130
0
            (pixel[2] <= comp[2]->threshold) ||
4131
0
            (pixel[3] <= comp[3]->threshold)   ) { /* Really a Color */
4132
4133
0
            if(pixel[1] >               comp[1]->threshold) {
4134
0
               pixel[1]              -= comp[1]->spotsize;
4135
0
                scan[1].bytes[ibyte] |= bit;
4136
0
            }
4137
4138
0
            if(pixel[2] >               comp[2]->threshold) {
4139
0
               pixel[2]              -= comp[2]->spotsize;
4140
0
                scan[2].bytes[ibyte] |= bit;
4141
0
            }
4142
4143
0
            if(pixel[3] >               comp[3]->threshold) {
4144
0
               pixel[3]              -= comp[3]->spotsize;
4145
0
                scan[3].bytes[ibyte] |= bit;
4146
0
            }
4147
4148
0
         } else {
4149
0
            pixel[1]              -= comp[1]->spotsize;
4150
0
            pixel[2]              -= comp[2]->spotsize;
4151
0
            pixel[3]              -= comp[3]->spotsize;
4152
0
            scan[0].bytes[ibyte] |= bit;
4153
0
         }
4154
0
      }
4155
4156
0
      FS_DIST(0)
4157
0
      FS_DIST(1)
4158
0
      FS_DIST(2)
4159
0
      FS_DIST(3)
4160
4161
/*
4162
 *    Adjust rowerr, bit & iword, depending on direction
4163
 */
4164
0
      S_FSTEP
4165
0
   }
4166
/*
4167
 * Finally call the limits-Routine
4168
 */
4169
0
   if(0 < upd->nlimits) upd_limits(upd,true);
4170
0
   return 0;
4171
0
}
4172
4173
/* ------------------------------------------------------------------- */
4174
/* upd_open_writer: Initialize rendering                               */
4175
/* ------------------------------------------------------------------- */
4176
4177
static int
4178
upd_open_writer(upd_device *udev)
4179
0
{
4180
0
   const upd_p upd                 = udev->upd;
4181
0
   bool        success             = true;
4182
4183
/** Reset the crucial values */
4184
0
   upd->start_writer = NULL;
4185
0
   upd->writer       = NULL;
4186
0
   upd->scnbuf       = NULL;
4187
0
   upd->nscnbuf      = 0;
4188
0
   upd->nbytes       = 0;
4189
0
   upd->nlimits      = 0;
4190
0
   upd->outbuf       = NULL;
4191
0
   upd->noutbuf      = 0;
4192
4193
/** Rendering should be succesfully initialized */
4194
0
   if(B_RENDER != ((B_RENDER | B_ERROR) & upd->flags))
4195
0
      success = false;
4196
4197
/** Create number of components */
4198
0
   upd->ocomp = upd->ncomp;
4199
0
   if(0 < upd->ints[I_OCOMP]) upd->ocomp = upd->ints[I_OCOMP];
4200
4201
/** Massage some Parameters */
4202
0
   if(success) {
4203
4204
/*    Make sure, that Pass & Pin-Numbers are at least 1 */
4205
0
      if(1 >  upd->ints[I_NYPASS]) upd->ints[I_NYPASS] = 1;
4206
0
      if(1 >  upd->ints[I_NXPASS]) upd->ints[I_NXPASS] = 1;
4207
0
      if(1 >  upd->ints[I_PINS2WRITE]) upd->ints[I_PINS2WRITE] = 1;
4208
4209
0
      if((upd->ints[I_NXPASS] * upd->ints[I_NYPASS]) > upd->ints[I_NPASS])
4210
0
         upd->ints[I_NPASS] = upd->ints[I_NXPASS] * upd->ints[I_NYPASS];
4211
4212
/*    Create Default noWeave-Feeds */
4213
4214
0
      if(upd->ints[I_NPASS] > upd->int_a[IA_STD_DY].size) {
4215
0
         int ix,iy,*ip;
4216
0
         UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_STD_DY]);
4217
0
         UPD_MM_GET_ARRAY(udev->memory, ip,upd->ints[I_NPASS]);
4218
0
         upd->int_a[IA_STD_DY].data = ip;
4219
0
         upd->int_a[IA_STD_DY].size = upd->ints[I_NPASS];
4220
4221
0
         for(iy = 1; iy < upd->ints[I_NYPASS]; ++iy) {
4222
0
            for(ix = 1; ix < upd->ints[I_NXPASS]; ++ix) *ip++ = 0;
4223
0
            *ip++ = 1;
4224
0
         }
4225
0
         for(ix = 1; ix < upd->ints[I_NXPASS]; ++ix) *ip++ = 0;
4226
0
         *ip = upd->ints[I_NYPASS] * upd->ints[I_PINS2WRITE]
4227
0
             - upd->ints[I_NYPASS] + 1;
4228
4229
0
         upd->ints[I_BEG_Y] = 0;
4230
0
         upd->ints[I_END_Y] = upd->ints[I_PHEIGHT] ?
4231
0
                              upd->ints[I_PHEIGHT] : upd->gsheight;
4232
0
      }
4233
4234
/*    Adjust BEG_Y */
4235
0
      if(0 >= upd->ints[I_BEG_Y]) {
4236
0
         if(0 <  upd->int_a[IA_BEG_DY].size) {
4237
0
            int i,sum = 0;
4238
0
            for(i = 0; i < upd->int_a[IA_BEG_DY].size; ++i)
4239
0
               sum +=  upd->int_a[IA_BEG_DY].data[i];
4240
0
            upd->ints[I_BEG_Y] = sum;
4241
0
         } else {
4242
0
            upd->ints[I_BEG_Y] = 0;
4243
0
         }
4244
0
      }
4245
4246
/*    Adjust END_Y */
4247
/*    Arrgh, I knew, why I refused to provide defaults for crucial */
4248
/*    parameters in uniprint. But o.k. it's nice for size-changing */
4249
/*    PostScript-Code. Nevertheless, it's still not perfect.       */
4250
4251
0
      if(0 >= upd->int_a[IA_ENDTOP].size ||
4252
0
         0 >= upd->int_a[IA_END_DY].size   ) upd->ints[I_END_Y] =
4253
0
         upd->ints[I_PHEIGHT] ? upd->ints[I_PHEIGHT] : upd->gsheight;
4254
4255
0
      if(0 >= upd->ints[I_END_Y]) upd->ints[I_END_Y] = upd->ints[I_PHEIGHT] ?
4256
0
        upd->ints[I_PHEIGHT] : upd->gsheight;
4257
4258
/*    Create Default X-Passes */
4259
4260
0
      if(0 >= upd->int_a[IA_STD_IX].size) {
4261
0
         int ix,i,*ip;
4262
0
         UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_STD_IX]);
4263
0
         UPD_MM_GET_ARRAY(udev->memory, ip,upd->int_a[IA_STD_DY].size);
4264
0
         upd->int_a[IA_STD_IX].data = ip;
4265
0
         upd->int_a[IA_STD_IX].size = upd->int_a[IA_STD_DY].size;
4266
4267
0
         for(i = 0, ix = 0; i < upd->int_a[IA_STD_IX].size; ++i) {
4268
0
            *ip++ = ix++;
4269
0
            if(ix == upd->ints[I_NXPASS]) ix = 0;
4270
0
         }
4271
0
      }
4272
4273
0
      if((0 >= upd->int_a[IA_BEG_IX].size) &&
4274
0
         (0 <  upd->int_a[IA_BEG_DY].size)   ) {
4275
0
         int ix,i,*ip;
4276
0
         UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_BEG_IX]);
4277
0
         UPD_MM_GET_ARRAY(udev->memory, ip,upd->int_a[IA_BEG_DY].size);
4278
0
         upd->int_a[IA_BEG_IX].data = ip;
4279
0
         upd->int_a[IA_BEG_IX].size = upd->int_a[IA_BEG_DY].size;
4280
4281
0
         for(i = 0, ix = 0; i < upd->int_a[IA_BEG_IX].size; ++i) {
4282
0
            *ip++ = ix++;
4283
0
            if(ix == upd->ints[I_NXPASS]) ix = 0;
4284
0
         }
4285
0
      }
4286
4287
0
      if((0 >= upd->int_a[IA_END_IX].size) &&
4288
0
         (0 <  upd->int_a[IA_END_DY].size)   ) {
4289
0
         int ix,i,*ip;
4290
0
         UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_END_IX]);
4291
0
         UPD_MM_GET_ARRAY(udev->memory, ip,upd->int_a[IA_END_DY].size);
4292
0
         upd->int_a[IA_END_IX].data = ip;
4293
0
         upd->int_a[IA_END_IX].size = upd->int_a[IA_END_DY].size;
4294
4295
0
         for(i = 0, ix = 0; i < upd->int_a[IA_END_IX].size; ++i) {
4296
0
            *ip++ = ix++;
4297
0
            if(ix == upd->ints[I_NXPASS]) ix = 0;
4298
0
         }
4299
0
      }
4300
0
   }
4301
4302
0
   if(upd->ints[I_NPASS] > upd->int_a[IA_STD_DY].size) {
4303
#if UPD_MESSAGES & UPD_M_WARNING
4304
      errprintf(udev->memory,
4305
        "upd_open_writer: Only %d instead of %d normal Feeds\n",
4306
        (int) upd->int_a[IA_STD_DY].size,upd->ints[I_NPASS]);
4307
#endif
4308
0
      success = false;
4309
4310
0
   } else if(upd->int_a[IA_STD_IX].size < upd->int_a[IA_STD_DY].size) {
4311
#if UPD_MESSAGES & UPD_M_WARNING
4312
      errprintf(udev->memory,
4313
        "upd_open_writer: Only %d instead of %d normal Xstarts\n",
4314
        (int) upd->int_a[IA_STD_IX].size,
4315
        (int) upd->int_a[IA_STD_DY].size);
4316
#endif
4317
0
      success = false;
4318
0
   }
4319
4320
/** The sum of Values in STD_DY should equal NYPASS * PINS2WRITE (diagnostic) */
4321
4322
#if UPD_MESSAGES & UPD_M_WARNING
4323
   if(success) {
4324
      int i,sum = 0;
4325
      for(i = 0; upd->ints[I_NPASS] > i; ++i)
4326
         sum += upd->int_a[IA_STD_DY].data[i];
4327
      if((upd->ints[I_NYPASS]*upd->ints[I_PINS2WRITE]) != sum)
4328
         errprintf(udev->memory,
4329
         "upd_open_writer: Sum of normal Feeds is %d rather than %d\n",
4330
         sum,upd->ints[I_NYPASS]*upd->ints[I_PINS2WRITE]);
4331
   }
4332
#endif
4333
4334
0
   if(upd->int_a[IA_BEG_IX].size < upd->int_a[IA_BEG_DY].size) {
4335
#if UPD_MESSAGES & UPD_M_WARNING
4336
      errprintf(udev->memory,
4337
        "upd_open_writer: Only %d instead of %d initial Xstarts\n",
4338
        (int) upd->int_a[IA_BEG_IX].size,
4339
        (int) upd->int_a[IA_BEG_DY].size);
4340
#endif
4341
0
      success = false;
4342
0
   }
4343
4344
0
   if(upd->int_a[IA_BEGBOT].size < upd->int_a[IA_BEG_DY].size) {
4345
#if UPD_MESSAGES & UPD_M_WARNING
4346
      errprintf(udev->memory,
4347
        "upd_open_writer: Only %d instead of %d initial Pins\n",
4348
        (int) upd->int_a[IA_BEGBOT].size,
4349
        (int) upd->int_a[IA_BEG_DY].size);
4350
#endif
4351
0
      success = false;
4352
4353
0
   } else {
4354
4355
0
      int i;
4356
0
      for(i = 0; i < upd->int_a[IA_BEG_DY].size; ++i)
4357
0
         if((upd->int_a[IA_BEGBOT].data[i] > upd->ints[I_PINS2WRITE]) ||
4358
0
            (upd->int_a[IA_BEGBOT].data[i] < 0                      )   ) break;
4359
4360
0
      if(i < upd->int_a[IA_BEG_DY].size) {
4361
#if UPD_MESSAGES & UPD_M_WARNING
4362
         errprintf(udev->memory,
4363
           "upd_open_writer: Only %d is invalid initial Pins\n",
4364
           upd->int_a[IA_BEGBOT].data[i]);
4365
#endif
4366
0
         success = false;
4367
0
      }
4368
0
   }
4369
4370
/** The sum of Values in BEG_DY should equal BEG_Y */
4371
4372
#if UPD_MESSAGES & UPD_M_WARNING
4373
   if(success) {
4374
      int i,sum = 0;
4375
      for(i = 0;  upd->int_a[IA_BEG_DY].size > i; ++i)
4376
         sum += upd->int_a[IA_BEG_DY].data[i];
4377
      if(upd->ints[I_BEG_Y] != sum)
4378
         errprintf(udev->memory,
4379
         "upd_open_writer: Sum of initial Feeds is %d rather than %d\n",
4380
         sum,upd->ints[I_BEG_Y]);
4381
   }
4382
#endif
4383
4384
0
   if(upd->int_a[IA_END_IX].size < upd->int_a[IA_END_DY].size) {
4385
#if UPD_MESSAGES & UPD_M_WARNING
4386
      errprintf(udev->memory,
4387
        "upd_open_writer: Only %d instead of %d final Xstarts\n",
4388
        (int) upd->int_a[IA_END_IX].size,
4389
        (int) upd->int_a[IA_END_DY].size);
4390
#endif
4391
0
      success = false;
4392
0
   }
4393
4394
0
   if(upd->int_a[IA_ENDTOP].size < upd->int_a[IA_END_DY].size) {
4395
#if UPD_MESSAGES & UPD_M_WARNING
4396
      errprintf(udev->memory,
4397
        "upd_open_writer: Only %d instead of %d Final Pins\n",
4398
        (int) upd->int_a[IA_ENDTOP].size,
4399
        (int) upd->int_a[IA_END_DY].size);
4400
#endif
4401
0
      success = false;
4402
4403
0
   } else {
4404
4405
0
      int i;
4406
0
      for(i = 0; i < upd->int_a[IA_END_DY].size; ++i)
4407
0
         if((upd->int_a[IA_ENDTOP].data[i] > upd->ints[I_PINS2WRITE]) ||
4408
0
            (upd->int_a[IA_ENDTOP].data[i] < 0                      )   ) break;
4409
4410
0
      if(i < upd->int_a[IA_END_DY].size) {
4411
#if UPD_MESSAGES & UPD_M_WARNING
4412
         errprintf(udev->memory,
4413
           "upd_open_writer: Only %d is invalid initial Pins\n",
4414
           upd->int_a[IA_ENDTOP].data[i]);
4415
#endif
4416
0
         success = false;
4417
0
      }
4418
0
   }
4419
4420
/** SA_SETCOMP must be valid, if present */
4421
0
   if((0 < upd->string_a[SA_SETCOMP].size) &&
4422
0
      (upd->ocomp > upd->string_a[SA_SETCOMP].size)) {
4423
#if UPD_MESSAGES & UPD_M_WARNING
4424
      errprintf(udev->memory,
4425
         "upd_open_writer: Only %d SETCOMP-Commands (%d required)\n",
4426
         (int) upd->string_a[SA_SETCOMP].size,upd->ocomp);
4427
#endif
4428
0
      success = false;
4429
0
   }
4430
4431
/** Determine required number of scan-Buffers */
4432
4433
0
   if(success) { /* Compute nscnbuf */
4434
0
      int32_t want,use;
4435
4436
0
      want  = upd->ints[I_NYPASS];
4437
0
      want *= upd->ints[I_PINS2WRITE];
4438
4439
0
      if(upd->ints[I_NSCNBUF] > want) want = upd->ints[I_NSCNBUF];
4440
4441
0
      if(1 > want)                         want = 1;
4442
4443
0
      for(use = 1; 0 < use; use <<= 1) if(use > want) break;
4444
4445
0
      upd->nscnbuf = upd->ints[I_NSCNBUF] = use;
4446
4447
0
   }                /* Compute nscnbuf */
4448
4449
/** Determine number of words in scan-buffers */
4450
4451
0
   if(success) { /* Compute pwidth, scnmsk, nbytes, pheight */
4452
4453
0
      if(0 < upd->ints[I_PWIDTH]) upd->pwidth = upd->ints[I_PWIDTH];
4454
0
      else                        upd->pwidth = upd->gswidth;
4455
4456
0
      upd->nbytes  = (upd->pwidth+CHAR_BIT*sizeof(upd->scnbuf[0]->bytes[0]) - 1)
4457
0
            /                   (CHAR_BIT*sizeof(upd->scnbuf[0]->bytes[0]));
4458
4459
0
      upd->scnmsk  = upd->nscnbuf - 1;
4460
4461
0
      if(0 < upd->ints[I_PHEIGHT]) upd->pheight = upd->ints[I_PHEIGHT];
4462
0
      else                         upd->pheight = upd->gsheight;
4463
4464
0
   }             /* Compute pwidth, scnmsk, nbytes */
4465
4466
/** Call the writer-specific open-function */
4467
4468
0
   if(success) { /* Determine sizes */
4469
0
      switch(upd->choice[C_FORMAT]) {
4470
0
         case FMT_RAS:
4471
0
            if(0 > upd_open_rascomp(udev)) success = false;
4472
0
         break;
4473
0
         case FMT_EPSON:
4474
0
            if(0 > upd_open_wrtescp(udev)) success = false;
4475
0
         break;
4476
0
         case FMT_ESCP2Y:
4477
0
         case FMT_ESCP2XY:
4478
0
         case FMT_ESCNMY: /* (GR) */
4479
0
            if(0 > upd_open_wrtescp2(udev)) success = false;
4480
0
         break;
4481
0
         case FMT_RTL:
4482
0
            if(0 > upd_open_wrtrtl(udev))   success = false;
4483
0
         break;
4484
0
         case FMT_CANON: /* (hr) */
4485
0
            if(0 > upd_open_wrtcanon(udev)) success = false;
4486
0
         break;
4487
0
         default:
4488
0
            success = false;
4489
#if UPD_MESSAGES & UPD_M_WARNING
4490
            errprintf(udev->memory,"upd_open_writer: Unknown writer-type %d\n",
4491
                upd->choice[C_FORMAT]);
4492
#endif
4493
0
         break;
4494
0
      }
4495
0
   }             /* Determine sizes*/
4496
4497
/** Allocate the Outputbuffer */
4498
0
   if(success && (0 < upd->noutbuf)) { /* Allocate outbuf */
4499
0
      upd->outbuf = gs_malloc(udev->memory, upd->noutbuf,sizeof(upd->outbuf[0]),"upd/outbuf");
4500
0
      if(!upd->outbuf) success = false;
4501
0
   }                                   /* Allocate outbuf */
4502
4503
/** Allocate the desired scan-buffer-pointers */
4504
0
   if(success) {
4505
0
      upd->scnbuf = gs_malloc(udev->memory, upd->nscnbuf,sizeof(upd->scnbuf[0]),"upd/scnbuf");
4506
0
      if(NULL == upd->scnbuf) {
4507
0
         success = false;
4508
0
      } else {
4509
0
         int ibuf;
4510
0
         for(ibuf = 0; ibuf < upd->nscnbuf; ++ibuf) {
4511
0
            if(success) upd->scnbuf[ibuf] =
4512
0
               gs_malloc(udev->memory, upd->ocomp,sizeof(upd->scnbuf[0][0]),"upd/scnbuf[]");
4513
0
            else upd->scnbuf[ibuf] = NULL;
4514
4515
0
            if(!upd->scnbuf[ibuf]) {
4516
0
               success = false;
4517
0
            } else {
4518
0
               int icomp;
4519
0
               for(icomp = 0; icomp < upd->ocomp; ++icomp) {
4520
0
                  if(success) upd->scnbuf[ibuf][icomp].bytes =
4521
0
                    gs_malloc(udev->memory, upd->nbytes,sizeof(upd->scnbuf[0][0].bytes[0]),
4522
0
                    "upd/bytes");
4523
0
                  else        upd->scnbuf[ibuf][icomp].bytes = NULL;
4524
0
                  if(!upd->scnbuf[ibuf][icomp].bytes) success = false;
4525
4526
0
                  if(0 < upd->nlimits) {
4527
4528
0
                     upd->scnbuf[ibuf][icomp].xbegin = gs_malloc(udev->memory, upd->nlimits,
4529
0
                        sizeof(upd->scnbuf[0][0].xbegin[0]),"upd/xbegin");
4530
0
                     if(!upd->scnbuf[ibuf][icomp].xbegin) success = false;
4531
4532
0
                     upd->scnbuf[ibuf][icomp].xend   = gs_malloc(udev->memory, upd->nlimits,
4533
0
                        sizeof(upd->scnbuf[0][0].xend[0]),"upd/xend");
4534
0
                     if(!upd->scnbuf[ibuf][icomp].xbegin) success = false;
4535
4536
0
                  } else {
4537
4538
0
                     upd->scnbuf[ibuf][icomp].xbegin = NULL;
4539
0
                     upd->scnbuf[ibuf][icomp].xend   = NULL;
4540
4541
0
                  }
4542
0
               }
4543
0
            }
4544
0
         }
4545
0
      }
4546
0
   }
4547
4548
0
   if(success) upd->flags |= B_FORMAT;
4549
0
   else        upd_close_writer(udev);
4550
4551
0
   return success ? 1 : -1;
4552
0
}
4553
4554
/* ------------------------------------------------------------------- */
4555
/* upd_close_writer: Deinitialize rendering                            */
4556
/* ------------------------------------------------------------------- */
4557
4558
static void
4559
upd_close_writer(upd_device *udev)
4560
0
{
4561
0
   const upd_p upd = udev->upd;
4562
4563
0
   if(upd) {
4564
0
      int ibuf,icomp;
4565
4566
0
      if((0 < upd->noutbuf) && upd->outbuf)
4567
0
         gs_free(udev->memory, upd->outbuf,upd->noutbuf,sizeof(upd->outbuf[0]),"upd/outbuf");
4568
0
      upd->noutbuf = 0;
4569
0
      upd->outbuf  = NULL;
4570
4571
0
      if((0 < upd->nscnbuf) && upd->scnbuf) {
4572
0
         for(ibuf = 0; upd->nscnbuf > ibuf; ++ibuf) {
4573
4574
0
            if(!upd->scnbuf[ibuf]) continue;
4575
4576
0
            for(icomp = 0; icomp < upd->ocomp; ++icomp) {
4577
4578
0
               if((0 < upd->nbytes) && upd->scnbuf[ibuf][icomp].bytes)
4579
0
                  gs_free(udev->memory, upd->scnbuf[ibuf][icomp].bytes,upd->nbytes,
4580
0
                     sizeof(upd->scnbuf[ibuf][icomp].words[0]),"upd/bytes");
4581
0
               upd->scnbuf[ibuf][icomp].bytes = NULL;
4582
4583
0
               if((0 < upd->nlimits) && upd->scnbuf[ibuf][icomp].xbegin)
4584
0
                  gs_free(udev->memory, upd->scnbuf[ibuf][icomp].xbegin,upd->nlimits,
4585
0
                     sizeof(upd->scnbuf[ibuf][icomp].xbegin[0]),"upd/xbegin");
4586
0
               upd->scnbuf[ibuf][icomp].xbegin = NULL;
4587
4588
0
               if((0 < upd->nlimits) && upd->scnbuf[ibuf][icomp].xend)
4589
0
                  gs_free(udev->memory, upd->scnbuf[ibuf][icomp].xend,upd->nlimits,
4590
0
                     sizeof(upd->scnbuf[ibuf][icomp].xend[0]),"upd/xend");
4591
0
               upd->scnbuf[ibuf][icomp].xend = NULL;
4592
0
            }
4593
4594
0
            if(icomp)
4595
0
               gs_free(udev->memory, upd->scnbuf[ibuf],upd->ocomp,sizeof(upd->scnbuf[0][0]),
4596
0
                  "upd/scnbuf[]");
4597
0
            upd->scnbuf[ibuf] = NULL;
4598
4599
0
         }
4600
0
         gs_free(udev->memory, upd->scnbuf,upd->nscnbuf,sizeof(upd->scnbuf[0]),"upd/scnbuf");
4601
0
      }
4602
4603
0
      upd->flags &= ~B_FORMAT;
4604
0
   }
4605
0
}
4606
4607
/* ------------------------------------------------------------------- */
4608
/* upd_limits: Establish passwise limits, after rendering              */
4609
/* ------------------------------------------------------------------- */
4610
4611
static void
4612
upd_limits(upd_p upd, bool check)
4613
0
{
4614
0
   updscan_p  scans = upd->scnbuf[upd->yscnbuf & upd->scnmsk], scan;
4615
0
   int   xs,x,xe,icomp,pass;
4616
0
   byte *bytes,bit;
4617
4618
0
   for(icomp = 0; icomp < upd->ocomp; ++icomp) {
4619
0
      scan = scans + icomp;
4620
0
      for(pass = 0; pass < upd->nlimits; ++pass) {
4621
0
         scan->xbegin[pass] = upd->pwidth;
4622
0
         scan->xend[  pass] = -1;
4623
0
      }
4624
0
   }
4625
4626
0
   if(check) { /* Really check */
4627
0
      for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Check Components */
4628
0
         scan  = scans + icomp;
4629
0
         bytes = scan->bytes;
4630
4631
0
         for(xs = 0; xs < upd->nbytes  && !bytes[xs];   ++xs);
4632
4633
0
         if(xs < upd->nbytes) { /* Has Data */
4634
0
            for(xe = upd->nbytes; xs < xe && !bytes[xe-1]; --xe);
4635
4636
0
            for(pass = 0; pass < upd->nlimits; ++pass) { /* limit (pass) loop */
4637
4638
0
               x = ((xs<<3)/upd->nlimits)*upd->nlimits + pass;
4639
0
               while((x >> 3) < xs) x += upd->nlimits;
4640
4641
0
               bit = 0x80 >> (x & 7);
4642
0
               while(x < scan->xbegin[pass]) {
4643
0
                  if(bytes[x>>3] & bit) scan->xbegin[pass] = x;
4644
0
                  x  += upd->nlimits;
4645
0
                  bit = 0x80 >> (x & 7);
4646
0
               }
4647
4648
0
               x = (((xe<<3)|7)/upd->nlimits)*upd->nlimits + pass;
4649
4650
0
               while((x >> 3) < xe) x += upd->nlimits;
4651
0
               while((x >> 3) > xe) x -= upd->nlimits;
4652
4653
0
               bit = 0x80 >> (xs & 7);
4654
0
               while(x > scan->xend[pass]) {
4655
0
                  if(bytes[x>>3] & bit) scan->xend[pass] = x;
4656
0
                  x -= upd->nlimits;
4657
0
                  bit = 0x80 >> (x & 7);
4658
0
               }
4659
4660
0
            }                                            /* limit (pass) loop */
4661
4662
0
         }                      /* Has Data */
4663
4664
0
      }                                             /* Check Components */
4665
4666
0
   }           /* Really check */
4667
4668
0
}
4669
4670
/* ------------------------------------------------------------------- */
4671
/* upd_open_rascomp: ncomp * 1Bit Raster-Writer                        */
4672
/* ------------------------------------------------------------------- */
4673
4674
static int
4675
upd_open_rascomp(upd_device *udev)
4676
0
{
4677
0
   const upd_p upd = udev->upd;
4678
0
   int32_t noutbuf;
4679
0
   int error = 0;
4680
4681
0
   noutbuf = upd->pwidth;
4682
4683
0
   if(1 < upd->ncomp) noutbuf *= 8; /* ??? upd->ocomp */
4684
4685
0
   noutbuf = ((noutbuf+15)>>4)<<1;
4686
4687
0
   if(noutbuf > 0) {
4688
0
      upd->noutbuf = noutbuf;
4689
0
      upd->start_writer = upd_start_rascomp;
4690
0
      upd->writer       = upd_rascomp;
4691
0
   } else {
4692
0
      error = -1;
4693
0
   }
4694
4695
0
   return error;
4696
0
}
4697
4698
/* ------------------------------------------------------------------- */
4699
/* upd_start_rascomp: write appropiate raster-header                   */
4700
/* ------------------------------------------------------------------- */
4701
#if ARCH_IS_BIG_ENDIAN
4702
#define put32(I32,Out)       \
4703
   gp_fwrite(&I32,1,4,Out)
4704
#else
4705
#define put32(I32,Out)       \
4706
0
   gp_fputc(((I32)>>24)&255,Out),\
4707
0
   gp_fputc(((I32)>>16)&255,Out),\
4708
0
   gp_fputc(((I32)>> 8)&255,Out),\
4709
0
   gp_fputc( (I32)     &255,Out)
4710
#endif
4711
4712
static int
4713
0
upd_start_rascomp(upd_p upd, gp_file *out) {
4714
4715
/** if no begin-sequence externally set */
4716
0
   if(0 == upd->strings[S_BEGIN].size) {
4717
0
      int32_t val;
4718
4719
/**   ras_magic */
4720
0
      val = 0x59a66a95;
4721
0
      put32(val,out);
4722
4723
/**   ras_width */
4724
0
      val = upd->pwidth;
4725
0
      put32(val,out);
4726
4727
/**   ras_height */
4728
0
      val = upd->pheight;
4729
0
      put32(val,out);
4730
4731
/**   ras_depth */
4732
0
      if(1 < upd->ncomp) val = 8; /* ??? upd->ocomp */
4733
0
      else               val = 1;
4734
0
      put32(val,out);
4735
4736
/**   ras_length */
4737
0
      val *= upd->pwidth;
4738
0
      val = ((val+15)>>4)<<1;
4739
0
      val *= upd->pheight;
4740
0
      put32(val,out);
4741
4742
/**   ras_type */
4743
0
      val = 1;
4744
0
      put32(val,out);
4745
4746
/**   ras_maptype */
4747
0
      val = 1;
4748
0
      put32(val,out);
4749
4750
/**   ras_maplength */
4751
0
      val = 3 * (1 << upd->ncomp); /* ??? upd->ocomp */
4752
0
      put32(val,out);
4753
4754
/**   R,G,B-Map */
4755
0
      if(1 == upd->ncomp) { /* ??? upd->ocomp */
4756
0
         const updcomp_p comp = upd->valptr[0];
4757
4758
0
         if(upd->cmap[comp->cmap].rise) {
4759
0
            gp_fputc((char) 0x00,out); gp_fputc((char) 0xff,out);
4760
0
            gp_fputc((char) 0x00,out); gp_fputc((char) 0xff,out);
4761
0
            gp_fputc((char) 0x00,out); gp_fputc((char) 0xff,out);
4762
0
         } else {
4763
0
            gp_fputc((char) 0xff,out); gp_fputc((char) 0x00,out);
4764
0
            gp_fputc((char) 0xff,out); gp_fputc((char) 0x00,out);
4765
0
            gp_fputc((char) 0xff,out); gp_fputc((char) 0x00,out);
4766
0
         }
4767
4768
0
      } else if(3 == upd->ncomp) { /* ??? upd->ocomp */
4769
0
         int rgb;
4770
4771
0
         for( rgb = 0; rgb < 3; ++rgb) {
4772
0
            int entry;
4773
0
            for(entry = 0; entry < 8; ++entry) {
4774
0
               byte xval = upd->cmap[rgb].rise ? 0x00 : 0xff;
4775
0
               if(entry & (1<<upd->cmap[rgb].comp)) xval ^= 0xff;
4776
0
               gp_fputc(xval,out);
4777
0
            }
4778
0
         }
4779
0
      } else { /* we have 4 components */
4780
0
         int rgb;
4781
4782
0
         for(rgb = 16; 0 <= rgb; rgb -= 8) {
4783
0
            int entry;
4784
0
            for(entry = 0; entry < 16; ++entry) {
4785
0
               uint32_t rgbval = 0;
4786
4787
0
               if(entry & (1<<upd->cmap[0].comp)) {
4788
4789
0
                  rgbval = 0xffffff;
4790
4791
0
               } else {
4792
4793
0
                  if(entry & (1<<upd->cmap[1].comp)) rgbval |= 0xff0000;
4794
0
                  if(entry & (1<<upd->cmap[2].comp)) rgbval |= 0x00ff00;
4795
0
                  if(entry & (1<<upd->cmap[3].comp)) rgbval |= 0x0000ff;
4796
0
               }
4797
4798
0
               if(!upd->cmap[1].rise) rgbval ^= 0xff0000;
4799
0
               if(!upd->cmap[2].rise) rgbval ^= 0x00ff00;
4800
0
               if(!upd->cmap[3].rise) rgbval ^= 0x0000ff;
4801
4802
0
               if(!(upd->choice[C_MAPPER] == MAP_RGBW)) rgbval ^= 0xffffff;
4803
4804
0
               gp_fputc((rgbval>>rgb)&255,out);
4805
0
            }
4806
0
         }
4807
0
      }
4808
0
   }
4809
0
   memset(upd->outbuf,0,upd->noutbuf);
4810
4811
0
   return 0;
4812
0
}
4813
4814
/* ------------------------------------------------------------------- */
4815
/* upd_rascomp: assemble & write a scanline                            */
4816
/* ------------------------------------------------------------------- */
4817
static int
4818
0
upd_rascomp(upd_p upd, gp_file *out) {
4819
0
   updscan_p scan = upd->scnbuf[upd->yscan & upd->scnmsk];
4820
0
   uint bits = upd->pwidth;
4821
4822
0
   if(1 == upd->ncomp) { /* ??? upd->ocomp */
4823
0
      uint nbytes;
4824
4825
0
      nbytes = (bits+7)>>3;
4826
0
      memcpy(upd->outbuf,scan->bytes,nbytes);
4827
0
      if((bits &= 7)) upd->outbuf[nbytes-1] &= ((byte) 0xff) << (8-bits);
4828
4829
0
   } else {
4830
4831
0
      byte  *buf   = upd->outbuf, bit = 0x80;
4832
0
      int    ibyte = 0;
4833
4834
0
      while(0 < bits--) {
4835
0
         byte val = 0;
4836
0
         switch(upd->ncomp) { /* ??? upd->ocomp */
4837
0
            case 4:  if(scan[3].bytes[ibyte] & bit) val |= 8;
4838
                    /* fall through */
4839
0
            case 3:  if(scan[2].bytes[ibyte] & bit) val |= 4;
4840
0
                     if(scan[1].bytes[ibyte] & bit) val |= 2;
4841
                    /* fall through */
4842
0
            case 1:  if(scan[0].bytes[ibyte] & bit) val |= 1;
4843
0
         }
4844
0
         *buf++ = val;
4845
0
         if(!(bit >>= 1)) {
4846
0
            bit    = 0x80;
4847
0
            ibyte += 1;
4848
0
         }
4849
0
      }
4850
0
   }
4851
4852
0
   gp_fwrite(upd->outbuf,1,upd->noutbuf,out);
4853
0
   upd->yscan += 1;
4854
4855
0
   return 0;
4856
0
}
4857
4858
/* ------------------------------------------------------------------- */
4859
/* upd_open_wrtescp: ESC/P Writer intended for ESC * m commands        */
4860
/* ------------------------------------------------------------------- */
4861
4862
static int
4863
upd_open_wrtescp(upd_device *udev)
4864
0
{
4865
0
   const upd_p      upd  = udev->upd;
4866
0
   int              error = 0;
4867
4868
/** Adjust the PageLength, If Requested */
4869
0
   if((B_PAGELENGTH & upd->flags) &&
4870
0
      (0 < upd->strings[S_BEGIN].size)) { /* BOP-Checker */
4871
0
     int   i,state = 0,value = 0;
4872
0
     byte *bp = (byte *) upd_cast(upd->strings[S_BEGIN].data);
4873
0
     for(i = 0; i < upd->strings[S_BEGIN].size; ++i) {
4874
0
        switch(state) {
4875
0
           case  0:
4876
0
              if(0x1b == bp[i]) state = 1;
4877
0
           break;
4878
0
           case  1:
4879
0
              if('C'  == bp[i]) state = 2;
4880
0
              else              state = 0;
4881
0
           break;
4882
0
           case  2:
4883
0
              if(bp[i]) {
4884
0
                 value = (int)(0.5 + udev->height * (float) bp[i]
4885
0
                               / udev->y_pixels_per_inch);
4886
0
                 if(       0 >= value) bp[i] = 1;
4887
0
                 else if(128 >  value) bp[i] = value;
4888
0
                 else                  bp[i] = 127;
4889
0
                 state = 0;
4890
0
              } else {
4891
0
                 state = 3;
4892
0
              }
4893
0
           break;
4894
0
           case  3:
4895
0
              value = (int)(0.5 + udev->height / udev->y_pixels_per_inch);
4896
0
              if(       0 >= value) bp[i] = 1;
4897
0
              else if( 22 >  value) bp[i] = value;
4898
0
              else                  bp[i] = 22;
4899
0
              state = 0;
4900
0
           break;
4901
0
        }
4902
0
     }
4903
0
   }                                    /* BOP-Checker */
4904
4905
/** Either SETLF or YMOVE must be set */
4906
0
   if((0 == upd->strings[S_SETLF].size) &&
4907
0
      (0 == upd->strings[S_YMOVE].size)   ) {
4908
#if UPD_MESSAGES & UPD_M_WARNING
4909
      errprintf(udev->memory,
4910
        "ESC/P-Open: Either SETLF- or YMOVE-Command must be present\n");
4911
#endif
4912
0
      error = -1;
4913
0
   }
4914
4915
/** X-Positioning must be set too */
4916
0
   if(((1 <  upd->ints[I_XSTEP]        ) &&
4917
0
       (0 == upd->strings[S_XSTEP].size)   ) ||
4918
0
      ((1 < upd->ints[I_NXPASS]        ) &&
4919
0
       (0 == upd->strings[S_XMOVE].size) &&
4920
0
       (0 == upd->strings[S_XSTEP].size)   )   ) {
4921
#if UPD_MESSAGES & UPD_M_WARNING
4922
      errprintf(udev->memory,
4923
         "ESC/P-Open: Missing XSTEP- and/or XMOVE-Command\n");
4924
#endif
4925
0
      error = -1;
4926
0
   }
4927
4928
/** SA_WRITECOMP must be valid */
4929
0
   if(upd->ncomp > upd->string_a[SA_WRITECOMP].size) { /* ??? upd->ocomp */
4930
#if UPD_MESSAGES & UPD_M_WARNING
4931
      errprintf(udev->memory,
4932
         "ESC/P-Open: WRITECOMP-Commands must be given\n");
4933
#endif
4934
0
      error = -1;
4935
0
   }
4936
4937
/**
4938
If all this is correct, it's time to coumput the size of the output-buffer.
4939
It must hold:
4940
  1. Y-Positioning
4941
  2. X-Positioning
4942
  3. Component-Selection
4943
  4. The Raster-Command
4944
  5. The Data
4945
*/
4946
0
   if(0 <= error) {
4947
0
      int32_t i,noutbuf,need;
4948
4949
0
      if(0 < upd->strings[S_YMOVE].size) {
4950
0
         noutbuf = upd->strings[S_YMOVE].size + 2;
4951
0
      } else {
4952
0
         int nmax = upd->pheight;
4953
0
         if(      1 < upd->ints[I_YSTEP]) nmax /=  upd->ints[I_YSTEP];
4954
0
         else if(-1 > upd->ints[I_YSTEP]) nmax *= -upd->ints[I_YSTEP];
4955
0
         noutbuf  = 2 * upd->strings[S_SETLF].size + 2;
4956
0
         noutbuf += nmax/255 + 1;
4957
0
      }
4958
4959
0
      if(1 < upd->ints[I_YSTEP])
4960
0
         noutbuf += (upd->ints[I_YSTEP]-1) * upd->strings[S_YSTEP].size;
4961
4962
0
      noutbuf +=  upd->strings[S_XMOVE].size + 2;
4963
4964
0
      if(1 < upd->ints[I_XSTEP])
4965
0
         noutbuf += (upd->ints[I_XSTEP]-1) * upd->strings[S_XSTEP].size;
4966
4967
0
      if(0 < upd->string_a[SA_SETCOMP].size) {
4968
0
         need = 0;
4969
0
         for(i = 0; i < upd->ocomp; ++i)
4970
0
            if(need < upd->string_a[SA_SETCOMP].data[i].size)
4971
0
               need = upd->string_a[SA_SETCOMP].data[i].size;
4972
0
         noutbuf += need;
4973
0
      }
4974
4975
0
      need = 0;
4976
0
      for(i = 0; i < upd->ocomp; ++i)
4977
0
         if(need < upd->string_a[SA_WRITECOMP].data[i].size)
4978
0
            need = upd->string_a[SA_WRITECOMP].data[i].size;
4979
0
      noutbuf += need + 2;
4980
4981
0
      noutbuf += ((upd->ints[I_PINS2WRITE] + 7) / 8)
4982
0
               * ((upd->pwidth + upd->ints[I_NXPASS] - 1)/upd->ints[I_NXPASS]);
4983
4984
0
      if(noutbuf > 0) {
4985
0
         upd->noutbuf      = noutbuf;
4986
0
         upd->writer       = upd_wrtescp;
4987
0
         upd->nlimits      = upd->ints[I_NXPASS];
4988
0
         error             = 1;
4989
0
      } else {
4990
0
         error = -1;
4991
#if      UPD_MESSAGES & UPD_M_WARNING
4992
            errprintf(udev->memory,
4993
              "ESC/P-Open: %ld is unreasonable size of Outputbuffer\n",
4994
              (long) noutbuf);
4995
#endif
4996
0
      }
4997
0
   }
4998
4999
0
   return error;
5000
0
}
5001
5002
/* ------------------------------------------------------------------- */
5003
/* upd_wrtescp: Write a pass                                           */
5004
/* ------------------------------------------------------------------- */
5005
5006
static int
5007
upd_wrtescp(upd_p upd, gp_file *out)
5008
0
{
5009
0
   int  pinbot,pin,pintop,xbegin,x,xend,icomp,ybegin,yend,y,ioutbuf,n,ixpass;
5010
0
   byte *obytes,bit;
5011
0
   updscan_p scan;
5012
5013
/** Determine the number of pins to write */
5014
5015
0
   if(upd->yscan < upd->ints[I_BEG_Y]) {
5016
0
      ixpass = upd->int_a[IA_BEG_IX].data[upd->ipass];
5017
0
      pintop = 0;
5018
0
      pinbot = upd->int_a[IA_BEGBOT].data[upd->ipass];
5019
0
   } else if(upd->yscan >= upd->ints[I_END_Y]) {
5020
0
      ixpass = upd->int_a[IA_END_IX].data[upd->ipass];
5021
0
      pinbot = upd->ints[I_PINS2WRITE];
5022
0
      pintop = pinbot - upd->int_a[IA_ENDTOP].data[upd->ipass];
5023
0
   } else {
5024
0
      ixpass = upd->int_a[IA_STD_IX].data[upd->ipass];
5025
0
      pintop = 0;
5026
0
      pinbot = upd->ints[I_PINS2WRITE];
5027
0
   }
5028
5029
0
   ybegin =  pintop * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
5030
0
   yend   =  pinbot * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
5031
5032
/** Determine Width of this scan */
5033
5034
0
   xbegin = upd->pwidth;
5035
0
   xend   = -1;
5036
5037
0
   for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Pin-testloop */
5038
5039
0
      if(0 > y) continue; /* Inserted Scanlines */
5040
5041
0
      scan = upd->scnbuf[y & upd->scnmsk];
5042
5043
0
      for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Compwise test */
5044
0
         if(xbegin > scan[icomp].xbegin[ixpass])
5045
0
            xbegin = scan[icomp].xbegin[ixpass];
5046
0
         if(xend   < scan[icomp].xend[  ixpass])
5047
0
            xend   = scan[icomp].xend[  ixpass];
5048
0
      }                                             /* Compwise test */
5049
5050
0
   }                                                     /* Pin-testloop */
5051
5052
0
   if(xbegin <= xend) { /* Some data to write */
5053
5054
0
      ioutbuf = 0;
5055
5056
0
      if(0 == upd->strings[S_XMOVE].size) xbegin = ixpass;
5057
5058
/*
5059
 *    Adjust the Printers Y-Position
5060
 */
5061
0
      if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
5062
0
         if(B_YABS & upd->flags) y = upd->yscan + upd->ints[I_YOFS];
5063
0
         else                    y = upd->yscan - upd->yprinter;
5064
5065
0
         if(      1 < upd->ints[I_YSTEP]) {
5066
0
            n      =  y / upd->ints[I_YSTEP];  /* Major-Steps */
5067
0
            y     -=  n * upd->ints[I_YSTEP];  /* Minor-Steps */
5068
0
         } else if(-1 > upd->ints[I_YSTEP]) {
5069
0
            n      = y * -upd->ints[I_YSTEP];  /* May this work? */
5070
0
            y      = 0;
5071
0
         } else {
5072
0
            n      = y;
5073
0
            y      = 0;
5074
0
         }
5075
5076
0
         if(n) { /* Coarse Positioning */
5077
0
            if(0 < upd->strings[S_YMOVE].size) {
5078
5079
0
               memcpy(upd->outbuf+ioutbuf,
5080
0
                          upd->strings[S_YMOVE].data,
5081
0
                          upd->strings[S_YMOVE].size);
5082
0
               ioutbuf += upd->strings[S_YMOVE].size;
5083
5084
0
               upd->outbuf[ioutbuf++] =  n     & 0xff;
5085
0
               upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5086
5087
0
            } else {
5088
5089
0
               while(n) {
5090
0
                  int n2do = n > 255 ? 255 : n;
5091
0
                  if(upd->lf != n2do) {
5092
0
                     memcpy(upd->outbuf+ioutbuf,
5093
0
                                upd->strings[S_SETLF].data,
5094
0
                                upd->strings[S_SETLF].size);
5095
0
                     ioutbuf += upd->strings[S_SETLF].size;
5096
0
                     upd->outbuf[ioutbuf++] = n2do;
5097
0
                     upd->lf                = n2do;
5098
0
                  }
5099
0
                  upd->outbuf[ioutbuf++] = '\n';
5100
0
                  n -= n2do;
5101
0
               }
5102
0
            }
5103
0
         }       /* Coarse Positioning */
5104
5105
0
         if(0 < upd->strings[S_YSTEP].size) {
5106
0
            while(y--) {
5107
0
               memcpy(upd->outbuf+ioutbuf,
5108
0
                          upd->strings[S_YSTEP].data,
5109
0
                          upd->strings[S_YSTEP].size);
5110
0
               ioutbuf += upd->strings[S_YSTEP].size;
5111
0
            }
5112
0
         }
5113
5114
0
         upd->yprinter = upd->yscan;
5115
0
      }                                 /* Adjust Y-Position */
5116
5117
/*
5118
 * Now write the required components
5119
 */
5120
0
      for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Component-Print */
5121
/*
5122
 *       First check, wether this Component needs printing
5123
 */
5124
0
         for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Comp-Test */
5125
0
            if(0 > y) continue;
5126
0
            scan = upd->scnbuf[y & upd->scnmsk]+icomp;
5127
0
            if(0 <= scan->xend[ixpass]) break;
5128
0
         }                                                     /* Comp-Test */
5129
0
         if(y >= yend) continue; /* Component not required */
5130
/*
5131
 *       Select the Component
5132
 */
5133
0
         if((0 < upd->string_a[SA_SETCOMP].size) &&
5134
0
            (upd->icomp != icomp               )   ) { /* Selection enabled */
5135
0
            upd->icomp = icomp;
5136
0
            if(0 < upd->string_a[SA_SETCOMP].data[icomp].size) {
5137
0
               memcpy(upd->outbuf+ioutbuf,
5138
0
                          upd->string_a[SA_SETCOMP].data[icomp].data,
5139
0
                          upd->string_a[SA_SETCOMP].data[icomp].size);
5140
0
               ioutbuf += upd->string_a[SA_SETCOMP].data[icomp].size;
5141
0
            }
5142
0
         }                                      /* Selection enabled */
5143
/*
5144
 *       Establish the X-Position
5145
 */
5146
0
         if(xbegin != upd->xprinter) {
5147
5148
0
            if(0 == upd->strings[S_XMOVE].size) {
5149
5150
0
               upd->outbuf[ioutbuf++] = '\r';
5151
0
               upd->xprinter          =  0;
5152
0
               n = 0;
5153
0
               x = ixpass;
5154
5155
0
            } else {
5156
5157
0
               if(B_XABS & upd->flags) n = x = xbegin + upd->ints[I_XOFS];
5158
0
               else                    n = x = xbegin - upd->xprinter;
5159
5160
0
               if(        1 < upd->ints[I_XSTEP]) {
5161
0
                  if(0 > n) {
5162
0
                     n  -= upd->ints[I_XSTEP];
5163
0
                     x  -= n;
5164
0
                  }
5165
0
                  if(n) n  /= upd->ints[I_XSTEP]; /* Major-Steps */
5166
0
                  if(x) x  %= upd->ints[I_XSTEP]; /* Minor-Steps */
5167
5168
0
               } else if(-1 > upd->ints[I_XSTEP]) {
5169
0
                  n *= -upd->ints[I_XSTEP]; /* May this work? */
5170
0
                  x  = 0;
5171
0
               }
5172
5173
0
               if(n) { /* Adjust X-Position */
5174
5175
0
                 memcpy(upd->outbuf+ioutbuf,
5176
0
                             upd->strings[S_XMOVE].data,
5177
0
                             upd->strings[S_XMOVE].size);
5178
0
                  ioutbuf += upd->strings[S_XMOVE].size;
5179
5180
0
                  upd->outbuf[ioutbuf++] =  n     & 0xff;
5181
0
                  upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5182
5183
0
               }       /* Adjust X-Position */
5184
5185
0
            }
5186
5187
0
            if(x && 0 < upd->strings[S_XSTEP].size) { /* Fine-Adjust X */
5188
0
               while(x--) {
5189
0
                  memcpy(upd->outbuf+ioutbuf,
5190
0
                             upd->strings[S_XSTEP].data,
5191
0
                             upd->strings[S_XSTEP].size);
5192
0
                  ioutbuf += upd->strings[S_XSTEP].size;
5193
0
               }
5194
0
            }                                         /* Fine-Adjust X */
5195
0
         }
5196
0
         upd->xprinter = xend+1;
5197
/*
5198
 *       Send the Write-Command
5199
 */
5200
0
         if(0 < upd->string_a[SA_WRITECOMP].data[icomp].size) {
5201
0
            memcpy(upd->outbuf+ioutbuf,
5202
0
                       upd->string_a[SA_WRITECOMP].data[icomp].data,
5203
0
                       upd->string_a[SA_WRITECOMP].data[icomp].size);
5204
0
            ioutbuf += upd->string_a[SA_WRITECOMP].data[icomp].size;
5205
0
         }
5206
0
         n = (xend - xbegin) / upd->ints[I_NXPASS] + 1;;
5207
0
         upd->outbuf[ioutbuf++] =  n     & 255;
5208
0
         upd->outbuf[ioutbuf++] = (n>>8) & 255;
5209
/*
5210
 *       Clear the data-Part
5211
 */
5212
0
         obytes   =  upd->outbuf+ioutbuf;
5213
0
         n       *= (upd->ints[I_PINS2WRITE]+7)>>3;
5214
0
         memset(obytes,0,n);
5215
0
         ioutbuf += n;
5216
/*
5217
 *       Set the Pixels
5218
 */
5219
0
         for(x = xbegin; x <= xend; x += upd->ints[I_NXPASS]) {
5220
5221
0
            bit     = 0x80 >> (pintop & 7);
5222
0
            obytes += pintop>>3;
5223
5224
0
            for(pin = pintop, y = ybegin; pin < pinbot;
5225
0
                pin++,        y += upd->ints[I_NYPASS]) {
5226
0
               if(0 <= y) {
5227
0
                  scan = upd->scnbuf[y & upd->scnmsk]+icomp;
5228
0
                  if(scan->bytes[x>>3] & (0x80 >> (x & 7))) *obytes |= bit;
5229
0
               }
5230
0
               if(!(bit >>= 1)) { obytes++; bit = 0x80; }
5231
0
            }
5232
5233
0
            obytes += (upd->ints[I_PINS2WRITE]-pinbot+7)>>3;
5234
0
         }
5235
/*
5236
 *       Send this Component to the Printer
5237
 */
5238
0
         gp_fwrite(upd->outbuf,1,ioutbuf,out);
5239
0
         ioutbuf = 0;
5240
0
      }                                             /* Component-Print */
5241
0
   }                    /* Some data to write */
5242
5243
/** Advance counters in upd, change modi */
5244
5245
0
   if(upd->yscan < upd->ints[I_BEG_Y]) {
5246
0
      upd->yscan += upd->int_a[IA_BEG_DY].data[upd->ipass++];
5247
0
      if(     upd->ints[I_BEG_Y] <= upd->yscan) upd->ipass = 0;
5248
0
      else if(upd->int_a[IA_BEG_DY].size <= upd->ipass) upd->ipass = 0;
5249
0
   } else if(upd->yscan >= upd->ints[I_END_Y]) {
5250
0
      upd->yscan += upd->int_a[IA_END_DY].data[upd->ipass++];
5251
0
      if(upd->int_a[IA_END_DY].size <= upd->ipass) upd->ipass = 0;
5252
0
   } else {
5253
0
      upd->yscan += upd->int_a[IA_STD_DY].data[upd->ipass++];
5254
0
      if(upd->int_a[IA_STD_DY].size <= upd->ipass) upd->ipass = 0;
5255
0
      if(upd->yscan >= upd->ints[I_END_Y])         upd->ipass = 0;
5256
0
   }
5257
5258
0
   return 0;
5259
0
}
5260
5261
/* ------------------------------------------------------------------- */
5262
/* upd_open_wrtescp2: ESC/P2 Writer intended for ESC . 1  commands     */
5263
/* ------------------------------------------------------------------- */
5264
5265
static int
5266
upd_open_wrtescp2(upd_device *udev)
5267
0
{
5268
0
   const upd_p      upd             = udev->upd;
5269
0
   int              error           = 0;
5270
0
   float            pixels_per_inch = 360.0;
5271
5272
/** Analyze (and optionally adjust) the BOP-Sequence */
5273
0
   if(0 < upd->strings[S_BEGIN].size) { /* BOP-Checker */
5274
0
     int   i,state = 0,value = 0;
5275
0
     byte *bp = (byte *) upd_cast(upd->strings[S_BEGIN].data);
5276
0
     for(i = 0; i < upd->strings[S_BEGIN].size; ++i) {
5277
0
        switch(state) {
5278
0
           case  0:
5279
0
              if(0x1b == bp[i]) state = 1;
5280
0
           break;
5281
0
           case  1:
5282
0
              if('('  == bp[i]) state = 2;
5283
0
              else              state = 0;
5284
0
           break;
5285
0
           case  2:
5286
0
              switch(bp[i]) {
5287
0
                 case 'U': state =  3; break; /* Printer-Resolution */
5288
0
                 case 'C': state =  6; break; /* Page-Length */
5289
0
                 case 'c': state = 10; break; /* Top/Bottom Margin */
5290
0
                 default:  state =  0; break;
5291
0
              }
5292
0
           break;
5293
0
           case  3:
5294
0
              if(1 == bp[i]) state = 4;
5295
0
              else           state = 0;
5296
0
           break;
5297
0
           case  4:
5298
0
              if(0 == bp[i]) state = 5;
5299
0
              else           state = 0;
5300
0
           break;
5301
0
           case  5:
5302
0
              pixels_per_inch = 3600.0 / (float) bp[i];
5303
0
              state = 0;
5304
0
           break;
5305
0
           case  6:
5306
0
              if(2 == bp[i]) state = 7;
5307
0
              else           state = 0;
5308
0
           break;
5309
0
           case  7:
5310
0
              if(0 == bp[i]) state = 8;
5311
0
              else           state = 0;
5312
0
           break;
5313
0
           case  8:
5314
0
              if(B_PAGELENGTH & upd->flags) {
5315
0
                 value = (int)(0.5 + udev->height
5316
0
                               * pixels_per_inch / udev->y_pixels_per_inch);
5317
0
                 bp[i] =  value     & 0xff;
5318
0
              }
5319
0
              state = 9;
5320
0
           break;
5321
0
           case  9:
5322
0
              if(B_PAGELENGTH & upd->flags) {
5323
0
                 bp[i] = (value>>8) & 0xff;
5324
0
              }
5325
0
              state = 0;
5326
0
           break;
5327
0
           case 10:
5328
0
              if(4 == bp[i]) state = 11;
5329
0
              else           state =  0;
5330
0
           break;
5331
0
           case 11:
5332
0
              if(0 == bp[i]) state = 12;
5333
0
              else           state =  0;
5334
0
           break;
5335
0
           case  12:
5336
0
              if(B_TOPMARGIN & upd->flags) {
5337
0
                 value =  (int)(dev_t_margin(udev) * pixels_per_inch);
5338
0
                 bp[i] =  value     & 0xff;
5339
0
              }
5340
0
              state = 13;
5341
0
           break;
5342
0
           case  13:
5343
0
              if(B_TOPMARGIN & upd->flags) {
5344
0
                 bp[i] = (value>>8) & 0xff;
5345
0
              }
5346
0
              state = 14;
5347
0
           break;
5348
0
           case  14:
5349
0
              if(B_BOTTOMMARGIN & upd->flags) {
5350
0
                 value = (int)(0.5 + udev->height
5351
0
                               * pixels_per_inch / udev->y_pixels_per_inch
5352
0
                       - dev_b_margin(udev) * pixels_per_inch);
5353
0
                 bp[i] =  value     & 0xff;
5354
0
              }
5355
0
              state = 15;
5356
0
           break;
5357
0
           case  15:
5358
0
              if(B_BOTTOMMARGIN & upd->flags) {
5359
0
                 bp[i] = (value>>8) & 0xff;
5360
0
              }
5361
0
              state =  0;
5362
0
           break;
5363
0
        }
5364
0
     }
5365
0
   }                                    /* BOP-Checker */
5366
5367
/** Create Y-Move-Command, if not given */
5368
0
   if(0 == upd->strings[S_YMOVE].size) {
5369
0
      byte *bp;
5370
0
      UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_YMOVE]);
5371
0
      UPD_MM_GET_ARRAY(udev->memory, bp,5);
5372
0
      upd->strings[S_YMOVE].data = bp;
5373
0
      upd->strings[S_YMOVE].size = 5;
5374
0
      *bp++ = 0x1b; /* ESC */
5375
0
      *bp++ = '(';
5376
0
      *bp++ = upd->flags & B_YABS ? 'V' : 'v';
5377
0
      *bp++ =  2;
5378
0
      *bp++ =  0;
5379
0
   }
5380
5381
/** X-Positioning must be set too, sometimes */
5382
0
   if((1 < upd->ints[I_XSTEP]) && (0 == upd->strings[S_XSTEP].size)) {
5383
5384
#if UPD_MESSAGES & UPD_M_WARNING
5385
      errprintf(udev->memory,
5386
         "ESC/P2-Open: XSTEP-Command required for XSTEP=%d\n",
5387
         upd->ints[I_XSTEP]);
5388
#endif
5389
0
      error = -1;
5390
5391
0
   } else if((1 <  upd->ints[I_NXPASS]       ) &&
5392
0
             (0 == upd->strings[S_XMOVE].size) &&
5393
0
             (0 == upd->strings[S_XSTEP].size)   ) {
5394
0
      byte *bp;
5395
0
      int ratio;
5396
5397
0
      ratio = (int)((udev->y_pixels_per_inch + 0.5) / udev->x_pixels_per_inch);
5398
5399
0
      if(0 == upd->ints[I_XSTEP]) { /* Adjust scale-factor too! */
5400
0
         if(ratio > 1) upd->ints[I_XSTEP] = -ratio;
5401
0
      } else {                     /* Adjust scale-factor too! */
5402
0
         ratio = -upd->ints[I_XSTEP];
5403
0
      }
5404
5405
0
      if(2 == upd->ints[I_NXPASS]) { /* Use a relative Step */
5406
5407
0
         UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_XSTEP]);
5408
0
         UPD_MM_GET_ARRAY(udev->memory, bp,4);
5409
0
         upd->strings[S_XSTEP].size = 4;
5410
0
         upd->strings[S_XSTEP].data = bp;
5411
0
         *bp++ = 0x1b;
5412
0
         *bp++ = '\\';
5413
0
         *bp++ =  ratio     & 0xff;
5414
0
         *bp++ = (ratio>>8) & 0xff;
5415
5416
0
      } else {                      /* Use relative or absolute Move */
5417
5418
0
         UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_XMOVE]);
5419
0
         UPD_MM_GET_ARRAY(udev->memory, bp,2);
5420
0
         upd->strings[S_XMOVE].size = 2;
5421
0
         upd->strings[S_XMOVE].data = bp;
5422
0
         *bp++  = 0x1b;
5423
0
         *bp++  = upd->flags & B_XABS ? '$' : '\\';
5424
5425
0
      }
5426
0
   }
5427
5428
   /* Check the Nozzle Map parameters and set some defaults */
5429
   /* Used a switch construct in case FMT_ESCNMXY is added later */
5430
0
   switch(upd->choice[C_FORMAT]){
5431
0
      case FMT_ESCNMY:
5432
         /* RowsPerPass */
5433
0
         if( 0 == upd->ints[I_ROWS] ){
5434
0
            upd->ints[I_ROWS] = 1;
5435
0
         }
5436
         /* PatternRepeat */
5437
0
         if( 0 == upd->ints[I_PATRPT] ){
5438
0
            upd->ints[I_PATRPT] = 1;
5439
0
         }
5440
         /* RowMask - default is all 1's */
5441
0
         if( upd->ints[I_PATRPT] != upd->int_a[IA_ROWMASK].size ) {
5442
0
            int i, *bp;
5443
0
            UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_ROWMASK]);
5444
0
            UPD_MM_GET_ARRAY(udev->memory, bp,upd->ints[I_PATRPT]);
5445
0
            upd->int_a[IA_ROWMASK].size = upd->ints[I_PATRPT];
5446
0
            upd->int_a[IA_ROWMASK].data = bp;
5447
0
            for (i = 0 ; i < upd->ints[I_PATRPT] ; i++){
5448
0
               *bp++  = 1; /* black */
5449
0
            }
5450
0
         }
5451
         /* MaskScanOffset - default is 0-patternRepeat */
5452
0
         if( upd->ints[I_PATRPT] != upd->int_a[IA_SCNOFS].size ) {
5453
0
            int i, *bp;
5454
0
            UPD_MM_DEL_PARAM(udev->memory, upd->int_a[IA_SCNOFS]);
5455
0
            UPD_MM_GET_ARRAY(udev->memory, bp,upd->ints[I_PATRPT]);
5456
0
            upd->int_a[IA_SCNOFS].size = upd->ints[I_PATRPT];
5457
0
            upd->int_a[IA_SCNOFS].data = bp;
5458
0
            for (i = 0 ; i < upd->ints[I_PATRPT] ; i++){
5459
0
               *bp++  = i;
5460
0
            }
5461
0
         }
5462
0
      break;
5463
0
      case FMT_ESCP2Y:
5464
0
      case FMT_ESCP2XY:
5465
         /* Nozzle map parameters are not valid for these formats
5466
            so ignore them*/
5467
0
      break;
5468
0
   }
5469
5470
/** If there is neither a writecomp nor a setcomp-command, generate both */
5471
0
   if((0 == upd->string_a[SA_WRITECOMP].size) &&
5472
0
      (0 == upd->string_a[SA_SETCOMP].size  )   ) { /* Default-commands */
5473
0
      byte *bp;
5474
0
      gs_param_string *ap;
5475
0
      int   i;
5476
5477
0
      if(4 == upd->ocomp) { /* Establish Component-Selection */
5478
0
         UPD_MM_DEL_APARAM(udev->memory, upd->string_a[SA_SETCOMP]);
5479
0
         UPD_MM_GET_ARRAY(udev->memory, ap,4);
5480
0
         upd->string_a[SA_SETCOMP].data = ap;
5481
0
         upd->string_a[SA_SETCOMP].size = 4;
5482
0
         for(i = 0; i < 4; ++i) {
5483
0
            UPD_MM_GET_ARRAY(udev->memory, bp,3);
5484
0
            ap[i].size = 3;
5485
0
            ap[i].data = bp;
5486
0
            *bp++ = 0x1b;
5487
0
            *bp++ = 'r';
5488
0
            switch(((updcomp_p)upd->valptr[i])->cmap) { /* use COMPORDER! */
5489
0
               case 0: *bp++ = 0; break; /* Black */
5490
0
               case 1: *bp++ = 2; break; /* Cyan */
5491
0
               case 2: *bp++ = 1; break; /* Magenta */
5492
0
               case 3: *bp++ = 4; break; /* Yellow */
5493
0
            }                                           /* use COMPORDER! */
5494
0
         }
5495
0
      }                     /* Establish Component-Selection */
5496
5497
0
      UPD_MM_DEL_APARAM(udev->memory, upd->string_a[SA_WRITECOMP]);
5498
0
      UPD_MM_GET_ARRAY(udev->memory, ap,upd->ocomp);
5499
0
      upd->string_a[SA_WRITECOMP].data = ap;
5500
0
      upd->string_a[SA_WRITECOMP].size = upd->ncomp;
5501
0
      for(i = 0; i < upd->ocomp; ++i) {
5502
0
         UPD_MM_GET_ARRAY(udev->memory, bp,6);
5503
0
         ap[i].size = 6;
5504
0
         ap[i].data = bp;
5505
0
         *bp++ = 0x1b;
5506
0
         *bp++ = '.';
5507
0
         *bp++ =  1;  /* RLE */
5508
0
         switch(upd->choice[C_FORMAT]){
5509
0
            case FMT_ESCP2Y:
5510
0
            case FMT_ESCP2XY:
5511
0
               *bp++ = (byte)(3600.0 * upd->ints[I_NYPASS] /
5512
0
                                 udev->y_pixels_per_inch + 0.5);
5513
0
               *bp++ = (byte)(3600.0 * upd->ints[I_NXPASS] /
5514
0
                                 udev->x_pixels_per_inch + 0.5);
5515
0
               *bp++ = upd->ints[I_PINS2WRITE];
5516
0
            break;
5517
0
            case FMT_ESCNMY:
5518
               /*
5519
               *bp++ = 3600.0 / udev->y_pixels_per_inch + 0.5;
5520
               *bp++ = 3600.0 / udev->x_pixels_per_inch + 0.5;
5521
               */
5522
0
               *bp++ = 10; /* needs to always be this for esc300 */
5523
0
               *bp++ = 10;
5524
0
               *bp++ = upd->ints[I_ROWS];
5525
0
            break;
5526
0
         }
5527
0
      }
5528
0
   }                                                /* Default-commands */
5529
5530
/** SA_WRITECOMP must be valid */
5531
0
   if(upd->ocomp > upd->string_a[SA_WRITECOMP].size) {
5532
#if UPD_MESSAGES & UPD_M_WARNING
5533
      errprintf(udev->memory,
5534
         "ESC/P2-Open: WRITECOMP-Commands must be given\n");
5535
#endif
5536
0
      error = -1;
5537
0
   }
5538
5539
/** Check Validity of X-Pass */
5540
0
   switch(upd->choice[C_FORMAT]) {
5541
0
      case FMT_ESCP2Y:
5542
0
         if(1 < upd->ints[I_NXPASS]) {
5543
#if         UPD_MESSAGES & UPD_M_WARNING
5544
               errprintf(udev->memory,
5545
                  "ESC/P2-Open: FMT_ESCP2Y cannot handle multiple X-Passes\n");
5546
#endif
5547
0
            error = -1;
5548
0
         } else {
5549
0
            upd->writer = upd_wrtescp2;
5550
0
         }
5551
0
      break;
5552
0
      case FMT_ESCP2XY:
5553
0
         upd->writer  = upd_wrtescp2x;
5554
0
         upd->nlimits = upd->ints[I_NXPASS];
5555
#if      UPD_MESSAGES & UPD_M_WARNING
5556
            if(1 == upd->ints[I_NXPASS])
5557
               errprintf(udev->memory,
5558
                  "ESC/P2-Open: FMT_ESCP2XY should not be used with 1X-Pass\n");
5559
#endif
5560
0
      break;
5561
0
      case FMT_ESCNMY:
5562
0
         if(1 < upd->ints[I_NXPASS]) {
5563
#if         UPD_MESSAGES & UPD_M_WARNING
5564
               errprintf(udev->memory,
5565
                  "ESC/P2-Open: FMT_ESCNMY cannot handle multiple X-Passes\n");
5566
#endif
5567
0
            error = -1;
5568
0
         } else {
5569
0
            upd->writer = upd_wrtescnm;
5570
0
         }
5571
0
      break;
5572
0
      default:
5573
#if      UPD_MESSAGES & UPD_M_WARNING
5574
            errprintf(udev->memory,
5575
               "ESC/P2-Open: %d is not a ESC/P2-Format\n",
5576
               upd->choice[C_FORMAT]);
5577
#endif
5578
0
         error = - 1;
5579
0
      break;
5580
0
   }
5581
5582
/**
5583
If all this is correct, it's time to compute the size of the output-buffer.
5584
It must hold:
5585
  1. Y-Positioning
5586
  2. X-Positioning
5587
  3. Component-Selection
5588
  4. The Raster-Command
5589
  5. The Data
5590
*/
5591
0
   if(0 <= error) {
5592
0
      int32_t i,noutbuf,need;
5593
      /* Y-Positioning */
5594
0
      if(0 < upd->strings[S_YMOVE].size) {
5595
0
         noutbuf = upd->strings[S_YMOVE].size + 2;
5596
0
      } else {
5597
0
         int nmax = upd->pheight;
5598
0
         if(      1 < upd->ints[I_YSTEP]) nmax /=  upd->ints[I_YSTEP];
5599
0
         else if(-1 > upd->ints[I_YSTEP]) nmax *= -upd->ints[I_YSTEP];
5600
0
         noutbuf  = 2 * upd->strings[S_SETLF].size + 2;
5601
0
         noutbuf += nmax/255 + 1;
5602
0
      }
5603
5604
0
      if(1 < upd->ints[I_YSTEP])
5605
0
         noutbuf += (upd->ints[I_YSTEP]-1) * upd->strings[S_YSTEP].size;
5606
5607
      /* X-Positioning */
5608
0
      if(0 == upd->strings[S_XMOVE].size) {
5609
0
         noutbuf += 1; /* The CR */
5610
0
         noutbuf += (upd->ints[I_NXPASS]-1) * upd->strings[S_XSTEP].size;
5611
0
      } else {
5612
0
         noutbuf +=  upd->strings[S_XMOVE].size + 2;
5613
5614
0
         if(1 < upd->ints[I_XSTEP])
5615
0
            noutbuf += (upd->ints[I_XSTEP]-1) * upd->strings[S_XSTEP].size;
5616
0
      }
5617
5618
      /* Component-Selection */
5619
0
      if(0 < upd->string_a[SA_SETCOMP].size) {
5620
0
          need = 0;
5621
0
          for(i = 0; i < upd->ocomp; ++i)
5622
0
             if(need < upd->string_a[SA_SETCOMP].data[i].size)
5623
0
                need = upd->string_a[SA_SETCOMP].data[i].size;
5624
0
          noutbuf += need;
5625
0
      }
5626
5627
      /* The Raster-Command */
5628
0
      need = 0;
5629
0
      for(i = 0; i < upd->ocomp; ++i)
5630
0
         if(need < upd->string_a[SA_WRITECOMP].data[i].size)
5631
0
            need = upd->string_a[SA_WRITECOMP].data[i].size;
5632
0
      noutbuf += need + 2;
5633
5634
      /* The Data */
5635
0
      noutbuf += 2*upd->nbytes + (upd->nbytes + 127) / 128;
5636
5637
0
      upd->noutbuf      = noutbuf;
5638
0
      error             = 1;
5639
0
   }
5640
5641
0
   return error;
5642
0
}
5643
5644
/* ------------------------------------------------------------------- */
5645
/* upd_wrtescp2: Write a pass                                          */
5646
/* ------------------------------------------------------------------- */
5647
5648
static int
5649
upd_wrtescp2(upd_p upd, gp_file *out)
5650
0
{
5651
0
   int  pinbot,pin,pintop,xbegin,x,xend,icomp,ybegin,yend,y,ioutbuf,n;
5652
0
   byte *obytes;
5653
0
   updscan_p scan;
5654
5655
/** Determine the number of pins to write */
5656
5657
0
   if(upd->yscan < upd->ints[I_BEG_Y]) {
5658
0
      pintop = 0;
5659
0
      pinbot = upd->int_a[IA_BEGBOT].data[upd->ipass];
5660
0
   } else if(upd->yscan >= upd->ints[I_END_Y]) {
5661
0
      pinbot = upd->ints[I_PINS2WRITE];
5662
0
      pintop = pinbot - upd->int_a[IA_ENDTOP].data[upd->ipass];
5663
0
   } else {
5664
0
      pintop = 0;
5665
0
      pinbot = upd->ints[I_PINS2WRITE];
5666
0
   }
5667
5668
0
   ybegin =  pintop * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
5669
0
   yend   =  pinbot * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
5670
5671
/** Determine Width of this scan */
5672
5673
0
   xbegin = upd->nbytes;
5674
0
   xend   = -1;
5675
5676
0
   for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Pin-testloop */
5677
5678
0
      if(0 > y) continue; /* Inserted Scanlines */
5679
5680
0
      scan = upd->scnbuf[y & upd->scnmsk];
5681
5682
0
      for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Compwise test */
5683
0
         obytes = scan[icomp].bytes;
5684
5685
0
         for(x = 0; x < xbegin && !obytes[x]; x++);
5686
0
         if(x < xbegin) xbegin = x;
5687
5688
0
         if(x < upd->nbytes) {
5689
0
            for(x = upd->nbytes-1; x > xend && !obytes[x]; x--);
5690
0
            if(x > xend) xend = x;
5691
0
         }
5692
0
      }                                             /* Compwise test */
5693
5694
0
   }                                                     /* Pin-testloop */
5695
5696
0
   if(xbegin <= xend) { /* Some data to write */
5697
5698
0
      ioutbuf = 0;
5699
5700
0
      if(0 == upd->strings[S_XMOVE].size) xbegin = 0;
5701
5702
/*
5703
 *    Adjust the Printers Y-Position
5704
 */
5705
0
      if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
5706
0
         if(B_YABS & upd->flags) y = upd->yscan + upd->ints[I_YOFS];
5707
0
         else                    y = upd->yscan - upd->yprinter;
5708
5709
0
         if(      1 < upd->ints[I_YSTEP]) {
5710
0
            n      =  y / upd->ints[I_YSTEP];  /* Major-Steps */
5711
0
            y     -=  n * upd->ints[I_YSTEP];  /* Minor-Steps */
5712
0
         } else if(-1 > upd->ints[I_YSTEP]) {
5713
0
            n      = y * -upd->ints[I_YSTEP];  /* May this work? */
5714
0
            y      = 0;
5715
0
         } else {
5716
0
            n      = y;
5717
0
            y      = 0;
5718
0
         }
5719
5720
0
         if(n) { /* Coarse Positioning */
5721
0
            memcpy(upd->outbuf+ioutbuf,
5722
0
                       upd->strings[S_YMOVE].data,upd->strings[S_YMOVE].size);
5723
0
            ioutbuf += upd->strings[S_YMOVE].size;
5724
5725
0
            upd->outbuf[ioutbuf++] =  n     & 0xff;
5726
0
            upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5727
5728
0
         }       /* Coarse Positioning */
5729
5730
0
         if(0 < upd->strings[S_YSTEP].size) {
5731
0
            while(y--) {
5732
0
               memcpy(upd->outbuf+ioutbuf,
5733
0
                          upd->strings[S_YSTEP].data,
5734
0
                          upd->strings[S_YSTEP].size);
5735
0
               ioutbuf += upd->strings[S_YSTEP].size;
5736
0
            }
5737
0
         }
5738
5739
0
         upd->yprinter = upd->yscan;
5740
0
      }                                 /* Adjust Y-Position */
5741
/*
5742
 * Now write the required components
5743
 */
5744
0
      for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Component-Print */
5745
/*
5746
 *       First check, wether this Component needs printing
5747
 */
5748
0
         for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Comp-Test */
5749
0
            if(0 > y) continue;
5750
0
            obytes = upd->scnbuf[y & upd->scnmsk][icomp].bytes;
5751
0
            for(x = xbegin; x <= xend && !obytes[x]; ++x);
5752
0
            if(             x <= xend) break;
5753
0
         }                                                     /* Comp-Test */
5754
0
         if(y >= yend) continue; /* Component not required */
5755
/*
5756
 *       Select the Component
5757
 */
5758
0
         if((0 < upd->string_a[SA_SETCOMP].size) &&
5759
0
            (upd->icomp != icomp               )   ) { /* Selection enabled */
5760
0
            upd->icomp = icomp;
5761
0
            if(0 < upd->string_a[SA_SETCOMP].data[icomp].size) {
5762
0
               memcpy(upd->outbuf+ioutbuf,
5763
0
                          upd->string_a[SA_SETCOMP].data[icomp].data,
5764
0
                          upd->string_a[SA_SETCOMP].data[icomp].size);
5765
0
               ioutbuf += upd->string_a[SA_SETCOMP].data[icomp].size;
5766
0
            }
5767
0
         }                                      /* Selection enabled */
5768
/*
5769
 *       Establish the X-Position
5770
 */
5771
0
         if(xbegin != upd->xprinter) {
5772
5773
0
            if(0 == upd->strings[S_XMOVE].size) {
5774
5775
0
               upd->outbuf[ioutbuf++] = '\r';
5776
0
               upd->xprinter          =  0;
5777
0
               n = 0;
5778
0
               x = 0;
5779
5780
0
            } else {
5781
5782
0
               if(B_XABS & upd->flags) n = x = xbegin + upd->ints[I_XOFS];
5783
0
               else                    n = x = xbegin - upd->xprinter;
5784
5785
0
               if(        1 < upd->ints[I_XSTEP]) {
5786
0
                  if(0 > n) {
5787
0
                     n  -= upd->ints[I_XSTEP];
5788
0
                     x  -= n;
5789
0
                  }
5790
0
                  if(n) n  /= upd->ints[I_XSTEP]; /* Major-Steps */
5791
0
                  if(x) x  %= upd->ints[I_XSTEP]; /* Minor-Steps */
5792
5793
0
               } else if(-1 > upd->ints[I_XSTEP]) {
5794
0
                  n *= -upd->ints[I_XSTEP]; /* May this work? */
5795
0
                  x  = 0;
5796
0
               }
5797
5798
0
               if(n) { /* Adjust X-Position */
5799
5800
0
                 memcpy(upd->outbuf+ioutbuf,
5801
0
                             upd->strings[S_XMOVE].data,
5802
0
                             upd->strings[S_XMOVE].size);
5803
0
                  ioutbuf += upd->strings[S_XMOVE].size;
5804
5805
0
                  upd->outbuf[ioutbuf++] =  n     & 0xff;
5806
0
                  upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5807
5808
0
               }       /* Adjust X-Position */
5809
5810
0
            }
5811
5812
0
            if(x && 0 < upd->strings[S_XSTEP].size) { /* Fine-Adjust X */
5813
0
               while(x--) {
5814
0
                  memcpy(upd->outbuf+ioutbuf,
5815
0
                             upd->strings[S_XSTEP].data,
5816
0
                             upd->strings[S_XSTEP].size);
5817
0
                  ioutbuf += upd->strings[S_XSTEP].size;
5818
0
               }
5819
0
            }                                         /* Fine-Adjust X */
5820
0
         }
5821
0
         upd->xprinter = xend+1;
5822
5823
/*
5824
 *       Send the Write-Command
5825
 */
5826
0
         if(0 < upd->string_a[SA_WRITECOMP].data[icomp].size) {
5827
0
            memcpy(upd->outbuf+ioutbuf,
5828
0
                       upd->string_a[SA_WRITECOMP].data[icomp].data,
5829
0
                       upd->string_a[SA_WRITECOMP].data[icomp].size);
5830
0
            ioutbuf += upd->string_a[SA_WRITECOMP].data[icomp].size;
5831
0
         }
5832
0
         n = xend + 1 - xbegin;
5833
0
         upd->outbuf[ioutbuf++] = (n<<3) & 255;
5834
0
         upd->outbuf[ioutbuf++] = (n>>5) & 255;
5835
/*
5836
 *       Set the Pixels
5837
 */
5838
0
         for(pin = 0; pin < pintop; ++pin) {
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 = ybegin; 0 > y;    y += upd->ints[I_NYPASS]) {
5845
0
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
5846
0
            gp_fwrite(upd->outbuf,1,ioutbuf,out);
5847
0
            ioutbuf = 0;
5848
0
         }
5849
5850
0
         for(; y < yend; y += upd->ints[I_NYPASS]) {
5851
0
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,
5852
0
               upd->scnbuf[y & upd->scnmsk][icomp].bytes+xbegin,n);
5853
0
            gp_fwrite(upd->outbuf,1,ioutbuf,out);
5854
0
            ioutbuf = 0;
5855
0
         }
5856
5857
0
         for(pin = pinbot; pin < upd->ints[I_PINS2WRITE]; ++pin) {
5858
0
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
5859
0
            gp_fwrite(upd->outbuf,1,ioutbuf,out);
5860
0
            ioutbuf = 0;
5861
0
         }
5862
0
      }                                             /* Component-Print */
5863
0
   }                    /* Some data to write */
5864
5865
/** Advance counters in upd, change modi */
5866
0
   if(upd->yscan < upd->ints[I_BEG_Y]) {
5867
0
      upd->yscan += upd->int_a[IA_BEG_DY].data[upd->ipass++];
5868
0
      if(     upd->ints[I_BEG_Y] <= upd->yscan) upd->ipass = 0;
5869
0
      else if(upd->int_a[IA_BEG_DY].size <= upd->ipass) upd->ipass = 0;
5870
0
   } else if(upd->yscan >= upd->ints[I_END_Y]) {
5871
0
      upd->yscan += upd->int_a[IA_END_DY].data[upd->ipass++];
5872
0
      if(upd->int_a[IA_END_DY].size <= upd->ipass) upd->ipass = 0;
5873
0
   } else {
5874
0
      upd->yscan += upd->int_a[IA_STD_DY].data[upd->ipass++];
5875
0
      if(upd->int_a[IA_STD_DY].size <= upd->ipass) upd->ipass = 0;
5876
0
      if(upd->yscan >= upd->ints[I_END_Y])         upd->ipass = 0;
5877
0
   }
5878
5879
0
   return 0;
5880
0
}
5881
5882
/* ------------------------------------------------------------------- */
5883
/* upd_wrtescnm: Write a pass                                          */
5884
/* ------------------------------------------------------------------- */
5885
5886
/*GR copied from upd_wrtescp2 and modified */
5887
5888
static int
5889
upd_wrtescnm(upd_p upd, gp_file *out)
5890
0
{
5891
0
   int  pinbot,pin,pintop,xbegin,x,xend,icomp,ybegin,yend,y,ioutbuf,n;
5892
0
   int  irow,imask,iyofs;
5893
0
   byte *obytes;
5894
0
   updscan_p scan;
5895
5896
/** Determine the number of pins to write */
5897
5898
0
   if(upd->yscan < upd->ints[I_BEG_Y]) {
5899
0
      pintop = 0;
5900
0
      pinbot = upd->int_a[IA_BEGBOT].data[upd->ipass];
5901
0
   } else if(upd->yscan >= upd->ints[I_END_Y]) {
5902
0
      pinbot = upd->ints[I_PINS2WRITE];
5903
0
      pintop = pinbot - upd->int_a[IA_ENDTOP].data[upd->ipass];
5904
0
   } else {
5905
0
      pintop = 0;
5906
0
      pinbot = upd->ints[I_PINS2WRITE];
5907
0
   }
5908
5909
0
   ybegin =  pintop * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
5910
0
   yend   =  pinbot * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
5911
5912
/** Determine Width of this scan */
5913
5914
0
   xbegin = upd->nbytes;
5915
0
   xend   = -1;
5916
5917
0
   for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Pin-testloop */
5918
5919
0
      if(0 > y) continue; /* Inserted Scanlines */
5920
5921
0
      scan = upd->scnbuf[y & upd->scnmsk];
5922
5923
0
      for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Compwise test */
5924
0
         obytes = scan[icomp].bytes;
5925
5926
0
         for(x = 0; x < xbegin && !obytes[x]; x++);
5927
0
         if(x < xbegin) xbegin = x;
5928
5929
0
         if(x < upd->nbytes) {
5930
0
            for(x = upd->nbytes-1; x > xend && !obytes[x]; x--);
5931
0
            if(x > xend) xend = x;
5932
0
         }
5933
0
      }                                             /* Compwise test */
5934
0
   }                                                     /* Pin-testloop */
5935
5936
0
   if(xbegin <= xend) { /* Some data to write */
5937
5938
0
      ioutbuf = 0;
5939
5940
0
      if(0 == upd->strings[S_XMOVE].size) xbegin = 0;
5941
5942
/*
5943
 *    Adjust the Printers Y-Position
5944
 */
5945
0
      if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
5946
0
         if(B_YABS & upd->flags) y = upd->yscan + upd->ints[I_YOFS];
5947
0
         else                    y = upd->yscan - upd->yprinter;
5948
5949
0
         if(      1 < upd->ints[I_YSTEP]) {
5950
0
            n      =  y / upd->ints[I_YSTEP];  /* Major-Steps */
5951
0
            y     -=  n * upd->ints[I_YSTEP];  /* Minor-Steps */
5952
0
         } else if(-1 > upd->ints[I_YSTEP]) {
5953
0
            n      = y * -upd->ints[I_YSTEP];  /* May this work? */
5954
0
            y      = 0;
5955
0
         } else {
5956
0
            n      = y;
5957
0
            y      = 0;
5958
0
         }
5959
5960
0
         if(n) { /* Coarse Positioning */
5961
0
            memcpy(upd->outbuf+ioutbuf,
5962
0
                       upd->strings[S_YMOVE].data,upd->strings[S_YMOVE].size);
5963
0
            ioutbuf += upd->strings[S_YMOVE].size;
5964
5965
0
            upd->outbuf[ioutbuf++] =  n     & 0xff;
5966
0
            upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
5967
5968
0
         }       /* Coarse Positioning */
5969
5970
0
         if(0 < upd->strings[S_YSTEP].size) {
5971
0
            while(y--) {
5972
0
               memcpy(upd->outbuf+ioutbuf,
5973
0
                          upd->strings[S_YSTEP].data,
5974
0
                          upd->strings[S_YSTEP].size);
5975
0
               ioutbuf += upd->strings[S_YSTEP].size;
5976
0
            }
5977
0
         }
5978
5979
0
         upd->yprinter = upd->yscan;
5980
0
      }                                 /* Adjust Y-Position */
5981
/*
5982
 * Now write the required components
5983
 */
5984
5985
/*
5986
*     Select the Component
5987
*
5988
*     Always issue an ESC 'r' 0 - don't know why - that
5989
*     is just what the windows driver does.
5990
*/
5991
0
      icomp=0;
5992
0
      if((0 < upd->string_a[SA_SETCOMP].size) /* &&
5993
0
         (upd->icomp != icomp               )   */) { /* Selection enabled */
5994
0
         upd->icomp = icomp;
5995
0
         if(0 < upd->string_a[SA_SETCOMP].data[icomp].size) {
5996
0
            memcpy(upd->outbuf+ioutbuf,
5997
0
                       upd->string_a[SA_SETCOMP].data[icomp].data,
5998
0
                       upd->string_a[SA_SETCOMP].data[icomp].size);
5999
0
            ioutbuf += upd->string_a[SA_SETCOMP].data[icomp].size;
6000
0
         }
6001
0
      }                                      /* Selection enabled */
6002
/*
6003
*     Establish the X-Position
6004
*/
6005
0
      if(xbegin != upd->xprinter) {
6006
6007
0
         if(0 == upd->strings[S_XMOVE].size) {
6008
6009
0
            upd->outbuf[ioutbuf++] = '\r';
6010
0
            upd->xprinter          =  0;
6011
0
            n = 0;
6012
0
            x = 0;
6013
6014
0
         } else {
6015
6016
0
            if(B_XABS & upd->flags) n = x = xbegin + upd->ints[I_XOFS];
6017
0
            else                    n = x = xbegin - upd->xprinter;
6018
6019
0
            if(        1 < upd->ints[I_XSTEP]) {
6020
0
               if(0 > n) {
6021
0
                  n  -= upd->ints[I_XSTEP];
6022
0
                  x  -= n;
6023
0
               }
6024
0
               if(n) n  /= upd->ints[I_XSTEP]; /* Major-Steps */
6025
0
               if(x) x  %= upd->ints[I_XSTEP]; /* Minor-Steps */
6026
6027
0
            } else if(-1 > upd->ints[I_XSTEP]) {
6028
0
               n *= -upd->ints[I_XSTEP]; /* May this work? */
6029
0
               x  = 0;
6030
0
            }
6031
6032
0
            if(n) { /* Adjust X-Position */
6033
6034
0
              memcpy(upd->outbuf+ioutbuf,
6035
0
                          upd->strings[S_XMOVE].data,
6036
0
                          upd->strings[S_XMOVE].size);
6037
0
               ioutbuf += upd->strings[S_XMOVE].size;
6038
6039
0
               upd->outbuf[ioutbuf++] =  n     & 0xff;
6040
0
               upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
6041
6042
0
            }       /* Adjust X-Position */
6043
6044
0
         }
6045
6046
0
         if(x && 0 < upd->strings[S_XSTEP].size) { /* Fine-Adjust X */
6047
0
            while(x--) {
6048
0
               memcpy(upd->outbuf+ioutbuf,
6049
0
                          upd->strings[S_XSTEP].data,
6050
0
                          upd->strings[S_XSTEP].size);
6051
0
               ioutbuf += upd->strings[S_XSTEP].size;
6052
0
            }
6053
0
         }                                         /* Fine-Adjust X */
6054
0
      }
6055
0
      upd->xprinter = xend+1;
6056
6057
/*
6058
*     Send the Write-Command - the default is ESC '.' 1
6059
*/
6060
0
      if(0 < upd->string_a[SA_WRITECOMP].data[icomp].size) {
6061
0
         memcpy(upd->outbuf+ioutbuf,
6062
0
                    upd->string_a[SA_WRITECOMP].data[icomp].data,
6063
0
                    upd->string_a[SA_WRITECOMP].data[icomp].size);
6064
0
         ioutbuf += upd->string_a[SA_WRITECOMP].data[icomp].size;
6065
0
      }
6066
0
      n = xend + 1 - xbegin;
6067
0
      upd->outbuf[ioutbuf++] = (n<<3) & 255;
6068
0
      upd->outbuf[ioutbuf++] = (n>>5) & 255;
6069
/*
6070
*       Set the Pixels
6071
*/
6072
0
      irow=0; /* row counter for output data */
6073
6074
      /*  pins at the top of the head that don't print */
6075
0
      for(pin = 0; pin < pintop; ++pin) {
6076
0
         int i;
6077
0
         for(i=0 ; i < upd->ints[I_PATRPT]; i++){
6078
0
            if(irow >= upd->ints[I_ROWS]) break;
6079
0
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6080
0
            gp_fwrite(upd->outbuf,1,ioutbuf,out);
6081
0
            irow++;
6082
0
            ioutbuf = 0;
6083
0
         }
6084
0
      }
6085
6086
      /*  I'm not really sure what this does */
6087
      /* it looks like we're filling in empty rows */
6088
0
      for(y = ybegin; 0 > y;    y += upd->ints[I_NYPASS]) {
6089
6090
0
         int i;
6091
0
         for(i=0 ; i < upd->ints[I_PATRPT]; i++){
6092
0
            if(irow >= upd->ints[I_ROWS]) break;
6093
0
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6094
0
            gp_fwrite(upd->outbuf,1,ioutbuf,out);
6095
0
            ioutbuf = 0;
6096
0
            irow++;
6097
0
         }
6098
0
      }
6099
6100
0
      for(; y < yend; y += upd->ints[I_NYPASS]) {
6101
6102
0
         int i,masklen=upd->ints[I_PATRPT],yinc=0;
6103
6104
0
         for(i=0 ; (i < upd->ints[I_PATRPT]); i++){
6105
0
            if(irow >= upd->ints[I_ROWS]) break;
6106
0
            imask = irow%masklen;
6107
0
            icomp = upd->int_a[IA_ROWMASK].data[imask];
6108
0
            if(icomp == 0) {
6109
0
               ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6110
0
            } else {
6111
0
               --icomp;
6112
0
               iyofs = upd->int_a[IA_SCNOFS].data[imask];
6113
0
               ioutbuf += upd_rle(upd->outbuf+ioutbuf,
6114
0
               upd->scnbuf[(y+iyofs) & upd->scnmsk][icomp].bytes+xbegin,n);
6115
0
               yinc+=upd->ints[I_NYPASS];
6116
0
            }
6117
0
            gp_fwrite(upd->outbuf,1,ioutbuf,out);
6118
0
            ioutbuf = 0;
6119
0
            irow++;
6120
0
         }
6121
6122
0
         if (upd->ints[I_NYPASS] < upd->ints[I_PATRPT]) {
6123
0
            y+=yinc;
6124
0
            if (y > 0)
6125
0
               y-=upd->ints[I_NYPASS];
6126
0
         }
6127
0
      }
6128
6129
      /*  I think this is the pins at the bottom of the head that don't print */
6130
0
      for(pin = pinbot; pin < upd->ints[I_PINS2WRITE]; ++pin) {
6131
0
         int i;
6132
0
         for(i=0 ; i < upd->ints[I_PATRPT]; i++){
6133
0
            if(irow >= upd->ints[I_ROWS]) break;
6134
0
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6135
0
            gp_fwrite(upd->outbuf,1,ioutbuf,out);
6136
0
            ioutbuf = 0;
6137
0
            irow++;
6138
0
         }
6139
0
      }
6140
6141
      /* pad empty rows that haven't been filled yet*/
6142
0
       if (irow < upd->ints[I_ROWS]) {
6143
0
         for( ; irow < upd->ints[I_ROWS]; irow++){
6144
0
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6145
0
            gp_fwrite(upd->outbuf,1,ioutbuf,out);
6146
0
            ioutbuf = 0;
6147
0
         }
6148
0
      }
6149
6150
0
   }              /* Some data to write */
6151
6152
/** Advance counters in upd, change modi */
6153
0
   if(upd->yscan < upd->ints[I_BEG_Y]) {
6154
0
      upd->yscan += upd->int_a[IA_BEG_DY].data[upd->ipass++];
6155
0
      if(     upd->ints[I_BEG_Y] <= upd->yscan) upd->ipass = 0;
6156
0
      else if(upd->int_a[IA_BEG_DY].size <= upd->ipass) upd->ipass = 0;
6157
0
   } else if(upd->yscan >= upd->ints[I_END_Y]) {
6158
0
      upd->yscan += upd->int_a[IA_END_DY].data[upd->ipass++];
6159
0
      if(upd->int_a[IA_END_DY].size <= upd->ipass) upd->ipass = 0;
6160
0
   } else {
6161
0
      upd->yscan += upd->int_a[IA_STD_DY].data[upd->ipass++];
6162
0
      if(upd->int_a[IA_STD_DY].size <= upd->ipass) upd->ipass = 0;
6163
0
      if(upd->yscan >= upd->ints[I_END_Y])         upd->ipass = 0;
6164
0
   }
6165
6166
0
   return 0;
6167
0
}
6168
6169
/* ------------------------------------------------------------------- */
6170
/* upd_wrtescp2x: Write an ESC/P2-pass with X-Weaving                  */
6171
/* ------------------------------------------------------------------- */
6172
6173
static int
6174
upd_wrtescp2x(upd_p upd, gp_file *out)
6175
0
{
6176
0
   int  pinbot,pin,pintop,xbegin,x,xend,icomp,ybegin,yend,y,ioutbuf,n,ixpass;
6177
0
   byte *obytes,bit;
6178
0
   updscan_p scan;
6179
6180
/** Determine the number of pins to write */
6181
6182
0
   if(upd->yscan < upd->ints[I_BEG_Y]) {
6183
0
      ixpass = upd->int_a[IA_BEG_IX].data[upd->ipass];
6184
0
      pintop = 0;
6185
0
      pinbot = upd->int_a[IA_BEGBOT].data[upd->ipass];
6186
0
   } else if(upd->yscan >= upd->ints[I_END_Y]) {
6187
0
      ixpass = upd->int_a[IA_END_IX].data[upd->ipass];
6188
0
      pinbot = upd->ints[I_PINS2WRITE];
6189
0
      pintop = pinbot - upd->int_a[IA_ENDTOP].data[upd->ipass];
6190
0
   } else {
6191
0
      ixpass = upd->int_a[IA_STD_IX].data[upd->ipass];
6192
0
      pintop = 0;
6193
0
      pinbot = upd->ints[I_PINS2WRITE];
6194
0
   }
6195
6196
0
   ybegin =  pintop * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
6197
0
   yend   =  pinbot * upd->ints[I_NYPASS] + upd->yscan - upd->ints[I_BEGSKIP];
6198
6199
/** Determine Width of this scan */
6200
6201
0
   xbegin = upd->pwidth;
6202
0
   xend   = -1;
6203
6204
0
   for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Pin-testloop */
6205
6206
0
      if(0 > y) continue; /* Inserted Scanlines */
6207
6208
0
      scan = upd->scnbuf[y & upd->scnmsk];
6209
6210
0
      for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Compwise test */
6211
0
         if(xbegin > scan[icomp].xbegin[ixpass])
6212
0
            xbegin = scan[icomp].xbegin[ixpass];
6213
0
         if(xend   < scan[icomp].xend[  ixpass])
6214
0
            xend   = scan[icomp].xend[  ixpass];
6215
0
      }                                             /* Compwise test */
6216
6217
0
   }                                                     /* Pin-testloop */
6218
6219
0
   if(xbegin <= xend) { /* Some data to write */
6220
6221
0
      ioutbuf = upd->nbytes;
6222
6223
0
      if(0 == upd->strings[S_XMOVE].size) xbegin = ixpass;
6224
6225
/*
6226
 *    Adjust the Printers Y-Position
6227
 */
6228
0
      if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
6229
0
         if(B_YABS & upd->flags) y = upd->yscan + upd->ints[I_YOFS];
6230
0
         else                    y = upd->yscan - upd->yprinter;
6231
6232
0
         if(      1 < upd->ints[I_YSTEP]) {
6233
0
            n      =  y / upd->ints[I_YSTEP];  /* Major-Steps */
6234
0
            y     -=  n * upd->ints[I_YSTEP];  /* Minor-Steps */
6235
0
         } else if(-1 > upd->ints[I_YSTEP]) {
6236
0
            n      = y * -upd->ints[I_YSTEP];  /* May this work? */
6237
0
            y      = 0;
6238
0
         } else {
6239
0
            n      = y;
6240
0
            y      = 0;
6241
0
         }
6242
6243
0
         if(n) { /* Coarse Positioning */
6244
0
            memcpy(upd->outbuf+ioutbuf,
6245
0
                       upd->strings[S_YMOVE].data,upd->strings[S_YMOVE].size);
6246
0
            ioutbuf += upd->strings[S_YMOVE].size;
6247
6248
0
            upd->outbuf[ioutbuf++] =  n     & 0xff;
6249
0
            upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
6250
6251
0
         }       /* Coarse Positioning */
6252
6253
0
         if(0 < upd->strings[S_YSTEP].size) {
6254
0
            while(y--) {
6255
0
               memcpy(upd->outbuf+ioutbuf,
6256
0
                          upd->strings[S_YSTEP].data,
6257
0
                          upd->strings[S_YSTEP].size);
6258
0
               ioutbuf += upd->strings[S_YSTEP].size;
6259
0
            }
6260
0
         }
6261
6262
0
         upd->yprinter = upd->yscan;
6263
0
      }                                 /* Adjust Y-Position */
6264
6265
/*
6266
 * Now write the required components
6267
 */
6268
0
      for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Component-Print */
6269
/*
6270
 *       First check, wether this Component needs printing
6271
 */
6272
0
         for(y = ybegin; y < yend; y += upd->ints[I_NYPASS]) { /* Comp-Test */
6273
0
            if(0 > y) continue;
6274
0
            scan = upd->scnbuf[y & upd->scnmsk]+icomp;
6275
0
            if(0 <= scan->xend[ixpass]) break;
6276
0
         }                                                     /* Comp-Test */
6277
0
         if(y >= yend) continue; /* Component not required */
6278
/*
6279
 *       Select the Component
6280
 */
6281
0
         if((0 < upd->string_a[SA_SETCOMP].size) &&
6282
0
            (upd->icomp != icomp               )   ) { /* Selection enabled */
6283
0
            upd->icomp = icomp;
6284
0
            if(0 < upd->string_a[SA_SETCOMP].data[icomp].size) {
6285
0
               memcpy(upd->outbuf+ioutbuf,
6286
0
                          upd->string_a[SA_SETCOMP].data[icomp].data,
6287
0
                          upd->string_a[SA_SETCOMP].data[icomp].size);
6288
0
               ioutbuf += upd->string_a[SA_SETCOMP].data[icomp].size;
6289
0
            }
6290
0
         }                                      /* Selection enabled */
6291
/*
6292
 *       Establish the X-Position
6293
 */
6294
0
         if(xbegin != upd->xprinter) {
6295
6296
0
            if(0 == upd->strings[S_XMOVE].size) {
6297
6298
0
               upd->outbuf[ioutbuf++] = '\r';
6299
0
               upd->xprinter          =  0;
6300
0
               n = 0;
6301
0
               x = ixpass;
6302
6303
0
            } else {
6304
6305
0
               if(B_XABS & upd->flags) n = x = xbegin + upd->ints[I_XOFS];
6306
0
               else                    n = x = xbegin - upd->xprinter;
6307
6308
0
               if(        1 < upd->ints[I_XSTEP]) {
6309
0
                  if(0 > n) {
6310
0
                     n  -= upd->ints[I_XSTEP];
6311
0
                     x  -= n;
6312
0
                  }
6313
0
                  if(n) n  /= upd->ints[I_XSTEP]; /* Major-Steps */
6314
0
                  if(x) x  %= upd->ints[I_XSTEP]; /* Minor-Steps */
6315
6316
0
               } else if(-1 > upd->ints[I_XSTEP]) {
6317
0
                  n *= -upd->ints[I_XSTEP]; /* May this work? */
6318
0
                  x  = 0;
6319
0
               }
6320
6321
0
               if(n) { /* Adjust X-Position */
6322
6323
0
                 memcpy(upd->outbuf+ioutbuf,
6324
0
                             upd->strings[S_XMOVE].data,
6325
0
                             upd->strings[S_XMOVE].size);
6326
0
                  ioutbuf += upd->strings[S_XMOVE].size;
6327
6328
0
                  upd->outbuf[ioutbuf++] =  n     & 0xff;
6329
0
                  upd->outbuf[ioutbuf++] = (n>>8) & 0xff;
6330
6331
0
               }       /* Adjust X-Position */
6332
6333
0
            }
6334
6335
0
            if(x && 0 < upd->strings[S_XSTEP].size) { /* Fine-Adjust X */
6336
0
               while(x--) {
6337
0
                  memcpy(upd->outbuf+ioutbuf,
6338
0
                             upd->strings[S_XSTEP].data,
6339
0
                             upd->strings[S_XSTEP].size);
6340
0
                  ioutbuf += upd->strings[S_XSTEP].size;
6341
0
               }
6342
0
            }                                         /* Fine-Adjust X */
6343
0
         }
6344
0
         upd->xprinter = xend+1;
6345
6346
/*
6347
 *       Send the Write-Command
6348
 */
6349
0
         if(0 < upd->string_a[SA_WRITECOMP].data[icomp].size) {
6350
0
            memcpy(upd->outbuf+ioutbuf,
6351
0
                       upd->string_a[SA_WRITECOMP].data[icomp].data,
6352
0
                       upd->string_a[SA_WRITECOMP].data[icomp].size);
6353
0
            ioutbuf += upd->string_a[SA_WRITECOMP].data[icomp].size;
6354
0
         }
6355
0
         n = ((xend - xbegin) / upd->ints[I_NXPASS] + 8) & ~7;
6356
0
         upd->outbuf[ioutbuf++] =  n     & 255;
6357
0
         upd->outbuf[ioutbuf++] = (n>>8) & 255;
6358
0
         n >>= 3;
6359
/*
6360
 *       Set the Pixels
6361
 */
6362
0
         for(pin = 0; pin < pintop; ++pin) {
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 = ybegin; 0 > y;    y += upd->ints[I_NYPASS]) {
6369
0
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6370
0
            gp_fwrite(upd->outbuf+upd->nbytes,1,ioutbuf-upd->nbytes,out);
6371
0
            ioutbuf = upd->nbytes;
6372
0
         }
6373
6374
0
         for(;           y < yend; y += upd->ints[I_NYPASS]) {
6375
0
            byte * ibytes = upd->scnbuf[y & upd->scnmsk][icomp].bytes;
6376
0
            obytes = upd->outbuf;
6377
0
            memset(obytes,0,upd->nbytes);
6378
0
            bit = 0x80;
6379
0
            for(x = xbegin; x <= xend; x += upd->ints[I_NXPASS]) {
6380
0
               if(ibytes[x>>3] & (0x80 >> (x & 7))) *obytes |= bit;
6381
0
               if(!(bit >>= 1)) { obytes++; bit = 0x80; }
6382
0
            }
6383
0
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,upd->outbuf,n);
6384
0
            gp_fwrite(upd->outbuf+upd->nbytes,1,ioutbuf-upd->nbytes,out);
6385
0
            ioutbuf = upd->nbytes;
6386
0
         }
6387
6388
0
         for(pin = pinbot; pin < upd->ints[I_PINS2WRITE]; ++pin) {
6389
0
            ioutbuf += upd_rle(upd->outbuf+ioutbuf,NULL,n);
6390
0
            gp_fwrite(upd->outbuf+upd->nbytes,1,ioutbuf-upd->nbytes,out);
6391
0
            ioutbuf = upd->nbytes;
6392
0
         }
6393
0
      }                                             /* Component-Print */
6394
0
   }                    /* Some data to write */
6395
6396
/** Advance counters in upd, change modi */
6397
6398
0
   if(upd->yscan < upd->ints[I_BEG_Y]) {
6399
0
      upd->yscan += upd->int_a[IA_BEG_DY].data[upd->ipass++];
6400
0
      if(     upd->ints[I_BEG_Y] <= upd->yscan) upd->ipass = 0;
6401
0
      else if(upd->int_a[IA_BEG_DY].size <= upd->ipass) upd->ipass = 0;
6402
0
   } else if(upd->yscan >= upd->ints[I_END_Y]) {
6403
0
      upd->yscan += upd->int_a[IA_END_DY].data[upd->ipass++];
6404
0
      if(upd->int_a[IA_END_DY].size <= upd->ipass) upd->ipass = 0;
6405
0
   } else {
6406
0
      upd->yscan += upd->int_a[IA_STD_DY].data[upd->ipass++];
6407
0
      if(upd->int_a[IA_STD_DY].size <= upd->ipass) upd->ipass = 0;
6408
0
      if(upd->yscan >= upd->ints[I_END_Y])         upd->ipass = 0;
6409
0
   }
6410
6411
0
   return 0;
6412
0
}
6413
6414
/* ------------------------------------------------------------------- */
6415
/* upd_rle: The Runlength-Compressor                                   */
6416
/* ------------------------------------------------------------------- */
6417
6418
static int
6419
upd_rle(byte *out,const byte *in,int nbytes)
6420
0
{
6421
6422
0
   int used = 0;
6423
0
   int crun,cdata;
6424
0
   byte run;
6425
6426
0
   if(in != NULL) { /* Data present */
6427
6428
0
      crun = 1;
6429
6430
0
      while(nbytes > 0) { /* something to compress */
6431
6432
0
         run = in[0];
6433
6434
0
         while((nbytes > crun) && (run == in[crun])) if(++crun == 128) break;
6435
6436
0
         if((crun > 2) || (crun == nbytes)) { /* use this run */
6437
6438
0
            *out++  = (257 - crun) & 0xff; *out++ = run; used += 2;
6439
6440
0
            nbytes -= crun; in    += crun;
6441
0
            crun = 1;
6442
6443
0
         } else {                            /* ignore this run */
6444
6445
0
            for(cdata = crun; (nbytes > cdata) && (crun < 4);) {
6446
0
               if(run  == in[cdata]) crun += 1;
6447
0
               else run = in[cdata], crun  = 1;
6448
0
               if(++cdata == 128) break;
6449
0
            }
6450
6451
0
            if(crun < 3) crun   = 0;    /* ignore trailing run */
6452
0
            else         cdata -= crun;
6453
6454
0
            *out++ = cdata-1;     used++;
6455
0
            memcpy(out,in,cdata); used += cdata; out   += cdata;
6456
6457
0
            nbytes -= cdata; in    += cdata;
6458
6459
0
         }              /* use/ignore run */
6460
6461
0
      }                  /* something to compress */
6462
6463
0
   } else {         /* Empty scans to fill bands */
6464
6465
0
      while(nbytes > 0) {
6466
0
         crun    = nbytes > 128 ? 128 : nbytes;
6467
0
         nbytes -= crun;
6468
0
         *out++  = (257 - crun) & 0xff;
6469
0
         *out++  = 0;
6470
0
         used   += 2;
6471
0
      }
6472
0
   }                /* Data present or empty */
6473
0
   return used;
6474
0
}
6475
6476
/* ------------------------------------------------------------------- */
6477
/* upd_open_wrtrtl: Basic HP-RTL Writer                                */
6478
/* ------------------------------------------------------------------- */
6479
6480
static int
6481
upd_open_wrtrtl(upd_device *udev)
6482
0
{
6483
0
   const upd_p      upd  = udev->upd;
6484
0
   int              error = 0;
6485
6486
/** Adjust the Raster-Width */
6487
6488
0
   if(0 < upd->strings[S_BEGIN].size) { /* BOP-Checker */
6489
6490
0
     int   i,j,state;
6491
0
     char  cv[24];
6492
0
     byte  *bp;
6493
0
     uint  ncv,nbp;
6494
6495
0
     j     = -1;
6496
0
     state = 0;
6497
0
     for(i = 0; i < upd->strings[S_BEGIN].size; ++i) {
6498
0
       const int c = upd->strings[S_BEGIN].data[i];
6499
6500
0
       switch(state) {
6501
/* ----- any character */
6502
0
         case  0:
6503
0
           if(        c == 0x1b) state =  1; /* ESC */
6504
0
         break;
6505
6506
/* ----- last was ESC */
6507
0
         case  1:
6508
0
           if(        c == 0x2a) state =  2; /* ESC * */
6509
0
           else if(   c == 0x25) state =  5; /* ESC % */
6510
0
           else                  state =  0;
6511
0
         break;
6512
6513
/* ----- got ESC * */
6514
0
         case  2:
6515
0
           j = i; /* This character is not part of the replaced text */
6516
0
           if(        c == 0x72) state =  3; /* ESC * r */
6517
0
           else if(   c == 0x74) state =  4; /* ESC * t */
6518
0
           else                  state =  0;
6519
0
         break;
6520
6521
/* ----- got ESC * r */
6522
/*         Pagewidth and Pagelength might be replaced */
6523
0
         case  3:
6524
6525
0
           if(       (B_PAGEWIDTH  & upd->flags) &&
6526
0
                     ((c == 0x73) || (c == 0x53))  ) { /* esc * r # S */
6527
6528
0
             gs_snprintf(cv,sizeof(cv),"%d",upd->pwidth);
6529
0
             ncv = strlen(cv);
6530
6531
0
             nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6532
0
             UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6533
6534
0
             if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6535
0
             memcpy(bp+j+1,    cv,ncv);
6536
0
             memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6537
0
                               upd->strings[S_BEGIN].size-i);
6538
0
             i = j+1+ncv;
6539
0
             UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6540
0
             upd->strings[S_BEGIN].data = bp;
6541
0
             upd->strings[S_BEGIN].size = nbp;
6542
6543
0
           } else if((B_PAGELENGTH & upd->flags) &&
6544
0
                     ((c == 0x74) || (c == 0x54))  ) { /* esc * r # T */
6545
6546
0
             gs_snprintf(cv,sizeof(cv),"%d",upd->pheight);
6547
0
             ncv = strlen(cv);
6548
6549
0
             nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6550
0
             UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6551
6552
0
             if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6553
0
             memcpy(bp+j+1,    cv,ncv);
6554
0
             memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6555
0
                               upd->strings[S_BEGIN].size-i);
6556
0
             i = j+1+ncv;
6557
0
             UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6558
0
             upd->strings[S_BEGIN].data = bp;
6559
0
             upd->strings[S_BEGIN].size = nbp;
6560
6561
0
           }
6562
6563
0
           if(       (0x40 < c) && (c < 0x5b))  state = 0; /* Term. cmd. */
6564
0
           else if(!((0x2f < c) && (c < 0x3a))) j     = i; /* Non-Number */
6565
6566
0
         break;
6567
6568
/* ----- got ESC * t */
6569
/*         Resolution might be replaced */
6570
0
         case  4: /* esc * t */
6571
6572
0
           if(        (B_RESOLUTION  & upd->flags) &&
6573
0
                     ((c == 0x72) || (c == 0x52))  ) { /* esc * t # R */
6574
6575
0
             gs_snprintf(cv,sizeof(cv),"%d",(int)
6576
0
               ((udev->y_pixels_per_inch < udev->x_pixels_per_inch ?
6577
0
                 udev->x_pixels_per_inch : udev->y_pixels_per_inch)
6578
0
               +0.5));
6579
0
             ncv = strlen(cv);
6580
6581
0
             nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6582
0
             UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6583
6584
0
             if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6585
0
             memcpy(bp+j+1,    cv,ncv);
6586
0
             memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6587
0
                               upd->strings[S_BEGIN].size-i);
6588
0
             i = j+1+ncv;
6589
0
             UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6590
0
             upd->strings[S_BEGIN].data = bp;
6591
0
             upd->strings[S_BEGIN].size = nbp;
6592
6593
0
           }
6594
6595
0
           if(       (0x40 < c) && (c < 0x5b))  state = 0; /* Term. cmd. */
6596
0
           else if(!((0x2f < c) && (c < 0x3a))) j     = i; /* Non-Number */
6597
6598
0
         break;
6599
6600
0
         case  5: /* ESC % - 1 2 3 4 5 X */
6601
0
           if( c == 0x2d) state =  6; /* ESC % - */
6602
0
           else           state =  0;
6603
0
         break;
6604
6605
0
         case  6: /* ESC %  - 1 2 3 4 5 X */
6606
0
           if( c == 0x31) state =  7; /* ESC % - 1 */
6607
0
           else           state =  0;
6608
0
         break;
6609
6610
0
         case  7: /* ESC %  - 1 2 3 4 5 X */
6611
0
           if( c == 0x32) state =  8; /* ESC % - 1 2 */
6612
0
           else           state =  0;
6613
0
         break;
6614
6615
0
         case  8: /* ESC %  - 1 2 3 4 5 X */
6616
0
           if( c == 0x33) state =  9; /* ESC % - 1 2 3 */
6617
0
           else           state =  0;
6618
0
         break;
6619
6620
0
         case  9: /* ESC %  - 1 2 3 4 5 X */
6621
0
           if( c == 0x34) state = 10; /* ESC % - 1 2 3 4 */
6622
0
           else           state =  0;
6623
0
         break;
6624
6625
0
         case 10: /* ESC %  - 1 2 3 4 5 X */
6626
0
           if( c == 0x35) state = 11; /* ESC % - 1 2 3 4 5 */
6627
0
           else           state =  0;
6628
0
         break;
6629
6630
0
         case 11: /* ESC %  - 1 2 3 4 5 X */
6631
0
           if( c == 0x58) state = 12; /* ESC % - 1 2 3 4 5 X */
6632
0
           else           state =  0;
6633
0
         break;
6634
6635
0
         case 12: /* PJL-BOL:  @ P J L ws */
6636
0
           if( c == 0x40) state = 13; /* @ */
6637
0
           else           state =  0;
6638
0
         break;
6639
6640
0
         case 13: /* PJL-BOL  @ P J L ws */
6641
0
           if( c == 0x50) state = 14; /* @ P */
6642
0
           else           state =  0;
6643
0
         break;
6644
6645
0
         case 14: /* PJL-BOL  @ P J L ws */
6646
0
           if( c == 0x4a) state = 15; /* @ P J */
6647
0
           else           state =  0;
6648
0
         break;
6649
6650
0
         case 15: /* PJL-BOL  @ P J L ws */
6651
0
           if( c == 0x4c) state = 16; /* @ P J L */
6652
0
           else           state =  0;
6653
0
         break;
6654
6655
0
         case 16: /* PJL-BOL  @ P J L ws */
6656
0
           if((c == 0x20) || (c == 0x09)) state = 19; /* @ P J L ws */
6657
0
           else if(           c == 0x0d ) state = 17;
6658
0
           else if(           c == 0x0a ) state = 12;
6659
0
           else                           state =  0; /* PJL-Error */
6660
0
         break;
6661
6662
0
         case 17: /* PJL-EOL  */
6663
0
           if( c == 0x0a) state = 12; /* Next PJL-Command */
6664
0
           else           state =  0; /* PJL-Error */
6665
0
         break;
6666
6667
0
         case 18: /* PJL-Eatup: Expect Newline */
6668
0
           if( c == 0x0a) state = 12;
6669
0
         break;
6670
6671
0
         case 19: /* Begin of PJL-Command */
6672
0
           if(     (c == 0x53) || (c == 0x73)) state = 20; /* S E T*/
6673
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6674
0
           else if( c == 0x0d                ) state = 17;
6675
0
         break;
6676
6677
0
         case 20: /* PJL-Set: S E T  */
6678
0
           if(     (c == 0x45) || (c == 0x65)) state = 21; /* S E */
6679
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6680
0
           else                                state = 18;
6681
0
         break;
6682
6683
0
         case 21: /* PJL-Set: S E T  */
6684
0
           if(     (c == 0x54) || (c == 0x74)) state = 22; /* S E T */
6685
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6686
0
           else                                state = 18;
6687
0
         break;
6688
6689
0
         case 22: /* PJL-Set: S E T ws  */
6690
0
           if(     (c == 0x20) || (c == 0x09)) state = 23; /* S E T ws */
6691
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6692
0
           else                                state = 18;
6693
0
         break;
6694
6695
0
         case 23: /* PJL-Set: S E T ws  */
6696
0
           if(     (c == 0x50) || (c == 0x70)) state = 24; /* set paper... */
6697
0
           else if((c == 0x52) || (c == 0x72)) state = 41; /* set resolution */
6698
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6699
0
           else                                state = 18;
6700
0
         break;
6701
6702
0
         case 24: /* PJL-Set: set paper...  */
6703
0
           if(     (c == 0x41) || (c == 0x61)) state = 25; /* set pa */
6704
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6705
0
           else                                state = 18;
6706
0
         break;
6707
6708
0
         case 25: /* PJL-Set: set paper...  */
6709
0
           if(     (c == 0x50) || (c == 0x70)) state = 26; /* set pap */
6710
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6711
0
           else                                state = 18;
6712
0
         break;
6713
6714
0
         case 26: /* PJL-Set: set paper...  */
6715
0
           if(     (c == 0x45) || (c == 0x65)) state = 27; /* set pape */
6716
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6717
0
           else                                state = 18;
6718
0
         break;
6719
6720
0
         case 27: /* PJL-Set: set paper...  */
6721
0
           if(     (c == 0x52) || (c == 0x72)) state = 28; /* set paper */
6722
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6723
0
           else                                state = 18;
6724
0
         break;
6725
6726
0
         case 28: /* PJL-Set: set paper?  */
6727
0
           if(     (c == 0x4c) || (c == 0x6c)) state = 29; /* set paperlength */
6728
0
           else if((c == 0x57) || (c == 0x77)) state = 36; /* set paperwidth */
6729
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6730
0
           else                                state = 18;
6731
0
         break;
6732
6733
0
         case 29: /* PJL: set paperlength  */
6734
0
           if(     (c == 0x45) || (c == 0x65)) state = 30; /* set paperle */
6735
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6736
0
           else                                state = 18;
6737
0
         break;
6738
6739
0
         case 30: /* PJL: set paperlength  */
6740
0
           if(     (c == 0x4e) || (c == 0x6e)) state = 31; /* set paperlen */
6741
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6742
0
           else                                state = 18;
6743
0
         break;
6744
6745
0
         case 31: /* PJL: set paperlength  */
6746
0
           if(     (c == 0x47) || (c == 0x67)) state = 32; /* set paperleng */
6747
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6748
0
           else                                state = 18;
6749
0
         break;
6750
6751
0
         case 32: /* PJL: set paperlength  */
6752
0
           if(     (c == 0x54) || (c == 0x74)) state = 33; /* set paperlengt */
6753
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6754
0
           else                                state = 18;
6755
0
         break;
6756
6757
0
         case 33: /* PJL: set paperlength  */
6758
0
           if(     (c == 0x48) || (c == 0x68)) state = 34; /* set paperlength */
6759
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6760
0
           else                                state = 18;
6761
0
         break;
6762
6763
0
         case 34: /* PJL: set paperlength  */
6764
0
           j = i; /* This character is not part of the replaced text */
6765
0
           if(      c == 0x3d                ) state = 51; /* set paperlength */
6766
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6767
0
           else if((c != 0x20) && (c != 0x09)) state = 18;
6768
0
         break;
6769
6770
0
         case 51: /* PJL: set paperlength = ws */
6771
0
           if(     c == 0x0a)                  state = 12;
6772
0
           else if((c == 0x20) || (c == 0x09)) j     = i;
6773
0
           else if(( 0x30 > c) || ( c > 0x39)) state = 18;
6774
0
           else                                state = 35;
6775
0
         break;
6776
6777
0
         case 35: /* PJL: set paperlength */
6778
0
           if((0x30 > c) || (c > 0x39)) { /* End of number */
6779
6780
0
             if(B_PAGELENGTH  & upd->flags) { /* insert new number */
6781
6782
0
               gs_snprintf(cv,sizeof(cv),"%d",(int)
6783
0
                 (720.0 * udev->height / udev->y_pixels_per_inch + 0.5));
6784
0
               ncv = strlen(cv);
6785
6786
0
               nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6787
0
               UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6788
6789
0
               if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6790
0
               memcpy(bp+j+1,    cv,ncv);
6791
0
               memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6792
0
                               upd->strings[S_BEGIN].size-i);
6793
0
               i = j+1+ncv;
6794
0
               UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6795
0
               upd->strings[S_BEGIN].data = bp;
6796
0
               upd->strings[S_BEGIN].size = nbp;
6797
0
             }                                /* insert new number */
6798
6799
0
             if( c == 0x0a ) state = 12;
6800
0
             else            state = 18;
6801
0
           }
6802
0
         break;
6803
6804
0
         case 36: /* PJL: set paperwidth  */
6805
0
           if(     (c == 0x49) || (c == 0x69)) state = 37; /* set paperwi */
6806
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6807
0
           else                                state = 18;
6808
0
         break;
6809
6810
0
         case 37: /* PJL: set paperwidth */
6811
0
           if(     (c == 0x44) || (c == 0x64)) state = 38; /* set paperwid */
6812
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6813
0
           else                                state = 18;
6814
0
         break;
6815
6816
0
         case 38: /* PJL: set paperwidth  */
6817
0
           if(     (c == 0x54) || (c == 0x74)) state = 39; /* set paperwidt */
6818
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6819
0
           else                                state = 18;
6820
0
         break;
6821
6822
0
         case 39: /* PJL: set paperwidth  */
6823
0
           if(     (c == 0x48) || (c == 0x68)) state = 52; /* set paperwidth */
6824
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6825
0
           else                                state = 18;
6826
0
         break;
6827
6828
0
         case 52: /* PJL: set paperwidth  */
6829
0
           j = i; /* This character is not part of the replaced text */
6830
0
           if(      c == 0x3d                ) state = 53; /* set paperwidth */
6831
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6832
0
           else if((c != 0x20) && (c != 0x09)) state = 18;
6833
0
         break;
6834
6835
0
         case 53: /* PJL: set paperwidth = ws */
6836
0
           if(     c == 0x0a)                  state = 12;
6837
0
           else if((c == 0x20) || (c == 0x09)) j     = i;
6838
0
           else if(( 0x30 > c) || ( c > 0x39)) state = 18;
6839
0
           else                                state = 40;
6840
0
         break;
6841
6842
0
         case 40: /* PJL: set paperlength */
6843
0
           if((0x30 > c) || (c > 0x39)) { /* End of number */
6844
6845
0
             if(B_PAGEWIDTH  & upd->flags) { /* insert new number */
6846
6847
0
               gs_snprintf(cv,sizeof(cv),"%d",(int)
6848
0
                 (720.0 * udev->width / udev->x_pixels_per_inch + 0.5));
6849
0
               ncv = strlen(cv);
6850
6851
0
               nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6852
0
               UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6853
6854
0
               if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6855
0
               memcpy(bp+j+1,    cv,ncv);
6856
0
               memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6857
0
                               upd->strings[S_BEGIN].size-i);
6858
0
               i = j+1+ncv;
6859
0
               UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6860
0
               upd->strings[S_BEGIN].data = bp;
6861
0
               upd->strings[S_BEGIN].size = nbp;
6862
0
             }                                /* insert new number */
6863
6864
0
             if( c == 0x0a ) state = 12;
6865
0
             else            state = 18;
6866
0
           }
6867
0
         break;
6868
6869
0
         case 41: /* PJL: set resolution */
6870
0
           if(     (c == 0x45) || (c == 0x65)) state = 42; /* set re */
6871
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6872
0
           else                                state = 18;
6873
0
         break;
6874
6875
0
         case 42: /* PJL: set resolution */
6876
0
           if(     (c == 0x53) || (c == 0x73)) state = 43; /* set res */
6877
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6878
0
           else                                state = 18;
6879
0
         break;
6880
6881
0
         case 43: /* PJL: set resolution */
6882
0
           if(     (c == 0x4f) || (c == 0x6f)) state = 44; /* set reso */
6883
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6884
0
           else                                state = 18;
6885
0
         break;
6886
6887
0
         case 44: /* PJL: set resolution */
6888
0
           if(     (c == 0x4c) || (c == 0x6c)) state = 45; /* set resol */
6889
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6890
0
           else                                state = 18;
6891
0
         break;
6892
6893
0
         case 45: /* PJL: set resolution */
6894
0
           if(     (c == 0x55) || (c == 0x75)) state = 46; /* set resolu */
6895
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6896
0
           else                                state = 18;
6897
0
         break;
6898
6899
0
         case 46: /* PJL: set resolution */
6900
0
           if(     (c == 0x54) || (c == 0x74)) state = 47; /* set resolut */
6901
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6902
0
           else                                state = 18;
6903
0
         break;
6904
6905
0
         case 47: /* PJL: set resolution */
6906
0
           if(     (c == 0x49) || (c == 0x69)) state = 48; /* set resoluti */
6907
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6908
0
           else                                state = 18;
6909
0
         break;
6910
6911
0
         case 48: /* PJL: set resolution */
6912
0
           if(     (c == 0x4f) || (c == 0x6f)) state = 49; /* set resolutio */
6913
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6914
0
           else                                state = 18;
6915
0
         break;
6916
6917
0
         case 49: /* PJL: set resolution */
6918
0
           if(     (c == 0x4e) || (c == 0x6e)) state = 54; /* set resolution */
6919
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6920
0
           else                                state = 18;
6921
0
         break;
6922
6923
0
         case 54: /* PJL: set resolution  */
6924
0
           j = i; /* This character is not part of the replaced text */
6925
0
           if(      c == 0x3d                ) state = 55; /* set resolution */
6926
0
           else if( c == 0x0a                ) state = 12; /* BOL */
6927
0
           else if((c != 0x20) && (c != 0x09)) state = 18;
6928
0
         break;
6929
6930
0
         case 55: /* PJL: set resolution = ws */
6931
0
           if(     c == 0x0a)                  state = 12;
6932
0
           else if((c == 0x20) || (c == 0x09)) j     = i;
6933
0
           else if(( 0x30 > c) || ( c > 0x39)) state = 18;
6934
0
           else                                state = 50;
6935
0
         break;
6936
6937
0
         case 50: /* PJL: set resolution */
6938
0
           if((0x30 > c) || (c > 0x39)) { /* End of number */
6939
6940
0
             if(B_RESOLUTION  & upd->flags) { /* insert new number */
6941
6942
0
               gs_snprintf(cv,sizeof(cv),"%d",(int)
6943
0
                 ((udev->y_pixels_per_inch < udev->x_pixels_per_inch ?
6944
0
                   udev->x_pixels_per_inch : udev->y_pixels_per_inch)
6945
0
                 +0.5));
6946
0
               ncv = strlen(cv);
6947
6948
0
               nbp = (j+1) + ncv + (upd->strings[S_BEGIN].size-i);
6949
0
               UPD_MM_GET_ARRAY(udev->memory, bp,nbp);
6950
6951
0
               if(0 <= j) memcpy(bp,upd->strings[S_BEGIN].data,j+1);
6952
0
               memcpy(bp+j+1,    cv,ncv);
6953
0
               memcpy(bp+j+1+ncv,upd->strings[S_BEGIN].data+i,
6954
0
                               upd->strings[S_BEGIN].size-i);
6955
0
               i = j+1+ncv;
6956
0
               UPD_MM_DEL_PARAM(udev->memory, upd->strings[S_BEGIN]);
6957
0
               upd->strings[S_BEGIN].data = bp;
6958
0
               upd->strings[S_BEGIN].size = nbp;
6959
0
             }                                /* insert new number */
6960
6961
0
             if( c == 0x0a ) state = 12;
6962
0
             else            state = 18;
6963
0
           }
6964
0
         break;
6965
6966
0
         default:
6967
0
#if UPD_MESSAGES & UPD_M_ERROR
6968
0
           errprintf(udev->memory,
6969
0
                     "UNIPRINT-Coding error, wrrtl, state = %d\n",state);
6970
0
#endif
6971
0
           state = 0;
6972
0
         break;
6973
0
       }
6974
0
     }
6975
0
   }                                    /* BOP-Checker */
6976
6977
/** SA_WRITECOMP must be valid */
6978
0
   if(upd->ocomp > upd->string_a[SA_WRITECOMP].size) {
6979
#if UPD_MESSAGES & UPD_M_WARNING
6980
      errprintf(udev->memory,
6981
         "PCL-Open: WRITECOMP-Commands must be given\n");
6982
#endif
6983
0
      error = -1;
6984
0
   }
6985
6986
/**
6987
If all this is correct, it's time to compute the size of the output-buffer.
6988
It must hold:
6989
  1. Y-Positioning
6990
  2. Component-Data
6991
*/
6992
0
   if(0 <= error) {
6993
0
      int32_t ny,noutbuf;
6994
0
      char  tmp[16];
6995
6996
0
      if(0 < upd->strings[S_YMOVE].size) {
6997
0
         gs_snprintf(tmp,sizeof(tmp),"%d",upd->pheight);
6998
0
         ny = upd->strings[S_YMOVE].size + strlen(tmp);
6999
0
      } else {
7000
0
         ny = 1 + upd->string_a[SA_WRITECOMP].data[upd->ocomp-1].size;
7001
0
         ny *= upd->pheight;
7002
0
      }
7003
7004
0
      noutbuf = upd->nbytes + (upd->nbytes + 127) / 128;
7005
7006
0
      if(ny > noutbuf) noutbuf = ny;
7007
0
      noutbuf += 16;
7008
7009
0
      if(noutbuf > 0) {
7010
0
         upd->noutbuf      = noutbuf;
7011
0
         upd->writer       = upd_wrtrtl;
7012
0
         error             = 1;
7013
0
      } else {
7014
0
         error = -1;
7015
#if      UPD_MESSAGES & UPD_M_WARNING
7016
            errprintf(udev->memory,
7017
              "PCL-Open: %ld is unreasonable size of Outputbuffer\n",
7018
              (long) noutbuf);
7019
#endif
7020
0
      }
7021
0
   }
7022
7023
0
   return error;
7024
0
}
7025
7026
/* ------------------------------------------------------------------- */
7027
/* upd_wrtrtl: Write a pass                                            */
7028
/* ------------------------------------------------------------------- */
7029
7030
static int
7031
upd_wrtrtl(upd_p upd, gp_file *out)
7032
0
{
7033
0
   const updscan_p scan = upd->scnbuf[upd->yscan & upd->scnmsk];
7034
7035
0
   int  x,xend,icomp,ioutbuf;
7036
0
   byte *data;
7037
7038
/** Determine Width of this scan */
7039
7040
0
   xend   = -1;
7041
0
   for(icomp = 0; icomp < upd->ocomp; ++icomp) {
7042
7043
0
      data = scan[icomp].bytes;
7044
7045
0
      for(x = upd->nbytes-1; 0 <= x; --x) if(data[x]) break;
7046
0
      if(x > xend) xend  = x;
7047
0
   }
7048
7049
0
   if(0 <= xend) { /* Some data to write */
7050
7051
0
      ioutbuf = 0;
7052
0
      xend   += 1;
7053
/*
7054
 *    Adjust the Printers Y-Position
7055
 */
7056
0
      if(upd->yscan != upd->yprinter) { /* Adjust Y-Position */
7057
0
         if(1 < upd->strings[S_YMOVE].size) {
7058
0
           gs_snprintf((char *)upd->outbuf+ioutbuf, upd->noutbuf-ioutbuf,
7059
0
             (const char *) upd->strings[S_YMOVE].data,
7060
0
             upd->yscan - upd->yprinter);
7061
0
           ioutbuf += strlen((char *)upd->outbuf+ioutbuf);
7062
0
         } else {
7063
0
           while(upd->yscan > upd->yprinter) {
7064
0
             for(icomp = 0; icomp < upd->ocomp; ++icomp) {
7065
0
               gs_snprintf((char *)upd->outbuf+ioutbuf, upd->noutbuf-ioutbuf,
7066
0
                 (const char *) upd->string_a[SA_WRITECOMP].data[icomp].data,0);
7067
0
               ioutbuf += strlen((char *)upd->outbuf+ioutbuf);
7068
0
             }
7069
0
             gp_fwrite(upd->outbuf,1,ioutbuf,out);
7070
0
             ioutbuf = 0;
7071
0
             upd->yprinter += 1;
7072
0
           }
7073
0
         }
7074
0
         upd->yprinter = upd->yscan;
7075
0
         gp_fwrite(upd->outbuf,1,ioutbuf,out);
7076
0
         ioutbuf = 0;
7077
0
      }                                 /* Adjust Y-Position */
7078
/*
7079
 * Now write the all! components
7080
 */
7081
0
      for(icomp = 0; icomp < upd->ocomp; ++icomp) { /* Component-Print */
7082
0
         data = scan[icomp].bytes;
7083
0
         for(x = 0; x <= xend; ++x) if(data[x]) break;
7084
0
         if(x <= xend) {
7085
0
           ioutbuf = upd_rle(upd->outbuf,scan[icomp].bytes,xend);
7086
0
           gp_fprintf(out,
7087
0
            (const char *)upd->string_a[SA_WRITECOMP].data[icomp].data,ioutbuf);
7088
0
           gp_fwrite(upd->outbuf,1,ioutbuf,out);
7089
0
         } else {
7090
0
           gp_fprintf(out,
7091
0
             (const char *)upd->string_a[SA_WRITECOMP].data[icomp].data,0);
7092
0
         }
7093
0
      }
7094
7095
0
      upd->yprinter += 1;
7096
7097
0
   }                    /* Some data to write */
7098
7099
/** Advance scan by one */
7100
7101
0
   upd->yscan += 1;
7102
7103
0
   return 0;
7104
0
}
7105
7106
/* ------------------------------------------------------------------- */
7107
/* upd_open_wrtcanon: Basic Canon Extended Mode Writer (hr)            */
7108
/* ------------------------------------------------------------------- */
7109
7110
static int
7111
upd_open_wrtcanon(upd_device *udev)
7112
0
{
7113
0
  const upd_p upd = udev->upd;
7114
0
  int error = 0;
7115
7116
  /* max length of one printer line */
7117
0
  upd->noutbuf = upd->nbytes + (upd->nbytes + 127) / 128;
7118
0
  upd->writer  = upd_wrtcanon;
7119
0
  error        = 1;
7120
7121
0
  return error;
7122
0
}
7123
7124
/* ------------------------------------------------------------------- */
7125
/* upd_wrtcanon: Write a pass (hr)                                     */
7126
/* ------------------------------------------------------------------- */
7127
7128
0
#define LOW(b)     ((b)&0xFF)
7129
0
#define HIGH(b)    ((b)>>8)
7130
0
#define ESC 0x1B
7131
0
#define CR  0x0D
7132
7133
static int
7134
upd_wrtcanon(upd_p upd, gp_file *out)
7135
0
{
7136
0
  const updscan_p scan = upd->scnbuf[upd->yscan & upd->scnmsk];
7137
7138
0
  int x, xend, icomp, ioutbuf, step, ioutbuf1;
7139
0
  byte *data;
7140
7141
  /* Check length of the printable date */
7142
0
  xend = -1;
7143
0
  for(icomp = 0; icomp < upd->ocomp; ++icomp) {
7144
0
    data = scan[icomp].bytes;
7145
7146
0
    for(x = upd->nbytes-1; 0 <= x; --x) if(data[x]) break;
7147
7148
0
    if(x > xend) xend  = x;
7149
0
  }
7150
7151
  /* If some date to print */
7152
0
  if(0 <= xend) { /* Some data to write */
7153
0
    ioutbuf = 0;
7154
0
    xend   += 1;
7155
7156
    /* Perform vertical tab */
7157
0
    if(upd->yscan != upd->yprinter) {
7158
0
      step = upd->yscan - upd->yprinter;
7159
7160
0
      gp_fputc(ESC,        out);
7161
0
      gp_fputc('(',        out);
7162
0
      gp_fputc('e',        out);
7163
0
      gp_fputc(2,          out);
7164
0
      gp_fputc(0,          out);
7165
0
      gp_fputc(HIGH(step), out);
7166
0
      gp_fputc(LOW(step),  out);
7167
7168
0
      upd->yprinter = upd->yscan;
7169
0
    }
7170
7171
0
    for(icomp = 0; icomp < upd->ocomp; ++icomp) {
7172
7173
      /* Are there date to print for the selected color component */
7174
0
      data = scan[icomp].bytes;
7175
0
      for(x = 0; x <= xend; ++x) if(data[x]) break;
7176
7177
      /* Compressing of the scan line */
7178
0
      if(x <= xend) {
7179
0
        ioutbuf = upd_rle(upd->outbuf, scan[icomp].bytes, xend);
7180
0
      } else {
7181
0
        ioutbuf = 0;
7182
0
      }
7183
7184
0
      ioutbuf1 = ioutbuf + 1;
7185
7186
      /* prints the scan line */
7187
0
      gp_fputc(ESC,            out);
7188
0
      gp_fputc('(',            out);
7189
0
      gp_fputc('A',            out);
7190
0
      gp_fputc(LOW(ioutbuf1),  out);
7191
0
      gp_fputc(HIGH(ioutbuf1), out);
7192
0
      switch(upd->ocomp) {
7193
0
        case 1:  gp_fputc('K',out); break;
7194
0
        case 3:
7195
0
        case 4:  gp_fputc("YMCK"[icomp],out); break;
7196
/*
7197
 *      Please Note:
7198
 *         the validity of the NCOMP-setting should be checked
7199
 *         in the put_params-routine, thus the default-case is
7200
 *         just a matter of coding-style.
7201
 */
7202
0
        default: gp_fputc('K',out); break;
7203
0
      }
7204
7205
0
      gp_fwrite(upd->outbuf, 1, ioutbuf, out);
7206
7207
0
      gp_fputc(CR,             out);
7208
0
    }
7209
7210
    /* Printer advances one raster line */
7211
0
    gp_fputc(ESC,        out);
7212
0
    gp_fputc('(',        out);
7213
0
    gp_fputc('e',        out);
7214
0
    gp_fputc(2,          out);
7215
0
    gp_fputc(0,          out);
7216
0
    gp_fputc(HIGH(1),    out);
7217
0
    gp_fputc(LOW(1),     out);
7218
7219
0
    upd->yprinter += 1;
7220
7221
0
  }
7222
7223
  /* Advance scan by one */
7224
0
  upd->yscan += 1;
7225
7226
0
  return 0;
7227
0
}
7228
7229
/* ------------------------------------------------------------------- */
7230
/* All the Pixel-Get Routines                                          */
7231
/* ------------------------------------------------------------------- */
7232
7233
/* That bunch of Pixel-Get Routines */
7234
7235
static upd_proc_pxlget(upd_pxlgetnix); /* A Dummy */
7236
7237
static upd_proc_pxlget(upd_pxlget1f1); /* 1 Bit Forward */
7238
static upd_proc_pxlget(upd_pxlget1f2);
7239
static upd_proc_pxlget(upd_pxlget1f3);
7240
static upd_proc_pxlget(upd_pxlget1f4);
7241
static upd_proc_pxlget(upd_pxlget1f5);
7242
static upd_proc_pxlget(upd_pxlget1f6);
7243
static upd_proc_pxlget(upd_pxlget1f7);
7244
static upd_proc_pxlget(upd_pxlget1f8);
7245
7246
static upd_proc_pxlget(upd_pxlget1r1); /* 1 Bit Reverse */
7247
static upd_proc_pxlget(upd_pxlget1r2);
7248
static upd_proc_pxlget(upd_pxlget1r3);
7249
static upd_proc_pxlget(upd_pxlget1r4);
7250
static upd_proc_pxlget(upd_pxlget1r5);
7251
static upd_proc_pxlget(upd_pxlget1r6);
7252
static upd_proc_pxlget(upd_pxlget1r7);
7253
static upd_proc_pxlget(upd_pxlget1r8);
7254
7255
static upd_proc_pxlget(upd_pxlget2f1); /* 2 Bit Forward */
7256
static upd_proc_pxlget(upd_pxlget2f2);
7257
static upd_proc_pxlget(upd_pxlget2f3);
7258
static upd_proc_pxlget(upd_pxlget2f4);
7259
7260
static upd_proc_pxlget(upd_pxlget2r1); /* 2 Bit Reverse */
7261
static upd_proc_pxlget(upd_pxlget2r2);
7262
static upd_proc_pxlget(upd_pxlget2r3);
7263
static upd_proc_pxlget(upd_pxlget2r4);
7264
7265
static upd_proc_pxlget(upd_pxlget4f1); /* 4 Bit Forward */
7266
static upd_proc_pxlget(upd_pxlget4f2);
7267
7268
static upd_proc_pxlget(upd_pxlget4r1); /* 4 Bit Reverse */
7269
static upd_proc_pxlget(upd_pxlget4r2);
7270
7271
static upd_proc_pxlget(upd_pxlget8f);  /* 8 Bit Forward */
7272
static upd_proc_pxlget(upd_pxlget8r);  /* 8 Bit Reverse */
7273
7274
static upd_proc_pxlget(upd_pxlget16f); /* 16 Bit Forward */
7275
static upd_proc_pxlget(upd_pxlget16r); /* 16Bit Reverse */
7276
7277
static upd_proc_pxlget(upd_pxlget24f); /* 24 Bit Forward */
7278
static upd_proc_pxlget(upd_pxlget24r); /* 24 Bit Reverse */
7279
7280
static upd_proc_pxlget(upd_pxlget32f); /* 32 Bit Forward */
7281
static upd_proc_pxlget(upd_pxlget32r); /* 32 Bit Reverse */
7282
7283
/* Initialize Forward-Run */
7284
7285
static uint32_t
7286
upd_pxlfwd(upd_p upd)
7287
0
{
7288
0
   if(!(upd->pxlptr = upd->gsscan)) {
7289
7290
0
      upd->pxlget = upd_pxlgetnix;
7291
7292
0
   } else {
7293
0
      switch(upd->int_a[IA_COLOR_INFO].data[1]) {
7294
0
         case  1: upd->pxlget = upd_pxlget1f1; break;
7295
0
         case  2: upd->pxlget = upd_pxlget2f1; break;
7296
0
         case  4: upd->pxlget = upd_pxlget4f1; break;
7297
0
         case  8: upd->pxlget = upd_pxlget8f;  break;
7298
0
         case 16: upd->pxlget = upd_pxlget16f; break;
7299
0
         case 24: upd->pxlget = upd_pxlget24f; break;
7300
0
         case 32: upd->pxlget = upd_pxlget32f; break;
7301
0
         default:
7302
0
#if UPD_MESSAGES & UPD_M_ERROR
7303
0
           errprintf(upd->memory, "upd_pxlfwd: unsupported depth (%d)\n",
7304
0
                     upd->int_a[IA_COLOR_INFO].data[1]);
7305
0
#endif
7306
0
           upd->pxlget = upd_pxlgetnix;
7307
0
           break;
7308
0
      }
7309
0
   }
7310
0
   return (uint32_t) 0;
7311
0
}
7312
7313
/* 1 Bit Forward */
7314
7315
static uint32_t
7316
upd_pxlget1f1(upd_p upd)
7317
0
{
7318
0
   upd->pxlget = upd_pxlget1f2;
7319
0
   return *upd->pxlptr   & 0x80 ? (uint32_t) 1 : (uint32_t) 0;
7320
0
}
7321
7322
static uint32_t
7323
upd_pxlget1f2(upd_p upd)
7324
0
{
7325
0
   upd->pxlget = upd_pxlget1f3;
7326
0
   return *upd->pxlptr   & 0x40 ? (uint32_t) 1 : (uint32_t) 0;
7327
0
}
7328
7329
static uint32_t
7330
upd_pxlget1f3(upd_p upd)
7331
0
{
7332
0
   upd->pxlget = upd_pxlget1f4;
7333
0
   return *upd->pxlptr   & 0x20 ? (uint32_t) 1 : (uint32_t) 0;
7334
0
}
7335
7336
static uint32_t
7337
upd_pxlget1f4(upd_p upd)
7338
0
{
7339
0
   upd->pxlget = upd_pxlget1f5;
7340
0
   return *upd->pxlptr   & 0x10 ? (uint32_t) 1 : (uint32_t) 0;
7341
0
}
7342
7343
static uint32_t
7344
upd_pxlget1f5(upd_p upd)
7345
0
{
7346
0
   upd->pxlget = upd_pxlget1f6;
7347
0
   return *upd->pxlptr   & 0x08 ? (uint32_t) 1 : (uint32_t) 0;
7348
0
}
7349
7350
static uint32_t
7351
upd_pxlget1f6(upd_p upd)
7352
0
{
7353
0
   upd->pxlget = upd_pxlget1f7;
7354
0
   return *upd->pxlptr   & 0x04 ? (uint32_t) 1 : (uint32_t) 0;
7355
0
}
7356
7357
static uint32_t
7358
upd_pxlget1f7(upd_p upd)
7359
0
{
7360
0
   upd->pxlget = upd_pxlget1f8;
7361
0
   return *upd->pxlptr   & 0x02 ? (uint32_t) 1 : (uint32_t) 0;
7362
0
}
7363
7364
static uint32_t
7365
upd_pxlget1f8(upd_p upd)
7366
0
{
7367
0
   upd->pxlget = upd_pxlget1f1;
7368
0
   return *upd->pxlptr++ & 0x01 ? (uint32_t) 1 : (uint32_t) 0;
7369
0
}
7370
7371
/* 2 Bit Forward */
7372
7373
static uint32_t
7374
upd_pxlget2f1(upd_p upd)
7375
0
{
7376
0
   upd->pxlget = upd_pxlget2f2;
7377
0
   return ((uint32_t) (*upd->pxlptr  ) & (uint32_t) 0xC0) >> 6;
7378
0
}
7379
7380
static uint32_t
7381
upd_pxlget2f2(upd_p upd)
7382
0
{
7383
0
   upd->pxlget = upd_pxlget2f3;
7384
0
   return ((uint32_t) (*upd->pxlptr  ) & (uint32_t) 0x30) >> 4;
7385
0
}
7386
7387
static uint32_t
7388
upd_pxlget2f3(upd_p upd)
7389
0
{
7390
0
   upd->pxlget = upd_pxlget2f4;
7391
0
   return ((uint32_t) (*upd->pxlptr  ) & (uint32_t) 0x0C) >> 2;
7392
0
}
7393
7394
static uint32_t
7395
upd_pxlget2f4(upd_p upd)
7396
0
{
7397
0
   upd->pxlget = upd_pxlget2f1;
7398
0
   return  (uint32_t) (*upd->pxlptr++) & (uint32_t) 0x03;
7399
0
}
7400
7401
/* 4 Bit Forward */
7402
static uint32_t
7403
upd_pxlget4f1(upd_p upd)
7404
0
{
7405
0
   upd->pxlget = upd_pxlget4f2;
7406
0
   return ((uint32_t) (*upd->pxlptr  ) & (uint32_t) 0xF0) >> 4;
7407
0
}
7408
7409
static uint32_t
7410
upd_pxlget4f2(upd_p upd)
7411
0
{
7412
0
   upd->pxlget = upd_pxlget4f1;
7413
0
   return  (uint32_t) (*upd->pxlptr++) & (uint32_t) 0x0F;
7414
0
}
7415
7416
/* 8 Bit Forward */
7417
static uint32_t
7418
upd_pxlget8f(upd_p upd)
7419
0
{
7420
0
   return (uint32_t) (*upd->pxlptr++);
7421
0
}
7422
7423
/* 16 Bit Forward */
7424
static uint32_t
7425
upd_pxlget16f(upd_p upd)
7426
0
{
7427
0
   uint32_t ci  = (uint32_t) (*upd->pxlptr++) << 8;
7428
0
                  ci |=                   *upd->pxlptr++;
7429
0
   return         ci;
7430
0
}
7431
7432
/* 24 Bit Forward */
7433
static uint32_t
7434
upd_pxlget24f(upd_p upd)
7435
0
{
7436
0
   uint32_t ci  = (uint32_t) (*upd->pxlptr++) << 16;
7437
0
          ci |= (uint32_t) (*upd->pxlptr++) <<  8;
7438
0
          ci |=           *upd->pxlptr++;
7439
0
   return ci;
7440
0
}
7441
7442
/* 32 Bit Forward */
7443
static uint32_t
7444
upd_pxlget32f(upd_p upd)
7445
0
{
7446
0
   uint32_t ci  = (uint32_t) (*upd->pxlptr++) << 24;
7447
0
                  ci |= (uint32_t) (*upd->pxlptr++) << 16;
7448
0
                  ci |= (uint32_t) (*upd->pxlptr++) <<  8;
7449
0
                  ci |=                   *upd->pxlptr++;
7450
0
   return         ci;
7451
0
}
7452
7453
/* Dummy-Routine */
7454
7455
static uint32_t
7456
upd_pxlgetnix(upd_p upd)
7457
0
{
7458
0
   return (uint32_t) 0;
7459
0
}
7460
7461
/* Initialize Reverse-Run */
7462
7463
static uint32_t
7464
upd_pxlrev(upd_p upd)
7465
0
{
7466
0
   const uint width = upd->pwidth < upd->gswidth ? upd->pwidth : upd->gswidth;
7467
7468
0
   if(!(upd->pxlptr = upd->gsscan)) {
7469
7470
0
      upd->pxlget = upd_pxlgetnix;
7471
7472
0
   } else {
7473
0
      uint32_t ofs = (uint32_t) upd->int_a[IA_COLOR_INFO].data[1] * (width-1);
7474
7475
0
      upd->pxlptr += ofs>>3;
7476
7477
0
      ofs &= 7;
7478
7479
0
      switch(upd->int_a[IA_COLOR_INFO].data[1]) {
7480
0
         case  1: switch(ofs) {
7481
0
               case 0:  upd->pxlget = upd_pxlget1r1; break;
7482
0
               case 1:  upd->pxlget = upd_pxlget1r2; break;
7483
0
               case 2:  upd->pxlget = upd_pxlget1r3; break;
7484
0
               case 3:  upd->pxlget = upd_pxlget1r4; break;
7485
0
               case 4:  upd->pxlget = upd_pxlget1r5; break;
7486
0
               case 5:  upd->pxlget = upd_pxlget1r6; break;
7487
0
               case 6:  upd->pxlget = upd_pxlget1r7; break;
7488
0
               case 7:  upd->pxlget = upd_pxlget1r8; break;
7489
0
            } break;
7490
0
         case  2: switch(ofs) {
7491
0
               case 0:  upd->pxlget = upd_pxlget2r1; break;
7492
0
               case 2:  upd->pxlget = upd_pxlget2r2; break;
7493
0
               case 4:  upd->pxlget = upd_pxlget2r3; break;
7494
0
               case 6:  upd->pxlget = upd_pxlget2r4; break;
7495
0
            } break;
7496
0
         case  4: switch(ofs) {
7497
0
               case 0:  upd->pxlget = upd_pxlget4r1; break;
7498
0
               case 4:  upd->pxlget = upd_pxlget4r2; break;
7499
0
            } break;
7500
0
         case  8: upd->pxlget = upd_pxlget8r;  break;
7501
0
         case 16:
7502
0
            upd->pxlget  = upd_pxlget16r;
7503
0
            upd->pxlptr += 1;
7504
0
            break;
7505
0
         case 24:
7506
0
            upd->pxlget = upd_pxlget24r;
7507
0
            upd->pxlptr += 2;
7508
0
            break;
7509
0
         case 32:
7510
0
            upd->pxlget = upd_pxlget32r;
7511
0
            upd->pxlptr += 3;
7512
0
            break;
7513
0
         default:
7514
0
#if UPD_MESSAGES & UPD_M_ERROR
7515
0
           errprintf(upd->memory, "upd_pxlrev: unsupported depth (%d)\n",
7516
0
                     upd->int_a[IA_COLOR_INFO].data[1]);
7517
0
#endif
7518
0
           upd->pxlget = upd_pxlgetnix;
7519
0
           break;
7520
0
      }
7521
0
   }
7522
0
   return (uint32_t) 0;
7523
0
}
7524
7525
/* 1 Bit Reverse */
7526
7527
static uint32_t
7528
upd_pxlget1r1(upd_p upd)
7529
0
{
7530
0
   upd->pxlget = upd_pxlget1r8;
7531
0
   return *upd->pxlptr-- & 0x80 ? (uint32_t) 1 : (uint32_t) 0;
7532
0
}
7533
7534
static uint32_t
7535
upd_pxlget1r2(upd_p upd)
7536
0
{
7537
0
   upd->pxlget = upd_pxlget1r1;
7538
0
   return *upd->pxlptr   & 0x40 ? (uint32_t) 1 : (uint32_t) 0;
7539
0
}
7540
7541
static uint32_t
7542
upd_pxlget1r3(upd_p upd)
7543
0
{
7544
0
   upd->pxlget = upd_pxlget1r2;
7545
0
   return *upd->pxlptr   & 0x20 ? (uint32_t) 1 : (uint32_t) 0;
7546
0
}
7547
7548
static uint32_t
7549
upd_pxlget1r4(upd_p upd)
7550
0
{
7551
0
   upd->pxlget = upd_pxlget1r3;
7552
0
   return *upd->pxlptr   & 0x10 ? (uint32_t) 1 : (uint32_t) 0;
7553
0
}
7554
7555
static uint32_t
7556
upd_pxlget1r5(upd_p upd)
7557
0
{
7558
0
   upd->pxlget = upd_pxlget1r4;
7559
0
   return *upd->pxlptr   & 0x08 ? (uint32_t) 1 : (uint32_t) 0;
7560
0
}
7561
7562
static uint32_t
7563
upd_pxlget1r6(upd_p upd)
7564
0
{
7565
0
   upd->pxlget = upd_pxlget1r5;
7566
0
   return *upd->pxlptr   & 0x04 ? (uint32_t) 1 : (uint32_t) 0;
7567
0
}
7568
7569
static uint32_t
7570
upd_pxlget1r7(upd_p upd)
7571
0
{
7572
0
   upd->pxlget = upd_pxlget1r6;
7573
0
   return *upd->pxlptr   & 0x02 ? (uint32_t) 1 : (uint32_t) 0;
7574
0
}
7575
7576
static uint32_t
7577
upd_pxlget1r8(upd_p upd)
7578
0
{
7579
0
   upd->pxlget = upd_pxlget1r7;
7580
0
   return *upd->pxlptr   & 0x01 ? (uint32_t) 1 : (uint32_t) 0;
7581
0
}
7582
7583
/* 2 Bit Reverse */
7584
7585
static uint32_t
7586
upd_pxlget2r1(upd_p upd)
7587
0
{
7588
0
   upd->pxlget = upd_pxlget2r4;
7589
0
   return ((uint32_t) (*upd->pxlptr--) & (uint32_t) 0xC0) >> 6;
7590
0
}
7591
7592
static uint32_t
7593
upd_pxlget2r2(upd_p upd)
7594
0
{
7595
0
   upd->pxlget = upd_pxlget2r1;
7596
0
   return ((uint32_t) (*upd->pxlptr  ) & (uint32_t) 0x30) >> 4;
7597
0
}
7598
7599
static uint32_t
7600
upd_pxlget2r3(upd_p upd)
7601
0
{
7602
0
   upd->pxlget = upd_pxlget2r2;
7603
0
   return ((uint32_t) (*upd->pxlptr  ) & (uint32_t) 0x0C) >> 2;
7604
0
}
7605
7606
static uint32_t
7607
upd_pxlget2r4(upd_p upd)
7608
0
{
7609
0
   upd->pxlget = upd_pxlget2r3;
7610
0
   return  (uint32_t) (*upd->pxlptr  ) & (uint32_t) 0x03;
7611
0
}
7612
7613
/* 4 Bit Reverse */
7614
7615
static uint32_t
7616
upd_pxlget4r1(upd_p upd)
7617
0
{
7618
0
   upd->pxlget = upd_pxlget4r2;
7619
0
   return ((uint32_t) (*upd->pxlptr--) & (uint32_t) 0xF0) >> 4;
7620
0
}
7621
7622
static uint32_t
7623
upd_pxlget4r2(upd_p upd)
7624
0
{
7625
0
   upd->pxlget = upd_pxlget4r1;
7626
0
   return  (uint32_t) (*upd->pxlptr  ) & (uint32_t) 0x0F;
7627
0
}
7628
7629
/* 8 Bit Reverse */
7630
static uint32_t
7631
upd_pxlget8r(upd_p upd)
7632
0
{
7633
0
   return (uint32_t) (*upd->pxlptr--);
7634
0
}
7635
7636
/* 16 Bit Reverse */
7637
static uint32_t
7638
upd_pxlget16r(upd_p upd)
7639
0
{
7640
0
   uint32_t ci  =                   *upd->pxlptr--;
7641
0
                  ci |= (uint32_t) (*upd->pxlptr--) << 8;
7642
0
   return         ci;
7643
0
}
7644
7645
/* 24 Bit Reverse */
7646
static uint32_t
7647
upd_pxlget24r(upd_p upd)
7648
0
{
7649
0
   uint32_t ci  =           *upd->pxlptr--;
7650
0
          ci |= (uint32_t) (*upd->pxlptr--) <<  8;
7651
0
          ci |= (uint32_t) (*upd->pxlptr--) << 16;
7652
0
   return ci;
7653
0
}
7654
7655
/* 32 Bit Reverse */
7656
static uint32_t
7657
upd_pxlget32r(upd_p upd)
7658
0
{
7659
0
   uint32_t ci  =                   *upd->pxlptr--;
7660
0
                  ci |= (uint32_t) (*upd->pxlptr--) <<  8;
7661
0
                  ci |= (uint32_t) (*upd->pxlptr--) << 16;
7662
0
                  ci |= (uint32_t) (*upd->pxlptr--) << 24;
7663
0
   return         ci;
7664
0
}