~ubuntu-branches/ubuntu/oneiric/ghostscript/oneiric

« back to all changes in this revision

Viewing changes to base/gdevphex.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2011-07-15 16:49:55 UTC
  • mfrom: (1.1.23 upstream)
  • Revision ID: james.westby@ubuntu.com-20110715164955-uga6qibao6kez05c
Tags: 9.04~dfsg~20110715-0ubuntu1
* New upstream release
   - GIT snapshot from Jult, 12 2011.
* debian/patches/020110406~a54df2d.patch,
  debian/patches/020110408~0791cc8.patch,
  debian/patches/020110408~507cbee.patch,
  debian/patches/020110411~4509a49.patch,
  debian/patches/020110412~78bb9a6.patch,
  debian/patches/020110418~a05ab8a.patch,
  debian/patches/020110420~20b6c78.patch,
  debian/patches/020110420~4ddefa2.patch: Removed upstream patches.
* debian/rules: Generate ABI version number (variable "abi") correctly,
  cutting off repackaging and pre-release parts.
* debian/rules: Added ./lcms2/ directory to DEB_UPSTREAM_REPACKAGE_EXCLUDES.
* debian/copyright: Added lcms2/* to the list of excluded files.
* debian/symbols.common: Updated for new upstream source. Applied patch
  which dpkg-gensymbols generated for debian/libgs9.symbols to this file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
2
2
   All Rights Reserved.
3
 
  
 
3
 
4
4
   This software is provided AS-IS with no warranty, either express or
5
5
   implied.
6
6
 
11
11
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12
12
*/
13
13
 
14
 
/* $Id: gdevphex.c 8250 2007-09-25 13:31:24Z giles $ */
 
14
/* $Id$ */
15
15
 
16
16
/****************************************************************************/
17
17
/*      Ghostscript printer driver for Epson Color Photo, Photo EX, Photo 700   */
31
31
 
32
32
8 June 1999 Zolt�n K�csi (aka Kocsonya) zoltan@bendor.com.au
33
33
 
34
 
        Initial revision. 
35
 
        No shingling, depletion.
36
 
        Colour only.
37
 
        Dither matrix is blatantly copied from gslib.c.
 
34
        Initial revision.
 
35
        No shingling, depletion.
 
36
        Colour only.
 
37
        Dither matrix is blatantly copied from gslib.c.
38
38
 
39
39
17 April 2000 Zolt�n K�csi
40
40
 
41
 
        After much play worked out a reasonably simple colour mapping
42
 
        that gives fairly good results. It has some very hairy things 
43
 
        in it but ot seems to work reasonably well on a variety of natural
44
 
        as well as artificial images.
45
 
        
46
 
                
 
41
        After much play worked out a reasonably simple colour mapping
 
42
        that gives fairly good results. It has some very hairy things
 
43
        in it but ot seems to work reasonably well on a variety of natural
 
44
        as well as artificial images.
 
45
 
47
46
LEGALISE
48
47
~~~~~~~~
49
48
 
50
 
The usual disclaimer applies, neither me (Zolt�n K�csi) nor 
51
 
Bendor Research Pty. Ltd. assume any liability whatsoever in 
52
 
relation to events arising out of or related to the use of 
53
 
the software or the included documentation in any form, way 
 
49
The usual disclaimer applies, neither me (Zolt�n K�csi) nor
 
50
Bendor Research Pty. Ltd. assume any liability whatsoever in
 
51
relation to events arising out of or related to the use of
 
52
the software or the included documentation in any form, way
54
53
or purpose. This software is not guaranteed to work, you
55
54
get it "as is" and use it for your own risk.
56
55
 
59
58
 
60
59
CREDIT
61
60
~~~~~~
62
 
This driver was written from scratch, however, I have used the 
 
61
This driver was written from scratch, however, I have used the
63
62
HP/BJ driver very heavily as a reference (GhostScript's documentation
64
63
needs some working :-). In addition, I got some help in understanding
65
64
the more arcane features of the printer by digging into the colour
66
 
Epson driver and its documentation (documentation for the Photo EX 
67
 
did not exist). I thank to the authors of these drivers and the 
68
 
related docs. 
 
65
Epson driver and its documentation (documentation for the Photo EX
 
66
did not exist). I thank to the authors of these drivers and the
 
67
related docs.
69
68
 
70
 
I do also hereby express my despising Epson, Inc. who try to enlarge 
71
 
Microsoft's monopoly by witholding programming information about such 
 
69
I do also hereby express my despising Epson, Inc. who try to enlarge
 
70
Microsoft's monopoly by witholding programming information about such
72
71
a commodity item as a printer.
73
72
 
74
73
KNOWN BUGS/LIMITATIONS
77
76
- The driver is not optimised for speed
78
77
- The driver does not support TIFF compression
79
78
- Shingling and depletion is not implemented
80
 
- The colour correction and ink transfer curve are hardcoded 
 
79
- The colour correction and ink transfer curve are hardcoded
81
80
- The dither matrix is straight stolen from Ghostscript
82
81
- The alternative error diffusion included but does not work (yet)
83
82
 
88
87
~~~~~~~
89
88
The Epson Stylus Photo EX is a colour ink-jet printer.
90
89
It can handle papers up to A3. It uses 6 inks, black in one cartridge
91
 
and cyan, magenta, yellow, light cyan and light magenta in an other 
92
 
cartridge. The head has 32 nozzles, with 1/90" spacing. 
 
90
and cyan, magenta, yellow, light cyan and light magenta in an other
 
91
cartridge. The head has 32 nozzles, with 1/90" spacing.
93
92
The maximal resolution is 1440 dpi horizontal 720 dpi vertical.
94
93
In 720x720 and 360x360 dpi it supports microweave. To achieve
95
94
1440x720 you must use software weaving. It has only one built-in font,
99
98
The printer uses the ESC/P Raster protocol. This protocol is somewhat
100
99
similar to the ESC/P2 one. Initially Epson refused to give any info
101
100
about it. Later (unfortunately after I had already spent lot of time
102
 
to reverse engineer it) they released its definition. It could be 
 
101
to reverse engineer it) they released its definition. It could be
103
102
found on their website (http://www.ercipd.com/isv/level1/6clr_98b.pdf).
104
103
Alas, they removed it, so at the moment I do not know about any existing
105
 
docs of the printer. 
 
104
docs of the printer.
106
105
There are still a few commands which are not covered by the docs
107
106
and for example the Windows driver uses them. There are others which
108
 
are in the docs, saying that you can find them in other docs but you 
109
 
can't. Fortunately, these commands apparently have no effect on the 
 
107
are in the docs, saying that you can find them in other docs but you
 
108
can't. Fortunately, these commands apparently have no effect on the
110
109
printing process so this driver simply ignores them. Tricky business.
111
110
 
112
 
By the way, my personal experience is that Epson tech support is 
 
111
By the way, my personal experience is that Epson tech support is
113
112
a joke, or in Usenet lingvo it sucks big time - they know absolutely
114
113
nothing about the product they supposed to support. Epson's webpage
115
114
contains false info as well (they state that the Photo EX uses ESC/P2,
120
119
 
121
120
If you think that you can get some useful info from me above of what you
122
121
can find below, feel free to email me at zoltan@bendor.com.au.
123
 
If you enhance the driver or find a bug *please* send me info about 
124
 
it. 
 
122
If you enhance the driver or find a bug *please* send me info about
 
123
it.
125
124
 
126
125
DRIVER
127
126
~~~~~~
130
129
The devices are "photoex" and "photoexm". The mono device driver is
131
130
catered for (that is, the rendering part knows how to render for B&W)
132
131
but it is not finished yet (no device structure and gray colour mapping
133
 
procedures) mainly because all my B&W needs are fairly well satisfied 
 
132
procedures) mainly because all my B&W needs are fairly well satisfied
134
133
by our laser printer.
135
134
 
136
135
The driver features the following:
137
136
 
138
137
Supported resolutions
139
138
 
140
 
         360x360        Y weaving (not that micro :-) by the printer
141
 
         720x720        Y microweave by the driver (quicker than the printer)
142
 
        1440x720        Y and X microweave by the driver
143
 
        
144
 
        Resolutions other than these will result in a rangecheck error.
145
 
        
 
139
         360x360        Y weaving (not that micro :-) by the printer
 
140
         720x720        Y microweave by the driver (quicker than the printer)
 
141
        1440x720        Y and X microweave by the driver
 
142
 
 
143
        Resolutions other than these will result in a rangecheck error.
 
144
 
146
145
Papersize:
147
 
        
148
 
        Whatever Ghostscript supports. The printer docs say that if you load
149
 
        multiple sheets of transparencies into the tray you should at least
150
 
        have 30mm or 1.2" top margin. The driver always sets the smallest 
151
 
        possible top margin (3mm or 0.12"), it's up to you to comply.
152
 
        
153
 
        In addition, the printer says that the bottom margin is at least
154
 
        14mm or 0.54". I violate it by setting it to 0.5" or 12.7mm.
155
 
        0.5" seems to be a common margin value for documents and you 
156
 
        would hate it when the last line of your page gets printed on the
157
 
        top of the next sheet ...
158
 
        
 
146
 
 
147
        Whatever Ghostscript supports. The printer docs say that if you load
 
148
        multiple sheets of transparencies into the tray you should at least
 
149
        have 30mm or 1.2" top margin. The driver always sets the smallest
 
150
        possible top margin (3mm or 0.12"), it's up to you to comply.
 
151
 
 
152
        In addition, the printer says that the bottom margin is at least
 
153
        14mm or 0.54". I violate it by setting it to 0.5" or 12.7mm.
 
154
        0.5" seems to be a common margin value for documents and you
 
155
        would hate it when the last line of your page gets printed on the
 
156
        top of the next sheet ...
 
157
 
159
158
Options:
160
 
        
161
 
        -dDotSize=n
162
 
        
163
 
                n = 0           Let the driver choose a dotsize
164
 
                n = 1           small dots
165
 
                n = 2           more ink
166
 
                n = 3           ink flood
167
 
                n = 4           'super microdots' (whatever they are, they are *big*)
168
 
                
169
 
                The default is 0 which is n=1 for 1440x720, 2 for 720x720 and
170
 
                3 for 360x360. Do not use large dots if you don't have to, you
171
 
                will soak the paper. If you print 720x720 on normal paper, try
172
 
                using n=1.
173
 
                
174
 
        -dRender=n
175
 
        
176
 
                n = 0           Floyd-Steinbeck error diffusion
177
 
                n = 1           Clustered dither
178
 
                n = 2           Bendor's error diffusion (experimental, do not use)
179
 
                
180
 
                Default is Floyd-Steinbeck error diffusion
181
 
                
182
 
        -dLeakage=nn
183
 
        
184
 
                nn is between 0 and 25. It only effects Bendor's error diffusion.
185
 
                It sets the percentage of the error which is left to 'leak', that
186
 
                is it is the coefficient of an exponential decay of the error.
187
 
                Experiments show that it can be beneficial on image quality.
188
 
                Default is 0 (no leakage).
189
 
                
190
 
        -dSplash=nn
191
 
        
192
 
                nn is between 0 and 100. It only affects Bendor's error diffusion.
193
 
                The ED routine tries to take the increase of dot diameter on certain
194
 
                paper types into account. 
195
 
                It sets the percentage of the ink dot size increase as it splashes
196
 
                onto the paper and spreads. 0 means no splashing, 100 means that 
197
 
                the dot is twice as large as it should be. 
198
 
                Default is 0.
199
 
                
200
 
        -dBinhibit=n
201
 
        
202
 
                If n is 1, then if black ink is deposited to a pixel, it will
203
 
                inhibit the deposition of any other ink to the same pixel.
204
 
                If 0, black ink may be deposited together with other inks.
205
 
                Default is on (1).
206
 
                 
 
159
 
 
160
        -dDotSize=n
 
161
 
 
162
                n = 0           Let the driver choose a dotsize
 
163
                n = 1           small dots
 
164
                n = 2           more ink
 
165
                n = 3           ink flood
 
166
                n = 4           'super microdots' (whatever they are, they are *big*)
 
167
 
 
168
                The default is 0 which is n=1 for 1440x720, 2 for 720x720 and
 
169
                3 for 360x360. Do not use large dots if you don't have to, you
 
170
                will soak the paper. If you print 720x720 on normal paper, try
 
171
                using n=1.
 
172
 
 
173
        -dRender=n
 
174
 
 
175
                n = 0           Floyd-Steinbeck error diffusion
 
176
                n = 1           Clustered dither
 
177
                n = 2           Bendor's error diffusion (experimental, do not use)
 
178
 
 
179
                Default is Floyd-Steinbeck error diffusion
 
180
 
 
181
        -dLeakage=nn
 
182
 
 
183
                nn is between 0 and 25. It only effects Bendor's error diffusion.
 
184
                It sets the percentage of the error which is left to 'leak', that
 
185
                is it is the coefficient of an exponential decay of the error.
 
186
                Experiments show that it can be beneficial on image quality.
 
187
                Default is 0 (no leakage).
 
188
 
 
189
        -dSplash=nn
 
190
 
 
191
                nn is between 0 and 100. It only affects Bendor's error diffusion.
 
192
                The ED routine tries to take the increase of dot diameter on certain
 
193
                paper types into account.
 
194
                It sets the percentage of the ink dot size increase as it splashes
 
195
                onto the paper and spreads. 0 means no splashing, 100 means that
 
196
                the dot is twice as large as it should be.
 
197
                Default is 0.
 
198
 
 
199
        -dBinhibit=n
 
200
 
 
201
                If n is 1, then if black ink is deposited to a pixel, it will
 
202
                inhibit the deposition of any other ink to the same pixel.
 
203
                If 0, black ink may be deposited together with other inks.
 
204
                Default is on (1).
 
205
 
207
206
ESC/P RASTER DOCS
208
207
~~~~~~~~~~~~~~~~~
209
 
The parts of the ESC/P Raster protocol which I've managed to decipher, 
 
208
The parts of the ESC/P Raster protocol which I've managed to decipher,
210
209
and which are actually used in this driver can be found below.
211
210
nn, mm, xx, etc. represent a single byte with a binary value in it.
212
211
nnnn, xxxx etc. represent a 16-bit binary number, sent in two bytes,
213
 
in little endian order (low byte first). 2-digit numbers are a single 
 
212
in little endian order (low byte first). 2-digit numbers are a single
214
213
byte in hex. Other chars are themselves.
215
 
Quite a few commands are identical to the ESC/P2 commands, these are 
 
214
Quite a few commands are identical to the ESC/P2 commands, these are
216
215
marked with (P2).
217
216
 
218
 
ESC @                                                           (P2)    
219
 
        
220
 
        Resets the printer.
 
217
ESC @                                                           (P2)
221
218
 
 
219
        Resets the printer.
222
220
 
223
221
ESC ( U 01 00 nn                                        (P2)
224
222
 
225
 
        Sets the unit to 3600/nn dpi. Note that 1440 can not be set !
226
 
 
 
223
        Sets the unit to 3600/nn dpi. Note that 1440 can not be set !
227
224
 
228
225
ESC ( C 02 00 nnnn                                      (P2)
229
226
 
230
 
        Sets the page (paper) length to nnnn units
231
 
        
 
227
        Sets the page (paper) length to nnnn units
232
228
 
233
229
ESC ( c 04 00 bbbb tttt                         (P2)
234
230
 
235
 
        Sets the top margin to tttt units, the bottom margin to
236
 
        bbbb units. The bottom margin is measured from the top
237
 
        of the page not from the bottom of the page !
238
 
                
239
 
        
 
231
        Sets the top margin to tttt units, the bottom margin to
 
232
        bbbb units. The bottom margin is measured from the top
 
233
        of the page not from the bottom of the page !
 
234
 
240
235
ESC     U nn                                                    (P2)
241
236
 
242
 
        Unidirectional printing
243
 
        
244
 
        nn
245
 
        00      off
246
 
        01      on
247
 
        30      off (this is ASCII 0)
248
 
        31      on      (this is ASCII 1)
249
 
        
250
 
                
 
237
        Unidirectional printing
 
238
 
 
239
        nn
 
240
        00      off
 
241
        01      on
 
242
        30      off (this is ASCII 0)
 
243
        31      on      (this is ASCII 1)
 
244
 
251
245
ESC     ( i 01 00 nn                                    (P2)
252
246
 
253
 
        Microweave
254
 
        
255
 
        nn
256
 
        00      off
257
 
        01      on
258
 
        30      off (this is ASCII 0)
259
 
        31      on      (this is ASCII 1)
260
 
        
261
 
        Turns microweave on for 720x720 dpi printing.
262
 
                                
 
247
        Microweave
 
248
 
 
249
        nn
 
250
        00      off
 
251
        01      on
 
252
        30      off (this is ASCII 0)
 
253
        31      on      (this is ASCII 1)
 
254
 
 
255
        Turns microweave on for 720x720 dpi printing.
 
256
 
263
257
ESC r nn                                                        (P2)
264
258
 
265
 
        Select colour
266
 
        
267
 
        nn
268
 
        01              Cyan
269
 
        02              Magenta
270
 
        04              Yellow
271
 
        08              Black
272
 
                
 
259
        Select colour
 
260
 
 
261
        nn
 
262
        01              Cyan
 
263
        02              Magenta
 
264
        04              Yellow
 
265
        08              Black
273
266
 
274
267
ESC ( G 01 00 nn                                        (P2)
275
268
 
276
 
        Selects graphics mode:
277
 
        
278
 
        nn
279
 
        00              Off
280
 
        01              On
281
 
        30              Off
282
 
        31              On
283
 
        
284
 
        
 
269
        Selects graphics mode:
 
270
 
 
271
        nn
 
272
        00              Off
 
273
        01              On
 
274
        30              Off
 
275
        31              On
 
276
 
285
277
ESC ( v 02 00 dddd                                      (P2)
286
278
 
287
 
        Advance the paper by dddd units defined by ESC ( U
288
 
 
 
279
        Advance the paper by dddd units defined by ESC ( U
289
280
 
290
281
ESC . cc vv hh nn mmmm <data>           (P2)
291
282
 
292
 
        Sends graphics data to the printer.
293
 
        
294
 
        cc      Encoding mode
295
 
        
296
 
                00      Raw data
297
 
                01      Run-length encoded data
298
 
        
299
 
        vv      Vertical resolution
300
 
        
301
 
                28        90 dpi        *interleave*
302
 
                14       180 dpi        *interleave*
303
 
                0a       360 dpi
304
 
                05       720 dpi
305
 
                
306
 
        hh      Horizontal resolution
307
 
        
308
 
                0a       360 dpi
309
 
                05       720 dpi
310
 
                
311
 
        nn      Number of nozzles
312
 
        
313
 
                It should be set to 32 (normal printing) or 1 (microweave)
314
 
                
315
 
        mmmm Number of collumns of data (not number of data bytes !)
316
 
        
317
 
        <data>
318
 
        
319
 
                The data should contain as many bytes as needed to fill the
320
 
                mmmm * nn pixels. Data is presented horizontally, that is,
321
 
                the bits of a byte will be represented by eight pixels in
322
 
                a row. If the number of collumns is not an integer multiple 
323
 
                of eight, then some bits from the last byte belonging to the
324
 
                row will be discarded and the next row starts on a byte boundary.
325
 
                If a bit in a byte is '1' ink is deposited, if '0' not.
326
 
                The leftmost pixel is represented by the MSB, rightmost by LSB.
327
 
                In case of raw data that's about it.
328
 
                
329
 
                In case of run-length encoded data, the following is done:
330
 
                The first byte is a counter. If the counter is <= 127 then
331
 
                the following counter+1 bytes are uncompressed data.
332
 
                If the counter is >= 128 then the following single byte should
333
 
                be repeated 257-counter times. 
334
 
                
335
 
        There are resolution restrictions:
336
 
        
337
 
                360x360 nozzle= 1 microweave on
338
 
                360x360 nozzle=32 microweave off
339
 
                720x 90 nozzle=32 microweave off
340
 
                720x720 nozzle= 1 microweave on
341
 
 
342
 
        Other combinations are not supported.
 
283
        Sends graphics data to the printer.
 
284
 
 
285
        cc      Encoding mode
 
286
 
 
287
                00      Raw data
 
288
                01      Run-length encoded data
 
289
 
 
290
        vv      Vertical resolution
 
291
 
 
292
                28        90 dpi        *interleave*
 
293
                14       180 dpi        *interleave*
 
294
                0a       360 dpi
 
295
                05       720 dpi
 
296
 
 
297
        hh      Horizontal resolution
 
298
 
 
299
                0a       360 dpi
 
300
                05       720 dpi
 
301
 
 
302
        nn      Number of nozzles
 
303
 
 
304
                It should be set to 32 (normal printing) or 1 (microweave)
 
305
 
 
306
        mmmm Number of collumns of data (not number of data bytes !)
 
307
 
 
308
        <data>
 
309
 
 
310
                The data should contain as many bytes as needed to fill the
 
311
                mmmm * nn pixels. Data is presented horizontally, that is,
 
312
                the bits of a byte will be represented by eight pixels in
 
313
                a row. If the number of collumns is not an integer multiple
 
314
                of eight, then some bits from the last byte belonging to the
 
315
                row will be discarded and the next row starts on a byte boundary.
 
316
                If a bit in a byte is '1' ink is deposited, if '0' not.
 
317
                The leftmost pixel is represented by the MSB, rightmost by LSB.
 
318
                In case of raw data that's about it.
 
319
 
 
320
                In case of run-length encoded data, the following is done:
 
321
                The first byte is a counter. If the counter is <= 127 then
 
322
                the following counter+1 bytes are uncompressed data.
 
323
                If the counter is >= 128 then the following single byte should
 
324
                be repeated 257-counter times.
 
325
 
 
326
        There are resolution restrictions:
 
327
 
 
328
                360x360 nozzle= 1 microweave on
 
329
                360x360 nozzle=32 microweave off
 
330
                720x 90 nozzle=32 microweave off
 
331
                720x720 nozzle= 1 microweave on
 
332
 
 
333
        Other combinations are not supported.
343
334
 
344
335
ESC ( e 02 00 00 nn
345
336
 
346
 
        Sets the amount of ink spat onto the paper.
347
 
        
348
 
        nn
349
 
        01              microdots (faint printing)
350
 
        02              normal dots (not so faint printing)
351
 
        03              double dots (full inking)
352
 
        04              super microdots (ink is continuously dripping :-)
353
 
        
354
 
        Values other than that have apparently no effect.
355
 
        
 
337
        Sets the amount of ink spat onto the paper.
 
338
 
 
339
        nn
 
340
        01              microdots (faint printing)
 
341
        02              normal dots (not so faint printing)
 
342
        03              double dots (full inking)
 
343
        04              super microdots (ink is continuously dripping :-)
 
344
 
 
345
        Values other than that have apparently no effect.
 
346
 
356
347
ESC ( K 02 00 xxxx
357
348
 
358
 
        This command is sent by the Windows driver but it is not used
359
 
        in the Epson test images. I have not found it having any effect
360
 
        whatsoever. The driver does not use it. The Epson docs don't
361
 
        mention it.
362
 
        
363
 
ESC ( r 02 00 nn mm                                     
364
 
        
365
 
        Selects the ink according to this:
366
 
 
367
 
        nn mm
368
 
        00 00   black
369
 
        00 01   magenta
370
 
        00 02   cyan
371
 
        00 04   yellow
372
 
        01 01   light magenta
373
 
        01 02   light yellow
374
 
 
 
349
        This command is sent by the Windows driver but it is not used
 
350
        in the Epson test images. I have not found it having any effect
 
351
        whatsoever. The driver does not use it. The Epson docs don't
 
352
        mention it.
 
353
 
 
354
ESC ( r 02 00 nn mm
 
355
 
 
356
        Selects the ink according to this:
 
357
 
 
358
        nn mm
 
359
        00 00   black
 
360
        00 01   magenta
 
361
        00 02   cyan
 
362
        00 04   yellow
 
363
        01 01   light magenta
 
364
        01 02   light yellow
375
365
 
376
366
ESC ( \ 04 00 xxxx llll
377
367
 
378
 
        Horizontal positioning of the head.
379
 
        
380
 
        Moves the head to the position llll times 1/xxxx inches from
381
 
        the left margin. 
382
 
        On the example images xxxx was always set to 1440.
383
 
        I tried other values in which case the command was ignored,
384
 
        so stick to 1440.
385
 
 
386
 
        
387
 
ESC ( R ll 00 00 <text> <cc> xxxx nn .. nn 
 
368
        Horizontal positioning of the head.
 
369
 
 
370
        Moves the head to the position llll times 1/xxxx inches from
 
371
        the left margin.
 
372
        On the example images xxxx was always set to 1440.
 
373
        I tried other values in which case the command was ignored,
 
374
        so stick to 1440.
 
375
 
 
376
ESC ( R ll 00 00 <text> <cc> xxxx nn .. nn
388
377
ESC 00 00 00
389
378
 
390
 
        This is supposedly sets the printer into 'remote' mode.
391
 
        ll is the length of the <text> + 1 which consists of ASCII
392
 
        characters (e.g. REMOTE1). 
393
 
        <cc> is a two-character code, for example "SN" or "LD".
394
 
        xxxx is the number of bytes (nn -s) which will follow.
395
 
        After that there's either a new <cc> xxxx nn .. nn sequence or
396
 
        the ESC 00 00 00.
397
 
        I have absolutely no idea about this command and the Epson document
398
 
        says that it's in an other document. It's not in that other one.
399
 
        The driver does not use it. The printer does not miss it.
400
 
        The Epson test images use it and the Windows driver uses it too.
401
 
        They send different <cc>-s and different values for identical <cc>-s.
402
 
        Go figure.
403
 
        
 
379
        This is supposedly sets the printer into 'remote' mode.
 
380
        ll is the length of the <text> + 1 which consists of ASCII
 
381
        characters (e.g. REMOTE1).
 
382
        <cc> is a two-character code, for example "SN" or "LD".
 
383
        xxxx is the number of bytes (nn -s) which will follow.
 
384
        After that there's either a new <cc> xxxx nn .. nn sequence or
 
385
        the ESC 00 00 00.
 
386
        I have absolutely no idea about this command and the Epson document
 
387
        says that it's in an other document. It's not in that other one.
 
388
        The driver does not use it. The printer does not miss it.
 
389
        The Epson test images use it and the Windows driver uses it too.
 
390
        They send different <cc>-s and different values for identical <cc>-s.
 
391
        Go figure.
 
392
 
404
393
DRIVER INTERNALS
405
394
~~~~~~~~~~~~~~~~
406
395
First, some comments.
407
 
Anything I know about the printer can be found above. 
408
 
Anything I know about Ghostscript internals (not much) can be 
409
 
found in the comments in the code. I do not believe in the 'it was hard 
410
 
to write, it should be hard to read' principle since I once had to 
 
396
Anything I know about the printer can be found above.
 
397
Anything I know about Ghostscript internals (not much) can be
 
398
found in the comments in the code. I do not believe in the 'it was hard
 
399
to write, it should be hard to read' principle since I once had to
411
400
understand my own code.
412
401
Therefore, the code has lots of comments in it, sometimes apparently
413
 
superfluous but I find it easier to understand the program 6 months 
 
402
superfluous but I find it easier to understand the program 6 months
414
403
later that way.
415
404
I did not follow the Ghostscript or GNU style guide, I write code the way
416
405
I like it - I'm a lazy dog :-) I use hard tabs at every 4th position,
417
406
I use a *lot* of whitespace (as recommended by K&R in their original
418
 
C book) and I have a formatting style similar to the K&R with the 
419
 
notable exception that I do not indent variable declarations that follow 
420
 
the curly. Anyway, you can run your favourite C formatter through the 
 
407
C book) and I have a formatting style similar to the K&R with the
 
408
notable exception that I do not indent variable declarations that follow
 
409
the curly. Anyway, you can run your favourite C formatter through the
421
410
source.
422
411
 
423
 
In addition to the above, the driver is not hand-optimised, it assumes 
 
412
In addition to the above, the driver is not hand-optimised, it assumes
424
413
that it is compiled with a good optimising compiler which will handle
425
414
common subexpression ellimination, move loop independent code out of
426
415
the loop, transform repeated array accesses to cached pointer arithmetics
427
 
and so on. The code is much more readable this way and gcc is fairly 
 
416
and so on. The code is much more readable this way and gcc is fairly
428
417
good at doing optimisation. Feel free to hand-optimise it.
429
418
 
430
419
So, the driver works the following way:
438
427
Then it calls the line scheduler. To see why do we have a scheduler, you
439
428
have to understand weaving. The printer head has 32 nozzles which are
440
429
spaced at 8 line intervals. Therefore, it prints 32 lines at a time but they
441
 
are distributed over a 256 line high area. Obviously, if you want to print 
442
 
all the lines under the head, you should pass over the paper 8 times.  
 
430
are distributed over a 256 line high area. Obviously, if you want to print
 
431
all the lines under the head, you should pass over the paper 8 times.
443
432
You can do it the obvious way:
444
433
Print, move down by one line, print ... repeat 8 times then move down
445
434
by 256 - 8 lines and start again. Unfortunately, this would result in
450
439
 
451
440
The solution is 'microweave', a funny way of doing interlaced printing.
452
441
Instead of moving down 1, 1, 1, 1, .. 1, 248, 1, 1 .. you move down
453
 
a constant, larger amount (called a band). This amount must be chosen 
454
 
in such a way that each line will be printed and preferably it will be 
 
442
a constant, larger amount (called a band). This amount must be chosen
 
443
in such a way that each line will be printed and preferably it will be
455
444
printed only once.
456
445
 
457
 
Let for example the move down amount (the band) be 31. Let's say, 
 
446
Let for example the move down amount (the band) be 31. Let's say,
458
447
in band N nozzle 31 is over line 300, in which case nozzle 30 is over
459
 
line 292. We move the head down by 31 lines, then line 299 will be 
 
448
line 292. We move the head down by 31 lines, then line 299 will be
460
449
under nozzle 27 and line 307 under nozzle 28.
461
450
Next move, nozzle 23 will print line 298 and nozzle 24 line 306, then
462
451
19/297 20/305, 15/296 16/304, 11/295 12/303, 7/294 8/302, 3/293 4/302,
463
 
0/292 3/301 which covers the entire area between 292 and 307. 
464
 
The same will apply to any other area on the page. Also note that 
465
 
adjacent lines are always printed by different nozzles. 
 
452
0/292 3/301 which covers the entire area between 292 and 307.
 
453
The same will apply to any other area on the page. Also note that
 
454
adjacent lines are always printed by different nozzles.
466
455
You probably have realised that line 292 was printed in the first pass
467
 
and in the last one. In this case, of course, the line must not be printed 
 
456
and in the last one. In this case, of course, the line must not be printed
468
457
twice, one or the other pass should not deliver data to the nozzle which
469
458
passes over this line.
470
459
 
472
461
to print each line twice, first depositing all even pixels then offset
473
462
the head by 1/1440" and deposit all odd pixels (the printer can only
474
463
print with 720 dpi but you can initially position the head with 1440 dpi
475
 
resolution). You could do it the easy way, passing over the same area 
476
 
twice but you can do better. You can find a band size which will result 
477
 
each line being printed twice. Instead of suppressing the double print, 
 
464
resolution). You could do it the easy way, passing over the same area
 
465
twice but you can do better. You can find a band size which will result
 
466
each line being printed twice. Instead of suppressing the double print,
478
467
you use this mechanism to print the odd and the even pixels.
479
468
Now if you print one line's odd pixels, obviously, all lines belonging
480
469
to the 31 other nozzles of the head will have their odd pixels printed too.
481
470
Therefore, you have to keep track which lines have been printed in which
482
471
phase and try to find an odd-even phase assignment to bands so that each line
483
 
has both groups printed (and each group only once). 
 
472
has both groups printed (and each group only once).
484
473
The added bonus is that even the same line will be printed by two different
485
474
nozzles thus effects of nozzle differences can be decreased further.
486
475
 
487
 
The whole issue is further complicated with the beginning of the page and 
 
476
The whole issue is further complicated with the beginning of the page and
488
477
the end of the page. When you print the first 8 lines you *must* use the
489
478
print, down by 1, print ... method but then you have to switch over to the
490
479
banding method. To do it well, you should minimise the number of lines which
491
 
are printed out of band. This optimisation is not complex but not trivial 
 
480
are printed out of band. This optimisation is not complex but not trivial
492
481
either. Our solution is to employ precalculated tables for the first 8 lines.
493
482
(Epson's solution is not to print the 'problematic' lines at all - they
494
483
warn you in the manual that at the top and bottom you may have "slight
495
484
distortions". Analyzing their output reveals the reason ... ).
496
 
The bottom is different. It is easier, because you are already banding, so 
 
485
The bottom is different. It is easier, because you are already banding, so
497
486
you can't screw up the rest of the image. On the other hand, you can't use
498
487
tables because these tables would depend on the page height which you don't
499
 
know a priori. Our solution is to switch to single line mode when we can 
500
 
not do the banding any more and try to finish the page with the minimal 
 
488
know a priori. Our solution is to switch to single line mode when we can
 
489
not do the banding any more and try to finish the page with the minimal
501
490
amount of passes.
502
491
 
503
 
So, first the driver calls the scheduler which returns a list of lines which 
504
 
it dispatched to print in the current band. Then the driver checks if it has 
505
 
all these lines halftoned. Since the head covers an area of 256 lines, we 
506
 
have to buffer that many lines (actually, 256-7). As the head moves down, 
 
492
So, first the driver calls the scheduler which returns a list of lines which
 
493
it dispatched to print in the current band. Then the driver checks if it has
 
494
all these lines halftoned. Since the head covers an area of 256 lines, we
 
495
have to buffer that many lines (actually, 256-7). As the head moves down,
507
496
we can flush lines which it has left and halftone the new ones.
508
497
 
509
 
 
510
498
Colour transformations
511
499
----------------------
512
500
 
520
508
ink of the real kind. You also have a black ink. Although in theory
521
509
mixing C, M, Y in equal amount will give you black, it doesn't exactly
522
510
work that way. In addition, black ink is cheap compared to the colour
523
 
so if you can use black, you rather use that. On top of all that, 
524
 
because of other effects (ink splashing on the paper and things like that) 
 
511
so if you can use black, you rather use that. On top of all that,
 
512
because of other effects (ink splashing on the paper and things like that)
525
513
you have to apply some non-linear functions to get reasonable colours.
526
514
 
527
515
Halftoning
534
522
it completely screws up some flat colours so don't use it.
535
523
There is also dithering, which is quick but noisy.
536
524
 
537
 
For any halftoning method, it is assumed that the haltoning can be 
 
525
For any halftoning method, it is assumed that the haltoning can be
538
526
done on the 4 colours (CMYK) separately and all interdependencies are
539
527
already handled. It is an optimistic assumption, however, close enough.
540
528
 
543
531
 
544
532
- Init, which is called before halftoning starts.
545
533
- Threshold, which should return a number which tells the driver how many
546
 
  empty lines needed before halftoning can be stopped (i.e. for how many 
 
534
  empty lines needed before halftoning can be stopped (i.e. for how many
547
535
  lines will a line affect halftoning of subsequent lines).
548
536
- Halftone, which halftones one colour of one line
549
537
- EndOfLine which is called when all colours of a scanline are halftoned,
550
538
  you can do your housekeeping functions here.
551
539
 
552
540
For example, in the case of ED init() clears the error buffers, threshold()
553
 
returns ~5 (5 empty lines are enough for the accumulated error to go to 
 
541
returns ~5 (5 empty lines are enough for the accumulated error to go to
554
542
almost zero), endofline() shuffles the error buffers and halftone() itself
555
543
does the error diffusion. In case of dithering, threshold is 0 (dithering
556
544
has no memory), init and endofline do nothing and halftone simply
564
552
  Therefore, an already set black pixel can block the halftoning of colours
565
553
  for that pixel. Whether this thing is activated or not is a command line
566
554
  switch (default is on). Your halftoner may choose to ignore this flag.
567
 
  
 
555
 
568
556
- the intensity value of the light-cyan and light-magenta ink can be
569
557
  set from the command line. My experience is that the default 127 is
570
558
  good enough, but you can override it if you want to.
571
 
  
572
 
Apart from these features, each halftoner can have all sorts of other 
573
 
switches. Currently there are switches for the Bendor ED, see the 
 
559
 
 
560
Apart from these features, each halftoner can have all sorts of other
 
561
switches. Currently there are switches for the Bendor ED, see the
574
562
comments in front of the BendorLine() function to see what they are.
575
563
 
576
564
Postprocessing
677
665
#define ICOLN                   4
678
666
 
679
667
/*
680
 
*       This is the maximum number of error lines needed by any 
 
668
*       This is the maximum number of error lines needed by any
681
669
*       currently implemented rendering function.
682
670
*       If you need more, increase it.
683
671
*/
685
673
#define MAX_ED_LINES    3
686
674
 
687
675
/*
688
 
*       If this is defined to !0 then we use Adobe's CMYK -> RGB mapping, 
 
676
*       If this is defined to !0 then we use Adobe's CMYK -> RGB mapping,
689
677
*       Ghostscript's otherwise. Ghostscript claims that their mapping
690
678
*       is better. The mapping of CMYK to RGB according to Adobe is:
691
 
*       
 
679
*
692
680
*               R = 1.0 - min( 1.0, C + K )
693
681
*               G = 1.0 - min( 1.0, M + K )
694
682
*               B = 1.0 - min( 1.0, Y + K )
695
683
*
696
684
*       while Ghostscript uses this:
697
 
*       
 
685
*
698
686
*               R = ( 1.0 - C ) * ( 1.0 - K )
699
687
*               G = ( 1.0 - M ) * ( 1.0 - K )
700
688
*               B = ( 1.0 - Y ) * ( 1.0 - K )
717
705
#define OFFS_K          3
718
706
 
719
707
#define DECOMPOSE_CMYK( index, c, m, y, k ) \
720
 
        {                                                                               \
721
 
                (k) = (index) & 255;                            \
722
 
                (y) = ( (index) >> 8 ) & 255;           \
723
 
                (m) = ( (index) >> 16 ) & 255;          \
724
 
                (c) = ( (index) >> 24 ) & 255;          \
725
 
        }
 
708
        {                                                                               \
 
709
                (k) = (index) & 255;                            \
 
710
                (y) = ( (index) >> 8 ) & 255;           \
 
711
                (m) = ( (index) >> 16 ) & 255;          \
 
712
                (c) = ( (index) >> 24 ) & 255;          \
 
713
        }
726
714
 
727
715
#define BUILD_CMYK( c, m, y, k ) \
728
 
        ((((long)(c)&255)<<24)|(((long)(m)&255)<<16)|\
729
 
        (((long)(y)&255)<<8)|((long)(k)&255))
 
716
        ((((long)(c)&255)<<24)|(((long)(m)&255)<<16)|\
 
717
        (((long)(y)&255)<<8)|((long)(k)&255))
730
718
 
731
719
/*
732
720
*       This structure is for colour compensation
733
721
*/
734
 
        
 
722
 
735
723
typedef struct {
736
724
 
737
 
        int             ra;                                             /* Real colour angle (hue)                              */
738
 
        int             ia;                                             /* Theoretical ink colour angle                 */
739
 
        int             c;                                              /* Cyan component                                               */
740
 
        int             m;                                              /* Magenta component                                    */
741
 
        int             y;                                              /* Yellow component                                             */
742
 
        
 
725
        int             ra;                                             /* Real colour angle (hue)                              */
 
726
        int             ia;                                             /* Theoretical ink colour angle                 */
 
727
        int             c;                                              /* Cyan component                                               */
 
728
        int             m;                                              /* Magenta component                                    */
 
729
        int             y;                                              /* Yellow component                                             */
 
730
 
743
731
} CCOMP;
744
732
 
745
733
/*
748
736
 
749
737
typedef struct gx_photoex_device_s {
750
738
 
751
 
        gx_device_common;                               /* This macro defines a graphics dev.   */
752
 
        gx_prn_device_common;                   /* This macro extends for printer dev.  */
753
 
        int             shingling;                              /* Shingling (multipass, overlap) mode  */
754
 
        int             depletion;                              /* Excess dot removal                                   */
755
 
        int             halftoner;                              /* Rendering type                                               */
756
 
        int             splash;                                 /* Splashing compensation factor                */
757
 
        int             leakage;                                /* Error leakage (percentage)                   */
758
 
        int             mono;                                   /* Monochrome mode (black only)                 */
759
 
        int             pureblack;                              /* Black ink blocks others                              */
760
 
        int             midcyan;                                /* Light cyan ink value                                 */
761
 
        int             midmagenta;                             /* Light magenta ink value                              */
762
 
        int             dotsize;                                /* Size of the ink dot                                  */
 
739
        gx_device_common;                               /* This macro defines a graphics dev.   */
 
740
        gx_prn_device_common;                   /* This macro extends for printer dev.  */
 
741
        int             shingling;                              /* Shingling (multipass, overlap) mode  */
 
742
        int             depletion;                              /* Excess dot removal                                   */
 
743
        int             halftoner;                              /* Rendering type                                               */
 
744
        int             splash;                                 /* Splashing compensation factor                */
 
745
        int             leakage;                                /* Error leakage (percentage)                   */
 
746
        int             mono;                                   /* Monochrome mode (black only)                 */
 
747
        int             pureblack;                              /* Black ink blocks others                              */
 
748
        int             midcyan;                                /* Light cyan ink value                                 */
 
749
        int             midmagenta;                             /* Light magenta ink value                              */
 
750
        int             dotsize;                                /* Size of the ink dot                                  */
763
751
 
764
752
} gx_photoex_device;
765
753
 
787
775
 
788
776
typedef struct  {
789
777
 
790
 
        int             first;                                  /* Index of the first useful byte       */
791
 
        int             last;                                   /* Index of the last useful byte        */
792
 
        byte    data[ MAX_BYTES ];              /* Actual raw data                                      */
 
778
        int             first;                                  /* Index of the first useful byte       */
 
779
        int             last;                                   /* Index of the last useful byte        */
 
780
        byte    data[ MAX_BYTES ];              /* Actual raw data                                      */
793
781
 
794
782
} RAWLINE;
795
783
 
796
784
/*
797
785
*       These definitions are used by the microweave scheduler.
798
786
*       These are the band height definitions. Do not fiddle with them,
799
 
*       they are the largest number with which no lines are skipped 
 
787
*       they are the largest number with which no lines are skipped
800
788
*       and the unused nozzles in the head for each band is minimal.
801
789
*       They, of course, depend on the number of nozzles in the head
802
790
*       and their spacing, these numbers are for 32 and 8, respectively.
812
800
 
813
801
/*
814
802
*       This structure is used to generate the line scheduling data.
815
 
*       Input/output refers to the scheduler I/F: input means data 
 
803
*       Input/output refers to the scheduler I/F: input means data
816
804
*       given to the scheduler, output is what it gives back. Unspecified
817
805
*       data is scheduler private.
818
806
*/
819
807
 
820
808
typedef struct {
821
809
 
822
 
        int             last;                                   /* Input        Last line to print                      */
823
 
        int             resol;                                  /* Input        X Resolution                            */
824
 
        int             nozzle;                                 /* Output       Number of nozzles                       */
825
 
        int             down;                                   /* Output       Lines to move down                      */
826
 
        int             head[ NOZZLES ];                /* Output       Which lines to be sent          */
827
 
        int             offset;                                 /* Output       Offset line by 1/1440"          */
828
 
        int             top;                                    /*                      Head position now                       */
829
 
        int             markbeg;                                /*                      First marked line                       */
830
 
        byte    mark[ MAX_MARK ];               /*                      Marks already printed lines     */
831
 
        
 
810
        int             last;                                   /* Input        Last line to print                      */
 
811
        int             resol;                                  /* Input        X Resolution                            */
 
812
        int             nozzle;                                 /* Output       Number of nozzles                       */
 
813
        int             down;                                   /* Output       Lines to move down                      */
 
814
        int             head[ NOZZLES ];                /* Output       Which lines to be sent          */
 
815
        int             offset;                                 /* Output       Offset line by 1/1440"          */
 
816
        int             top;                                    /*                      Head position now                       */
 
817
        int             markbeg;                                /*                      First marked line                       */
 
818
        byte    mark[ MAX_MARK ];               /*                      Marks already printed lines     */
 
819
 
832
820
} SCHEDUL;
833
821
 
834
822
/*
838
826
#define SendByte( s, x )        fputc( (x), (s) )
839
827
 
840
828
#define SendWord( s, x )        SendByte((s), (x) & 255); \
841
 
                                                        SendByte((s), ((x) >> 8 ) & 255);
 
829
                                                        SendByte((s), ((x) >> 8 ) & 255);
842
830
 
843
831
/*
844
832
*       This structure stores all the data during rendering
845
833
*/
846
834
 
847
835
typedef struct {
848
 
        
849
 
        EDEV    *dev;                                   /* The actual device struct                     */
850
 
        FILE    *stream;                                /* Output stream                                        */
851
 
        int             yres;                                   /* Y resolution                                         */
852
 
        int             xres;                                   /* X resolution                                         */
853
 
        int             start;                                  /* Left margin in 1/1440 inches         */      
854
 
        int             width;                                  /* Input data width in pixels           */
855
 
        int             lines;                                  /* Number of lines                                      */
856
 
        int             mono;                                   /* Black only                                           */
857
 
        byte    *dbuff;                                 /* Data buffer                                          */
858
 
        int             htone_thold;                    /* Halftoner restart threshold          */
859
 
        int             htone_last;                             /* Last line halftoned                          */
860
 
        SCHEDUL schedule;                               /* Line scheduling info                         */
861
 
        
862
 
        /* These are the error buffers for error diffusion. MAX_PIXELS*2
863
 
           is needed for 1440 dpi printing. */
864
 
        
865
 
        short   err[ MAX_ED_LINES ][ ICOLN ][ MAX_PIXELS*2 ];
866
 
        
867
 
        /* Error buffer pointers. I love C :-) */
868
 
        
869
 
        short   ( *error[ MAX_ED_LINES ] )[ MAX_PIXELS*2 ];
870
 
        
871
 
        /* This stores the halftoning result for a line, 
872
 
           not yet in device format. (It's CMYK 1 byte/pixel/colour) */
873
 
        
874
 
        byte    res[ ICOLN ][ MAX_PIXELS*2 ];
875
 
        
876
 
        /* This is the buffer for rendered lines, converted
877
 
           to raw device data (not yet run-length encoded).
878
 
           That is, it's 6 colours, 1 bit/pixel/colour.
879
 
           The first index is the 1440 dpi X-weave phase. */
880
 
           
881
 
        RAWLINE raw[ 2 ][ DCOLN ][ MAX_MARK ];  
882
 
        
883
 
        /* This buffer stores a single line of one colour,
884
 
           run-length encoded, ready to send to the printer */
885
 
        
886
 
        byte    rle[ MAX_PIXELS * 2 ];
887
 
        
 
836
 
 
837
        EDEV    *dev;                                   /* The actual device struct                     */
 
838
        FILE    *stream;                                /* Output stream                                        */
 
839
        int             yres;                                   /* Y resolution                                         */
 
840
        int             xres;                                   /* X resolution                                         */
 
841
        int             start;                                  /* Left margin in 1/1440 inches         */
 
842
        int             width;                                  /* Input data width in pixels           */
 
843
        int             lines;                                  /* Number of lines                                      */
 
844
        int             mono;                                   /* Black only                                           */
 
845
        byte    *dbuff;                                 /* Data buffer                                          */
 
846
        int             htone_thold;                    /* Halftoner restart threshold          */
 
847
        int             htone_last;                             /* Last line halftoned                          */
 
848
        SCHEDUL schedule;                               /* Line scheduling info                         */
 
849
 
 
850
        /* These are the error buffers for error diffusion. MAX_PIXELS*2
 
851
           is needed for 1440 dpi printing. */
 
852
 
 
853
        short   err[ MAX_ED_LINES ][ ICOLN ][ MAX_PIXELS*2 ];
 
854
 
 
855
        /* Error buffer pointers. I love C :-) */
 
856
 
 
857
        short   ( *error[ MAX_ED_LINES ] )[ MAX_PIXELS*2 ];
 
858
 
 
859
        /* This stores the halftoning result for a line,
 
860
           not yet in device format. (It's CMYK 1 byte/pixel/colour) */
 
861
 
 
862
        byte    res[ ICOLN ][ MAX_PIXELS*2 ];
 
863
 
 
864
        /* This is the buffer for rendered lines, converted
 
865
           to raw device data (not yet run-length encoded).
 
866
           That is, it's 6 colours, 1 bit/pixel/colour.
 
867
           The first index is the 1440 dpi X-weave phase. */
 
868
 
 
869
        RAWLINE raw[ 2 ][ DCOLN ][ MAX_MARK ];
 
870
 
 
871
        /* This buffer stores a single line of one colour,
 
872
           run-length encoded, ready to send to the printer */
 
873
 
 
874
        byte    rle[ MAX_PIXELS * 2 ];
 
875
 
888
876
} RENDER;
889
877
 
890
878
/*
892
880
*/
893
881
 
894
882
typedef struct  {
895
 
        
896
 
        RENDER  *render;                                /* Render info, if needed                               */
897
 
        byte    *data;                                  /* Input data                                                   */
898
 
        int     step;                                   /* Steps on input data                                  */
899
 
        byte    *res;                                   /* Result                                                               */
900
 
        byte    *block;                                 /* Blocking data                                                */
901
 
        short   **err;                                  /* Pointers to error buffers                    */
902
 
        int             lim1;                                   /* Halftoning lower limit                               */
903
 
        int             lim2;                                   /* Halftoning upper limit                               */
904
 
        int             mval;                                   /* Level represented by 'light' colour  */
905
 
        
906
 
} HTONE;        
 
883
 
 
884
        RENDER  *render;                                /* Render info, if needed                               */
 
885
        byte    *data;                                  /* Input data                                                   */
 
886
        int     step;                                   /* Steps on input data                                  */
 
887
        byte    *res;                                   /* Result                                                               */
 
888
        byte    *block;                                 /* Blocking data                                                */
 
889
        short   **err;                                  /* Pointers to error buffers                    */
 
890
        int             lim1;                                   /* Halftoning lower limit                               */
 
891
        int             lim2;                                   /* Halftoning upper limit                               */
 
892
        int             mval;                                   /* Level represented by 'light' colour  */
 
893
 
 
894
} HTONE;
907
895
 
908
896
/*
909
897
*       Halftoner function table
911
899
 
912
900
typedef struct {
913
901
 
914
 
        int             (*hthld)( RENDER *rend );
915
 
        void    (*hstrt)( RENDER *rend, int line );
916
 
        void    (*hteol)( RENDER *rend, int line );
917
 
        void    (*htone)( HTONE *htone, int line );
 
902
        int             (*hthld)( RENDER *rend );
 
903
        void    (*hstrt)( RENDER *rend, int line );
 
904
        void    (*hteol)( RENDER *rend, int line );
 
905
        void    (*htone)( HTONE *htone, int line );
918
906
 
919
907
} HFUNCS;
920
908
 
930
918
 
931
919
#define DMATRIX_X               16
932
920
#define DMATRIX_Y               16
933
 
        
 
921
 
934
922
/****************************************************************************/
935
923
/*                                                      Prototypes                                                                              */
936
924
/****************************************************************************/
943
931
static  int             photoex_put_params( DEV *dev, PLIST *plist );
944
932
 
945
933
static int      PutInt( PLIST *plist, PNAME name, int *val,
946
 
                                                int minval, int maxval, int code );
 
934
                                                int minval, int maxval, int code );
947
935
static  int             GetInt( PLIST *list, PNAME name, int *value, int code );
948
936
 
949
937
static  int             Cmy2A( int c, int m, int y );
1005
993
 
1006
994
static  const HFUNCS    htable[ MAXHTONE ] = {
1007
995
 
1008
 
        { FloydSThold, FloydSStart, FloydSEol, FloydSLine },
1009
 
        { DitherThold, DitherStart, DitherEol, DitherLine },
1010
 
        { BendorThold, BendorStart, BendorEol, BendorLine }
 
996
        { FloydSThold, FloydSStart, FloydSEol, FloydSLine },
 
997
        { DitherThold, DitherStart, DitherEol, DitherLine },
 
998
        { BendorThold, BendorStart, BendorEol, BendorLine }
1011
999
};
1012
1000
 
1013
1001
/*
1014
1002
*       Define the printer procedures.
1015
 
*       The definition is based on GS macros, the only real stuff that we 
 
1003
*       The definition is based on GS macros, the only real stuff that we
1016
1004
*       define here are the photoex_ functions.
1017
1005
*/
1018
1006
 
1019
1007
static  gx_device_procs photoex_device_procs = prn_color_params_procs(
1020
1008
 
1021
 
        photoex_open,                                   /* Opens the device                                             */
1022
 
        gdev_prn_output_page,
1023
 
        gdev_prn_close,
1024
 
        photoex_map_rgb_color,                  /* Maps an RGB pixel to device colour   */
1025
 
        photoex_map_color_rgb,                  /* Maps device colour back to RGB               */
1026
 
        photoex_get_params,                             /* Gets device parameters                               */
1027
 
        photoex_put_params                              /* Puts device parameters                               */
 
1009
        photoex_open,                                   /* Opens the device                                             */
 
1010
        gdev_prn_output_page,
 
1011
        gdev_prn_close,
 
1012
        photoex_map_rgb_color,                  /* Maps an RGB pixel to device colour   */
 
1013
        photoex_map_color_rgb,                  /* Maps device colour back to RGB               */
 
1014
        photoex_get_params,                             /* Gets device parameters                               */
 
1015
        photoex_put_params                              /* Puts device parameters                               */
1028
1016
);
1029
1017
 
1030
1018
/*
1034
1022
*/
1035
1023
 
1036
1024
gx_photoex_device far_data gs_photoex_device = {
1037
 
        
1038
 
        /* This is a macro that fills GS specific fields in the struct */
1039
 
        
1040
 
        prn_device_body(
1041
 
        
1042
 
                gx_photoex_device,                      /* Device struct type                                   */
1043
 
                photoex_device_procs,           /* Procedure table                                              */
1044
 
                "photoex",                                      /* Name of the device                                   */
1045
 
                DEFAULT_WIDTH_10THS,            /* Default width                                                */
1046
 
                DEFAULT_HEIGHT_10THS,           /* Default height                                               */
1047
 
                X_DPI,                                          /* Vertical resolution                                  */
1048
 
                Y_DPI,                                          /* Horizontal resolution                                */
1049
 
                MARGIN_L,                                       /* Left margin                                                  */
1050
 
                MARGIN_B,                                       /* Bottom margin                                                */
1051
 
                MARGIN_R,                                       /* Right margin                                                 */
1052
 
                MARGIN_T,                                       /* Top margin                                                   */
1053
 
                ICOLN,                                          /* Number of colours (4:CMYK)                   */
1054
 
                32,                                                     /* Bit per pixel for the device(!)              */
1055
 
                255,                                            /* Max. gray level                                              */
1056
 
                255,                                            /* Max. colour level                                    */
1057
 
                256,                                            /* Number of gray gradations                    */
1058
 
                256,                                            /* Number of colour gradations                  */
1059
 
                photoex_print_page                      /* Print page procedure                                 */
1060
 
        ),
1061
 
        
1062
 
        /* Here come our extensions */
1063
 
                
1064
 
        0,                                                              /* Shingling off, not implemented               */
1065
 
        0,                                                              /* Depletion off, not implemented               */
1066
 
        0,                                                              /* Dither type: FS ED                                   */
1067
 
        0,                                                              /* No splash correction                                 */
1068
 
        0,                                                              /* No leakage                                                   */
1069
 
        0,                                                              /* Not monochrome                                               */
1070
 
        1,                                                              /* Colour inhibition on black                   */
1071
 
        127,                                                    /* Mid level cyan                                               */
1072
 
        127,                                                    /* Mid level magenta                                    */
1073
 
        0                                                               /* Automatic dot size setting                   */
 
1025
 
 
1026
        /* This is a macro that fills GS specific fields in the struct */
 
1027
 
 
1028
        prn_device_body(
 
1029
 
 
1030
                gx_photoex_device,                      /* Device struct type                                   */
 
1031
                photoex_device_procs,           /* Procedure table                                              */
 
1032
                "photoex",                                      /* Name of the device                                   */
 
1033
                DEFAULT_WIDTH_10THS,            /* Default width                                                */
 
1034
                DEFAULT_HEIGHT_10THS,           /* Default height                                               */
 
1035
                X_DPI,                                          /* Vertical resolution                                  */
 
1036
                Y_DPI,                                          /* Horizontal resolution                                */
 
1037
                MARGIN_L,                                       /* Left margin                                                  */
 
1038
                MARGIN_B,                                       /* Bottom margin                                                */
 
1039
                MARGIN_R,                                       /* Right margin                                                 */
 
1040
                MARGIN_T,                                       /* Top margin                                                   */
 
1041
                ICOLN,                                          /* Number of colours (4:CMYK)                   */
 
1042
                32,                                                     /* Bit per pixel for the device(!)              */
 
1043
                255,                                            /* Max. gray level                                              */
 
1044
                255,                                            /* Max. colour level                                    */
 
1045
                256,                                            /* Number of gray gradations                    */
 
1046
                256,                                            /* Number of colour gradations                  */
 
1047
                photoex_print_page                      /* Print page procedure                                 */
 
1048
        ),
 
1049
 
 
1050
        /* Here come our extensions */
 
1051
 
 
1052
        0,                                                              /* Shingling off, not implemented               */
 
1053
        0,                                                              /* Depletion off, not implemented               */
 
1054
        0,                                                              /* Dither type: FS ED                                   */
 
1055
        0,                                                              /* No splash correction                                 */
 
1056
        0,                                                              /* No leakage                                                   */
 
1057
        0,                                                              /* Not monochrome                                               */
 
1058
        1,                                                              /* Colour inhibition on black                   */
 
1059
        127,                                                    /* Mid level cyan                                               */
 
1060
        127,                                                    /* Mid level magenta                                    */
 
1061
        0                                                               /* Automatic dot size setting                   */
1074
1062
};
1075
1063
 
1076
1064
/*
1077
 
*       This table contains the line scheduling table for the first 
 
1065
*       This table contains the line scheduling table for the first
1078
1066
*       few runs if we are in 720 dpi mode.
1079
1067
*/
1080
1068
 
1081
1069
static  const int       start_720[ HEAD_SPACING ][ NOZZLES ] = {
1082
1070
 
1083
 
        {         0,      8,     16,     24,     32,     40,     48,     56,
1084
 
                 64,     72,     80,     88,     96,    104,    112,    120,
1085
 
                128,    136,    144,    152,    160,    168,    176,    184,
1086
 
                192,    200,    208,    216,    224,    232,    240,    248 },
1087
 
 
1088
 
        {         1,      9,     17,     25,     33,     41,     49,     57,
1089
 
                 65,     73,     81,     89,     97,    105,    113,    121,
1090
 
                129,    137,    145,    153,    161,    169,    177,    185,
1091
 
                193,    201,    209,     -1,     -1,     -1,     -1,     -1 },
1092
 
 
1093
 
        {         2,     10,     18,     26,     34,     42,     50,     58,
1094
 
                 66,     74,     82,     90,     98,    106,    114,    122,
1095
 
                130,    138,    146,    154,    162,    170,    178,     -1,
1096
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
1097
 
 
1098
 
        {         3,     11,     19,     27,     35,     43,     51,     59,
1099
 
                 67,     75,     83,     91,     99,    107,    115,    123,
1100
 
                131,    139,    147,     -1,     -1,     -1,     -1,     -1,
1101
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
1102
 
 
1103
 
        {         4,     12,     20,     28,     36,     44,     52,     60,
1104
 
                 68,     76,     84,     92,    100,    108,    116,     -1,
1105
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1106
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
1107
 
 
1108
 
        {         5,     13,     21,     29,     37,     45,     53,     61,
1109
 
                 69,     77,     85,     -1,     -1,     -1,     -1,     -1,
1110
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1111
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
1112
 
 
1113
 
        {         6,     14,     22,     30,     38,     46,     54,     -1,
1114
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1115
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1116
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
1117
 
 
1118
 
        {         7,     15,     23,     -1,     -1,     -1,     -1,     -1,
1119
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1120
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1121
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 }
 
1071
        {         0,      8,     16,     24,     32,     40,     48,     56,
 
1072
                 64,     72,     80,     88,     96,    104,    112,    120,
 
1073
                128,    136,    144,    152,    160,    168,    176,    184,
 
1074
                192,    200,    208,    216,    224,    232,    240,    248 },
 
1075
 
 
1076
        {         1,      9,     17,     25,     33,     41,     49,     57,
 
1077
                 65,     73,     81,     89,     97,    105,    113,    121,
 
1078
                129,    137,    145,    153,    161,    169,    177,    185,
 
1079
                193,    201,    209,     -1,     -1,     -1,     -1,     -1 },
 
1080
 
 
1081
        {         2,     10,     18,     26,     34,     42,     50,     58,
 
1082
                 66,     74,     82,     90,     98,    106,    114,    122,
 
1083
                130,    138,    146,    154,    162,    170,    178,     -1,
 
1084
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
 
1085
 
 
1086
        {         3,     11,     19,     27,     35,     43,     51,     59,
 
1087
                 67,     75,     83,     91,     99,    107,    115,    123,
 
1088
                131,    139,    147,     -1,     -1,     -1,     -1,     -1,
 
1089
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
 
1090
 
 
1091
        {         4,     12,     20,     28,     36,     44,     52,     60,
 
1092
                 68,     76,     84,     92,    100,    108,    116,     -1,
 
1093
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1094
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
 
1095
 
 
1096
        {         5,     13,     21,     29,     37,     45,     53,     61,
 
1097
                 69,     77,     85,     -1,     -1,     -1,     -1,     -1,
 
1098
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1099
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
 
1100
 
 
1101
        {         6,     14,     22,     30,     38,     46,     54,     -1,
 
1102
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1103
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1104
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
 
1105
 
 
1106
        {         7,     15,     23,     -1,     -1,     -1,     -1,     -1,
 
1107
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1108
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1109
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 }
1122
1110
};
1123
1111
 
1124
 
 
1125
1112
/*
1126
 
*       This table contains the scheduling table for the first 
 
1113
*       This table contains the scheduling table for the first
1127
1114
*       few lines if we are in 1440 dpi mode
1128
1115
*/
1129
1116
 
1130
1117
static  const int       start_1440[ 2 ][ HEAD_SPACING ][ NOZZLES ] = {
1131
1118
  {
1132
 
        {         0,      8,     16,     24,     32,     40,     48,     56,
1133
 
                 64,     72,     80,     88,     96,    104,    112,    120,
1134
 
                128,    136,    144,    152,    160,    168,    176,    184,
1135
 
                192,    200,    208,    216,    224,    232,    240,    248 },
1136
 
 
1137
 
        {         1,      9,     17,     25,     33,     41,     49,     57,
1138
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1139
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1140
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
1141
 
 
1142
 
        {         2,     10,     18,     -1,     -1,     -1,     -1,     -1,
1143
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1144
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1145
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
1146
 
 
1147
 
        {         3,     11,     19,     27,     35,     43,     51,     59,
1148
 
                 67,     75,     83,     -1,     -1,     -1,     -1,     -1,
1149
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1150
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
1151
 
 
1152
 
        {         4,     12,     20,     28,     36,     44,     -1,     -1,
1153
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1154
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1155
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
1156
 
 
1157
 
        {         5,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1158
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1159
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1160
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
1161
 
 
1162
 
        {         6,     14,     22,     30,     38,     46,     54,     62,
1163
 
                 70,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1164
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1165
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
1166
 
 
1167
 
        {         7,     15,     23,     31,     -1,     -1,     -1,     -1,
1168
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1169
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1170
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
 
1119
        {         0,      8,     16,     24,     32,     40,     48,     56,
 
1120
                 64,     72,     80,     88,     96,    104,    112,    120,
 
1121
                128,    136,    144,    152,    160,    168,    176,    184,
 
1122
                192,    200,    208,    216,    224,    232,    240,    248 },
 
1123
 
 
1124
        {         1,      9,     17,     25,     33,     41,     49,     57,
 
1125
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1126
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1127
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
 
1128
 
 
1129
        {         2,     10,     18,     -1,     -1,     -1,     -1,     -1,
 
1130
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1131
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1132
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
 
1133
 
 
1134
        {         3,     11,     19,     27,     35,     43,     51,     59,
 
1135
                 67,     75,     83,     -1,     -1,     -1,     -1,     -1,
 
1136
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1137
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
 
1138
 
 
1139
        {         4,     12,     20,     28,     36,     44,     -1,     -1,
 
1140
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1141
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1142
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
 
1143
 
 
1144
        {         5,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1145
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1146
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1147
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
 
1148
 
 
1149
        {         6,     14,     22,     30,     38,     46,     54,     62,
 
1150
                 70,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1151
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1152
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
 
1153
 
 
1154
        {         7,     15,     23,     31,     -1,     -1,     -1,     -1,
 
1155
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1156
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1157
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
1171
1158
 
1172
1159
  },
1173
1160
  {
1174
 
        {         0,      8,     16,     24,     32,     40,     48,     56,
1175
 
                 64,     72,     80,     88,     96,     -1,     -1,     -1,
1176
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1177
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
1178
 
 
1179
 
        {         1,      9,     17,     25,     33,     41,     49,     57,
1180
 
                 65,     73,     81,     89,     97,    105,    113,    121,
1181
 
                129,    137,    145,    153,    161,     -1,     -1,     -1,
1182
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
1183
 
 
1184
 
        {         2,     10,     18,     26,     34,     42,     50,     58,
1185
 
                 66,     74,     82,     90,     98,    106,    114,    122,
1186
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1187
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
1188
 
 
1189
 
        {         3,     11,     19,     27,     35,     43,     51,     59,
1190
 
                 67,     75,     83,     91,     99,    107,    115,    123,
1191
 
                131,    139,    147,    155,    163,    171,    179,    187,
1192
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
1193
 
 
1194
 
        {         4,     12,     20,     28,     36,     44,     52,     60,
1195
 
                 68,     76,     84,     92,    100,    108,    116,    124,
1196
 
                132,    140,    148,     -1,     -1,     -1,     -1,     -1,
1197
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
1198
 
 
1199
 
        {         5,     13,     21,     29,     37,     45,     53,     61,
1200
 
                 69,     77,     85,     93,    101,    109,     -1,     -1,
1201
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1202
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
1203
 
 
1204
 
        {         6,     14,     22,     30,     38,     46,     54,     62,
1205
 
                 70,     78,     86,     94,    102,    110,    118,    126,
1206
 
                134,    142,    150,    158,    166,    174,     -1,     -1,
1207
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
1208
 
 
1209
 
        {         7,     15,     23,     31,     39,     47,     55,     63,
1210
 
                 71,     79,     87,     95,    103,    111,    119,    127,
1211
 
                135,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
1212
 
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
 
1161
        {         0,      8,     16,     24,     32,     40,     48,     56,
 
1162
                 64,     72,     80,     88,     96,     -1,     -1,     -1,
 
1163
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1164
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
 
1165
 
 
1166
        {         1,      9,     17,     25,     33,     41,     49,     57,
 
1167
                 65,     73,     81,     89,     97,    105,    113,    121,
 
1168
                129,    137,    145,    153,    161,     -1,     -1,     -1,
 
1169
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
 
1170
 
 
1171
        {         2,     10,     18,     26,     34,     42,     50,     58,
 
1172
                 66,     74,     82,     90,     98,    106,    114,    122,
 
1173
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1174
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
 
1175
 
 
1176
        {         3,     11,     19,     27,     35,     43,     51,     59,
 
1177
                 67,     75,     83,     91,     99,    107,    115,    123,
 
1178
                131,    139,    147,    155,    163,    171,    179,    187,
 
1179
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
 
1180
 
 
1181
        {         4,     12,     20,     28,     36,     44,     52,     60,
 
1182
                 68,     76,     84,     92,    100,    108,    116,    124,
 
1183
                132,    140,    148,     -1,     -1,     -1,     -1,     -1,
 
1184
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
 
1185
 
 
1186
        {         5,     13,     21,     29,     37,     45,     53,     61,
 
1187
                 69,     77,     85,     93,    101,    109,     -1,     -1,
 
1188
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1189
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
 
1190
 
 
1191
        {         6,     14,     22,     30,     38,     46,     54,     62,
 
1192
                 70,     78,     86,     94,    102,    110,    118,    126,
 
1193
                134,    142,    150,    158,    166,    174,     -1,     -1,
 
1194
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
 
1195
 
 
1196
        {         7,     15,     23,     31,     39,     47,     55,     63,
 
1197
                 71,     79,     87,     95,    103,    111,    119,    127,
 
1198
                135,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
 
1199
                 -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1 },
1213
1200
 
1214
1201
  }
1215
1202
};
1220
1207
*/
1221
1208
 
1222
1209
static  byte    dmatrix[ DMATRIX_Y ][ DMATRIX_X ] = {
1223
 
        {
1224
 
                0x0e, 0x8e, 0x2e, 0xae, 0x06, 0x86, 0x26, 0xa6,
1225
 
                0x0c, 0x8c, 0x2c, 0xac, 0x04, 0x84, 0x24, 0xa4
1226
 
        },
1227
 
        {
1228
 
                0xce, 0x4e, 0xee, 0x6e, 0xc6, 0x46, 0xe6, 0x66,
1229
 
                0xcc, 0x4c, 0xec, 0x6c, 0xc4, 0x44, 0xe4, 0x64
1230
 
        },
1231
 
        {
1232
 
                0x3e, 0xbe, 0x1e, 0x9e, 0x36, 0xb6, 0x16, 0x96,
1233
 
                0x3c, 0xbc, 0x1c, 0x9c, 0x34, 0xb4, 0x14, 0x94
1234
 
        },
1235
 
        {
1236
 
                0xfe, 0x7e, 0xde, 0x5e, 0xf6, 0x76, 0xd6, 0x56,
1237
 
                0xfc, 0x7c, 0xdc, 0x5c, 0xf4, 0x74, 0xd4, 0x54
1238
 
        },
1239
 
        {
1240
 
                0x01, 0x81, 0x21, 0xa1, 0x09, 0x89, 0x29, 0xa9,
1241
 
                0x03, 0x83, 0x23, 0xa3, 0x0b, 0x8b, 0x2b, 0xab
1242
 
        },
1243
 
        {
1244
 
                0xc1, 0x41, 0xe1, 0x61, 0xc9, 0x49, 0xe9, 0x69,
1245
 
                0xc3, 0x43, 0xe3, 0x63, 0xcb, 0x4b, 0xeb, 0x6b
1246
 
        },
1247
 
        {
1248
 
                0x31, 0xb1, 0x11, 0x91, 0x39, 0xb9, 0x19, 0x99,
1249
 
                0x33, 0xb3, 0x13, 0x93, 0x3b, 0xbb, 0x1b, 0x9b
1250
 
        },
1251
 
        {
1252
 
                0xf1, 0x71, 0xd1, 0x51, 0xf9, 0x79, 0xd9, 0x59,
1253
 
                0xf3, 0x73, 0xd3, 0x53, 0xfb, 0x7b, 0xdb, 0x5b
1254
 
        },
1255
 
        {
1256
 
                0x0d, 0x8d, 0x2d, 0xad, 0x05, 0x85, 0x25, 0xa5,
1257
 
                0x0f, 0x8f, 0x2f, 0xaf, 0x07, 0x87, 0x27, 0xa7
1258
 
        },
1259
 
        {
1260
 
                0xcd, 0x4d, 0xed, 0x6d, 0xc5, 0x45, 0xe5, 0x65,
1261
 
                0xcf, 0x4f, 0xef, 0x6f, 0xc7, 0x47, 0xe7, 0x67
1262
 
        },
1263
 
        {
1264
 
                0x3d, 0xbd, 0x1d, 0x9d, 0x35, 0xb5, 0x15, 0x95,
1265
 
                0x3f, 0xbf, 0x1f, 0x9f, 0x37, 0xb7, 0x17, 0x97
1266
 
        },
1267
 
        {
1268
 
                0xfd, 0x7d, 0xdd, 0x5d, 0xf5, 0x75, 0xd5, 0x55,
1269
 
                0xff, 0x7f, 0xdf, 0x5f, 0xf7, 0x77, 0xd7, 0x57
1270
 
        },
1271
 
        {
1272
 
                0x02, 0x82, 0x22, 0xa2, 0x0a, 0x8a, 0x2a, 0xaa,
1273
 
                0x01, 0x80, 0x20, 0xa0, 0x08, 0x88, 0x28, 0xa8
1274
 
        },
1275
 
        {
1276
 
                0xc2, 0x42, 0xe2, 0x62, 0xca, 0x4a, 0xea, 0x6a,
1277
 
                0xc0, 0x40, 0xe0, 0x60, 0xc8, 0x48, 0xe8, 0x68
1278
 
        },
1279
 
        {
1280
 
                0x32, 0xb2, 0x12, 0x92, 0x3a, 0xba, 0x1a, 0x9a,
1281
 
                0x30, 0xb0, 0x10, 0x90, 0x38, 0xb8, 0x18, 0x98
1282
 
        },
1283
 
        {
1284
 
                0xf2, 0x72, 0xd2, 0x52, 0xfa, 0x7a, 0xda, 0x5a,
1285
 
                0xf0, 0x70, 0xd0, 0x50, 0xf8, 0x78, 0xd8, 0x58
1286
 
        }
 
1210
        {
 
1211
                0x0e, 0x8e, 0x2e, 0xae, 0x06, 0x86, 0x26, 0xa6,
 
1212
                0x0c, 0x8c, 0x2c, 0xac, 0x04, 0x84, 0x24, 0xa4
 
1213
        },
 
1214
        {
 
1215
                0xce, 0x4e, 0xee, 0x6e, 0xc6, 0x46, 0xe6, 0x66,
 
1216
                0xcc, 0x4c, 0xec, 0x6c, 0xc4, 0x44, 0xe4, 0x64
 
1217
        },
 
1218
        {
 
1219
                0x3e, 0xbe, 0x1e, 0x9e, 0x36, 0xb6, 0x16, 0x96,
 
1220
                0x3c, 0xbc, 0x1c, 0x9c, 0x34, 0xb4, 0x14, 0x94
 
1221
        },
 
1222
        {
 
1223
                0xfe, 0x7e, 0xde, 0x5e, 0xf6, 0x76, 0xd6, 0x56,
 
1224
                0xfc, 0x7c, 0xdc, 0x5c, 0xf4, 0x74, 0xd4, 0x54
 
1225
        },
 
1226
        {
 
1227
                0x01, 0x81, 0x21, 0xa1, 0x09, 0x89, 0x29, 0xa9,
 
1228
                0x03, 0x83, 0x23, 0xa3, 0x0b, 0x8b, 0x2b, 0xab
 
1229
        },
 
1230
        {
 
1231
                0xc1, 0x41, 0xe1, 0x61, 0xc9, 0x49, 0xe9, 0x69,
 
1232
                0xc3, 0x43, 0xe3, 0x63, 0xcb, 0x4b, 0xeb, 0x6b
 
1233
        },
 
1234
        {
 
1235
                0x31, 0xb1, 0x11, 0x91, 0x39, 0xb9, 0x19, 0x99,
 
1236
                0x33, 0xb3, 0x13, 0x93, 0x3b, 0xbb, 0x1b, 0x9b
 
1237
        },
 
1238
        {
 
1239
                0xf1, 0x71, 0xd1, 0x51, 0xf9, 0x79, 0xd9, 0x59,
 
1240
                0xf3, 0x73, 0xd3, 0x53, 0xfb, 0x7b, 0xdb, 0x5b
 
1241
        },
 
1242
        {
 
1243
                0x0d, 0x8d, 0x2d, 0xad, 0x05, 0x85, 0x25, 0xa5,
 
1244
                0x0f, 0x8f, 0x2f, 0xaf, 0x07, 0x87, 0x27, 0xa7
 
1245
        },
 
1246
        {
 
1247
                0xcd, 0x4d, 0xed, 0x6d, 0xc5, 0x45, 0xe5, 0x65,
 
1248
                0xcf, 0x4f, 0xef, 0x6f, 0xc7, 0x47, 0xe7, 0x67
 
1249
        },
 
1250
        {
 
1251
                0x3d, 0xbd, 0x1d, 0x9d, 0x35, 0xb5, 0x15, 0x95,
 
1252
                0x3f, 0xbf, 0x1f, 0x9f, 0x37, 0xb7, 0x17, 0x97
 
1253
        },
 
1254
        {
 
1255
                0xfd, 0x7d, 0xdd, 0x5d, 0xf5, 0x75, 0xd5, 0x55,
 
1256
                0xff, 0x7f, 0xdf, 0x5f, 0xf7, 0x77, 0xd7, 0x57
 
1257
        },
 
1258
        {
 
1259
                0x02, 0x82, 0x22, 0xa2, 0x0a, 0x8a, 0x2a, 0xaa,
 
1260
                0x01, 0x80, 0x20, 0xa0, 0x08, 0x88, 0x28, 0xa8
 
1261
        },
 
1262
        {
 
1263
                0xc2, 0x42, 0xe2, 0x62, 0xca, 0x4a, 0xea, 0x6a,
 
1264
                0xc0, 0x40, 0xe0, 0x60, 0xc8, 0x48, 0xe8, 0x68
 
1265
        },
 
1266
        {
 
1267
                0x32, 0xb2, 0x12, 0x92, 0x3a, 0xba, 0x1a, 0x9a,
 
1268
                0x30, 0xb0, 0x10, 0x90, 0x38, 0xb8, 0x18, 0x98
 
1269
        },
 
1270
        {
 
1271
                0xf2, 0x72, 0xd2, 0x52, 0xfa, 0x7a, 0xda, 0x5a,
 
1272
                0xf0, 0x70, 0xd0, 0x50, 0xf8, 0x78, 0xd8, 0x58
 
1273
        }
1287
1274
};
1288
1275
 
1289
1276
/*
1292
1279
 
1293
1280
static  CCOMP   ctable[] = {
1294
1281
 
1295
 
        { -255, -255,   0,   0, 255 },          /* same as green */
1296
 
        {  102,    0, 255,   0,   0 },          /* cyan */
1297
 
        {  255,  255, 255, 255,   0 },          /* blue */
1298
 
        {  560,  512,   0, 255,   0 },          /* magenta */
1299
 
        {  765,  765,   0, 255, 255 },          /* red */
1300
 
        { 1045, 1020,   0,   0, 255 },          /* yellow */
1301
 
        { 1275, 1275, 255,   0, 255 },          /* green */
1302
 
        { 1632, 1530, 255,   0,   0 }           /* same as cyan */
 
1282
        { -255, -255,   0,   0, 255 },          /* same as green */
 
1283
        {  102,    0, 255,   0,   0 },          /* cyan */
 
1284
        {  255,  255, 255, 255,   0 },          /* blue */
 
1285
        {  560,  512,   0, 255,   0 },          /* magenta */
 
1286
        {  765,  765,   0, 255, 255 },          /* red */
 
1287
        { 1045, 1020,   0,   0, 255 },          /* yellow */
 
1288
        { 1275, 1275, 255,   0, 255 },          /* green */
 
1289
        { 1632, 1530, 255,   0,   0 }           /* same as cyan */
1303
1290
};
1304
1291
 
1305
1292
/*
1309
1296
 
1310
1297
static const unsigned char      xtrans[ 256 ] = {
1311
1298
 
1312
 
          0,   0,   0,   0,   0,   0,   0,   0,   
1313
 
          0,   0,   0,   0,   0,   0,   0,   0, 
1314
 
          0,   0,   0,   0,   0,   0,   0,   0,   
1315
 
          0,   0,   0,   0,   0,   0,   0,   0, 
1316
 
          0,   0,   0,   0,   1,   1,   1,   1,   
1317
 
          1,   1,   1,   1,   1,   1,   1,   1, 
1318
 
          1,   1,   1,   1,   2,   2,   2,   2,   
1319
 
          2,   2,   2,   2,   2,   2,   3,   3, 
1320
 
          3,   3,   3,   3,   3,   4,   4,   4,   
1321
 
          4,   4,   4,   5,   5,   5,   5,   5, 
1322
 
          6,   6,   6,   6,   6,   7,   7,   7,   
1323
 
          7,   8,   8,   8,   8,   9,   9,   9, 
1324
 
         10,  10,  10,  11,  11,  11,  12,  12,  
1325
 
         12,  13,  13,  13,  14,  14,  14,  15, 
1326
 
         15,  16,  16,  17,  17,  17,  18,  18,  
1327
 
         19,  19,  20,  20,  21,  21,  22,  22, 
1328
 
         23,  23,  24,  24,  25,  26,  26,  27,  
1329
 
         27,  28,  29,  29,  30,  30,  31,  32, 
1330
 
         32,  33,  34,  34,  35,  36,  37,  37,  
1331
 
         38,  39,  40,  40,  41,  42,  43,  44, 
1332
 
         44,  45,  46,  47,  48,  49,  50,  51,  
1333
 
         51,  52,  53,  54,  55,  56,  57,  58, 
1334
 
         59,  60,  61,  62,  63,  64,  65,  67,  
1335
 
         68,  69,  70,  71,  72,  73,  74,  76, 
1336
 
         77,  78,  79,  80,  82,  83,  84,  86,  
1337
 
         87,  88,  89,  91,  92,  94,  95,  96, 
1338
 
         98,  99, 101, 102, 103, 105, 106, 108, 
1339
 
        109, 111, 112, 114, 116, 117, 119, 120, 
1340
 
        122, 124, 125, 127, 129, 130, 132, 134, 
1341
 
        136, 137, 139, 141, 143, 145, 146, 148, 
1342
 
        150, 152, 154, 156, 158, 160, 162, 164, 
1343
 
        166, 168, 170, 172, 174, 176, 178, 180
 
1299
          0,   0,   0,   0,   0,   0,   0,   0,
 
1300
          0,   0,   0,   0,   0,   0,   0,   0,
 
1301
          0,   0,   0,   0,   0,   0,   0,   0,
 
1302
          0,   0,   0,   0,   0,   0,   0,   0,
 
1303
          0,   0,   0,   0,   1,   1,   1,   1,
 
1304
          1,   1,   1,   1,   1,   1,   1,   1,
 
1305
          1,   1,   1,   1,   2,   2,   2,   2,
 
1306
          2,   2,   2,   2,   2,   2,   3,   3,
 
1307
          3,   3,   3,   3,   3,   4,   4,   4,
 
1308
          4,   4,   4,   5,   5,   5,   5,   5,
 
1309
          6,   6,   6,   6,   6,   7,   7,   7,
 
1310
          7,   8,   8,   8,   8,   9,   9,   9,
 
1311
         10,  10,  10,  11,  11,  11,  12,  12,
 
1312
         12,  13,  13,  13,  14,  14,  14,  15,
 
1313
         15,  16,  16,  17,  17,  17,  18,  18,
 
1314
         19,  19,  20,  20,  21,  21,  22,  22,
 
1315
         23,  23,  24,  24,  25,  26,  26,  27,
 
1316
         27,  28,  29,  29,  30,  30,  31,  32,
 
1317
         32,  33,  34,  34,  35,  36,  37,  37,
 
1318
         38,  39,  40,  40,  41,  42,  43,  44,
 
1319
         44,  45,  46,  47,  48,  49,  50,  51,
 
1320
         51,  52,  53,  54,  55,  56,  57,  58,
 
1321
         59,  60,  61,  62,  63,  64,  65,  67,
 
1322
         68,  69,  70,  71,  72,  73,  74,  76,
 
1323
         77,  78,  79,  80,  82,  83,  84,  86,
 
1324
         87,  88,  89,  91,  92,  94,  95,  96,
 
1325
         98,  99, 101, 102, 103, 105, 106, 108,
 
1326
        109, 111, 112, 114, 116, 117, 119, 120,
 
1327
        122, 124, 125, 127, 129, 130, 132, 134,
 
1328
        136, 137, 139, 141, 143, 145, 146, 148,
 
1329
        150, 152, 154, 156, 158, 160, 162, 164,
 
1330
        166, 168, 170, 172, 174, 176, 178, 180
1344
1331
};
1345
1332
 
1346
1333
/****************************************************************************/
1353
1340
double  width;
1354
1341
float   margins[ 4 ];                                           /* L, B, R, T                                   */
1355
1342
 
1356
 
        height = pdev->height / pdev->y_pixels_per_inch;
1357
 
        width  = pdev->width  / pdev->x_pixels_per_inch;
1358
 
        
1359
 
        margins[ 0 ] = 0.12;
1360
 
        margins[ 1 ] = 0.5;
1361
 
        margins[ 2 ] = 0.12;
1362
 
        margins[ 3 ] = ( width > 11.46+0.12 ) ? width - (11.46+0.12) : 0.12;
1363
 
        
1364
 
        gx_device_set_margins( pdev, margins, true );
1365
 
        return( gdev_prn_open( pdev ) );
 
1343
        height = pdev->height / pdev->y_pixels_per_inch;
 
1344
        width  = pdev->width  / pdev->x_pixels_per_inch;
 
1345
 
 
1346
        margins[ 0 ] = 0.12;
 
1347
        margins[ 1 ] = 0.5;
 
1348
        margins[ 2 ] = 0.12;
 
1349
        margins[ 3 ] = ( width > 11.46+0.12 ) ? width - (11.46+0.12) : 0.12;
 
1350
 
 
1351
        gx_device_set_margins( pdev, margins, true );
 
1352
        return( gdev_prn_open( pdev ) );
1366
1353
}
1367
1354
 
1368
1355
/****************************************************************************/
1370
1357
/****************************************************************************/
1371
1358
 
1372
1359
/*
1373
 
*       Map an RGB colour to device colour. 
 
1360
*       Map an RGB colour to device colour.
1374
1361
*       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1375
1362
*
1376
 
*       Since we present ourselves to Ghostscript as if we were a 
1377
 
*       full colour resolution RGB device, we calculate the CMYK 
 
1363
*       Since we present ourselves to Ghostscript as if we were a
 
1364
*       full colour resolution RGB device, we calculate the CMYK
1378
1365
*       values and pack them into the result. This depends on
1379
1366
*       color_index being at least 32 bit !!!
1380
1367
*/
1386
1373
EDEV    *edev;
1387
1374
int             i;
1388
1375
 
1389
 
        edev = (EDEV *) dev;
1390
 
                
1391
 
        /* White and black are treated on their own */
1392
 
        
1393
 
        if ( ( r & g & b ) == ( 1 << gx_color_value_bits ) - 1 ) {
1394
 
        
1395
 
                /* White */
1396
 
                
1397
 
                return( BUILD_CMYK( 0, 0, 0, 0 ) );     
1398
 
        }
1399
 
        
1400
 
        if ( ( r | g | b ) == 0 ) {
1401
 
        
1402
 
                /* Black */
1403
 
                
1404
 
                return( BUILD_CMYK( 0, 0, 0, xtrans[ 0xff ] ) );
1405
 
        }
1406
 
 
1407
 
        /* Map RGB to 8 bit/colour CMY */
1408
 
        
1409
 
        c = 255 - ( r >> ( gx_color_value_bits - 8 ) );
1410
 
        m = 255 - ( g >> ( gx_color_value_bits - 8 ) );
1411
 
        y = 255 - ( b >> ( gx_color_value_bits - 8 ) );
1412
 
        
1413
 
        k = xtrans[ min( c, min( m, y ) ) ] * 0.8; /* FIXME:empirical constant */
1414
 
        c -= k;
1415
 
        m -= k;
1416
 
        y -= k;
1417
 
        
1418
 
        s = max ( c, max( y, m ) );
1419
 
                        
1420
 
        /* Map the colour to an angle and find the relevant table range */
1421
 
        
1422
 
        a = Cmy2A( c, m, y );
1423
 
        for ( i = 1 ; a > ctable[ i ].ra ; i++ );
1424
 
 
1425
 
        /* Now map c, m, y. */
1426
 
        
1427
 
        f = ((a - ctable[ i-1 ].ra) << 16 ) / (ctable[ i ].ra - ctable[ i-1 ].ra);
1428
 
        c = (( ctable[i-1].c << 16 ) + ( ctable[i].c - ctable[i-1].c ) * f ) >> 16;
1429
 
        m = (( ctable[i-1].m << 16 ) + ( ctable[i].m - ctable[i-1].m ) * f ) >> 16;
1430
 
        y = (( ctable[i-1].y << 16 ) + ( ctable[i].y - ctable[i-1].y ) * f ) >> 16;
1431
 
        
1432
 
        s = xtrans[ s ];
1433
 
        c = ( c * s ) >> 8;
1434
 
        m = ( m * s ) >> 8;
1435
 
        y = ( y * s ) >> 8;
1436
 
        
1437
 
        return( BUILD_CMYK( c, m, y, k ) );
 
1376
        edev = (EDEV *) dev;
 
1377
 
 
1378
        /* White and black are treated on their own */
 
1379
 
 
1380
        if ( ( r & g & b ) == ( 1 << gx_color_value_bits ) - 1 ) {
 
1381
 
 
1382
                /* White */
 
1383
 
 
1384
                return( BUILD_CMYK( 0, 0, 0, 0 ) );
 
1385
        }
 
1386
 
 
1387
        if ( ( r | g | b ) == 0 ) {
 
1388
 
 
1389
                /* Black */
 
1390
 
 
1391
                return( BUILD_CMYK( 0, 0, 0, xtrans[ 0xff ] ) );
 
1392
        }
 
1393
 
 
1394
        /* Map RGB to 8 bit/colour CMY */
 
1395
 
 
1396
        c = 255 - ( r >> ( gx_color_value_bits - 8 ) );
 
1397
        m = 255 - ( g >> ( gx_color_value_bits - 8 ) );
 
1398
        y = 255 - ( b >> ( gx_color_value_bits - 8 ) );
 
1399
 
 
1400
        k = xtrans[ min( c, min( m, y ) ) ] * 0.8; /* FIXME:empirical constant */
 
1401
        c -= k;
 
1402
        m -= k;
 
1403
        y -= k;
 
1404
 
 
1405
        s = max ( c, max( y, m ) );
 
1406
 
 
1407
        /* Map the colour to an angle and find the relevant table range */
 
1408
 
 
1409
        a = Cmy2A( c, m, y );
 
1410
        for ( i = 1 ; a > ctable[ i ].ra ; i++ );
 
1411
 
 
1412
        /* Now map c, m, y. */
 
1413
 
 
1414
        f = ((a - ctable[ i-1 ].ra) << 16 ) / (ctable[ i ].ra - ctable[ i-1 ].ra);
 
1415
        c = (( ctable[i-1].c << 16 ) + ( ctable[i].c - ctable[i-1].c ) * f ) >> 16;
 
1416
        m = (( ctable[i-1].m << 16 ) + ( ctable[i].m - ctable[i-1].m ) * f ) >> 16;
 
1417
        y = (( ctable[i-1].y << 16 ) + ( ctable[i].y - ctable[i-1].y ) * f ) >> 16;
 
1418
 
 
1419
        s = xtrans[ s ];
 
1420
        c = ( c * s ) >> 8;
 
1421
        m = ( m * s ) >> 8;
 
1422
        y = ( y * s ) >> 8;
 
1423
 
 
1424
        return( BUILD_CMYK( c, m, y, k ) );
1438
1425
}
1439
1426
 
1440
1427
/*
1441
 
*       Map a device colour value back to RGB. 
 
1428
*       Map a device colour value back to RGB.
1442
1429
*       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1443
1430
*
1444
1431
*       CAVEAT:
1451
1438
uint    c, m, y, k;
1452
1439
CVAL    r, g, b;
1453
1440
 
1454
 
        /* Let's separate the colours */
1455
 
        
1456
 
        DECOMPOSE_CMYK( index, c, m, y, k );
1457
 
        
1458
 
        k = index & 255;
1459
 
        y = ( index >> 8 ) & 255;
1460
 
        m = ( index >> 16 ) & 255;
1461
 
        c = ( index >> 24 ) & 255;
1462
 
        
1463
 
        /* Depending on whether we use Adobe or Ghostscript mapping,
1464
 
           calculate the colours */
1465
 
                
1466
 
        if ( MAP_RGB_ADOBE ) {
1467
 
 
1468
 
                r = gx_max_color_value * ( 1.0 - min( 1.0, (c / 255.0 + k / 255.0) ) );
1469
 
                g = gx_max_color_value * ( 1.0 - min( 1.0, (m / 255.0 + k / 255.0) ) );
1470
 
                b = gx_max_color_value * ( 1.0 - min( 1.0, (y / 255.0 + k / 255.0) ) );
1471
 
        }
1472
 
        else {
1473
 
        
1474
 
                r = gx_max_color_value * ( 1.0 - c / 255.0 ) * ( 1.0 - k / 255.0);
1475
 
                g = gx_max_color_value * ( 1.0 - m / 255.0 ) * ( 1.0 - k / 255.0);
1476
 
                b = gx_max_color_value * ( 1.0 - y / 255.0 ) * ( 1.0 - k / 255.0);
1477
 
        }
1478
 
        
1479
 
        prgb[ 0 ] = r;
1480
 
        prgb[ 1 ] = g;
1481
 
        prgb[ 2 ] = b;
1482
 
        
1483
 
        return( 0 );
 
1441
        /* Let's separate the colours */
 
1442
 
 
1443
        DECOMPOSE_CMYK( index, c, m, y, k );
 
1444
 
 
1445
        k = index & 255;
 
1446
        y = ( index >> 8 ) & 255;
 
1447
        m = ( index >> 16 ) & 255;
 
1448
        c = ( index >> 24 ) & 255;
 
1449
 
 
1450
        /* Depending on whether we use Adobe or Ghostscript mapping,
 
1451
           calculate the colours */
 
1452
 
 
1453
        if ( MAP_RGB_ADOBE ) {
 
1454
 
 
1455
                r = gx_max_color_value * ( 1.0 - min( 1.0, (c / 255.0 + k / 255.0) ) );
 
1456
                g = gx_max_color_value * ( 1.0 - min( 1.0, (m / 255.0 + k / 255.0) ) );
 
1457
                b = gx_max_color_value * ( 1.0 - min( 1.0, (y / 255.0 + k / 255.0) ) );
 
1458
        }
 
1459
        else {
 
1460
 
 
1461
                r = gx_max_color_value * ( 1.0 - c / 255.0 ) * ( 1.0 - k / 255.0);
 
1462
                g = gx_max_color_value * ( 1.0 - m / 255.0 ) * ( 1.0 - k / 255.0);
 
1463
                b = gx_max_color_value * ( 1.0 - y / 255.0 ) * ( 1.0 - k / 255.0);
 
1464
        }
 
1465
 
 
1466
        prgb[ 0 ] = r;
 
1467
        prgb[ 1 ] = g;
 
1468
        prgb[ 2 ] = b;
 
1469
 
 
1470
        return( 0 );
1484
1471
}
1485
1472
 
1486
1473
/*
1487
1474
*       This function maps a (c,m,y) triplet into an angle.
1488
1475
*       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1489
1476
*
1490
 
*       Angle:    0 cyan        C=255 M=  0 Y=  0 
 
1477
*       Angle:    0 cyan        C=255 M=  0 Y=  0
1491
1478
*                       255 blue    C=255 M=255 Y=  0
1492
1479
*                       510 magenta     C=  0 M=255 Y=  0
1493
1480
*                       765 red     C=  0 M=255 Y=255
1494
1481
*                  1020 yellow  C=  0 M=  0 Y=255
1495
1482
*                  1275 green   C=255 M=  0 Y=255
1496
 
*                  1530 cyan 
 
1483
*                  1530 cyan
1497
1484
*/
1498
1485
 
1499
1486
static  int             Cmy2A( int c, int m, int y )
1502
1489
int             maxim;
1503
1490
int             a;
1504
1491
 
1505
 
        /* Calculate the black level */
1506
 
        
1507
 
        black = min( c, min( m, y ) );
1508
 
         
1509
 
        /* Remove the black from the colours themselves */
1510
 
        
1511
 
        c -= black;
1512
 
        m -= black;
1513
 
        y -= black;
1514
 
        
1515
 
        /* If all 3 remaining colours are 0, then it is a gray: special case */
1516
 
        
1517
 
        if ( ! c && ! m && ! y ) return( 0 );
1518
 
        
1519
 
        /* Normalise the colours. At least one at most two of them is 0
1520
 
           and at least one at most two of them is 255 */
1521
 
        
1522
 
        maxim = max( c, max( m, y ) );
1523
 
        
1524
 
        c = ( 255 * c ) / maxim;
1525
 
        m = ( 255 * m ) / maxim;
1526
 
        y = ( 255 * y ) / maxim;
1527
 
        
1528
 
        if ( c == 255 ) {
1529
 
        
1530
 
                if ( ! y )
1531
 
                
1532
 
                        a = m;                                  /* cyan - blue */
1533
 
                else
1534
 
                        a = 1530 - y;                   /* green - cyan */
1535
 
        }
1536
 
        else if ( m == 255 ) {
1537
 
        
1538
 
                if ( ! c )
1539
 
                        
1540
 
                        a = 510 + y;                    /* magenta - red */
1541
 
                else
1542
 
                        a = 510 - c;                    /* blue - magenta */
1543
 
        }
1544
 
        else {
1545
 
        
1546
 
                if ( ! m )
1547
 
                        
1548
 
                        a = 1020 + c;                   /* yellow - green */
1549
 
                else
1550
 
                        a = 1020 - m;                   /* red - yellow */
1551
 
        }
1552
 
        
1553
 
        return( a );
 
1492
        /* Calculate the black level */
 
1493
 
 
1494
        black = min( c, min( m, y ) );
 
1495
 
 
1496
        /* Remove the black from the colours themselves */
 
1497
 
 
1498
        c -= black;
 
1499
        m -= black;
 
1500
        y -= black;
 
1501
 
 
1502
        /* If all 3 remaining colours are 0, then it is a gray: special case */
 
1503
 
 
1504
        if ( ! c && ! m && ! y ) return( 0 );
 
1505
 
 
1506
        /* Normalise the colours. At least one at most two of them is 0
 
1507
           and at least one at most two of them is 255 */
 
1508
 
 
1509
        maxim = max( c, max( m, y ) );
 
1510
 
 
1511
        c = ( 255 * c ) / maxim;
 
1512
        m = ( 255 * m ) / maxim;
 
1513
        y = ( 255 * y ) / maxim;
 
1514
 
 
1515
        if ( c == 255 ) {
 
1516
 
 
1517
                if ( ! y )
 
1518
 
 
1519
                        a = m;                                  /* cyan - blue */
 
1520
                else
 
1521
                        a = 1530 - y;                   /* green - cyan */
 
1522
        }
 
1523
        else if ( m == 255 ) {
 
1524
 
 
1525
                if ( ! c )
 
1526
 
 
1527
                        a = 510 + y;                    /* magenta - red */
 
1528
                else
 
1529
                        a = 510 - c;                    /* blue - magenta */
 
1530
        }
 
1531
        else {
 
1532
 
 
1533
                if ( ! m )
 
1534
 
 
1535
                        a = 1020 + c;                   /* yellow - green */
 
1536
                else
 
1537
                        a = 1020 - m;                   /* red - yellow */
 
1538
        }
 
1539
 
 
1540
        return( a );
1554
1541
}
1555
1542
 
1556
1543
/****************************************************************************/
1567
1554
int             code;
1568
1555
EDEV    *dev;
1569
1556
 
1570
 
        dev  = (EDEV *) device;
1571
 
        
1572
 
        code = gdev_prn_get_params( device, plist );
1573
 
        
1574
 
        code = GetInt( plist, "Depletion",      &dev->depletion, code );
1575
 
        code = GetInt( plist, "Shingling",      &dev->shingling, code );
1576
 
        code = GetInt( plist, "Render",         &dev->halftoner, code );
1577
 
        code = GetInt( plist, "Splash",         &dev->splash,    code );
1578
 
        code = GetInt( plist, "Leakage",        &dev->leakage,   code );
1579
 
        code = GetInt( plist, "Binhibit",       &dev->pureblack, code );
1580
 
        code = GetInt( plist, "DotSize",        &dev->dotsize,   code );        
1581
 
        return( code );
 
1557
        dev  = (EDEV *) device;
 
1558
 
 
1559
        code = gdev_prn_get_params( device, plist );
 
1560
 
 
1561
        code = GetInt( plist, "Depletion",      &dev->depletion, code );
 
1562
        code = GetInt( plist, "Shingling",      &dev->shingling, code );
 
1563
        code = GetInt( plist, "Render",         &dev->halftoner, code );
 
1564
        code = GetInt( plist, "Splash",         &dev->splash,    code );
 
1565
        code = GetInt( plist, "Leakage",        &dev->leakage,   code );
 
1566
        code = GetInt( plist, "Binhibit",       &dev->pureblack, code );
 
1567
        code = GetInt( plist, "DotSize",        &dev->dotsize,   code );
 
1568
        return( code );
1582
1569
}
1583
1570
 
1584
1571
/*
1591
1578
int             code;
1592
1579
EDEV    *dev;
1593
1580
 
1594
 
        dev  = (EDEV *) device;
1595
 
        code = 0;
1596
 
        
1597
 
        code = PutInt( plist, "Depletion",      &dev->depletion, 0,                 2, code );
1598
 
        code = PutInt( plist, "Shingling",      &dev->shingling, 0,         2, code );
1599
 
        code = PutInt( plist, "Render",         &dev->halftoner, 0,MAXHTONE-1, code );
1600
 
        code = PutInt( plist, "Splash",         &dev->splash,    0,                50, code );
1601
 
        code = PutInt( plist, "Leakage",        &dev->leakage,   0,                25, code );
1602
 
        code = PutInt( plist, "Binhibit",       &dev->pureblack, 0,                 1, code );
1603
 
        code = PutInt( plist, "DotSize",        &dev->dotsize,   0,                 4, code );
1604
 
 
1605
 
        if ( code < 0 )
1606
 
        
1607
 
                return( code );
1608
 
        else
1609
 
                return( gdev_prn_put_params( device, plist ) ); 
 
1581
        dev  = (EDEV *) device;
 
1582
        code = 0;
 
1583
 
 
1584
        code = PutInt( plist, "Depletion",      &dev->depletion, 0,                 2, code );
 
1585
        code = PutInt( plist, "Shingling",      &dev->shingling, 0,         2, code );
 
1586
        code = PutInt( plist, "Render",         &dev->halftoner, 0,MAXHTONE-1, code );
 
1587
        code = PutInt( plist, "Splash",         &dev->splash,    0,                50, code );
 
1588
        code = PutInt( plist, "Leakage",        &dev->leakage,   0,                25, code );
 
1589
        code = PutInt( plist, "Binhibit",       &dev->pureblack, 0,                 1, code );
 
1590
        code = PutInt( plist, "DotSize",        &dev->dotsize,   0,                 4, code );
 
1591
 
 
1592
        if ( code < 0 )
 
1593
 
 
1594
                return( code );
 
1595
        else
 
1596
                return( gdev_prn_put_params( device, plist ) );
1610
1597
}
1611
1598
 
1612
1599
/*
1615
1602
*/
1616
1603
 
1617
1604
static int      PutInt( PLIST *plist, PNAME name, int *val,
1618
 
                                                int minval, int maxval, int code )
 
1605
                                                int minval, int maxval, int code )
1619
1606
{
1620
1607
int             new;
1621
1608
 
1622
 
        /* If code is already an error, we return it and do nothing. */
1623
 
        
1624
 
        if ( code ) return( code );
1625
 
        
1626
 
        /* Otherwise we try to read the value */
1627
 
        
1628
 
        new = *val;
1629
 
                
1630
 
        switch ( code = param_read_int( plist, name, &new ) ) {
1631
 
        
1632
 
                case 1:                                         /* No such parameter defined, it's OK   */
1633
 
                
1634
 
                        code = 0;
1635
 
                        break;
1636
 
                
1637
 
                case 0:                                         /* We have received a value, rangecheck */
1638
 
        
1639
 
                        if ( minval > new || new > maxval )
1640
 
                        
1641
 
                                param_signal_error( plist, name, gs_error_rangecheck );
1642
 
                        else
1643
 
                                *val = new;
1644
 
                                
1645
 
                        break;
1646
 
                
1647
 
                default:                                        /* Error                                                                */
1648
 
                        break;
1649
 
        }
1650
 
        
1651
 
        return( code );
 
1609
        /* If code is already an error, we return it and do nothing. */
 
1610
 
 
1611
        if ( code ) return( code );
 
1612
 
 
1613
        /* Otherwise we try to read the value */
 
1614
 
 
1615
        new = *val;
 
1616
 
 
1617
        switch ( code = param_read_int( plist, name, &new ) ) {
 
1618
 
 
1619
                case 1:                                         /* No such parameter defined, it's OK   */
 
1620
 
 
1621
                        code = 0;
 
1622
                        break;
 
1623
 
 
1624
                case 0:                                         /* We have received a value, rangecheck */
 
1625
 
 
1626
                        if ( minval > new || new > maxval )
 
1627
 
 
1628
                                param_signal_error( plist, name, gs_error_rangecheck );
 
1629
                        else
 
1630
                                *val = new;
 
1631
 
 
1632
                        break;
 
1633
 
 
1634
                default:                                        /* Error                                                                */
 
1635
                        break;
 
1636
        }
 
1637
 
 
1638
        return( code );
1652
1639
}
1653
1640
 
1654
1641
/*
1658
1645
 
1659
1646
static  int             GetInt( PLIST *list, PNAME name, int *value, int code )
1660
1647
{
1661
 
        if ( code < 0 ) return( code );
1662
 
        return( param_write_int( list, name, value ) );
 
1648
        if ( code < 0 ) return( code );
 
1649
        return( param_write_int( list, name, value ) );
1663
1650
}
1664
1651
 
1665
1652
/****************************************************************************/
1683
1670
int                     unit;
1684
1671
double          psize;
1685
1672
 
1686
 
        dev = (EDEV *) device;  
1687
 
        
1688
 
        /* Check if the resolution is one of the supported ones */
1689
 
        
1690
 
        yres = (int) dev->y_pixels_per_inch;
1691
 
        xres = (int) dev->x_pixels_per_inch;
1692
 
        
1693
 
        if ( ! ( ( xres ==  360 && yres == 360 ) ||
1694
 
                         ( xres ==  720 && yres == 720 ) ||
1695
 
                         ( xres == 1440 && yres == 720 ) ) )
1696
 
                         
1697
 
                return( gs_error_rangecheck );
1698
 
                
1699
 
        pixels = gdev_prn_raster( device ) / sizeof( long );
1700
 
        psize  = device->height / device->y_pixels_per_inch;
1701
 
        
1702
 
        /* Check if the requested width is within device limits.
1703
 
           The calculations are in 1440 dpi units. */
1704
 
        
1705
 
        start = 1440.0 * dev_l_margin( device );
1706
 
 
1707
 
        x = xres == 360 ? 4 : xres == 720 ? 2 : 1;
1708
 
        
1709
 
        if ( start + x * pixels > 2 * MAX_PIXELS ) {
1710
 
        
1711
 
                /* We're over the limit, clip width to the required level */
1712
 
                
1713
 
                width = ( 2 * MAX_PIXELS - start ) / x;
1714
 
                
1715
 
                /* It is rather inprobable that someone would set up a 
1716
 
                   left margin wider than the printer, still ... */
1717
 
                
1718
 
                if ( width <= 0 ) return( gs_error_rangecheck );
1719
 
        }
1720
 
        else {
1721
 
        
1722
 
                /* We accept the width as it is */
1723
 
                
1724
 
                width = pixels;
1725
 
        }
1726
 
        
1727
 
        /* Now try to get the memory we need. It's actually quite a lot,
1728
 
           since we have to cache 256 processed lines at 6kbyte each plus
1729
 
           we need error buffers and stuff. All in all, we'll request
1730
 
           about 1.5 ~ 2M. */
1731
 
                
1732
 
        if ( ! ( render = (RENDER *) gs_malloc( dev->memory, 1, sizeof( RENDER ), "PhotoEX" )))
1733
 
                
1734
 
                return_error( gs_error_VMerror );
1735
 
        
1736
 
        if ( ! ( render->dbuff = (byte *) gs_malloc( dev->memory, pixels, sizeof( long ), 
1737
 
                        "PhotoEX" ) ) ) {
1738
 
                        
1739
 
                gs_free( dev->memory, render, 1, sizeof( RENDER ), "PhotoEX" );
1740
 
                return_error( gs_error_VMerror );
1741
 
        }
1742
 
        
1743
 
        /* We've done every possible check and preparation, now 
1744
 
           do the work. Fill the rest of the structure so we can pass 
1745
 
           it to the actual render routine. */
1746
 
        
1747
 
        render->dev             = dev;
1748
 
        render->yres    = yres;
1749
 
        render->xres    = xres;
1750
 
        render->width   = width;
1751
 
        render->lines   = dev->height;
1752
 
        render->stream  = stream;               
1753
 
        render->mono    = dev->mono;
1754
 
        
1755
 
        /* Initialise the printer */
1756
 
                                
1757
 
        SendReset( stream );
1758
 
        SendReset( stream );
1759
 
        SendGmode( stream, 1 );
1760
 
        
1761
 
        /* Set up units */
1762
 
        
1763
 
        unit = ( yres == 360 ) ? 360 : 720;
1764
 
        SendUnit( stream, RESCODE( unit ) );
1765
 
        
1766
 
        /* Set up papersize and margins */
1767
 
        
1768
 
        SendPaper( stream, device->height / device->y_pixels_per_inch * unit );
1769
 
        SendMargin( stream, ( psize - dev_b_margin( device ) ) * unit, 
1770
 
                                            dev_t_margin( device ) * unit );
1771
 
 
1772
 
        /* Dot size as per user setting */
1773
 
        
1774
 
        if ( dev->dotsize )
1775
 
        
1776
 
                SendInk( stream, dev->dotsize );
1777
 
        else
1778
 
                SendInk( stream, yres == 360 ? 3 : ( xres == 720 ? 2 : 1 ) );
1779
 
        
1780
 
        /* Microveawe is off, unidirectional printing on */
1781
 
        
1782
 
        SendMicro( stream, 0 );
1783
 
        SendUnidir( stream, 1 );
1784
 
        
1785
 
        /* Render the page and send image data to printer */
1786
 
        
1787
 
        RenderPage( render );
1788
 
                                        
1789
 
        /* Eject the paper, reset printer */
1790
 
        
1791
 
        SendByte( stream, FF );
1792
 
        SendReset( stream );
1793
 
        
1794
 
        /* Release the memory and return */
1795
 
        
1796
 
        gs_free( dev->memory, render->dbuff, pixels, sizeof( long ), "PhotoEX" );
1797
 
        gs_free( dev->memory, render, 1, sizeof( RENDER ), "PhotoEX" );
1798
 
        return( 0 );
 
1673
        dev = (EDEV *) device;
 
1674
 
 
1675
        /* Check if the resolution is one of the supported ones */
 
1676
 
 
1677
        yres = (int) dev->y_pixels_per_inch;
 
1678
        xres = (int) dev->x_pixels_per_inch;
 
1679
 
 
1680
        if ( ! ( ( xres ==  360 && yres == 360 ) ||
 
1681
                         ( xres ==  720 && yres == 720 ) ||
 
1682
                         ( xres == 1440 && yres == 720 ) ) )
 
1683
 
 
1684
                return( gs_error_rangecheck );
 
1685
 
 
1686
        pixels = gdev_prn_raster( device ) / sizeof( long );
 
1687
        psize  = device->height / device->y_pixels_per_inch;
 
1688
 
 
1689
        /* Check if the requested width is within device limits.
 
1690
           The calculations are in 1440 dpi units. */
 
1691
 
 
1692
        start = 1440.0 * dev_l_margin( device );
 
1693
 
 
1694
        x = xres == 360 ? 4 : xres == 720 ? 2 : 1;
 
1695
 
 
1696
        if ( start + x * pixels > 2 * MAX_PIXELS ) {
 
1697
 
 
1698
                /* We're over the limit, clip width to the required level */
 
1699
 
 
1700
                width = ( 2 * MAX_PIXELS - start ) / x;
 
1701
 
 
1702
                /* It is rather inprobable that someone would set up a
 
1703
                   left margin wider than the printer, still ... */
 
1704
 
 
1705
                if ( width <= 0 ) return( gs_error_rangecheck );
 
1706
        }
 
1707
        else {
 
1708
 
 
1709
                /* We accept the width as it is */
 
1710
 
 
1711
                width = pixels;
 
1712
        }
 
1713
 
 
1714
        /* Now try to get the memory we need. It's actually quite a lot,
 
1715
           since we have to cache 256 processed lines at 6kbyte each plus
 
1716
           we need error buffers and stuff. All in all, we'll request
 
1717
           about 1.5 ~ 2M. */
 
1718
 
 
1719
        if ( ! ( render = (RENDER *) gs_malloc( dev->memory, 1, sizeof( RENDER ), "PhotoEX" )))
 
1720
 
 
1721
                return_error( gs_error_VMerror );
 
1722
 
 
1723
        if ( ! ( render->dbuff = (byte *) gs_malloc( dev->memory, pixels, sizeof( long ),
 
1724
                        "PhotoEX" ) ) ) {
 
1725
 
 
1726
                gs_free( dev->memory, render, 1, sizeof( RENDER ), "PhotoEX" );
 
1727
                return_error( gs_error_VMerror );
 
1728
        }
 
1729
 
 
1730
        /* We've done every possible check and preparation, now
 
1731
           do the work. Fill the rest of the structure so we can pass
 
1732
           it to the actual render routine. */
 
1733
 
 
1734
        render->dev             = dev;
 
1735
        render->yres    = yres;
 
1736
        render->xres    = xres;
 
1737
        render->width   = width;
 
1738
        render->lines   = dev->height;
 
1739
        render->stream  = stream;
 
1740
        render->mono    = dev->mono;
 
1741
 
 
1742
        /* Initialise the printer */
 
1743
 
 
1744
        SendReset( stream );
 
1745
        SendReset( stream );
 
1746
        SendGmode( stream, 1 );
 
1747
 
 
1748
        /* Set up units */
 
1749
 
 
1750
        unit = ( yres == 360 ) ? 360 : 720;
 
1751
        SendUnit( stream, RESCODE( unit ) );
 
1752
 
 
1753
        /* Set up papersize and margins */
 
1754
 
 
1755
        SendPaper( stream, device->height / device->y_pixels_per_inch * unit );
 
1756
        SendMargin( stream, ( psize - dev_b_margin( device ) ) * unit,
 
1757
                                            dev_t_margin( device ) * unit );
 
1758
 
 
1759
        /* Dot size as per user setting */
 
1760
 
 
1761
        if ( dev->dotsize )
 
1762
 
 
1763
                SendInk( stream, dev->dotsize );
 
1764
        else
 
1765
                SendInk( stream, yres == 360 ? 3 : ( xres == 720 ? 2 : 1 ) );
 
1766
 
 
1767
        /* Microveawe is off, unidirectional printing on */
 
1768
 
 
1769
        SendMicro( stream, 0 );
 
1770
        SendUnidir( stream, 1 );
 
1771
 
 
1772
        /* Render the page and send image data to printer */
 
1773
 
 
1774
        RenderPage( render );
 
1775
 
 
1776
        /* Eject the paper, reset printer */
 
1777
 
 
1778
        SendByte( stream, FF );
 
1779
        SendReset( stream );
 
1780
 
 
1781
        /* Release the memory and return */
 
1782
 
 
1783
        gs_free( dev->memory, render->dbuff, pixels, sizeof( long ), "PhotoEX" );
 
1784
        gs_free( dev->memory, render, 1, sizeof( RENDER ), "PhotoEX" );
 
1785
        return( 0 );
1799
1786
}
1800
1787
 
1801
1788
/*
1813
1800
int             phase;                                          /* 1440dpi X weave offset                               */
1814
1801
int             i, j, l, col;
1815
1802
 
1816
 
        p->htone_thold = HalftoneThold( p );
1817
 
        p->htone_last  = -1 - p->htone_thold;
1818
 
        
1819
 
        p->schedule.top   = -1;
1820
 
        p->schedule.resol = p->xres;
1821
 
        p->schedule.last  = p->lines;
1822
 
        
1823
 
        last_done = -1;
1824
 
        move_down = 0;
1825
 
                
1826
 
        do {
1827
 
        
1828
 
                /* Schedule the next batch of lines */
1829
 
                
1830
 
                last_band = ScheduleLines( &p->schedule );
1831
 
                
1832
 
                /* Find the largest line number we have to process and
1833
 
                   halftone all lines which have not yet been done */
1834
 
                
1835
 
                last_need = last_done;
1836
 
                for ( i = NOZZLES-1 ; i >= 0 && p->schedule.head[ i ] == -1 ; i-- );
1837
 
                if ( i >= 0 ) last_need = p->schedule.head[ i ];
1838
 
                while ( last_need > last_done ) RenderLine( p, ++last_done );
1839
 
                
1840
 
                /* Now loop through the colours and build the data stream */
1841
 
                
1842
 
                phase = p->schedule.offset;
1843
 
                
1844
 
                for ( col = 0 ; col < DCOLN ; col++ ) {
1845
 
                
1846
 
                        /* First see if we have to send any data at all */
1847
 
                        
1848
 
                        min = MAX_BYTES;
1849
 
                        max = 0;
1850
 
                                
1851
 
                        for ( i = 0 ; i < NOZZLES && i < p->schedule.nozzle ; i++ ) {
1852
 
                        
1853
 
                                if ( ( j = p->schedule.head[ i ] ) != -1 ) {
1854
 
                                
1855
 
                                        j %= MAX_MARK;
1856
 
                                        
1857
 
                                        if ( p->raw[ phase ][ col ][ j ].first < min )
1858
 
        
1859
 
                                                min = p->raw[ phase ][ col ][ j ].first;
1860
 
                                                
1861
 
                                        if ( p->raw[ phase ][ col ][ j ].last > max )
1862
 
        
1863
 
                                                max = p->raw[ phase ][ col ][ j ].last;
1864
 
                                }
1865
 
                        }
1866
 
                        
1867
 
                        if ( min <= max ) {
1868
 
                        
1869
 
                                max++;
1870
 
                                
1871
 
                                /* We have to send data to the printer. If we have 
1872
 
                                   to position the head, do so now */
1873
 
                                
1874
 
                                if ( move_down ) {
1875
 
                                
1876
 
                                        SendDown( p->stream, move_down );
1877
 
                                        move_down = 0;
1878
 
                                }
1879
 
                                
1880
 
                                /* Set the desired colour */
1881
 
                                
1882
 
                                SendColour( p->stream, col );
1883
 
                                
1884
 
                                /* Move the head to the desired position */
1885
 
                                
1886
 
                                if ( p->xres == 360 )
1887
 
                                
1888
 
                                        SendRight( p->stream, 4 * 8 * min );
1889
 
                                        
1890
 
                                else if ( p->xres == 720 )
1891
 
                                
1892
 
                                        SendRight( p->stream, 2 * 8 * min );
1893
 
                                else
1894
 
                                        SendRight( p->stream, 8 * min + phase );
1895
 
                                
1896
 
                                /* Send the data */
1897
 
                                
1898
 
                                SendData( p->stream, p->xres, p->yres, p->schedule.nozzle, 
1899
 
                                                  ( max-min ) * 8 );
1900
 
                                
1901
 
                                for ( i = 0 ; i < p->schedule.nozzle ; i++ ) {
1902
 
                                
1903
 
                                        if ( ( j = p->schedule.head[ i ] ) == -1 ||
1904
 
                                                 ( p->raw[ phase ][ col ][ j % MAX_MARK ].last <
1905
 
                                                   p->raw[ phase ][ col ][ j % MAX_MARK ].first ) ) {
1906
 
 
1907
 
                                                l = RleCompress( NULL, min, max, p->rle );
1908
 
                                        }
1909
 
                                        else {
1910
 
                                        
1911
 
                                                l = RleCompress( p->raw[ phase ][ col ] + j % MAX_MARK,
1912
 
                                                                           min, max, p->rle );
1913
 
                                        }
1914
 
                                        
1915
 
                                        fwrite( p->rle, l, 1, p->stream );
1916
 
                                }
1917
 
                                
1918
 
                                SendByte( p->stream, CR );
1919
 
                        }
1920
 
                }
1921
 
                
1922
 
                /* Note the amount the head should go down before it prints the
1923
 
                   next band */
1924
 
                
1925
 
                move_down += p->schedule.down;
1926
 
        
1927
 
        } while ( ! last_band );
 
1803
        p->htone_thold = HalftoneThold( p );
 
1804
        p->htone_last  = -1 - p->htone_thold;
 
1805
 
 
1806
        p->schedule.top   = -1;
 
1807
        p->schedule.resol = p->xres;
 
1808
        p->schedule.last  = p->lines;
 
1809
 
 
1810
        last_done = -1;
 
1811
        move_down = 0;
 
1812
 
 
1813
        do {
 
1814
 
 
1815
                /* Schedule the next batch of lines */
 
1816
 
 
1817
                last_band = ScheduleLines( &p->schedule );
 
1818
 
 
1819
                /* Find the largest line number we have to process and
 
1820
                   halftone all lines which have not yet been done */
 
1821
 
 
1822
                last_need = last_done;
 
1823
                for ( i = NOZZLES-1 ; i >= 0 && p->schedule.head[ i ] == -1 ; i-- );
 
1824
                if ( i >= 0 ) last_need = p->schedule.head[ i ];
 
1825
                while ( last_need > last_done ) RenderLine( p, ++last_done );
 
1826
 
 
1827
                /* Now loop through the colours and build the data stream */
 
1828
 
 
1829
                phase = p->schedule.offset;
 
1830
 
 
1831
                for ( col = 0 ; col < DCOLN ; col++ ) {
 
1832
 
 
1833
                        /* First see if we have to send any data at all */
 
1834
 
 
1835
                        min = MAX_BYTES;
 
1836
                        max = 0;
 
1837
 
 
1838
                        for ( i = 0 ; i < NOZZLES && i < p->schedule.nozzle ; i++ ) {
 
1839
 
 
1840
                                if ( ( j = p->schedule.head[ i ] ) != -1 ) {
 
1841
 
 
1842
                                        j %= MAX_MARK;
 
1843
 
 
1844
                                        if ( p->raw[ phase ][ col ][ j ].first < min )
 
1845
 
 
1846
                                                min = p->raw[ phase ][ col ][ j ].first;
 
1847
 
 
1848
                                        if ( p->raw[ phase ][ col ][ j ].last > max )
 
1849
 
 
1850
                                                max = p->raw[ phase ][ col ][ j ].last;
 
1851
                                }
 
1852
                        }
 
1853
 
 
1854
                        if ( min <= max ) {
 
1855
 
 
1856
                                max++;
 
1857
 
 
1858
                                /* We have to send data to the printer. If we have
 
1859
                                   to position the head, do so now */
 
1860
 
 
1861
                                if ( move_down ) {
 
1862
 
 
1863
                                        SendDown( p->stream, move_down );
 
1864
                                        move_down = 0;
 
1865
                                }
 
1866
 
 
1867
                                /* Set the desired colour */
 
1868
 
 
1869
                                SendColour( p->stream, col );
 
1870
 
 
1871
                                /* Move the head to the desired position */
 
1872
 
 
1873
                                if ( p->xres == 360 )
 
1874
 
 
1875
                                        SendRight( p->stream, 4 * 8 * min );
 
1876
 
 
1877
                                else if ( p->xres == 720 )
 
1878
 
 
1879
                                        SendRight( p->stream, 2 * 8 * min );
 
1880
                                else
 
1881
                                        SendRight( p->stream, 8 * min + phase );
 
1882
 
 
1883
                                /* Send the data */
 
1884
 
 
1885
                                SendData( p->stream, p->xres, p->yres, p->schedule.nozzle,
 
1886
                                                  ( max-min ) * 8 );
 
1887
 
 
1888
                                for ( i = 0 ; i < p->schedule.nozzle ; i++ ) {
 
1889
 
 
1890
                                        if ( ( j = p->schedule.head[ i ] ) == -1 ||
 
1891
                                                 ( p->raw[ phase ][ col ][ j % MAX_MARK ].last <
 
1892
                                                   p->raw[ phase ][ col ][ j % MAX_MARK ].first ) ) {
 
1893
 
 
1894
                                                l = RleCompress( NULL, min, max, p->rle );
 
1895
                                        }
 
1896
                                        else {
 
1897
 
 
1898
                                                l = RleCompress( p->raw[ phase ][ col ] + j % MAX_MARK,
 
1899
                                                                           min, max, p->rle );
 
1900
                                        }
 
1901
 
 
1902
                                        fwrite( p->rle, l, 1, p->stream );
 
1903
                                }
 
1904
 
 
1905
                                SendByte( p->stream, CR );
 
1906
                        }
 
1907
                }
 
1908
 
 
1909
                /* Note the amount the head should go down before it prints the
 
1910
                   next band */
 
1911
 
 
1912
                move_down += p->schedule.down;
 
1913
 
 
1914
        } while ( ! last_band );
1928
1915
}
1929
1916
 
1930
1917
/*
1942
1929
byte    *data;
1943
1930
int             i;
1944
1931
 
1945
 
        /* Get the line from Ghostscript and see if its empty */
1946
 
        
1947
 
        gdev_prn_get_bits( (PDEV *) p->dev, line, p->dbuff, &data );
1948
 
 
1949
 
        if ( IsScanlineEmpty( p, data ) ) {
1950
 
        
1951
 
                if ( line - p->htone_last > p->htone_thold ) {
1952
 
                
1953
 
                        /* The line is empty and is farer from the last nonempty
1954
 
                           line than the threshold, no need to render it. */
1955
 
                           
1956
 
                        for ( i = 0 ; i < DCOLN ; i++ ) {
1957
 
                        
1958
 
                                p->raw[ 0 ][ i ][ line % MAX_MARK ].first = MAX_BYTES;
1959
 
                                p->raw[ 0 ][ i ][ line % MAX_MARK ].last  = 0;
1960
 
                                p->raw[ 1 ][ i ][ line % MAX_MARK ].first = MAX_BYTES;
1961
 
                                p->raw[ 1 ][ i ][ line % MAX_MARK ].last  = 0;
1962
 
                                
1963
 
                        }
1964
 
                }
1965
 
                else {
1966
 
                        
1967
 
                        /* The line is empty but it is within the threshold, so we 
1968
 
                           have to render it. We do not move the index, though */
1969
 
                           
1970
 
                        HalftoneLine( p, line, data );
1971
 
                }
1972
 
        }
1973
 
        else {
1974
 
        
1975
 
                /* This line is not empty */
1976
 
                
1977
 
                if ( line - p->htone_last >= p->htone_thold ) {
1978
 
                
1979
 
                        /* Previous lines were empty and we have already stopped 
1980
 
                           rendering them. We have to restart the renderer */
1981
 
                           
1982
 
                        HalftonerStart( p, line );
1983
 
                }
1984
 
                
1985
 
                /* Render the line and move the last active index to this line */
1986
 
                
1987
 
                HalftoneLine( p, line, data );
1988
 
                p->htone_last = line;
1989
 
        }
 
1932
        /* Get the line from Ghostscript and see if its empty */
 
1933
 
 
1934
        gdev_prn_get_bits( (PDEV *) p->dev, line, p->dbuff, &data );
 
1935
 
 
1936
        if ( IsScanlineEmpty( p, data ) ) {
 
1937
 
 
1938
                if ( line - p->htone_last > p->htone_thold ) {
 
1939
 
 
1940
                        /* The line is empty and is farer from the last nonempty
 
1941
                           line than the threshold, no need to render it. */
 
1942
 
 
1943
                        for ( i = 0 ; i < DCOLN ; i++ ) {
 
1944
 
 
1945
                                p->raw[ 0 ][ i ][ line % MAX_MARK ].first = MAX_BYTES;
 
1946
                                p->raw[ 0 ][ i ][ line % MAX_MARK ].last  = 0;
 
1947
                                p->raw[ 1 ][ i ][ line % MAX_MARK ].first = MAX_BYTES;
 
1948
                                p->raw[ 1 ][ i ][ line % MAX_MARK ].last  = 0;
 
1949
 
 
1950
                        }
 
1951
                }
 
1952
                else {
 
1953
 
 
1954
                        /* The line is empty but it is within the threshold, so we
 
1955
                           have to render it. We do not move the index, though */
 
1956
 
 
1957
                        HalftoneLine( p, line, data );
 
1958
                }
 
1959
        }
 
1960
        else {
 
1961
 
 
1962
                /* This line is not empty */
 
1963
 
 
1964
                if ( line - p->htone_last >= p->htone_thold ) {
 
1965
 
 
1966
                        /* Previous lines were empty and we have already stopped
 
1967
                           rendering them. We have to restart the renderer */
 
1968
 
 
1969
                        HalftonerStart( p, line );
 
1970
                }
 
1971
 
 
1972
                /* Render the line and move the last active index to this line */
 
1973
 
 
1974
                HalftoneLine( p, line, data );
 
1975
                p->htone_last = line;
 
1976
        }
1990
1977
}
1991
1978
 
1992
1979
/*
1998
1985
{
1999
1986
int             i;
2000
1987
long    *p;
2001
 
        
2002
 
        p = (long *) line;
2003
 
        
2004
 
        for ( i = 0 ; i < r->width ; i++ ) {
2005
 
        
2006
 
                if ( *p++ ) return( FALSE );
2007
 
        }
2008
 
        
2009
 
        return( TRUE ); 
 
1988
 
 
1989
        p = (long *) line;
 
1990
 
 
1991
        for ( i = 0 ; i < r->width ; i++ ) {
 
1992
 
 
1993
                if ( *p++ ) return( FALSE );
 
1994
        }
 
1995
 
 
1996
        return( TRUE );
2010
1997
}
2011
1998
 
2012
1999
/****************************************************************************/
2026
2013
*       The down field contains the number of units which the head should
2027
2014
*       move down when printing of the band is finished. Other fields are
2028
2015
*       mainly for the routine's internal use. At the first call, however,
2029
 
*       the top field should be set to -1, the resol field should be set 
 
2016
*       the top field should be set to -1, the resol field should be set
2030
2017
*       to 360, 720 or 1440 and the last field should contain the number
2031
 
*       of lines to print (that is, last + 1 :-). 
 
2018
*       of lines to print (that is, last + 1 :-).
2032
2019
*
2033
2020
*       The routine returns a flag indicating if this was the last print
2034
2021
*       for the page.
2035
2022
*/
2036
 
        
 
2023
 
2037
2024
static  int     ScheduleLines( SCHEDUL *p )
2038
2025
{
2039
2026
int             i;
2040
2027
 
2041
 
        if ( p->top == -1 ) {
2042
 
        
2043
 
                /* First call, init everything, then fall through to the rest */
2044
 
                
2045
 
                SchedulerInit( p );
2046
 
        }
2047
 
        
2048
 
        /* If nozzle is one, just schedule the next line and that's it.
2049
 
           You can use this feature for hardware microweave at 720 dpi,
2050
 
           the driver uses it for 360 dpi. */
2051
 
        
2052
 
        if ( p->nozzle == 1 ) {
2053
 
        
2054
 
                p->head[ 0 ] = p->top;
2055
 
                p->down = 1;
2056
 
                p->top++;
2057
 
                return( p->top == p->last );
2058
 
        }
2059
 
        
2060
 
        /* Release all expired entries in the mark array */
2061
 
        
2062
 
        for ( i = p->markbeg ; i < p->top ; i++ ) p->mark[ i % MAX_MARK ] = 0;
2063
 
        p->markbeg = p->top;
2064
 
        
2065
 
        /* If top is less than the the head spacing, then create the image 
2066
 
           by single steps. This will cause banding on the very top, but
2067
 
           there's nothing we can do about it. We're still better than
2068
 
           Epson's driver which simply ignores the first few lines,
2069
 
           it does not even try to schedule them ... */
2070
 
                
2071
 
        if ( p->top < HEAD_SPACING ) {
2072
 
        
2073
 
                ScheduleLeading( p );
2074
 
                return( FALSE );
2075
 
        }
2076
 
        
2077
 
        /* See if we are almost at the end. If yes, we will advance line by
2078
 
           line. */
2079
 
        
2080
 
        if ( p->top + p->resol + (NOZZLES) * HEAD_SPACING > p->last ) {
2081
 
                
2082
 
                ScheduleTrailing( p );
2083
 
                
2084
 
                if ( p->down )
2085
 
                
2086
 
                        return( p->top + (NOZZLES-1) * HEAD_SPACING >= p->last );
2087
 
                else
2088
 
                        return( FALSE );
2089
 
        }
2090
 
                
2091
 
        /* Otherwise we're in the middle of the page, just do the
2092
 
           simple banding and selecting as many lines as we can. */
2093
 
 
2094
 
        ScheduleMiddle( p );
2095
 
        return( FALSE );
 
2028
        if ( p->top == -1 ) {
 
2029
 
 
2030
                /* First call, init everything, then fall through to the rest */
 
2031
 
 
2032
                SchedulerInit( p );
 
2033
        }
 
2034
 
 
2035
        /* If nozzle is one, just schedule the next line and that's it.
 
2036
           You can use this feature for hardware microweave at 720 dpi,
 
2037
           the driver uses it for 360 dpi. */
 
2038
 
 
2039
        if ( p->nozzle == 1 ) {
 
2040
 
 
2041
                p->head[ 0 ] = p->top;
 
2042
                p->down = 1;
 
2043
                p->top++;
 
2044
                return( p->top == p->last );
 
2045
        }
 
2046
 
 
2047
        /* Release all expired entries in the mark array */
 
2048
 
 
2049
        for ( i = p->markbeg ; i < p->top ; i++ ) p->mark[ i % MAX_MARK ] = 0;
 
2050
        p->markbeg = p->top;
 
2051
 
 
2052
        /* If top is less than the the head spacing, then create the image
 
2053
           by single steps. This will cause banding on the very top, but
 
2054
           there's nothing we can do about it. We're still better than
 
2055
           Epson's driver which simply ignores the first few lines,
 
2056
           it does not even try to schedule them ... */
 
2057
 
 
2058
        if ( p->top < HEAD_SPACING ) {
 
2059
 
 
2060
                ScheduleLeading( p );
 
2061
                return( FALSE );
 
2062
        }
 
2063
 
 
2064
        /* See if we are almost at the end. If yes, we will advance line by
 
2065
           line. */
 
2066
 
 
2067
        if ( p->top + p->resol + (NOZZLES) * HEAD_SPACING > p->last ) {
 
2068
 
 
2069
                ScheduleTrailing( p );
 
2070
 
 
2071
                if ( p->down )
 
2072
 
 
2073
                        return( p->top + (NOZZLES-1) * HEAD_SPACING >= p->last );
 
2074
                else
 
2075
                        return( FALSE );
 
2076
        }
 
2077
 
 
2078
        /* Otherwise we're in the middle of the page, just do the
 
2079
           simple banding and selecting as many lines as we can. */
 
2080
 
 
2081
        ScheduleMiddle( p );
 
2082
        return( FALSE );
2096
2083
}
2097
2084
 
2098
2085
/*
2103
2090
static  void    SchedulerInit( SCHEDUL *p )
2104
2091
{
2105
2092
int             i;
2106
 
                        
2107
 
        p->top = 0;
2108
 
                
2109
 
        switch ( p->resol ) {
2110
 
                
2111
 
                case 360:       
2112
 
                        p->offset = 0;
2113
 
                        p->resol  = BAND_360; 
2114
 
                        p->nozzle = NOZZLE_360;
2115
 
                        break;
2116
 
                        
2117
 
                case 720:       
2118
 
                        p->offset = 0;
2119
 
                        p->resol  = BAND_720; 
2120
 
                        p->nozzle = NOZZLE_720;
2121
 
                        break;
2122
 
                        
2123
 
                case 1440:      
2124
 
                        p->offset = 1;                  /* Need to be set for the algorithm! */
2125
 
                        p->resol  = BAND_1440; 
2126
 
                        p->nozzle = NOZZLE_1440;
2127
 
                        break;
2128
 
        }
2129
 
        
2130
 
        for ( i = 0 ; i < NOZZLES  ; i++ ) p->head[ i ] = -1;
2131
 
        for ( i = 0 ; i < MAX_MARK ; i++ ) p->mark[ i ] = 0;
2132
 
        p->markbeg = 0;
 
2093
 
 
2094
        p->top = 0;
 
2095
 
 
2096
        switch ( p->resol ) {
 
2097
 
 
2098
                case 360:
 
2099
                        p->offset = 0;
 
2100
                        p->resol  = BAND_360;
 
2101
                        p->nozzle = NOZZLE_360;
 
2102
                        break;
 
2103
 
 
2104
                case 720:
 
2105
                        p->offset = 0;
 
2106
                        p->resol  = BAND_720;
 
2107
                        p->nozzle = NOZZLE_720;
 
2108
                        break;
 
2109
 
 
2110
                case 1440:
 
2111
                        p->offset = 1;                  /* Need to be set for the algorithm! */
 
2112
                        p->resol  = BAND_1440;
 
2113
                        p->nozzle = NOZZLE_1440;
 
2114
                        break;
 
2115
        }
 
2116
 
 
2117
        for ( i = 0 ; i < NOZZLES  ; i++ ) p->head[ i ] = -1;
 
2118
        for ( i = 0 ; i < MAX_MARK ; i++ ) p->mark[ i ] = 0;
 
2119
        p->markbeg = 0;
2133
2120
}
2134
2121
 
2135
2122
/*
2141
2128
{
2142
2129
int             i;
2143
2130
 
2144
 
        if ( p->resol == BAND_720 ) {
2145
 
 
2146
 
                /* Copy the line scheduling data to the struct */
2147
 
                        
2148
 
                memcpy( p->head, start_720[ p->top ], sizeof( int ) * NOZZLES );
2149
 
                        
2150
 
                /* Mark all lines to be set */
2151
 
                        
2152
 
                for ( i = 0 ; i < NOZZLES ; i++ )
2153
 
                        
2154
 
                        if ( p->head[ i ] != -1 ) 
2155
 
                                
2156
 
                                p->mark[ p->head[ i ] % MAX_MARK ] = 1;
2157
 
                        
2158
 
                /* We move down by one line except at the end */
2159
 
                                
2160
 
                if ( p->top == HEAD_SPACING - 1 ) {
2161
 
                        
2162
 
                        p->down = BAND_720 - p->top;
2163
 
                        p->top  = BAND_720;
2164
 
                }
2165
 
                else {
2166
 
                        
2167
 
                        p->down = 1;
2168
 
                        p->top++;
2169
 
                }
2170
 
        }
2171
 
        else {
2172
 
                        
2173
 
                /* 1440 dpi version, two passes needed for each scanline */
2174
 
                                
2175
 
                if ( p->offset ) {
2176
 
                                                
2177
 
                        /* Copy the non-offseted scheduling data to the struct */
2178
 
                        
2179
 
                        memcpy( p->head, start_1440[0][p->top], sizeof( int ) * NOZZLES );
2180
 
                        
2181
 
                        /* Mark all lines to be set */
2182
 
                        
2183
 
                        for ( i = 0 ; i < NOZZLES ; i++ )
2184
 
                        
2185
 
                                if ( p->head[ i ] != -1 )
2186
 
                                
2187
 
                                        p->mark[ p->head[ i ] % MAX_MARK ] = 1;
2188
 
                        
2189
 
                        /* This is the non-offseted line, do not move ! */
2190
 
                                
2191
 
                        p->offset = 0;
2192
 
                        p->down = 0;
2193
 
                }
2194
 
                else {
2195
 
                        
2196
 
                        /* Copy the non-offseted schduling data to the struct */
2197
 
                        
2198
 
                        memcpy( p->head, start_1440[1][p->top], sizeof( int ) * NOZZLES );
2199
 
                        
2200
 
                        /* Mark all lines to be set */
2201
 
                        
2202
 
                        for ( i = 0 ; i < NOZZLES ; i++ )
2203
 
                        
2204
 
                                if ( p->head[ i ] != -1 )
2205
 
        
2206
 
                                        p->mark[ p->head[ i ] % MAX_MARK ] |= 2;
2207
 
                        
2208
 
                        /* We move down by one line except at the end and set offset */
2209
 
                                
2210
 
                        if ( p->top == HEAD_SPACING - 1 ) {
2211
 
                        
2212
 
                                p->down = BAND_1440 - p->top;
2213
 
                                p->top  = BAND_1440;
2214
 
                        }
2215
 
                        else {
2216
 
                        
2217
 
                                p->down = 1;
2218
 
                                p->top++;
2219
 
                        }
2220
 
                        
2221
 
                        p->offset = 1;
2222
 
                }
2223
 
        }       
 
2131
        if ( p->resol == BAND_720 ) {
 
2132
 
 
2133
                /* Copy the line scheduling data to the struct */
 
2134
 
 
2135
                memcpy( p->head, start_720[ p->top ], sizeof( int ) * NOZZLES );
 
2136
 
 
2137
                /* Mark all lines to be set */
 
2138
 
 
2139
                for ( i = 0 ; i < NOZZLES ; i++ )
 
2140
 
 
2141
                        if ( p->head[ i ] != -1 )
 
2142
 
 
2143
                                p->mark[ p->head[ i ] % MAX_MARK ] = 1;
 
2144
 
 
2145
                /* We move down by one line except at the end */
 
2146
 
 
2147
                if ( p->top == HEAD_SPACING - 1 ) {
 
2148
 
 
2149
                        p->down = BAND_720 - p->top;
 
2150
                        p->top  = BAND_720;
 
2151
                }
 
2152
                else {
 
2153
 
 
2154
                        p->down = 1;
 
2155
                        p->top++;
 
2156
                }
 
2157
        }
 
2158
        else {
 
2159
 
 
2160
                /* 1440 dpi version, two passes needed for each scanline */
 
2161
 
 
2162
                if ( p->offset ) {
 
2163
 
 
2164
                        /* Copy the non-offseted scheduling data to the struct */
 
2165
 
 
2166
                        memcpy( p->head, start_1440[0][p->top], sizeof( int ) * NOZZLES );
 
2167
 
 
2168
                        /* Mark all lines to be set */
 
2169
 
 
2170
                        for ( i = 0 ; i < NOZZLES ; i++ )
 
2171
 
 
2172
                                if ( p->head[ i ] != -1 )
 
2173
 
 
2174
                                        p->mark[ p->head[ i ] % MAX_MARK ] = 1;
 
2175
 
 
2176
                        /* This is the non-offseted line, do not move ! */
 
2177
 
 
2178
                        p->offset = 0;
 
2179
                        p->down = 0;
 
2180
                }
 
2181
                else {
 
2182
 
 
2183
                        /* Copy the non-offseted schduling data to the struct */
 
2184
 
 
2185
                        memcpy( p->head, start_1440[1][p->top], sizeof( int ) * NOZZLES );
 
2186
 
 
2187
                        /* Mark all lines to be set */
 
2188
 
 
2189
                        for ( i = 0 ; i < NOZZLES ; i++ )
 
2190
 
 
2191
                                if ( p->head[ i ] != -1 )
 
2192
 
 
2193
                                        p->mark[ p->head[ i ] % MAX_MARK ] |= 2;
 
2194
 
 
2195
                        /* We move down by one line except at the end and set offset */
 
2196
 
 
2197
                        if ( p->top == HEAD_SPACING - 1 ) {
 
2198
 
 
2199
                                p->down = BAND_1440 - p->top;
 
2200
                                p->top  = BAND_1440;
 
2201
                        }
 
2202
                        else {
 
2203
 
 
2204
                                p->down = 1;
 
2205
                                p->top++;
 
2206
                        }
 
2207
 
 
2208
                        p->offset = 1;
 
2209
                }
 
2210
        }
2224
2211
}
2225
2212
 
2226
2213
/*
2234
2221
int             line, mask;
2235
2222
int             i;
2236
2223
 
2237
 
        if ( p->resol == BAND_720 ) {
2238
 
        
2239
 
                /* 720 DPI printing. See which lines should we print and
2240
 
                   fill the head array accordingly, then move down a band. */
2241
 
                
2242
 
                ScheduleBand( p, 1 );
2243
 
                p->down = BAND_720;
2244
 
                p->top += BAND_720;
2245
 
        }
2246
 
        else {
2247
 
        
2248
 
                /* 1440 dpi printing. This is a bit more complex than the
2249
 
                   720 dpi one. First, see how many lines in each phase
2250
 
                   has already been printed. */
2251
 
                
2252
 
                ph0 = ph1 = 0;
2253
 
                
2254
 
                for ( line = p->top, i=0 ; i < NOZZLES ; i++, line += HEAD_SPACING ) {
2255
 
                
2256
 
                        line = p->top + i * HEAD_SPACING;
2257
 
                        ph0 += p->mark[ line % MAX_MARK ] & 1;
2258
 
                        ph1 += p->mark[ line % MAX_MARK ] & 2;
2259
 
                }
2260
 
                
2261
 
                ph1 >>= 1;
2262
 
        
2263
 
                /* Choose the phase which has less lines in it. */
2264
 
                
2265
 
                if ( ph0 <= ph1 ) {
2266
 
                
2267
 
                        p->offset = 0;
2268
 
                        mask = 1;
2269
 
                }
2270
 
                else {
2271
 
                
2272
 
                        p->offset = 1;
2273
 
                        mask = 2;
2274
 
                }
2275
 
                
2276
 
                /* Fill the line array and mark the phase.
2277
 
                   We should check here if moving down the head will leave
2278
 
                   any line empty, but we do not because we *know* that it
2279
 
                   won't - the BAND_1440 is selected by finding a value 
2280
 
                   which guarantees that it will cover every line. */
2281
 
                
2282
 
                ScheduleBand( p, mask );
2283
 
                p->down = BAND_1440;
2284
 
                p->top += BAND_1440;
2285
 
        }
 
2224
        if ( p->resol == BAND_720 ) {
 
2225
 
 
2226
                /* 720 DPI printing. See which lines should we print and
 
2227
                   fill the head array accordingly, then move down a band. */
 
2228
 
 
2229
                ScheduleBand( p, 1 );
 
2230
                p->down = BAND_720;
 
2231
                p->top += BAND_720;
 
2232
        }
 
2233
        else {
 
2234
 
 
2235
                /* 1440 dpi printing. This is a bit more complex than the
 
2236
                   720 dpi one. First, see how many lines in each phase
 
2237
                   has already been printed. */
 
2238
 
 
2239
                ph0 = ph1 = 0;
 
2240
 
 
2241
                for ( line = p->top, i=0 ; i < NOZZLES ; i++, line += HEAD_SPACING ) {
 
2242
 
 
2243
                        line = p->top + i * HEAD_SPACING;
 
2244
                        ph0 += p->mark[ line % MAX_MARK ] & 1;
 
2245
                        ph1 += p->mark[ line % MAX_MARK ] & 2;
 
2246
                }
 
2247
 
 
2248
                ph1 >>= 1;
 
2249
 
 
2250
                /* Choose the phase which has less lines in it. */
 
2251
 
 
2252
                if ( ph0 <= ph1 ) {
 
2253
 
 
2254
                        p->offset = 0;
 
2255
                        mask = 1;
 
2256
                }
 
2257
                else {
 
2258
 
 
2259
                        p->offset = 1;
 
2260
                        mask = 2;
 
2261
                }
 
2262
 
 
2263
                /* Fill the line array and mark the phase.
 
2264
                   We should check here if moving down the head will leave
 
2265
                   any line empty, but we do not because we *know* that it
 
2266
                   won't - the BAND_1440 is selected by finding a value
 
2267
                   which guarantees that it will cover every line. */
 
2268
 
 
2269
                ScheduleBand( p, mask );
 
2270
                p->down = BAND_1440;
 
2271
                p->top += BAND_1440;
 
2272
        }
2286
2273
}
2287
2274
 
2288
2275
/*
2294
2281
{
2295
2282
int             mask;
2296
2283
 
2297
 
        if ( p->down > 1 ) {
2298
 
                
2299
 
                /* This is the first time we came here. */
2300
 
                
2301
 
                p->offset = 1;
2302
 
        }
2303
 
        
2304
 
        if ( p->resol == BAND_720 ) {
2305
 
                
2306
 
                p->offset = 0;
2307
 
                p->down   = 1;
2308
 
                mask      = 1;
2309
 
        }
2310
 
        else {
2311
 
                
2312
 
                if ( p->offset ) {
2313
 
                        
2314
 
                        p->offset = 0;
2315
 
                        p->down   = 0;
2316
 
                        mask      = 1;
2317
 
                }
2318
 
                else {
2319
 
                        
2320
 
                        p->offset = 1;
2321
 
                        p->down   = 1;
2322
 
                        mask      = 2;
2323
 
                }
2324
 
        }
2325
 
        
2326
 
        ScheduleBand( p, mask );
2327
 
        p->top += p->down;
 
2284
        if ( p->down > 1 ) {
 
2285
 
 
2286
                /* This is the first time we came here. */
 
2287
 
 
2288
                p->offset = 1;
 
2289
        }
 
2290
 
 
2291
        if ( p->resol == BAND_720 ) {
 
2292
 
 
2293
                p->offset = 0;
 
2294
                p->down   = 1;
 
2295
                mask      = 1;
 
2296
        }
 
2297
        else {
 
2298
 
 
2299
                if ( p->offset ) {
 
2300
 
 
2301
                        p->offset = 0;
 
2302
                        p->down   = 0;
 
2303
                        mask      = 1;
 
2304
                }
 
2305
                else {
 
2306
 
 
2307
                        p->offset = 1;
 
2308
                        p->down   = 1;
 
2309
                        mask      = 2;
 
2310
                }
 
2311
        }
 
2312
 
 
2313
        ScheduleBand( p, mask );
 
2314
        p->top += p->down;
2328
2315
}
2329
2316
 
2330
2317
/*
2337
2324
int             i;
2338
2325
int             line;
2339
2326
 
2340
 
        for ( line = p->top, i = 0 ; i < NOZZLES ; i++, line += HEAD_SPACING ) {
2341
 
                        
2342
 
 
2343
 
                if ( p->mark[ line % MAX_MARK ] & mask ) {
2344
 
                        
2345
 
                        p->head[ i ] = -1;
2346
 
                }
2347
 
                else {
2348
 
                        
2349
 
                        p->head[ i ] = line;
2350
 
                        p->mark[ line % MAX_MARK ] |= mask;
2351
 
                }
2352
 
        }
 
2327
        for ( line = p->top, i = 0 ; i < NOZZLES ; i++, line += HEAD_SPACING ) {
 
2328
 
 
2329
                if ( p->mark[ line % MAX_MARK ] & mask ) {
 
2330
 
 
2331
                        p->head[ i ] = -1;
 
2332
                }
 
2333
                else {
 
2334
 
 
2335
                        p->head[ i ] = line;
 
2336
                        p->mark[ line % MAX_MARK ] |= mask;
 
2337
                }
 
2338
        }
2353
2339
}
2354
2340
 
2355
2341
/****************************************************************************/
2366
2352
*/
2367
2353
 
2368
2354
static  void    PackLine( byte *input, int pixnum, int lev_on, int step,
2369
 
                                                  RAWLINE *line )
 
2355
                                                  RAWLINE *line )
2370
2356
{
2371
2357
byte    bits;
2372
2358
char    *result;
2373
2359
int             i, j, k;
2374
2360
 
2375
 
        result = line->data;
2376
 
        line->first = MAX_PIXELS;
2377
 
        line->last  = 0;
2378
 
                
2379
 
        for ( j = 0x80, bits = k = i = 0 ; i < pixnum ; i += step, input += step ){
2380
 
        
2381
 
                if ( *input == lev_on ) bits |= j;
2382
 
                
2383
 
                if ( ! ( j >>= 1 ) ) {
2384
 
                
2385
 
                        if ( bits ) {
2386
 
                        
2387
 
                                if ( line->first > k ) line->first = k;
2388
 
                                if ( line->last  < k ) line->last  = k;
2389
 
                        }
2390
 
                        
2391
 
                        *result++ = bits;
2392
 
                        j                 = 0x80;
2393
 
                        bits      = 0;
2394
 
                        k++;
2395
 
                }
2396
 
        }
2397
 
        
2398
 
        if ( j != 0x80 ) {
2399
 
        
2400
 
                *result = bits;
2401
 
                
2402
 
                if ( bits ) {
2403
 
                        
2404
 
                        if ( line->first > k ) line->first = k;
2405
 
                        if ( line->last  < k ) line->last  = k;
2406
 
                }
2407
 
        }
 
2361
        result = line->data;
 
2362
        line->first = MAX_PIXELS;
 
2363
        line->last  = 0;
 
2364
 
 
2365
        for ( j = 0x80, bits = k = i = 0 ; i < pixnum ; i += step, input += step ){
 
2366
 
 
2367
                if ( *input == lev_on ) bits |= j;
 
2368
 
 
2369
                if ( ! ( j >>= 1 ) ) {
 
2370
 
 
2371
                        if ( bits ) {
 
2372
 
 
2373
                                if ( line->first > k ) line->first = k;
 
2374
                                if ( line->last  < k ) line->last  = k;
 
2375
                        }
 
2376
 
 
2377
                        *result++ = bits;
 
2378
                        j                 = 0x80;
 
2379
                        bits      = 0;
 
2380
                        k++;
 
2381
                }
 
2382
        }
 
2383
 
 
2384
        if ( j != 0x80 ) {
 
2385
 
 
2386
                *result = bits;
 
2387
 
 
2388
                if ( bits ) {
 
2389
 
 
2390
                        if ( line->first > k ) line->first = k;
 
2391
                        if ( line->last  < k ) line->last  = k;
 
2392
                }
 
2393
        }
2408
2394
}
2409
2395
 
2410
2396
/*
2413
2399
*
2414
2400
*       Returns the length of the RLE data.
2415
2401
*/
2416
 
                                                                 
 
2402
 
2417
2403
static  int             RleCompress( RAWLINE *raw, int min, int max, byte *rle_data )
2418
2404
{
2419
2405
int             i, n;
2423
2409
byte    *input;
2424
2410
int     len;
2425
2411
 
2426
 
        if ( ! raw ) {
2427
 
        
2428
 
                /* This is an empty line */
2429
 
        
2430
 
                for ( n = 0, i = max - min ; i >= 129 ; i -= 129 ) {
2431
 
                
2432
 
                        *rle_data++ = 128;
2433
 
                        *rle_data++ = 0;
2434
 
                        n += 2;
2435
 
                }
2436
 
                
2437
 
                if ( i >= 2 ) {
2438
 
                
2439
 
                        *rle_data++ = 257 - i;
2440
 
                        *rle_data++ = 0;
2441
 
                        n += 2;
2442
 
                }
2443
 
                else if ( i ) {
2444
 
                
2445
 
                        *rle_data++ = 0;
2446
 
                        *rle_data++ = 0;
2447
 
                        n+= 2;
2448
 
                }
2449
 
                
2450
 
                return( n );
2451
 
        }
2452
 
        
2453
 
        /* There's data, set up encoding parameters */
2454
 
        
2455
 
        input = raw->data + min;
2456
 
        len   = max - min;
2457
 
                
2458
 
        /* Create a run-length encoded version. We do it even if no pixel
2459
 
           was set because it may be that this line is just part of a 
2460
 
           multi-line band. */
2461
 
        
2462
 
        length = 0;
2463
 
        start  = input;
2464
 
        rstrt  = NULL;
2465
 
        pbyte  = *input++;
2466
 
        
2467
 
        for ( i = 1 ; i < len ; i++, input++ ) {
2468
 
                
2469
 
                if ( *input == pbyte ) {
2470
 
                
2471
 
                        /* This byte is identical to the previous one(s). */
2472
 
                        
2473
 
                        if ( ! rstrt ) {
2474
 
                        
2475
 
                                /* This is the start of a new repeating sequence */
2476
 
                                
2477
 
                                rstrt = input - 1;
2478
 
                        }
2479
 
                }
2480
 
                else {
2481
 
                
2482
 
                        /* Different byte than the previous one(s) */
2483
 
                        
2484
 
                        if ( rstrt ) {
2485
 
                        
2486
 
                                /* There was a repetitive sequence. */
2487
 
                                
2488
 
                                if ( rstrt - input < 4 ) {
2489
 
                                
2490
 
                                        /* For less than four bytes it isn't worth
2491
 
                                           to do RLE, we discard them */
2492
 
                                        
2493
 
                                        rstrt = NULL;
2494
 
                                }
2495
 
                                else {
2496
 
                                
2497
 
                                        /* We must flush */
2498
 
                                        
2499
 
                                        n = RleFlush( start, rstrt, input, rle_data );
2500
 
                                        rle_data  += n;
2501
 
                                        length += n;
2502
 
                                        
2503
 
                                        /* Initialise again */
2504
 
                                        
2505
 
                                        start = rle_data;
2506
 
                                        rstrt = NULL;
2507
 
                                }
2508
 
                        }                                               
2509
 
                        
2510
 
                        pbyte = *rle_data;
2511
 
                }
2512
 
        }
2513
 
        
2514
 
        /* We flush whatever is left over */
2515
 
        
2516
 
        length += RleFlush( start, rstrt, input, rle_data );
2517
 
        
2518
 
        return( length );
 
2412
        if ( ! raw ) {
 
2413
 
 
2414
                /* This is an empty line */
 
2415
 
 
2416
                for ( n = 0, i = max - min ; i >= 129 ; i -= 129 ) {
 
2417
 
 
2418
                        *rle_data++ = 128;
 
2419
                        *rle_data++ = 0;
 
2420
                        n += 2;
 
2421
                }
 
2422
 
 
2423
                if ( i >= 2 ) {
 
2424
 
 
2425
                        *rle_data++ = 257 - i;
 
2426
                        *rle_data++ = 0;
 
2427
                        n += 2;
 
2428
                }
 
2429
                else if ( i ) {
 
2430
 
 
2431
                        *rle_data++ = 0;
 
2432
                        *rle_data++ = 0;
 
2433
                        n+= 2;
 
2434
                }
 
2435
 
 
2436
                return( n );
 
2437
        }
 
2438
 
 
2439
        /* There's data, set up encoding parameters */
 
2440
 
 
2441
        input = raw->data + min;
 
2442
        len   = max - min;
 
2443
 
 
2444
        /* Create a run-length encoded version. We do it even if no pixel
 
2445
           was set because it may be that this line is just part of a
 
2446
           multi-line band. */
 
2447
 
 
2448
        length = 0;
 
2449
        start  = input;
 
2450
        rstrt  = NULL;
 
2451
        pbyte  = *input++;
 
2452
 
 
2453
        for ( i = 1 ; i < len ; i++, input++ ) {
 
2454
 
 
2455
                if ( *input == pbyte ) {
 
2456
 
 
2457
                        /* This byte is identical to the previous one(s). */
 
2458
 
 
2459
                        if ( ! rstrt ) {
 
2460
 
 
2461
                                /* This is the start of a new repeating sequence */
 
2462
 
 
2463
                                rstrt = input - 1;
 
2464
                        }
 
2465
                }
 
2466
                else {
 
2467
 
 
2468
                        /* Different byte than the previous one(s) */
 
2469
 
 
2470
                        if ( rstrt ) {
 
2471
 
 
2472
                                /* There was a repetitive sequence. */
 
2473
 
 
2474
                                if ( rstrt - input < 4 ) {
 
2475
 
 
2476
                                        /* For less than four bytes it isn't worth
 
2477
                                           to do RLE, we discard them */
 
2478
 
 
2479
                                        rstrt = NULL;
 
2480
                                }
 
2481
                                else {
 
2482
 
 
2483
                                        /* We must flush */
 
2484
 
 
2485
                                        n = RleFlush( start, rstrt, input, rle_data );
 
2486
                                        rle_data  += n;
 
2487
                                        length += n;
 
2488
 
 
2489
                                        /* Initialise again */
 
2490
 
 
2491
                                        start = rle_data;
 
2492
                                        rstrt = NULL;
 
2493
                                }
 
2494
                        }
 
2495
 
 
2496
                        pbyte = *rle_data;
 
2497
                }
 
2498
        }
 
2499
 
 
2500
        /* We flush whatever is left over */
 
2501
 
 
2502
        length += RleFlush( start, rstrt, input, rle_data );
 
2503
 
 
2504
        return( length );
2519
2505
}
2520
 
                        
 
2506
 
2521
2507
/*
2522
2508
*       This function flushes the RLE encoding buffer
2523
2509
*       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2537
2523
*       but it isn't. This can cause some penalty, however, we will live
2538
2524
*       with that for now.
2539
2525
*/
2540
 
                                
 
2526
 
2541
2527
static  int             RleFlush( byte *first, byte *reps, byte *now, byte *out )
2542
2528
{
2543
2529
int             count;
2544
2530
int             l;
2545
2531
 
2546
 
        if ( ! first ) return( 0 );
2547
 
        
2548
 
        if ( ! reps ) reps = now;
2549
 
        
2550
 
        count = 0;
2551
 
                
2552
 
        /* Write the nonrepetitve pattern first */
2553
 
 
2554
 
        while ( ( l = reps - first ) ) {
2555
 
        
2556
 
                if ( l > 128 ) {
2557
 
                
2558
 
                        /* More than 128 consecutive bytes, write out a 128 byte chunk */
2559
 
                        
2560
 
                        *out++ = 127;
2561
 
                        memcpy( out, first, 128 );
2562
 
                        out   += 128;
2563
 
                        first += 128;
2564
 
                        count += 129;
2565
 
                }
2566
 
                else {
2567
 
                
2568
 
                        /* There are not more than 128 bytes, write them into a 
2569
 
                           single chunk */
2570
 
                        
2571
 
                        *out++ = l - 1;
2572
 
                        memcpy( out, first, l );
2573
 
                        count += l + 1;
2574
 
                        first += l;
2575
 
                        out   += l;
2576
 
                }
2577
 
        }                               
2578
 
                                        
2579
 
        /* Now write the repeated pattern */
2580
 
        
2581
 
        while ( ( l = now - reps ) ) {
2582
 
        
2583
 
                if ( l > 128 ) {
2584
 
                
2585
 
                        /* More than 128 bytes are identical, write out a
2586
 
                           129 byte chunk */
2587
 
                           
2588
 
                        *out++ = 128;
2589
 
                        *out++ = *reps;
2590
 
                        count += 2;
2591
 
                        reps  += 129;
2592
 
                }
2593
 
                else {
2594
 
                
2595
 
                        if ( l == 1 ) {
2596
 
                        
2597
 
                                /* There is only one byte left, write it out as a
2598
 
                                   nonrepetitive chunk */
2599
 
                                   
2600
 
                                *out++ = 0;
2601
 
                                *out++ = *reps;
2602
 
                                count += 2;
2603
 
                                reps++;
2604
 
                        }
2605
 
                        else {
2606
 
                                
2607
 
                                /* What remains is at least 2 bytes but not larger than what
2608
 
                                   can be written in a single chunk */
2609
 
                                   
2610
 
                                *out++ = 257 - l;
2611
 
                                *out++ = *reps;
2612
 
                                count += 2;
2613
 
                                reps   = now;
2614
 
                        }
2615
 
                }
2616
 
        }
2617
 
        
2618
 
        return( count );
 
2532
        if ( ! first ) return( 0 );
 
2533
 
 
2534
        if ( ! reps ) reps = now;
 
2535
 
 
2536
        count = 0;
 
2537
 
 
2538
        /* Write the nonrepetitve pattern first */
 
2539
 
 
2540
        while ( ( l = reps - first ) ) {
 
2541
 
 
2542
                if ( l > 128 ) {
 
2543
 
 
2544
                        /* More than 128 consecutive bytes, write out a 128 byte chunk */
 
2545
 
 
2546
                        *out++ = 127;
 
2547
                        memcpy( out, first, 128 );
 
2548
                        out   += 128;
 
2549
                        first += 128;
 
2550
                        count += 129;
 
2551
                }
 
2552
                else {
 
2553
 
 
2554
                        /* There are not more than 128 bytes, write them into a
 
2555
                           single chunk */
 
2556
 
 
2557
                        *out++ = l - 1;
 
2558
                        memcpy( out, first, l );
 
2559
                        count += l + 1;
 
2560
                        first += l;
 
2561
                        out   += l;
 
2562
                }
 
2563
        }
 
2564
 
 
2565
        /* Now write the repeated pattern */
 
2566
 
 
2567
        while ( ( l = now - reps ) ) {
 
2568
 
 
2569
                if ( l > 128 ) {
 
2570
 
 
2571
                        /* More than 128 bytes are identical, write out a
 
2572
                           129 byte chunk */
 
2573
 
 
2574
                        *out++ = 128;
 
2575
                        *out++ = *reps;
 
2576
                        count += 2;
 
2577
                        reps  += 129;
 
2578
                }
 
2579
                else {
 
2580
 
 
2581
                        if ( l == 1 ) {
 
2582
 
 
2583
                                /* There is only one byte left, write it out as a
 
2584
                                   nonrepetitive chunk */
 
2585
 
 
2586
                                *out++ = 0;
 
2587
                                *out++ = *reps;
 
2588
                                count += 2;
 
2589
                                reps++;
 
2590
                        }
 
2591
                        else {
 
2592
 
 
2593
                                /* What remains is at least 2 bytes but not larger than what
 
2594
                                   can be written in a single chunk */
 
2595
 
 
2596
                                *out++ = 257 - l;
 
2597
                                *out++ = *reps;
 
2598
                                count += 2;
 
2599
                                reps   = now;
 
2600
                        }
 
2601
                }
 
2602
        }
 
2603
 
 
2604
        return( count );
2619
2605
}
2620
2606
 
2621
2607
/****************************************************************************/
2624
2610
 
2625
2611
static  void    SendReset( FILE *stream )
2626
2612
{
2627
 
        SendString( stream, ESC "@" );
 
2613
        SendString( stream, ESC "@" );
2628
2614
}
2629
2615
 
2630
2616
static  void    SendMargin( FILE *stream, int top, int bot )
2631
2617
{
2632
 
        SendString( stream, ESC "(c" );
2633
 
        SendWord( stream, 4 );
2634
 
        SendWord( stream, bot );
2635
 
        SendWord( stream, top );
 
2618
        SendString( stream, ESC "(c" );
 
2619
        SendWord( stream, 4 );
 
2620
        SendWord( stream, bot );
 
2621
        SendWord( stream, top );
2636
2622
}
2637
2623
 
2638
2624
static  void    SendPaper( FILE *stream, int length )
2639
2625
{
2640
 
        SendString( stream, ESC "(C" );
2641
 
        SendWord( stream, 2 );
2642
 
        SendWord( stream, length );
 
2626
        SendString( stream, ESC "(C" );
 
2627
        SendWord( stream, 2 );
 
2628
        SendWord( stream, length );
2643
2629
}
2644
2630
 
2645
2631
static  void    SendGmode( FILE *stream, int on )
2646
2632
{
2647
 
        SendString( stream, ESC "(G" );
2648
 
        SendWord( stream, 1 );
2649
 
        SendByte( stream, on );
 
2633
        SendString( stream, ESC "(G" );
 
2634
        SendWord( stream, 1 );
 
2635
        SendByte( stream, on );
2650
2636
}
2651
2637
 
2652
2638
static void     SendUnit( FILE *stream, int res )
2653
2639
{
2654
 
        SendString( stream, ESC "(U" );
2655
 
        SendWord( stream, 1 );
2656
 
        SendByte( stream, res );
 
2640
        SendString( stream, ESC "(U" );
 
2641
        SendWord( stream, 1 );
 
2642
        SendByte( stream, res );
2657
2643
}
2658
2644
 
2659
2645
static  void    SendUnidir( FILE *stream, int on )
2660
2646
{
2661
 
        SendString( stream, ESC "U" );
2662
 
        SendByte( stream, on );
 
2647
        SendString( stream, ESC "U" );
 
2648
        SendByte( stream, on );
2663
2649
}
2664
2650
 
2665
2651
static  void    SendMicro( FILE *stream, int on )
2666
2652
{
2667
 
        SendString( stream, ESC "(i" );
2668
 
        SendWord( stream, 1 );
2669
 
        SendByte( stream, on );
 
2653
        SendString( stream, ESC "(i" );
 
2654
        SendWord( stream, 1 );
 
2655
        SendByte( stream, on );
2670
2656
}
2671
2657
 
2672
2658
static void     SendInk( FILE *stream, int x )
2673
2659
{
2674
 
        SendString( stream, ESC "(e" );
2675
 
        SendWord( stream, 2 );
2676
 
        SendByte( stream, 0 );
2677
 
        SendByte( stream, x );
 
2660
        SendString( stream, ESC "(e" );
 
2661
        SendWord( stream, 2 );
 
2662
        SendByte( stream, 0 );
 
2663
        SendByte( stream, x );
2678
2664
}
2679
2665
 
2680
2666
static  void    SendDown( FILE *stream, int x )
2681
2667
{
2682
 
        SendString( stream, ESC "(v" );
2683
 
        SendWord( stream, 2 );
2684
 
        SendWord( stream, x );
 
2668
        SendString( stream, ESC "(v" );
 
2669
        SendWord( stream, 2 );
 
2670
        SendWord( stream, x );
2685
2671
}
2686
2672
 
2687
2673
static  void    SendRight( FILE *stream, int amount )
2688
2674
{
2689
 
        SendString( stream, ESC "(\\" );
2690
 
        SendWord( stream, 4 );
2691
 
        SendWord( stream, 1440 );
2692
 
        SendWord( stream, amount );
 
2675
        SendString( stream, ESC "(\\" );
 
2676
        SendWord( stream, 4 );
 
2677
        SendWord( stream, 1440 );
 
2678
        SendWord( stream, amount );
2693
2679
}
2694
2680
 
2695
2681
static  void    SendColour( FILE *stream, int col )
2696
2682
{
2697
2683
static  int     ccode[] = { 0x000, 0x200, 0x100, 0x400, 0x201, 0x101 };
2698
2684
 
2699
 
        SendString( stream, ESC "(r" );
2700
 
        SendWord( stream, 2 );
2701
 
        SendWord( stream, ccode[ col ] );
 
2685
        SendString( stream, ESC "(r" );
 
2686
        SendWord( stream, 2 );
 
2687
        SendWord( stream, ccode[ col ] );
2702
2688
}
2703
2689
 
2704
 
static void     SendData( FILE *stream, int hres, int vres, int noz, int col ) 
 
2690
static void     SendData( FILE *stream, int hres, int vres, int noz, int col )
2705
2691
{
2706
 
        SendString( stream, ESC "." );
2707
 
        SendByte( stream, 1 );                          /* Run-length encoded data */
2708
 
        
2709
 
        /* If we use 1 nozzle, then vertical resolution is what it is.
2710
 
           Otherwise it must be set to 90 dpi */
2711
 
           
2712
 
        if ( noz == 1 )
2713
 
        
2714
 
                SendByte( stream, RESCODE( vres ) );
2715
 
        else
2716
 
                SendByte( stream, RESCODE( 90 ) );
2717
 
 
2718
 
        /* The horizontal resolution is max. 720 dpi */
2719
 
        
2720
 
        if ( hres > 720 )
2721
 
        
2722
 
                SendByte( stream, RESCODE( 720 ) );
2723
 
        else
2724
 
                SendByte( stream, RESCODE( hres ) );
2725
 
                
2726
 
        SendByte( stream, noz );
2727
 
        SendWord( stream, col );
 
2692
        SendString( stream, ESC "." );
 
2693
        SendByte( stream, 1 );                          /* Run-length encoded data */
 
2694
 
 
2695
        /* If we use 1 nozzle, then vertical resolution is what it is.
 
2696
           Otherwise it must be set to 90 dpi */
 
2697
 
 
2698
        if ( noz == 1 )
 
2699
 
 
2700
                SendByte( stream, RESCODE( vres ) );
 
2701
        else
 
2702
                SendByte( stream, RESCODE( 90 ) );
 
2703
 
 
2704
        /* The horizontal resolution is max. 720 dpi */
 
2705
 
 
2706
        if ( hres > 720 )
 
2707
 
 
2708
                SendByte( stream, RESCODE( 720 ) );
 
2709
        else
 
2710
                SendByte( stream, RESCODE( hres ) );
 
2711
 
 
2712
        SendByte( stream, noz );
 
2713
        SendWord( stream, col );
2728
2714
}
2729
 
                
 
2715
 
2730
2716
static  void    SendString( FILE *stream, const char *s )
2731
2717
{
2732
 
        while ( *s ) SendByte( stream, *s++ );
 
2718
        while ( *s ) SendByte( stream, *s++ );
2733
2719
}
2734
2720
 
2735
2721
/****************************************************************************/
2743
2729
 
2744
2730
static  void    HalftonerStart( RENDER *render, int line )
2745
2731
{
2746
 
        (*(htable[ render->dev->halftoner ].hstrt))( render, line );
 
2732
        (*(htable[ render->dev->halftoner ].hstrt))( render, line );
2747
2733
}
2748
2734
 
2749
2735
/*
2753
2739
 
2754
2740
static  int             HalftoneThold( RENDER *render )
2755
2741
{
2756
 
        return( (*(htable[ render->dev->halftoner ].hthld))( render ) );
 
2742
        return( (*(htable[ render->dev->halftoner ].hthld))( render ) );
2757
2743
}
2758
2744
 
2759
2745
/*
2762
2748
*
2763
2749
*       This function has one fundamental assumption: halftoning of separate
2764
2750
*       colours is independent of each other.
2765
 
*       
 
2751
*
2766
2752
*       It calls the mono halftoner with the K, C, M, Y components.
2767
2753
*/
2768
2754
 
2775
2761
short           *errs[ MAX_ED_LINES ];
2776
2762
int                     i;
2777
2763
 
2778
 
        /* Get the rendering function */
2779
 
        
2780
 
        dev   = render->dev;
2781
 
        htone = htable[ render->dev->halftoner ].htone;
2782
 
        offs  = render->mono ? 0 : OFFS_K;
2783
 
        
2784
 
        if ( dev->mono ) {
2785
 
        
2786
 
                /* Monochrome, do only the black */
2787
 
                        
2788
 
                for ( i = 0 ; i < MAX_ED_LINES ; i++ ) 
2789
 
        
2790
 
                        errs[ i ] = render->error[ i ][ OFFS_K ];
2791
 
                
2792
 
                hdata.render = render;
2793
 
                hdata.data   = data + OFFS_K;
2794
 
                hdata.step       = sizeof( byte );
2795
 
                hdata.res        = render->res[ OFFS_K ];
2796
 
                hdata.block  = NULL;
2797
 
                hdata.err        = errs;
2798
 
                hdata.mval       = 255;
2799
 
                
2800
 
                (*htone)( &hdata, line );
2801
 
        }
2802
 
        else {
2803
 
                
2804
 
                /* Colour. D black first */
2805
 
        
2806
 
                for ( i = 0 ; i < MAX_ED_LINES ; i++ ) 
2807
 
                        
2808
 
                        errs[ i ] = render->error[ i ][ OFFS_K ];
2809
 
                
2810
 
                hdata.render = render;
2811
 
                hdata.step       = sizeof( long );
2812
 
                hdata.data   = data + OFFS_K;
2813
 
                hdata.res        = render->res[ OFFS_K ];
2814
 
                hdata.block  = NULL;
2815
 
                hdata.err        = errs;
2816
 
                hdata.mval       = 255;
2817
 
                
2818
 
                (*htone)( &hdata, line );
2819
 
                
2820
 
                /* Yellow has no intermediate ink. The already done black
2821
 
                   may inhibit it. */
2822
 
        
2823
 
                for ( i = 0 ; i < MAX_ED_LINES ; i++ ) 
2824
 
                
2825
 
                        errs[ i ] = render->error[ i ][ OFFS_Y ];
2826
 
                        
2827
 
                hdata.render = render;
2828
 
                hdata.step       = sizeof( long );
2829
 
                hdata.data   = data + OFFS_Y;
2830
 
                hdata.res        = render->res[ OFFS_Y ];
2831
 
                hdata.block  = dev->pureblack ? render->res[ OFFS_K ] : NULL;
2832
 
                hdata.err        = errs;
2833
 
                hdata.mval       = 255;
2834
 
 
2835
 
                (*htone)( &hdata, line );
2836
 
        
2837
 
                /* Cyan and magenta has intermediate colour ink, black may inhibit */
2838
 
        
2839
 
                for ( i = 0 ; i < MAX_ED_LINES ; i++ ) 
2840
 
                
2841
 
                        errs[ i ] = render->error[ i ][ OFFS_C ];
2842
 
                        
2843
 
                hdata.data   = data + OFFS_C;
2844
 
                hdata.res        = render->res[ OFFS_C ];
2845
 
                hdata.block  = dev->pureblack ? render->res[ OFFS_K ] : NULL;
2846
 
                hdata.mval       = dev->midcyan;
2847
 
 
2848
 
                (*htone)( &hdata, line );
2849
 
 
2850
 
                for ( i = 0 ; i < MAX_ED_LINES ; i++ ) 
2851
 
                
2852
 
                        errs[ i ] = render->error[ i ][ OFFS_M ];
2853
 
                        
2854
 
                hdata.data   = data + OFFS_M;
2855
 
                hdata.res        = render->res[ OFFS_M ];
2856
 
                hdata.block  = dev->pureblack ? render->res[ OFFS_K ] : NULL;
2857
 
                hdata.mval       = dev->midmagenta;
2858
 
 
2859
 
                (*htone)( &hdata, line );
2860
 
        }
2861
 
        
2862
 
        /* Here we have create the raw device format scanlines */
2863
 
        
2864
 
        if ( dev->mono ) {
2865
 
        
2866
 
                if ( render->xres == 1440 ) {
2867
 
                
2868
 
                        PackLine( render->res[ OFFS_K ], render->width, 255, 2, 
2869
 
                                          render->raw[ 0 ][ DEV_BLACK ]+ line % MAX_MARK );
2870
 
                                          
2871
 
                        PackLine( render->res[ OFFS_K ]+1, render->width-1, 255, 2, 
2872
 
                                          render->raw[ 1 ][ DEV_BLACK ]+ line % MAX_MARK );
2873
 
                }
2874
 
                else {
2875
 
                
2876
 
                        PackLine( render->res[ OFFS_K ], render->width, 255, 1, 
2877
 
                                          render->raw[ 0 ][ DEV_BLACK ]+ line % MAX_MARK );
2878
 
                }
2879
 
        }
2880
 
        else {
2881
 
        
2882
 
                if ( render->xres == 1440 ) {
2883
 
                
2884
 
                        PackLine( render->res[ OFFS_K ], render->width, 255, 2, 
2885
 
                                          render->raw[ 0 ][ DEV_BLACK ]+ line % MAX_MARK );
2886
 
                                          
2887
 
                        PackLine( render->res[ OFFS_K ]+1, render->width-1, 255, 2, 
2888
 
                                          render->raw[ 1 ][ DEV_BLACK ]+ line % MAX_MARK );
2889
 
                                          
2890
 
                        PackLine( render->res[ OFFS_C ], render->width, 255, 2, 
2891
 
                                          render->raw[ 0 ][ DEV_CYAN ]+ line % MAX_MARK );
2892
 
                                          
2893
 
                        PackLine( render->res[ OFFS_C ]+1, render->width-1, 255, 2, 
2894
 
                                          render->raw[ 1 ][ DEV_CYAN ]+ line % MAX_MARK );
2895
 
                                          
2896
 
                        PackLine( render->res[ OFFS_M ], render->width, 255, 2, 
2897
 
                                          render->raw[ 0 ][ DEV_MAGENTA ]+ line % MAX_MARK);
2898
 
                                          
2899
 
                        PackLine( render->res[ OFFS_M ]+1, render->width-1, 255, 2, 
2900
 
                                          render->raw[ 1 ][ DEV_MAGENTA ]+ line % MAX_MARK);
2901
 
                                          
2902
 
                        PackLine( render->res[ OFFS_Y ], render->width, 255, 2, 
2903
 
                                          render->raw[ 0 ][ DEV_YELLOW ]+ line % MAX_MARK );
2904
 
                                          
2905
 
                        PackLine( render->res[ OFFS_Y ]+1, render->width-1, 255, 2, 
2906
 
                                          render->raw[ 1 ][ DEV_YELLOW ]+ line % MAX_MARK );
2907
 
                                          
2908
 
                        PackLine( render->res[ OFFS_C ], render->width, dev->midcyan, 
2909
 
                                          2, render->raw[ 0 ][ DEV_LCYAN ]+ line % MAX_MARK );
2910
 
                                          
2911
 
                        PackLine( render->res[ OFFS_C ]+1, render->width-1, dev->midcyan, 
2912
 
                                          2, render->raw[ 1 ][ DEV_LCYAN ]+ line % MAX_MARK );
2913
 
                                          
2914
 
                        PackLine( render->res[ OFFS_M ], render->width, dev->midmagenta, 
2915
 
                                          2, render->raw[0][ DEV_LMAGENTA ]+ line % MAX_MARK );
2916
 
                                          
2917
 
                        PackLine( render->res[ OFFS_M ]+1, render->width-1,dev->midmagenta,
2918
 
                                          2, render->raw[1][ DEV_LMAGENTA ]+ line % MAX_MARK );
2919
 
                }
2920
 
                else {
2921
 
                
2922
 
                        PackLine( render->res[ OFFS_K ], render->width, 255, 1, 
2923
 
                                          render->raw[ 0 ][ DEV_BLACK ]+ line % MAX_MARK );
2924
 
                                          
2925
 
                        PackLine( render->res[ OFFS_C ], render->width, 255, 1, 
2926
 
                                          render->raw[ 0 ][ DEV_CYAN ]+ line % MAX_MARK );
2927
 
                                          
2928
 
                        PackLine( render->res[ OFFS_M ], render->width, 255, 1, 
2929
 
                                          render->raw[ 0 ][ DEV_MAGENTA ]+ line % MAX_MARK);
2930
 
                                          
2931
 
                        PackLine( render->res[ OFFS_Y ], render->width, 255, 1, 
2932
 
                                          render->raw[ 0 ][ DEV_YELLOW ]+ line % MAX_MARK );
2933
 
                                          
2934
 
                        PackLine( render->res[ OFFS_C ], render->width, dev->midcyan, 
2935
 
                                          1, render->raw[ 0 ][ DEV_LCYAN ]+ line % MAX_MARK );
2936
 
                                          
2937
 
                        PackLine( render->res[ OFFS_M ], render->width, dev->midmagenta, 
2938
 
                                          1, render->raw[0][ DEV_LMAGENTA ]+ line % MAX_MARK );
2939
 
                }
2940
 
        }
2941
 
        
2942
 
        /* Call the halftoner specific end-of-line function */
2943
 
        
2944
 
        (*htable[ render->dev->halftoner ].hteol)( render, line );
 
2764
        /* Get the rendering function */
 
2765
 
 
2766
        dev   = render->dev;
 
2767
        htone = htable[ render->dev->halftoner ].htone;
 
2768
        offs  = render->mono ? 0 : OFFS_K;
 
2769
 
 
2770
        if ( dev->mono ) {
 
2771
 
 
2772
                /* Monochrome, do only the black */
 
2773
 
 
2774
                for ( i = 0 ; i < MAX_ED_LINES ; i++ )
 
2775
 
 
2776
                        errs[ i ] = render->error[ i ][ OFFS_K ];
 
2777
 
 
2778
                hdata.render = render;
 
2779
                hdata.data   = data + OFFS_K;
 
2780
                hdata.step       = sizeof( byte );
 
2781
                hdata.res        = render->res[ OFFS_K ];
 
2782
                hdata.block  = NULL;
 
2783
                hdata.err        = errs;
 
2784
                hdata.mval       = 255;
 
2785
 
 
2786
                (*htone)( &hdata, line );
 
2787
        }
 
2788
        else {
 
2789
 
 
2790
                /* Colour. D black first */
 
2791
 
 
2792
                for ( i = 0 ; i < MAX_ED_LINES ; i++ )
 
2793
 
 
2794
                        errs[ i ] = render->error[ i ][ OFFS_K ];
 
2795
 
 
2796
                hdata.render = render;
 
2797
                hdata.step       = sizeof( long );
 
2798
                hdata.data   = data + OFFS_K;
 
2799
                hdata.res        = render->res[ OFFS_K ];
 
2800
                hdata.block  = NULL;
 
2801
                hdata.err        = errs;
 
2802
                hdata.mval       = 255;
 
2803
 
 
2804
                (*htone)( &hdata, line );
 
2805
 
 
2806
                /* Yellow has no intermediate ink. The already done black
 
2807
                   may inhibit it. */
 
2808
 
 
2809
                for ( i = 0 ; i < MAX_ED_LINES ; i++ )
 
2810
 
 
2811
                        errs[ i ] = render->error[ i ][ OFFS_Y ];
 
2812
 
 
2813
                hdata.render = render;
 
2814
                hdata.step       = sizeof( long );
 
2815
                hdata.data   = data + OFFS_Y;
 
2816
                hdata.res        = render->res[ OFFS_Y ];
 
2817
                hdata.block  = dev->pureblack ? render->res[ OFFS_K ] : NULL;
 
2818
                hdata.err        = errs;
 
2819
                hdata.mval       = 255;
 
2820
 
 
2821
                (*htone)( &hdata, line );
 
2822
 
 
2823
                /* Cyan and magenta has intermediate colour ink, black may inhibit */
 
2824
 
 
2825
                for ( i = 0 ; i < MAX_ED_LINES ; i++ )
 
2826
 
 
2827
                        errs[ i ] = render->error[ i ][ OFFS_C ];
 
2828
 
 
2829
                hdata.data   = data + OFFS_C;
 
2830
                hdata.res        = render->res[ OFFS_C ];
 
2831
                hdata.block  = dev->pureblack ? render->res[ OFFS_K ] : NULL;
 
2832
                hdata.mval       = dev->midcyan;
 
2833
 
 
2834
                (*htone)( &hdata, line );
 
2835
 
 
2836
                for ( i = 0 ; i < MAX_ED_LINES ; i++ )
 
2837
 
 
2838
                        errs[ i ] = render->error[ i ][ OFFS_M ];
 
2839
 
 
2840
                hdata.data   = data + OFFS_M;
 
2841
                hdata.res        = render->res[ OFFS_M ];
 
2842
                hdata.block  = dev->pureblack ? render->res[ OFFS_K ] : NULL;
 
2843
                hdata.mval       = dev->midmagenta;
 
2844
 
 
2845
                (*htone)( &hdata, line );
 
2846
        }
 
2847
 
 
2848
        /* Here we have create the raw device format scanlines */
 
2849
 
 
2850
        if ( dev->mono ) {
 
2851
 
 
2852
                if ( render->xres == 1440 ) {
 
2853
 
 
2854
                        PackLine( render->res[ OFFS_K ], render->width, 255, 2,
 
2855
                                          render->raw[ 0 ][ DEV_BLACK ]+ line % MAX_MARK );
 
2856
 
 
2857
                        PackLine( render->res[ OFFS_K ]+1, render->width-1, 255, 2,
 
2858
                                          render->raw[ 1 ][ DEV_BLACK ]+ line % MAX_MARK );
 
2859
                }
 
2860
                else {
 
2861
 
 
2862
                        PackLine( render->res[ OFFS_K ], render->width, 255, 1,
 
2863
                                          render->raw[ 0 ][ DEV_BLACK ]+ line % MAX_MARK );
 
2864
                }
 
2865
        }
 
2866
        else {
 
2867
 
 
2868
                if ( render->xres == 1440 ) {
 
2869
 
 
2870
                        PackLine( render->res[ OFFS_K ], render->width, 255, 2,
 
2871
                                          render->raw[ 0 ][ DEV_BLACK ]+ line % MAX_MARK );
 
2872
 
 
2873
                        PackLine( render->res[ OFFS_K ]+1, render->width-1, 255, 2,
 
2874
                                          render->raw[ 1 ][ DEV_BLACK ]+ line % MAX_MARK );
 
2875
 
 
2876
                        PackLine( render->res[ OFFS_C ], render->width, 255, 2,
 
2877
                                          render->raw[ 0 ][ DEV_CYAN ]+ line % MAX_MARK );
 
2878
 
 
2879
                        PackLine( render->res[ OFFS_C ]+1, render->width-1, 255, 2,
 
2880
                                          render->raw[ 1 ][ DEV_CYAN ]+ line % MAX_MARK );
 
2881
 
 
2882
                        PackLine( render->res[ OFFS_M ], render->width, 255, 2,
 
2883
                                          render->raw[ 0 ][ DEV_MAGENTA ]+ line % MAX_MARK);
 
2884
 
 
2885
                        PackLine( render->res[ OFFS_M ]+1, render->width-1, 255, 2,
 
2886
                                          render->raw[ 1 ][ DEV_MAGENTA ]+ line % MAX_MARK);
 
2887
 
 
2888
                        PackLine( render->res[ OFFS_Y ], render->width, 255, 2,
 
2889
                                          render->raw[ 0 ][ DEV_YELLOW ]+ line % MAX_MARK );
 
2890
 
 
2891
                        PackLine( render->res[ OFFS_Y ]+1, render->width-1, 255, 2,
 
2892
                                          render->raw[ 1 ][ DEV_YELLOW ]+ line % MAX_MARK );
 
2893
 
 
2894
                        PackLine( render->res[ OFFS_C ], render->width, dev->midcyan,
 
2895
                                          2, render->raw[ 0 ][ DEV_LCYAN ]+ line % MAX_MARK );
 
2896
 
 
2897
                        PackLine( render->res[ OFFS_C ]+1, render->width-1, dev->midcyan,
 
2898
                                          2, render->raw[ 1 ][ DEV_LCYAN ]+ line % MAX_MARK );
 
2899
 
 
2900
                        PackLine( render->res[ OFFS_M ], render->width, dev->midmagenta,
 
2901
                                          2, render->raw[0][ DEV_LMAGENTA ]+ line % MAX_MARK );
 
2902
 
 
2903
                        PackLine( render->res[ OFFS_M ]+1, render->width-1,dev->midmagenta,
 
2904
                                          2, render->raw[1][ DEV_LMAGENTA ]+ line % MAX_MARK );
 
2905
                }
 
2906
                else {
 
2907
 
 
2908
                        PackLine( render->res[ OFFS_K ], render->width, 255, 1,
 
2909
                                          render->raw[ 0 ][ DEV_BLACK ]+ line % MAX_MARK );
 
2910
 
 
2911
                        PackLine( render->res[ OFFS_C ], render->width, 255, 1,
 
2912
                                          render->raw[ 0 ][ DEV_CYAN ]+ line % MAX_MARK );
 
2913
 
 
2914
                        PackLine( render->res[ OFFS_M ], render->width, 255, 1,
 
2915
                                          render->raw[ 0 ][ DEV_MAGENTA ]+ line % MAX_MARK);
 
2916
 
 
2917
                        PackLine( render->res[ OFFS_Y ], render->width, 255, 1,
 
2918
                                          render->raw[ 0 ][ DEV_YELLOW ]+ line % MAX_MARK );
 
2919
 
 
2920
                        PackLine( render->res[ OFFS_C ], render->width, dev->midcyan,
 
2921
                                          1, render->raw[ 0 ][ DEV_LCYAN ]+ line % MAX_MARK );
 
2922
 
 
2923
                        PackLine( render->res[ OFFS_M ], render->width, dev->midmagenta,
 
2924
                                          1, render->raw[0][ DEV_LMAGENTA ]+ line % MAX_MARK );
 
2925
                }
 
2926
        }
 
2927
 
 
2928
        /* Call the halftoner specific end-of-line function */
 
2929
 
 
2930
        (*htable[ render->dev->halftoner ].hteol)( render, line );
2945
2931
}
2946
2932
 
2947
2933
/****************************************************************************/
2955
2941
 
2956
2942
static  int             FloydSThold( RENDER *p )
2957
2943
{
2958
 
        return( 5 );
 
2944
        return( 5 );
2959
2945
}
2960
2946
 
2961
2947
/*
2965
2951
 
2966
2952
static  void    FloydSStart( RENDER *p, int line )
2967
2953
{
2968
 
        memset( p->err, 0, ICOLN * MAX_PIXELS*2 );
2969
 
        p->error[ 0 ] = p->err[ 0 ];
 
2954
        memset( p->err, 0, ICOLN * MAX_PIXELS*2 );
 
2955
        p->error[ 0 ] = p->err[ 0 ];
2970
2956
}
2971
2957
 
2972
2958
/*
2976
2962
 
2977
2963
static  void    FloydSEol( RENDER *p, int line )
2978
2964
{
2979
 
        /* Since we use single error buffering, nothing to do */
 
2965
        /* Since we use single error buffering, nothing to do */
2980
2966
}
2981
2967
 
2982
2968
/*
2988
2974
*          *    7/16    r
2989
2975
*   3/16  5/16  1/16
2990
2976
*
2991
 
*       r is the residual (0, in theory). 
 
2977
*       r is the residual (0, in theory).
2992
2978
*       Absolutely nothing fancy is done here.
2993
2979
*
2994
2980
*/
3006
2992
short   e0, e1;                                         /* Propagating errors in current line   */
3007
2993
short   *l0;                                            /* Error buffer pointer                                 */
3008
2994
 
3009
 
        length  = htone->render->width;
3010
 
 
3011
 
        res             = htone->res;
3012
 
        data    = htone->data;
3013
 
        block   = htone->block;
3014
 
        
3015
 
        lim1    = htone->mval / 2;
3016
 
        lim2    = ( htone->mval + 256 ) / 2;
3017
 
        
3018
 
        l0              = htone->err[ 0 ];
3019
 
        
3020
 
        e0              = l0[ 1 ];
3021
 
        e1              = l0[ 2 ];
3022
 
        
3023
 
        l0[ 1 ] = 0;
3024
 
        l0[ 2 ] = 0;
3025
 
                
3026
 
        for ( x = 0 ; x < length ; x++ ) {
3027
 
        
3028
 
                /* First, clear the res byte. It is needed for the black */
3029
 
                
3030
 
                *res = 0;
3031
 
                
3032
 
                /* Add the actual error to the pixel, normalise, init, whatever. */
3033
 
                
3034
 
                pixel = ( ( *data << 4 ) + e0 );
3035
 
                e0 = e1;
3036
 
                e1 = l0[ 3 ] + ( pixel & 15 );                  /* This is the residual */
3037
 
                
3038
 
                l0[ 3 ] = 0;
3039
 
                pixel >>= 4;
3040
 
                
3041
 
                if ( ( block && *block ) || ( pixel < lim1 ) )
3042
 
                
3043
 
                        *res = 0;
3044
 
 
3045
 
                else if ( pixel >= lim2 )
3046
 
                
3047
 
                        *res = 255;
3048
 
                else
3049
 
                        *res = htone->mval;
3050
 
                
3051
 
                /* Calculate the err */
3052
 
                
3053
 
                pixerr = pixel - *res;
3054
 
                
3055
 
                /* Diffuse the err */
3056
 
        
3057
 
                e0              += ( pixerr << 3 ) - pixerr;    /* 7/16         */
3058
 
                l0[ 0 ] += ( pixerr << 2 ) - pixerr;    /* 3/16         */
3059
 
                l0[ 1 ] += ( pixerr << 2 ) + pixerr;    /* 5/16         */
3060
 
                l0[ 2 ] += pixerr;                                              /* 1/16         */
3061
 
                                
3062
 
                /* We have done everything, move the pointers */
3063
 
                
3064
 
                res++;
3065
 
                if ( block ) block++;
3066
 
                data += htone->step;
3067
 
                l0++;
3068
 
        }
 
2995
        length  = htone->render->width;
 
2996
 
 
2997
        res             = htone->res;
 
2998
        data    = htone->data;
 
2999
        block   = htone->block;
 
3000
 
 
3001
        lim1    = htone->mval / 2;
 
3002
        lim2    = ( htone->mval + 256 ) / 2;
 
3003
 
 
3004
        l0              = htone->err[ 0 ];
 
3005
 
 
3006
        e0              = l0[ 1 ];
 
3007
        e1              = l0[ 2 ];
 
3008
 
 
3009
        l0[ 1 ] = 0;
 
3010
        l0[ 2 ] = 0;
 
3011
 
 
3012
        for ( x = 0 ; x < length ; x++ ) {
 
3013
 
 
3014
                /* First, clear the res byte. It is needed for the black */
 
3015
 
 
3016
                *res = 0;
 
3017
 
 
3018
                /* Add the actual error to the pixel, normalise, init, whatever. */
 
3019
 
 
3020
                pixel = ( ( *data << 4 ) + e0 );
 
3021
                e0 = e1;
 
3022
                e1 = l0[ 3 ] + ( pixel & 15 );                  /* This is the residual */
 
3023
 
 
3024
                l0[ 3 ] = 0;
 
3025
                pixel >>= 4;
 
3026
 
 
3027
                if ( ( block && *block ) || ( pixel < lim1 ) )
 
3028
 
 
3029
                        *res = 0;
 
3030
 
 
3031
                else if ( pixel >= lim2 )
 
3032
 
 
3033
                        *res = 255;
 
3034
                else
 
3035
                        *res = htone->mval;
 
3036
 
 
3037
                /* Calculate the err */
 
3038
 
 
3039
                pixerr = pixel - *res;
 
3040
 
 
3041
                /* Diffuse the err */
 
3042
 
 
3043
                e0              += ( pixerr << 3 ) - pixerr;    /* 7/16         */
 
3044
                l0[ 0 ] += ( pixerr << 2 ) - pixerr;    /* 3/16         */
 
3045
                l0[ 1 ] += ( pixerr << 2 ) + pixerr;    /* 5/16         */
 
3046
                l0[ 2 ] += pixerr;                                              /* 1/16         */
 
3047
 
 
3048
                /* We have done everything, move the pointers */
 
3049
 
 
3050
                res++;
 
3051
                if ( block ) block++;
 
3052
                data += htone->step;
 
3053
                l0++;
 
3054
        }
3069
3055
}
3070
3056
 
3071
3057
/****************************************************************************/
3079
3065
 
3080
3066
static  int             DitherThold( RENDER *p )
3081
3067
{
3082
 
        return( 0 );
 
3068
        return( 0 );
3083
3069
}
3084
3070
 
3085
3071
/*
3089
3075
 
3090
3076
static  void    DitherStart( RENDER *p, int line )
3091
3077
{
3092
 
        /* Nothing to initialise */
 
3078
        /* Nothing to initialise */
3093
3079
}
3094
3080
 
3095
3081
/*
3099
3085
 
3100
3086
static  void    DitherEol( RENDER *p, int line )
3101
3087
{
3102
 
        /* Nothing to do - dithering has no memory */
 
3088
        /* Nothing to do - dithering has no memory */
3103
3089
}
3104
3090
 
3105
3091
/*
3119
3105
int             mx;                                                     /* Matrix index                                                 */
3120
3106
int             lval, hval;                                     /* Halftoned high/low values                    */
3121
3107
 
3122
 
        length  = htone->render->width;
3123
 
 
3124
 
        res             = htone->res;
3125
 
        data    = htone->data;
3126
 
        block   = htone->block;
3127
 
        
3128
 
        matrix  = dmatrix[ y % DMATRIX_Y ];
3129
 
                
3130
 
        for ( mx = x = 0 ; x < length ; x++ ) {
3131
 
        
3132
 
                /* First, clear the res byte. It is needed for the black */
3133
 
                
3134
 
                *res = 0;
3135
 
                
3136
 
                /* Next, see if the pixel is above the mval */
3137
 
                
3138
 
                if ( ( pixel = *data ) > htone->mval ) {
3139
 
                
3140
 
                        lval = htone->mval;
3141
 
                        hval = 255;
3142
 
                        
3143
 
                        if ( htone->mval == 127 )
3144
 
 
3145
 
                                pixel = ( ( pixel - htone->mval ) * 2 - 1 ) / 2;
3146
 
                        else
3147
 
                                pixel = ( pixel - htone->mval ) * 255 / ( 255 - htone->mval );
3148
 
                }
3149
 
                else {
3150
 
                
3151
 
                        lval = 0;
3152
 
                        hval = htone->mval;
3153
 
                        
3154
 
                        if ( htone->mval != 255 ) {
3155
 
                        
3156
 
                                if ( htone->mval == 127 )
3157
 
                                
3158
 
                                        pixel = ( pixel * 4 + 1 ) / 2;
3159
 
                                else
3160
 
                                        pixel = pixel * 255 / htone->mval;
3161
 
                        }
3162
 
                }
3163
 
                
3164
 
                if ( block && *block ) {
3165
 
                
3166
 
                        *res = 0;
3167
 
                }
3168
 
                else {
3169
 
                
3170
 
                        if ( pixel >= matrix[ mx ] )
3171
 
                
3172
 
                                *res = hval;
3173
 
                        else
3174
 
                                *res = lval;
3175
 
                }
3176
 
                
3177
 
                res++;
3178
 
                if ( ++mx == DMATRIX_X ) mx = 0;
3179
 
                if ( block ) block++;
3180
 
                data += htone->step;
3181
 
        }
 
3108
        length  = htone->render->width;
 
3109
 
 
3110
        res             = htone->res;
 
3111
        data    = htone->data;
 
3112
        block   = htone->block;
 
3113
 
 
3114
        matrix  = dmatrix[ y % DMATRIX_Y ];
 
3115
 
 
3116
        for ( mx = x = 0 ; x < length ; x++ ) {
 
3117
 
 
3118
                /* First, clear the res byte. It is needed for the black */
 
3119
 
 
3120
                *res = 0;
 
3121
 
 
3122
                /* Next, see if the pixel is above the mval */
 
3123
 
 
3124
                if ( ( pixel = *data ) > htone->mval ) {
 
3125
 
 
3126
                        lval = htone->mval;
 
3127
                        hval = 255;
 
3128
 
 
3129
                        if ( htone->mval == 127 )
 
3130
 
 
3131
                                pixel = ( ( pixel - htone->mval ) * 2 - 1 ) / 2;
 
3132
                        else
 
3133
                                pixel = ( pixel - htone->mval ) * 255 / ( 255 - htone->mval );
 
3134
                }
 
3135
                else {
 
3136
 
 
3137
                        lval = 0;
 
3138
                        hval = htone->mval;
 
3139
 
 
3140
                        if ( htone->mval != 255 ) {
 
3141
 
 
3142
                                if ( htone->mval == 127 )
 
3143
 
 
3144
                                        pixel = ( pixel * 4 + 1 ) / 2;
 
3145
                                else
 
3146
                                        pixel = pixel * 255 / htone->mval;
 
3147
                        }
 
3148
                }
 
3149
 
 
3150
                if ( block && *block ) {
 
3151
 
 
3152
                        *res = 0;
 
3153
                }
 
3154
                else {
 
3155
 
 
3156
                        if ( pixel >= matrix[ mx ] )
 
3157
 
 
3158
                                *res = hval;
 
3159
                        else
 
3160
                                *res = lval;
 
3161
                }
 
3162
 
 
3163
                res++;
 
3164
                if ( ++mx == DMATRIX_X ) mx = 0;
 
3165
                if ( block ) block++;
 
3166
                data += htone->step;
 
3167
        }
3182
3168
}
3183
3169
 
3184
3170
/****************************************************************************/
3192
3178
 
3193
3179
static  int             BendorThold( RENDER *p )
3194
3180
{
3195
 
        return( 5 );
 
3181
        return( 5 );
3196
3182
}
3197
3183
 
3198
3184
/*
3202
3188
 
3203
3189
static  void    BendorStart( RENDER *p, int line )
3204
3190
{
3205
 
        memset( p->err, 0, 2 * ICOLN * MAX_PIXELS*2 );
3206
 
        p->error[ 0 ] = p->err[ 0 ];
3207
 
        p->error[ 1 ] = p->err[ 1 ];
 
3191
        memset( p->err, 0, 2 * ICOLN * MAX_PIXELS*2 );
 
3192
        p->error[ 0 ] = p->err[ 0 ];
 
3193
        p->error[ 1 ] = p->err[ 1 ];
3208
3194
}
3209
3195
 
3210
3196
/*
3216
3202
{
3217
3203
void    *x;
3218
3204
 
3219
 
        x = p->error[ 0 ];
3220
 
        p->error[ 0 ] = p->error[ 1 ];
3221
 
        p->error[ 1 ] = x;
 
3205
        x = p->error[ 0 ];
 
3206
        p->error[ 0 ] = p->error[ 1 ];
 
3207
        p->error[ 1 ] = x;
3222
3208
}
3223
3209
 
3224
3210
/*
3227
3213
*
3228
3214
*       This is not yet finished (the matrix is bad, actually).
3229
3215
*
3230
 
*       The matrix is the following (the normalisation factor is 1/128, 
 
3216
*       The matrix is the following (the normalisation factor is 1/128,
3231
3217
*       '*' represents the current pixel, r is the truncation residual):
3232
3218
*
3233
3219
*                                *      20      10  r
3241
3227
*                       *       3
3242
3228
*               2       3       2
3243
3229
*
3244
 
*       and the normalisation factor can be set by the user. 
3245
 
*       The splash matrix is only applied if we have actually deposited 
3246
 
*       ink and the amount added to the errors is independent that of the 
 
3230
*       and the normalisation factor can be set by the user.
 
3231
*       The splash matrix is only applied if we have actually deposited
 
3232
*       ink and the amount added to the errors is independent that of the
3247
3233
*       actual image value, it only depends on the ink applied.
3248
3234
*       Of course, the ink spreads up and left as well and we could compensate
3249
3235
*       for this for a certain extent by keeping track of the errors caused in
3250
3236
*       previous pixels and lines and modifying them accordingly but it
3251
3237
*       would lead to a horrible code mess and it wouldn't be worth the effort.
3252
3238
*
3253
 
*       A further enhancement that we allow the error to 'leak'. Experimental 
3254
 
*       results show that with a 5-15% loss of error the image quality 
 
3239
*       A further enhancement that we allow the error to 'leak'. Experimental
 
3240
*       results show that with a 5-15% loss of error the image quality
3255
3241
*       increases and the colour distortion remains very low. If you think
3256
3242
*       about it, this, in effect stops the error to spread its effect over
3257
 
*       large areas but it will have almost undisturbed effect on neighbouring 
3258
 
*       areas (you allow for an exponential error decay). 
 
3243
*       large areas but it will have almost undisturbed effect on neighbouring
 
3244
*       areas (you allow for an exponential error decay).
3259
3245
*       This parameter is user definable, too.
3260
3246
*/
3261
3247
 
3276
3262
short   e0, e1;                                         /* Propagating errors in current line   */
3277
3263
short   *l0, *l1;                                       /* Error buffer pointers                                */
3278
3264
 
3279
 
        splash  = htone->render->dev->splash;
3280
 
        leakage = htone->render->dev->splash;
3281
 
        length  = htone->render->width;
3282
 
 
3283
 
        res             = htone->res;
3284
 
        data    = htone->data;
3285
 
        block   = htone->block;
3286
 
        
3287
 
        lim1    = htone->mval / 2;
3288
 
        lim2    = ( htone->mval + 256 ) / 2;
3289
 
        
3290
 
        l0              = htone->err[ 0 ];
3291
 
        l1              = htone->err[ 1 ];
3292
 
        
3293
 
        e0              = l0[ 2 ];
3294
 
        e1              = l0[ 3 ];
3295
 
        
3296
 
        l0[ 2 ] = 0;
3297
 
        l0[ 3 ] = 0;
3298
 
                
3299
 
        for ( x = 0 ; x < length ; x++ ) {
3300
 
        
3301
 
                /* First, clear the res byte. It is needed for the black */
3302
 
                
3303
 
                *res = 0;
3304
 
                
3305
 
                /* Add the actual error to the pixel, normalise, init, whatever. */
3306
 
                
3307
 
                pixel = ( ( *data << 7 ) + e0 );
3308
 
                e0 = e1;
3309
 
                e1 = l0[ 4 ] + ( pixel & 127 );                 /* This is the residual */
3310
 
                
3311
 
                l0[ 4 ] = 0;
3312
 
                pixel >>= 7;
3313
 
                
3314
 
                if ( ( block && *block ) || ( pixel < lim1 ) )
3315
 
                
3316
 
                        *res = 0;
3317
 
 
3318
 
                else if ( pixel >= lim2 )
3319
 
                
3320
 
                        *res = 255;
3321
 
                else
3322
 
                        *res = htone->mval;
3323
 
                
3324
 
                /* Calculate the err */
3325
 
                
3326
 
                pixerr = pixel - *res;
3327
 
                
3328
 
                /* If leakage is defined, apply it */
3329
 
                
3330
 
                if ( leakage ) pixerr -= ( pixerr * leakage ) / 100;
3331
 
                
3332
 
                /* Diffuse the err */
3333
 
        
3334
 
                pixerr <<= 1;                                                   /* Multiplier is 2      */
3335
 
                pixe14 = pixerr;                                                /* pixe14 now 2         */
3336
 
                pixerr <<= 1;                                                   /* Multiplier is 4      */
3337
 
                pixe14 += pixerr;                                               /* pixe14 now 6         */
3338
 
                
3339
 
                l0[ 0 ] += pixerr;
3340
 
                l0[ 4 ] += pixerr;
3341
 
                
3342
 
                pixerr <<= 1;                                                   /* Multiplier is 8      */
3343
 
                pixe14 += pixerr;                                               /* pixe14 now 14        */
3344
 
                
3345
 
                l0[ 1 ] += pixerr;
3346
 
                l0[ 3 ] += pixerr;
3347
 
                l1[ 0 ] += pixerr;
3348
 
                l1[ 4 ] += pixerr;
3349
 
                
3350
 
                pixerr += pixerr >> 2;                                  /* Multiplier is 10     */
3351
 
                
3352
 
                l0[ 2 ] += pixerr;
3353
 
                e1              += pixerr;
3354
 
                
3355
 
                pixerr <<= 1;                                                   /* Multiplier is 20 */
3356
 
                
3357
 
                l1[ 2 ] += pixerr;
3358
 
                e0              += pixerr;
3359
 
                
3360
 
                /* pixe14 already contains 14 * err */
3361
 
                
3362
 
                l1[ 1 ] += pixe14;
3363
 
                l1[ 3 ] += pixe14;
3364
 
                
3365
 
                /* If splashing is defined, apply the splash matrix.
3366
 
                   The splash value is normalised to the same level as the err */
3367
 
                
3368
 
                if ( splash && *res ) {
3369
 
                
3370
 
                        sval = splash * *res;                           /* This is the 2x value */
3371
 
                        
3372
 
                        l1[ 1 ] -= sval;
3373
 
                        l1[ 3 ] -= sval;
3374
 
                        
3375
 
                        sval += sval >> 1;                                      /* This represents 3x   */
3376
 
                        
3377
 
                        e0              -= sval;
3378
 
                        l1[ 2 ] -= sval;
3379
 
                }
3380
 
                
3381
 
                /* We have done everything, move the pointers */
3382
 
                
3383
 
                res++;
3384
 
                if ( block ) block++;
3385
 
                data += htone->step;
3386
 
                l0++, l1++;
3387
 
        }
 
3265
        splash  = htone->render->dev->splash;
 
3266
        leakage = htone->render->dev->splash;
 
3267
        length  = htone->render->width;
 
3268
 
 
3269
        res             = htone->res;
 
3270
        data    = htone->data;
 
3271
        block   = htone->block;
 
3272
 
 
3273
        lim1    = htone->mval / 2;
 
3274
        lim2    = ( htone->mval + 256 ) / 2;
 
3275
 
 
3276
        l0              = htone->err[ 0 ];
 
3277
        l1              = htone->err[ 1 ];
 
3278
 
 
3279
        e0              = l0[ 2 ];
 
3280
        e1              = l0[ 3 ];
 
3281
 
 
3282
        l0[ 2 ] = 0;
 
3283
        l0[ 3 ] = 0;
 
3284
 
 
3285
        for ( x = 0 ; x < length ; x++ ) {
 
3286
 
 
3287
                /* First, clear the res byte. It is needed for the black */
 
3288
 
 
3289
                *res = 0;
 
3290
 
 
3291
                /* Add the actual error to the pixel, normalise, init, whatever. */
 
3292
 
 
3293
                pixel = ( ( *data << 7 ) + e0 );
 
3294
                e0 = e1;
 
3295
                e1 = l0[ 4 ] + ( pixel & 127 );                 /* This is the residual */
 
3296
 
 
3297
                l0[ 4 ] = 0;
 
3298
                pixel >>= 7;
 
3299
 
 
3300
                if ( ( block && *block ) || ( pixel < lim1 ) )
 
3301
 
 
3302
                        *res = 0;
 
3303
 
 
3304
                else if ( pixel >= lim2 )
 
3305
 
 
3306
                        *res = 255;
 
3307
                else
 
3308
                        *res = htone->mval;
 
3309
 
 
3310
                /* Calculate the err */
 
3311
 
 
3312
                pixerr = pixel - *res;
 
3313
 
 
3314
                /* If leakage is defined, apply it */
 
3315
 
 
3316
                if ( leakage ) pixerr -= ( pixerr * leakage ) / 100;
 
3317
 
 
3318
                /* Diffuse the err */
 
3319
 
 
3320
                pixerr <<= 1;                                                   /* Multiplier is 2      */
 
3321
                pixe14 = pixerr;                                                /* pixe14 now 2         */
 
3322
                pixerr <<= 1;                                                   /* Multiplier is 4      */
 
3323
                pixe14 += pixerr;                                               /* pixe14 now 6         */
 
3324
 
 
3325
                l0[ 0 ] += pixerr;
 
3326
                l0[ 4 ] += pixerr;
 
3327
 
 
3328
                pixerr <<= 1;                                                   /* Multiplier is 8      */
 
3329
                pixe14 += pixerr;                                               /* pixe14 now 14        */
 
3330
 
 
3331
                l0[ 1 ] += pixerr;
 
3332
                l0[ 3 ] += pixerr;
 
3333
                l1[ 0 ] += pixerr;
 
3334
                l1[ 4 ] += pixerr;
 
3335
 
 
3336
                pixerr += pixerr >> 2;                                  /* Multiplier is 10     */
 
3337
 
 
3338
                l0[ 2 ] += pixerr;
 
3339
                e1              += pixerr;
 
3340
 
 
3341
                pixerr <<= 1;                                                   /* Multiplier is 20 */
 
3342
 
 
3343
                l1[ 2 ] += pixerr;
 
3344
                e0              += pixerr;
 
3345
 
 
3346
                /* pixe14 already contains 14 * err */
 
3347
 
 
3348
                l1[ 1 ] += pixe14;
 
3349
                l1[ 3 ] += pixe14;
 
3350
 
 
3351
                /* If splashing is defined, apply the splash matrix.
 
3352
                   The splash value is normalised to the same level as the err */
 
3353
 
 
3354
                if ( splash && *res ) {
 
3355
 
 
3356
                        sval = splash * *res;                           /* This is the 2x value */
 
3357
 
 
3358
                        l1[ 1 ] -= sval;
 
3359
                        l1[ 3 ] -= sval;
 
3360
 
 
3361
                        sval += sval >> 1;                                      /* This represents 3x   */
 
3362
 
 
3363
                        e0              -= sval;
 
3364
                        l1[ 2 ] -= sval;
 
3365
                }
 
3366
 
 
3367
                /* We have done everything, move the pointers */
 
3368
 
 
3369
                res++;
 
3370
                if ( block ) block++;
 
3371
                data += htone->step;
 
3372
                l0++, l1++;
 
3373
        }
3388
3374
}