Coverage Report

Created: 2026-08-08 08:00

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