~ubuntu-branches/ubuntu/wily/ptouch-driver/wily

« back to all changes in this revision

Viewing changes to .pc/send-esc-i-A.patch/rastertoptch.c

  • Committer: Package Import Robot
  • Author(s): Didier Raboud
  • Date: 2011-08-29 12:27:35 UTC
  • mfrom: (2.1.10 oneiric)
  • Revision ID: package-import@ubuntu.com-20110829122735-pz8m0lrofxe0wzgt
Tags: 1.3-1
* Initial Debian release (Closes: #555892).

* Start from the Ubuntu packaging, thanks!

* Put under Debian Printing Team umbrella, with myself as uploader.
* Convert to 3.0 (quilt) source format.
* Add the Ubuntu apport hook conditionally
* Add VCS-* fields.
* Use dh-autoreconf to have a cleaner build.
* debian/watch: add.
* Use dh_pyppd trough the --with stanza.
* Drop explicit pyppd depends, they come trough dh_pyppd.
* Add DEP-3 headers to all patches.
* Rewrite debian/copyright DEP-5-style.
* Enable parallel building, including specifying the number of threads for
  the foomatic compilation.
* Drop unneeded dh_auto_test override.
* Slightly rewrite the "long" description.
* Bump Standards-Version to 3.9.2 without changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* rastertoptch is a filter to convert CUPS raster data into a Brother
 
2
 * P-touch label printer command byte stream.
 
3
 *
 
4
 * Copyright (c) 2006  Arne John Glenstrup <panic@itu.dk>
 
5
 *
 
6
 * This file is part of ptouch-driver
 
7
 *
 
8
 * ptouch-driver is free software; you can redistribute it and/or modify
 
9
 * it under the terms of the GNU General Public License as published by
 
10
 * the Free Software Foundation; either version 2 of the License, or
 
11
 * (at your option) any later version.
 
12
 *
 
13
 * ptouch-driver is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 * GNU General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU General Public License
 
19
 * along with ptouch-driver; if not, write to the Free Software
 
20
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
21
 *
 
22
 *
 
23
 * Please note: This software is not in any way related to Brother
 
24
 * Industries, Ltd., except that it is intended for use with their
 
25
 * products.  Any comments to this software should NOT be directed to
 
26
 * Brother Industries, Ltd.
 
27
 */
 
28
 
 
29
/** @file
 
30
 * This filter processes CUPS raster data, converting it into a byte
 
31
 * stream on stdout suitable for sending directly to a label printer
 
32
 * of the Brother P-touch family.
 
33
 *
 
34
 * @version 1.2
 
35
 * @author  Arne John Glenstrup <panic@itu.dk>
 
36
 * @date    2006
 
37
 
 
38
 * <h2>Invocation</h2>
 
39
 * The filter is invoked thus:
 
40
 *
 
41
 *         rastertoptch job user title copies options [filename]
 
42
 *
 
43
 * @param printer  The name of the printer queue (ignored)
 
44
 * @param job      The numeric job ID (ignored)
 
45
 * @param user     The string from the originating-user-name (ignored)
 
46
 * @param title    The string from the job-name attribute (ignored)
 
47
 * @param copies   The number of copies to be printed (ignored)
 
48
 * @param options  String representations of the job template
 
49
 *                 parameters, separated by spaces. Boolean attributes
 
50
 *                 are provided as "name" for true values and "noname"
 
51
 *                 for false values. All other attributes are provided
 
52
 *                 as "name=value" for single-valued attributes and
 
53
 *                 "name=value1,value2,...,valueN" for set attributes
 
54
 * @param filename The request file (if omitted, read from stdin)
 
55
 *
 
56
 * Available options (default values in [brackets]):
 
57
 *
 
58
 * @param PixelXfer=ULP|RLE|BIP  Use uncompressed line printing (ULP),
 
59
 *                               run-length encoding (RLE) or bit
 
60
 *                               image printing (BIP) when emitting
 
61
 *                               pixel data [ULP]
 
62
 * @param PrintQuality=High|Fast Use high quality or fast printing [High]
 
63
 * @param HalfCut                Perform half-cut (crack & peel) when
 
64
 *                               cutting [noHalfCut]
 
65
 * @param BytesPerLine=N         Emit N bytes per line [90]
 
66
 * @param Align=Right|Center     Pixel data alignment on tape [Right]
 
67
 * @param PrintDensity=1|...|5   Print density level: 1=light, 5=dark
 
68
 * @param ConcatPages            Output all pages in one page [noConcatPages]
 
69
 * @param RLEMemMax              Maximum memory used for RLE buffer [1000000]
 
70
 * @param SoftwareMirror         Make the filter mirror pixel data
 
71
 *                               if MirrorPrint is requested [noSoftwareMirror]
 
72
 * @param LabelPreamble          Emit preamble containing print quality,
 
73
 *                               roll/label type, tape width, label height,
 
74
 *                               and pixel lines [noLabelPreamble]
 
75
 * @param Debug                  Emit diagnostic output to stderr [noDebug]
 
76
 *                               (only if compiled with DEBUG set)
 
77
 *
 
78
 * Information about media type, resolution, mirror print, negative
 
79
 * print, cut media, advance distance (feed) is extracted from the
 
80
 * CUPS raster page headers given in the input stream.  The MediaType
 
81
 * page header field can be either "roll" or "labels" for continuous
 
82
 * tape or pre-cut labels, respectively.
 
83
 *
 
84
 * LabelPreamble should usually not be used for the PT series printers.
 
85
 *
 
86
 * <h2>Output</h2>
 
87
 * Each invocation of this filter is one job, containing a number of
 
88
 * pages, each page containing a number of lines, each line consisting
 
89
 * of a number of pixel bytes.
 
90
 *
 
91
 * Output consists of job-related printer initialisation commands,
 
92
 * followed by a number of pages, each page consisting of page-related
 
93
 * commands, followed by raster line data.  Each page is followed by a
 
94
 * finish page or (after the final page) finish job command.
 
95
 *
 
96
 * The following printer command language, printer, and tape
 
97
 * information has been deduced from many sources, but is not official
 
98
 * Brother documentation and may thus contain errors.  Please send any
 
99
 * corrections based on actual experience with these printers to the
 
100
 * maintainer.
 
101
 *
 
102
 * <h3>Job-related commands</h3>
 
103
 * <table>
 
104
 * <tr><th>Byte sequence</th><th>Function</th><th>Description</th></tr>
 
105
 * <tr><td>ESC @ (1b 40)</td>
 
106
       <td>Initialise</td><td>Clear print buffer</td></tr>
 
107
 * <tr><td>ESC i D # (1b 69 44 ##)
 
108
 *     <td>Set print density</td>
 
109
 *     <td>bit 0-3: 0=no change, 1-5=density level</td></tr>
 
110
 * <tr><td>ESC i K # (1b 69 4b ##)
 
111
 *     <td>Set half cut</td>
 
112
 *     <td>bit 2: 0=full cut, 1=half cut</td></tr>
 
113
 * <tr><td>ESC i R ## (1b 69 52 ##)</td>
 
114
 *     <td>Set transfer mode</td>
 
115
 *     <td>##: ?: 1=?</td></tr>
 
116
 * <tr><td>M ## (4d ##)</td>
 
117
 *     <td>Set compression</td>
 
118
 *     <td>##: Compression type: 2=RLE</td></tr>
 
119
 * </table>
 
120
 *
 
121
 * <h3>Page-related commands</h3>
 
122
 * <table>
 
123
 * <tr><th>Byte sequence</th><th>Function</th><th>Description</th></tr>
 
124
 * <tr><td>ESC i c #1 #2 #3 NUL #4 <br>(1b 63 #1 #2 #3 00 #4)
 
125
 *     <td>Set width & resolution</td>
 
126
 *     <td>360x360DPI: #1 #2 #4 = 0x84 0x00 0x00<br>
 
127
 *         360x720DPI: #1 #2 #4 = 0x86 0x09 0x01<br>
 
128
 *         #3: Tape width in mm</td></tr>
 
129
 * <tr><td>ESC i M # <br>(1b 69 4d ##)</td>
 
130
 *     <td>Set mode</td>
 
131
 *     <td>bit 0-4: Feed amount (default=large): 0-7=none, 8-11=small,
 
132
 *                  12-25=medium, 26-31=large<br>
 
133
 *         bit 6: Auto cut/cut mark (default=on): 0=off, 1=on<br>
 
134
 *         bit 7: Mirror print (default=off): 0=off, 1=on.
 
135
 *                (note that it seems that QL devices do not reverse the
 
136
 *                data stream themselves, but rely on the driver doing
 
137
 *                it!)</td></tr>
 
138
 * <tr><td>ESC i z #1 #2 #3 #4 #5 #6 NUL NUL NUL NUL<br>
 
139
 *         (1b 69 7a #1 #2 #3 #4 #5 #6 00 00 00 00)</td>
 
140
 *     <td>Set media & quality</td>
 
141
 *     <td>#1, bit 6: Print quality: 0=fast, 1=high<br>
 
142
 *         #2, bit 0: Media type: 0=continuous roll,
 
143
 *                                1=pre-cut labels<br>
 
144
 *         #3: Tape width in mm<br>
 
145
 *         #4: Label height in mm (0 for continuous roll)<br>
 
146
 *         #5 #6: Page consists of N=#5+256*#6 pixel lines</td></tr>
 
147
 * <tr><td>ESC i d #1 #2 <br>(1b 69 64 #1 #2)</td>
 
148
 *     <td>Set margin</td>
 
149
 *     <td>Set size of right(?) margin to N=#1+256*#2 pixels</td></tr>
 
150
 * <tr><td>FF (0c)</td>
 
151
 *     <td>Form feed</td>
 
152
 *     <td>Print buffer data without ejecting.</td></tr>
 
153
 * <tr><td>SUB (1a)</td>
 
154
 *     <td>Eject</td>
 
155
 *     <td>Print buffer data and ejects.</td></tr>
 
156
 * </table>
 
157
 *
 
158
 * <h3>Line-related commands</h3>
 
159
 * <table>
 
160
 * <tr><th>Byte sequence</th><th>Function</th><th>Description</th></tr>
 
161
 * <tr><td>G #1 #2 ...data... <br>(47 #1 #2 ...data...)</td>
 
162
 *     <td>Send raster line</td>
 
163
 *     <td>data consists of
 
164
 *         N=#1+256*#2 bytes of RLE compressed raster data.
 
165
 *         </td></tr>
 
166
 * <tr><td>Z (5a)</td>
 
167
 *     <td>Advance tape</td><td>Print 1 empty line</td></tr>
 
168
 * <tr><td>g #1 #2 ...data... <br>(67 #1 #2 ...data...)</td>
 
169
 *     <td>Send raster line</td>
 
170
 *     <td>data consists of
 
171
 *         N=#2 bytes of uncompressed raster data.</td></tr>
 
172
 * <tr><td>ESC * ' #1 #2 ...data... <br>(1b 2a 27 #1 #2 ...data...)</td>
 
173
 *     <td>Bit image printing (BIP)</td>
 
174
 *     <td>Print N=#1+256*#2 lines of 24 pixels; data consists of 3*N
 
175
 *         bytes</td></tr>
 
176
 * </table>
 
177
 *
 
178
 * <h3>Compressed-data-related commands (RLE)</h3>
 
179
 * <table>
 
180
 * <tr><th>Byte sequence</th><th>Function</th><th>Description</th></tr>
 
181
 * <tr><td>#1 ...data...</td>
 
182
 *     <td>#1 >= 0: Print uncompressed</td>
 
183
 *     <td>data consists of 1+#1 uncompressed bytes</td></tr>
 
184
 * <tr><td>#1 #2</td>
 
185
 *     <td>#1 < 0: Print compressed</td>
 
186
 *     <td>#2 should be printed 1-#1 times</td></tr>
 
187
 * </table>
 
188
 * #1 is represented as a 2-complement signed integer.
 
189
 *
 
190
 * <h2>Printer model characteristics</h2>
 
191
 * The following table lists for each model what kind of cutter it has
 
192
 * (manual, auto, half cut), what kind of pixel data transfer mode it
 
193
 * requires, its resolution, number of print head pixels, number of
 
194
 * bytes of pixel data that must be transmitted per line (regardless
 
195
 * of actual tape width!), and what kinds of tape it can take.
 
196
 *
 
197
 * For PC models, pixel data must be centered, so narrow tapes require
 
198
 * padding raster data with zero bits on each side.  For QL models,
 
199
 * labels are left-aligned, so pixel data must be right aligned, so
 
200
 * narrow tapes require padding raster data with zero bits at the end.
 
201
 *
 
202
 * For PC-PT, only the central 24 pixels (= 3,4mm!) can be used for
 
203
 * pixel-based graphics.  It might be possible to print several strips
 
204
 * of 24 pixels side-by side by issuing CR and line-positioning
 
205
 * commands.  That is currently not supported, let alone attempted,
 
206
 * with this driver.
 
207
 *
 
208
 * <table>
 
209
 * <tr><th>Model    <th>Cutter  <th>Xfer<th>DPI<th>Pixels<th>Bytes<th>Tape
 
210
 * <tr><td>QL-500   <td>manual   <td>ULP<td>300<td>720<td>90<td>DK12-62mm
 
211
 * <tr><td>QL-550   <td>auto     <td>ULP<td>300<td>720<td>90<td>DK12-62mm
 
212
 * <tr><td>QL-650TD <td>auto     <td>ULP<td>300<td>720<td>90<td>DK12-62mm
 
213
 * <tr><td>PT-PC    <td>auto     <td>BIP<td>180<td>128<td> 3<td>TZ6-24mm
 
214
 * <tr><td>PT-18R   <td>auto     <td>RLE<td>180<td>128<td>16<td>TZ6-18mm
 
215
 * <tr><td>PT-550A  <td>auto     <td>RLE<td>180<td>128<td>16<td>TZ6-36mm
 
216
 * <tr><td>PT-1500PC<td>manual   <td>RLE<td>180<td>112<td>14<td>TZ6-24mm
 
217
 * <tr><td>PT-1950  <td>auto     <td>RLE<td>180<td>128<td>16<td>TZ6-18mm
 
218
 * <tr><td>PT-1950VP<td>auto     <td>RLE<td>180<td>112<td>14<td>TZ6-18mm
 
219
 * <tr><td>PT-1960  <td>auto     <td>RLE<td>180<td> 96<td>12<td>TZ6-18mm
 
220
 * <tr><td>PT-2300  <td>auto     <td>RLE<td>180<td>112<td>14<td>TZ6-18mm
 
221
 * <tr><td>PT-2420PC<td>manual   <td>RLE<td>180<td>128<td>16<td>TZ6-24mm
 
222
 * <tr><td>PT-2450DX<td>auto     <td>RLE<td>180<td>128<td>16<td>TZ6-24mm
 
223
 * <tr><td>PT-2500PC<td>auto     <td>RLE<td>180<td>128<td>16<td>TZ6-24mm
 
224
 * <tr><td>PT-2600  <td>auto     <td>RLE<td>180<td>128<td>16<td>TZ,AV6-24mm
 
225
 * <tr><td>PT-2610  <td>auto     <td>RLE<td>180<td>128<td>16<td>TZ,AV6-24mm
 
226
 * <tr><td>PT-3600  <td>auto/half<td>RLE<td>360<td>384<td>48<td>TZ,AV6-36mm
 
227
 * <tr><td>PT-9200DX<td>auto/half<td>RLE<td>360<td>384<td>48<td>TZ6-36mm
 
228
 * <tr><td>PT-9200PC<td>auto/half<td>RLE<td>360<td>384<td>48<td>TZ6-36mm
 
229
 * <tr><td>PT-9400  <td>auto/half<td>RLE<td>360<td>384<td>48<td>TZ6-36mm
 
230
 * <tr><td>PT-9500PC<td>auto/half<td>RLE<td>360<br>
 
231
                                        360x720<td>384<td>48<td>TZ,AV6-36mm
 
232
 * <tr><td>PT-9600  <td>auto/half<td>RLE<td>360<td>384<td>48<td>TZ,AV6-36mm
 
233
 * </table>
 
234
 *
 
235
 * <h2>Tape characteristics</h2>
 
236
 * <table>
 
237
 * <tr><th>Tape width
 
238
 *     <th colspan=2>Print area        <th>Margins</th><th>DPI</th></tr>
 
239
 * <tr><td>62mm<td>61.0mm<td>720pixels</td><td>0.5mm</td><td>300</td></tr>
 
240
 * <tr><td>36mm<td>27.1mm<td>384pixels</td><td>4.5mm</td><td>360</td></tr>
 
241
 * <tr><td>24mm<td>18.0mm<td>128pixels</td><td>3mm</td><td>180</td></tr>
 
242
 * <tr><td>18mm<td>12.0mm<td> 85pixels</td><td>3mm</td><td>180</td></tr>
 
243
 * <tr><td>12mm<td> 8.0mm<td> 57pixels</td><td>2mm</td><td>180</td></tr>
 
244
 * <tr><td> 9mm<td> 6.9mm<td> 49pixels</td><td>1mm</td><td>180</td></tr>
 
245
 * <tr><td> 6mm<td> 3.9mm<td> 28pixels</td><td>1mm</td><td>180</td></tr>
 
246
 * </table>
 
247
 *
 
248
 * <h2>Notes</h2>
 
249
 * - Pixels bytes sent are printed from right to left, with bit 7
 
250
 *   rightmost!
 
251
 * - Bit image printing (BIP) using "ESC * ' #1 #2 ...data..."
 
252
 *   probably only works for the PT-PC model.
 
253
 * - QL Printer documentation might state that the print area is less
 
254
 *   than 61mm, which is probably to ensure that printed pixels stay
 
255
 *   within the tape even if it is not precisely positioned.  The
 
256
 *   print head really IS 720 pixels.
 
257
 */
 
258
/** Default pixel transfer method */
 
259
#define PIXEL_XFER_DEFAULT         RLE
 
260
/** Default print quality */
 
261
#define PRINT_QUALITY_HIGH_DEFAULT true
 
262
/** Default half cut mode */
 
263
#define HALF_CUT_DEFAULT           false
 
264
/** Maximum number of bytes per line */
 
265
#define BYTES_PER_LINE_MAX         255 /* cf. ULP_emit_line */
 
266
/** Default number of bytes per line */
 
267
#define BYTES_PER_LINE_DEFAULT     90
 
268
/** Default pixel data alignment on narrow tapes */
 
269
#define ALIGN_DEFAULT              RIGHT
 
270
/** Maximum print density value */
 
271
#define PRINT_DENSITY_MAX          5
 
272
/** Default print density value (1: light, ..., 5:dark, 0: no change) */
 
273
#define PRINT_DENSITY_DEFAULT      0
 
274
/** Transfer mode default ??? (-1 = don't set) */
 
275
#define TRANSFER_MODE_DEFAULT      -1
 
276
/** Driver pixel data mirroring default */
 
277
#define SOFTWARE_MIRROR_DEFAULT    false
 
278
/** Label preamble emitting default */
 
279
#define LABEL_PREAMBLE_DEFAULT     false
 
280
/** Interlabel margin removal default */
 
281
#define CONCAT_PAGES_DEFAULT       false
 
282
/** RLE buffer maximum memory usage */
 
283
#define RLE_ALLOC_MAX_DEFAULT      1000000
 
284
/** Mirror printing default */
 
285
#define MIRROR_DEFAULT             false
 
286
/** Negative printing default */
 
287
#define NEGATIVE_DEFAULT           false
 
288
/** Cut media mode default */
 
289
#define CUT_MEDIA_DEFAULT          CUPS_CUT_NONE
 
290
/** Roll fed media default */
 
291
#define ROLL_FED_MEDIA_DEFAULT     true
 
292
/** Device resolution default in DPI */
 
293
#define RESOLUTION_DEFAULT         { 300, 300 }
 
294
/** Page size default in PostScript points */
 
295
#define PAGE_SIZE_DEFAULT          { 176, 142 } /* 62x50mm */
 
296
/** Image size default in pixels */
 
297
#define IMAGE_HEIGHT_DEFAULT       0
 
298
/** Feed amount default */
 
299
#define FEED_DEFAULT               0
 
300
/** When to perform feed default */
 
301
#define PERFORM_FEED_DEFAULT       CUPS_ADVANCE_NONE
 
302
 
 
303
#include <config.h>
 
304
#include <stdio.h>
 
305
#include <unistd.h>
 
306
#include <limits.h>
 
307
#include <stdlib.h>
 
308
#include <string.h>
 
309
#include <errno.h>
 
310
#include <fcntl.h>
 
311
#include <signal.h>
 
312
#include <math.h>
 
313
#include <cups/raster.h>
 
314
#include <cups/cups.h>
 
315
 
 
316
#if STDC_HEADERS
 
317
# include <string.h>
 
318
#else
 
319
# if !HAVE_MEMCPY
 
320
#  define memcpy(d, s, n) bcopy ((s), (d), (n))
 
321
# endif
 
322
#endif
 
323
#if HAVE_STDBOOL_H
 
324
# include <stdbool.h>
 
325
#else
 
326
# if ! HAVE__BOOL
 
327
#  ifdef __cplusplus
 
328
typedef bool _Bool;
 
329
#  else
 
330
typedef unsigned char _Bool;
 
331
#  endif
 
332
# endif
 
333
# define bool _Bool
 
334
# define false 0
 
335
# define true 1
 
336
# define __bool_true_false_are_defined 1
 
337
#endif
 
338
 
 
339
 
 
340
 
 
341
#ifdef DEBUG
 
342
#include <sys/times.h>
 
343
/** Debug flag */
 
344
int debug = 0;
 
345
/** Number of emitted lines */
 
346
unsigned emitted_lines = 0;
 
347
#endif
 
348
 
 
349
/** Length of a PostScript point in mm */
 
350
#define MM_PER_PT    (25.4 / 72.0)
 
351
/** Printer code: Eject */
 
352
#define PTC_EJECT    0x1a
 
353
/** Printer code: Form feed */
 
354
#define PTC_FORMFEED 0x0c
 
355
 
 
356
/** ASCII escape value */
 
357
#define ESC 0x1b
 
358
 
 
359
/**
 
360
 * Pixel transfer mode type.
 
361
 */
 
362
typedef enum {
 
363
  ULP, /**< Uncompressed line printing */
 
364
  RLE, /**< Run-length encoding        */
 
365
  BIP, /**< Bit image printing         */
 
366
} xfer_t;
 
367
 
 
368
/**
 
369
 * Pixel data alignment type.
 
370
 */
 
371
typedef enum {RIGHT, CENTER} align_t;
 
372
 
 
373
/** Flag signalling whether any errors were encountered. */
 
374
int error_occurred;
 
375
 
 
376
/** CUPS Raster line buffer.                             */
 
377
unsigned char* buffer;
 
378
/** Buffer holding line data to emit to the printer.     */
 
379
unsigned char* emit_line_buffer;
 
380
/** Buffer holding RLE line data to emit to the printer. */
 
381
unsigned char* rle_buffer = NULL;
 
382
/** Pointer to first free pos in rle_buffer.             */
 
383
unsigned char* rle_buffer_next = NULL;
 
384
/** Size of rle_buffer.                                  */
 
385
unsigned long rle_alloced = 0;
 
386
/** Number of empty lines (input data only zeros) waiting to be stored */
 
387
int empty_lines = 0;
 
388
/** Number of pixel lines waiting to be emitted.         */
 
389
unsigned lines_waiting = 0;
 
390
/** Threshold for flushing waiting lines to printer.     */
 
391
unsigned max_lines_waiting = INT_MAX;
 
392
 
 
393
/** Macro for obtaining integer option values. */
 
394
#define OBTAIN_INT_OPTION(name, var, min, max)                  \
 
395
  cups_option                                                   \
 
396
    = cupsGetOption (name, num_options, cups_options);          \
 
397
  if (cups_option) {                                            \
 
398
    errno = 0;                                                  \
 
399
    char* rest;                                                 \
 
400
    long int var = strtol (cups_option, &rest, 0);              \
 
401
    if (errno || *rest != '\0' || rest == cups_option           \
 
402
        || var < min || var > max) {                            \
 
403
      fprintf (stderr, "ERROR: " name " '%s', "                 \
 
404
               "must be an integer N, where %ld <= N <= %ld\n", \
 
405
               cups_option, (long) min, (long) max);            \
 
406
      error_occurred = 1;                                       \
 
407
    } else                                                      \
 
408
      options.var = var;                                        \
 
409
  }
 
410
 
 
411
/** Macro for obtaining boolean option values. */
 
412
#define OBTAIN_BOOL_OPTION(name, var)                      \
 
413
  cups_option                                              \
 
414
    = cupsGetOption (name, num_options, cups_options);     \
 
415
  if (cups_option) options.var = true;                     \
 
416
  cups_option                                              \
 
417
    = cupsGetOption ("no"name, num_options, cups_options); \
 
418
  if (cups_option) options.var = false;                    \
 
419
 
 
420
/**
 
421
 * Struct type for holding all the job options.
 
422
 */
 
423
typedef struct {
 
424
  xfer_t pixel_xfer;    /**< pixel transfer mode                  */
 
425
  cups_bool_t print_quality_high; /**< print quality is high      */
 
426
  bool half_cut;        /**< half cut                             */
 
427
  int bytes_per_line;   /**< bytes per line (print head width)    */
 
428
  align_t align;        /**< pixel data alignment                 */
 
429
  int software_mirror;  /**< mirror pixel data if mirror printing */
 
430
  int print_density;    /**< printing density (0=don't change)    */
 
431
  int xfer_mode;        /**< transfer mode ???                    */
 
432
  int label_preamble;   /**< emit ESC i z ...                     */
 
433
  bool concat_pages;    /**< remove interlabel margins            */
 
434
  unsigned long rle_alloc_max; /**< max bytes used for rle_buffer */
 
435
} job_options_t;
 
436
 
 
437
/**
 
438
 * Struct type for holding current page options.
 
439
 */
 
440
typedef struct {
 
441
  cups_cut_t cut_media;    /**< cut media mode                     */
 
442
  cups_bool_t mirror;      /**< mirror printing                    */
 
443
  bool roll_fed_media;     /**< continuous (not labels) roll media */
 
444
  unsigned resolution [2]; /**< horiz & vertical resolution in DPI */
 
445
  unsigned page_size [2];  /**< width & height of page in points   */
 
446
  unsigned image_height;   /**< height of page image in pixels     */
 
447
  unsigned feed;           /**< feed size in points                */
 
448
  cups_adv_t perform_feed; /**< When to feed                       */
 
449
} page_options_t;
 
450
 
 
451
/**
 
452
 * Parse options given in command line argument 5.
 
453
 * @param argc  number of command line arguments plus one
 
454
 * @param argv  command line arguments
 
455
 * @return      options, where each option set to its default value if
 
456
 *              not specified in argv [5]
 
457
 */
 
458
job_options_t
 
459
parse_options (int argc, const char* argv []) {
 
460
  job_options_t options = {
 
461
    PIXEL_XFER_DEFAULT,
 
462
    PRINT_QUALITY_HIGH_DEFAULT,
 
463
    HALF_CUT_DEFAULT,
 
464
    BYTES_PER_LINE_DEFAULT,
 
465
    ALIGN_DEFAULT,
 
466
    SOFTWARE_MIRROR_DEFAULT,
 
467
    PRINT_DENSITY_DEFAULT,
 
468
    TRANSFER_MODE_DEFAULT,
 
469
    LABEL_PREAMBLE_DEFAULT,
 
470
    CONCAT_PAGES_DEFAULT,
 
471
    RLE_ALLOC_MAX_DEFAULT,
 
472
  };
 
473
  if (argc < 6) return options;
 
474
  int num_options = 0;
 
475
  cups_option_t* cups_options = NULL;
 
476
  num_options
 
477
    = cupsParseOptions (argv [5], num_options, &cups_options);
 
478
  const char* cups_option
 
479
    = cupsGetOption ("PixelXfer", num_options, cups_options);
 
480
  if (cups_option) {
 
481
    if (strcasecmp (cups_option, "ULP") == 0)
 
482
      options.pixel_xfer = ULP;
 
483
    else if (strcasecmp (cups_option, "RLE") == 0)
 
484
      options.pixel_xfer = RLE;
 
485
    else if (strcasecmp (cups_option, "BIP") == 0)
 
486
      options.pixel_xfer = BIP;
 
487
    else {
 
488
      fprintf (stderr, "ERROR: Unknown PicelXfer '%s', "
 
489
               "must be RLE, BIP or ULP\n", cups_option);
 
490
      error_occurred = 1;
 
491
    }
 
492
  }
 
493
  cups_option
 
494
    = cupsGetOption ("PrintQuality", num_options, cups_options);
 
495
  if (cups_option) {
 
496
    if (strcasecmp (cups_option, "High") == 0)
 
497
      options.print_quality_high = true;
 
498
    else if (strcasecmp (cups_option, "Fast") == 0)
 
499
      options.print_quality_high = false;
 
500
    else {
 
501
      fprintf (stderr, "ERROR: Unknown PrintQuality '%s', "
 
502
               "must be High or Fast\n", cups_option);
 
503
      error_occurred = 1;
 
504
    }
 
505
  }
 
506
  OBTAIN_BOOL_OPTION ("HalfCut", half_cut);
 
507
  OBTAIN_INT_OPTION ("BytesPerLine", bytes_per_line,
 
508
                     1, BYTES_PER_LINE_MAX);
 
509
  cups_option
 
510
    = cupsGetOption ("Align", num_options, cups_options);
 
511
  if (cups_option) {
 
512
    if (strcasecmp (cups_option, "Right") == 0)
 
513
      options.align = RIGHT;
 
514
    else if (strcasecmp (cups_option, "Center") == 0)
 
515
      options.align = CENTER;
 
516
    else {
 
517
      fprintf (stderr, "ERROR: Unknown Align '%s', "
 
518
               "must be Right or Center\n", cups_option);
 
519
      error_occurred = 1;
 
520
    }
 
521
  }
 
522
  OBTAIN_INT_OPTION ("PrintDensity", print_density,
 
523
                     0, PRINT_DENSITY_MAX);
 
524
  OBTAIN_BOOL_OPTION ("ConcatPages", concat_pages);
 
525
  OBTAIN_INT_OPTION ("RLEMemMax", rle_alloc_max, 0, LONG_MAX);
 
526
  OBTAIN_INT_OPTION ("TransferMode", xfer_mode, 0, 255);
 
527
  OBTAIN_BOOL_OPTION ("SoftwareMirror", software_mirror);
 
528
  OBTAIN_BOOL_OPTION ("LabelPreamble", label_preamble);
 
529
  /* Release memory allocated for CUPS options struct */
 
530
  cupsFreeOptions (num_options, cups_options);
 
531
  return options;
 
532
}
 
533
 
 
534
/**
 
535
 * Determine input stream and open it.  If there are 6 command line
 
536
 * arguments, argv[6] is taken to be the input file name
 
537
 * otherwise stdin is used.  This funtion exits the program on error.
 
538
 * @param argc  number of command line arguments plus one
 
539
 * @param argv  command line arguments
 
540
 * @return      file descriptor for the opened input stream
 
541
 */
 
542
int
 
543
open_input_file (int argc, const char* argv []) {
 
544
  int fd;
 
545
  if (argc == 7) {
 
546
    if ((fd = open (argv[6], O_RDONLY)) < 0) {
 
547
      perror ("ERROR: Unable to open raster file - ");
 
548
      sleep (1);
 
549
      exit (1);
 
550
    }
 
551
  } else
 
552
    fd = 0;
 
553
  return fd;
 
554
}
 
555
 
 
556
/**
 
557
 * Update page_options with information found in header.
 
558
 * @param header        CUPS page header
 
559
 * @param page_options  page options to be updated
 
560
 */
 
561
void
 
562
update_page_options (cups_page_header_t* header,
 
563
                     page_options_t* page_options) {
 
564
  page_options->cut_media = header->CutMedia;
 
565
  page_options->mirror = header->MirrorPrint;
 
566
  const char* media_type = header->MediaType;
 
567
  page_options->roll_fed_media /* Default is continuous roll */
 
568
    = (strcasecmp ("Labels", media_type) != 0);
 
569
  page_options->resolution [0] = header->HWResolution [0];
 
570
  page_options->resolution [1] = header->HWResolution [1];
 
571
  page_options->page_size [0] = header->PageSize [0];
 
572
  page_options->page_size [1] = header->PageSize [1];
 
573
  page_options->image_height = header->cupsHeight;
 
574
  page_options->feed = header->AdvanceDistance;
 
575
  page_options->perform_feed = header->AdvanceMedia;
 
576
}
 
577
 
 
578
void cancel_job (int signal);
 
579
/**
 
580
 * Prepare for a new page by setting up signalling infrastructure and
 
581
 * memory allocation.
 
582
 * @param cups_buffer_size    Required size of CUPS raster line buffer
 
583
 * @param device_buffer_size  Required size of device pixel line buffer
 
584
 */
 
585
void
 
586
page_prepare (unsigned cups_buffer_size, unsigned device_buffer_size) {
 
587
  /* Set up signalling to handle print job cancelling */
 
588
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
 
589
  struct sigaction action;
 
590
#endif
 
591
 
 
592
#ifdef HAVE_SIGSET
 
593
  sigset (SIGTERM, cancel_job);
 
594
#elif defined(HAVE_SIGACTION)
 
595
  memset (&action, 0, sizeof (action));
 
596
  sigemptyset (&action.sa_mask);
 
597
  action.sa_handler = cancel_job;
 
598
  sigaction (SIGTERM, &action, NULL);
 
599
#else
 
600
  signal (SIGTERM, cancel_job);
 
601
#endif
 
602
 
 
603
  /* Allocate line buffer */
 
604
  buffer = malloc (cups_buffer_size);
 
605
  emit_line_buffer = malloc (device_buffer_size);
 
606
  if (!buffer || !emit_line_buffer) {
 
607
    fprintf
 
608
      (stderr,
 
609
       "ERROR: Cannot allocate memory for raster line buffer\n");
 
610
    exit (1);
 
611
  }
 
612
}
 
613
 
 
614
/**
 
615
 * Clean up signalling and memory after emitting a page
 
616
*/
 
617
void
 
618
page_end () {
 
619
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
 
620
  struct sigaction action;
 
621
#endif
 
622
 
 
623
#ifdef HAVE_SIGSET
 
624
  sigset (SIGTERM, SIG_IGN);
 
625
#elif defined(HAVE_SIGACTION)
 
626
  memset (&action, 0, sizeof (action));
 
627
  sigemptyset (&action.sa_mask);
 
628
  action.sa_handler = SIG_IGN;
 
629
  sigaction (SIGTERM, &action, NULL);
 
630
#else
 
631
  signal (SIGTERM, SIG_IGN);
 
632
#endif
 
633
  /* Release line buffer memory */
 
634
  free (buffer);
 
635
  free (emit_line_buffer);
 
636
}
 
637
 
 
638
/**
 
639
 * Cancel print job.
 
640
 */
 
641
void
 
642
cancel_job (int signal) {
 
643
  /* Emit page end & eject marker */
 
644
  putchar (PTC_EJECT);
 
645
  page_end ();
 
646
  if (rle_buffer) free (rle_buffer);
 
647
  exit (0);
 
648
}
 
649
 
 
650
/**
 
651
 * Emit printer command codes at start of print job.
 
652
 * This function does not emit P-touch page specific codes.
 
653
 * @param job_options   Job options
 
654
 */
 
655
void
 
656
emit_job_cmds (job_options_t* job_options) {
 
657
  /* Initialise printer */
 
658
  putchar (ESC); putchar ('@');
 
659
  /* Emit print density selection command if required */
 
660
  int density = job_options->print_density;
 
661
  switch (density) {
 
662
  case 1: case 2: case 3: case 4: case 5:
 
663
    putchar (ESC); putchar ('i'); putchar ('D'); putchar (density);
 
664
    break;
 
665
  default: break;
 
666
  }
 
667
  /* Emit transfer mode selection command if required */
 
668
  int xfer_mode = job_options->xfer_mode;
 
669
  if (xfer_mode >= 0 && xfer_mode < 0x100) {
 
670
    putchar (ESC); putchar ('i'); putchar ('R'); putchar (xfer_mode);
 
671
  }
 
672
  /* Emit half cut selection command if required */
 
673
  if (job_options->half_cut) {
 
674
    putchar (ESC); putchar ('i'); putchar ('K'); putchar (0x04);
 
675
  }
 
676
}
 
677
 
 
678
/**
 
679
 * Emit feed, cut and mirror command codes.
 
680
 * @param do_feed    Emit codes to actually feed
 
681
 * @param feed       Feed size
 
682
 * @param do_cut     Emit codes to actually cut
 
683
 * @param do_mirror  Emit codes to mirror print
 
684
 */
 
685
inline void
 
686
emit_feed_cut_mirror (bool do_feed, unsigned feed,
 
687
                      bool do_cut,
 
688
                      bool do_mirror) {
 
689
  /* Determine feed nibble */
 
690
  unsigned feed_nibble;
 
691
  if (do_feed) {
 
692
    feed_nibble = lrint (feed / 2.6 + 2.4); /* one suggested conversion */
 
693
    if (feed_nibble > 31) feed_nibble = 31;
 
694
  } else
 
695
    feed_nibble = 0;
 
696
  /* Determine auto cut bit - we only handle after each page */
 
697
  unsigned char auto_cut_bit = do_cut ? 0x40 : 0x00;
 
698
  /* Determine mirror print bit*/
 
699
  unsigned char mirror_bit = do_mirror ? 0x80 : 0x00;
 
700
  /* Combine & emit printer command code */
 
701
  putchar (ESC); putchar ('i'); putchar ('M');
 
702
  putchar ((char) (feed & 0x1f) | auto_cut_bit | mirror_bit);
 
703
}
 
704
 
 
705
/**
 
706
 * Emit quality, roll fed media, and label size command codes.
 
707
 * @param job_options      Current job options
 
708
 * @param page_options     Current page options
 
709
 * @param page_size_y      Page size (height) in pt
 
710
 * @param image_height_px  Number of pixel lines in current page
 
711
 */
 
712
void
 
713
emit_quality_rollfed_size (job_options_t* job_options,
 
714
                           page_options_t* page_options,
 
715
                           unsigned page_size_y,
 
716
                           unsigned image_height_px) {
 
717
  bool roll_fed_media = page_options->roll_fed_media;
 
718
  /* Determine print quality bit */
 
719
  unsigned char print_quality_bit
 
720
    = (job_options->print_quality_high == CUPS_TRUE) ? 0x40 : 0x00;
 
721
  unsigned char roll_fed_media_bit = roll_fed_media ? 0x00 : 0x01;
 
722
  /* Get tape width in mm */
 
723
  int tape_width_mm = lrint (page_options->page_size [0] * MM_PER_PT);
 
724
  if (tape_width_mm > 0xff) {
 
725
    fprintf (stderr,
 
726
             "ERROR: Page width (%umm) exceeds 255mm\n",
 
727
             tape_width_mm);
 
728
    tape_width_mm = 0xff;
 
729
  }
 
730
  /* Get tape height in mm */
 
731
  unsigned tape_height_mm;
 
732
  if (roll_fed_media)
 
733
    tape_height_mm = 0;
 
734
  else
 
735
    tape_height_mm = lrint (page_size_y * MM_PER_PT);
 
736
  if (tape_height_mm > 0xff) {
 
737
    fprintf (stderr,
 
738
             "ERROR: Page height (%umm) exceeds 255mm; use continuous tape (MediaType=roll)\n",
 
739
             tape_height_mm);
 
740
    tape_height_mm = 0xff;
 
741
  }
 
742
  /* Combine & emit printer command code */
 
743
  putchar (ESC); putchar ('i'); putchar ('z');
 
744
  putchar (print_quality_bit); putchar (roll_fed_media_bit);
 
745
  putchar (tape_width_mm & 0xff); putchar (tape_height_mm & 0xff);
 
746
  putchar (image_height_px & 0xff);
 
747
  putchar ((image_height_px >> 8) & 0xff);
 
748
  putchar (0x00); putchar (0x00); putchar (0x00); putchar (0x00);
 
749
}
 
750
/**
 
751
 * Emit printer command codes at start of page for options that have
 
752
 * changed.
 
753
 * @param job_options       Job options
 
754
 * @param old_page_options  Page options for preceding page
 
755
 * @param new_page_options  Page options for page to be printed
 
756
 * @param force             Ignore old_page_options and emit commands
 
757
 *                          for selecting all options in new_page_options
 
758
 */
 
759
void
 
760
emit_page_cmds (job_options_t* job_options,
 
761
                page_options_t* old_page_options,
 
762
                page_options_t* new_page_options,
 
763
                bool force) {
 
764
  int tape_width_mm = -1;
 
765
 
 
766
  /* Set width and resolution */
 
767
  unsigned hres = new_page_options->resolution [0];
 
768
  unsigned vres = new_page_options->resolution [1];
 
769
  unsigned old_page_size_x = old_page_options->page_size [0];
 
770
  unsigned new_page_size_x = new_page_options->page_size [0];
 
771
  if (force
 
772
      || hres != old_page_options->resolution [0]
 
773
      || vres != old_page_options->resolution [1]
 
774
      || new_page_size_x != old_page_size_x)
 
775
    /* We only know how to select 360x360DPI or 360x720DPI */
 
776
    if (hres == 360 && (vres == 360 || vres == 720)) {
 
777
      /* Get tape width in mm */
 
778
      tape_width_mm = lrint (new_page_size_x * MM_PER_PT);
 
779
      if (tape_width_mm > 0xff) {
 
780
        fprintf (stderr,
 
781
                 "ERROR: Page width (%umm) exceeds 255mm\n",
 
782
                 tape_width_mm);
 
783
        tape_width_mm = 0xff;
 
784
      }
 
785
      /* Emit printer commands */
 
786
      putchar (ESC); putchar ('i'); putchar ('c');
 
787
      if (vres == 360) {
 
788
        putchar (0x84); putchar (0x00); putchar (tape_width_mm & 0xff);
 
789
        putchar (0x00); putchar (0x00);
 
790
      } else {
 
791
        putchar (0x86); putchar (0x09); putchar (tape_width_mm & 0xff);
 
792
        putchar (0x00); putchar (0x01);
 
793
      }
 
794
    }
 
795
 
 
796
  /* Set feed, auto cut and mirror print */
 
797
  unsigned feed = new_page_options->feed;
 
798
  cups_adv_t perform_feed = new_page_options->perform_feed;
 
799
  cups_cut_t cut_media = new_page_options->cut_media;
 
800
  cups_bool_t mirror = new_page_options->mirror;
 
801
  if (force
 
802
      || feed != old_page_options->feed
 
803
      || perform_feed != old_page_options->perform_feed
 
804
      || cut_media != old_page_options->cut_media
 
805
      || mirror != old_page_options->mirror)
 
806
    /* We only know how to feed after each page */
 
807
    emit_feed_cut_mirror (perform_feed == CUPS_ADVANCE_PAGE, feed,
 
808
                          cut_media == CUPS_CUT_PAGE,
 
809
                          mirror == CUPS_TRUE);
 
810
  /* Set media and quality if label preamble is requested */
 
811
  unsigned page_size_y = new_page_options->page_size [1];
 
812
  unsigned image_height_px = lrint (page_size_y * vres / 72.0);
 
813
  if (job_options->label_preamble && !job_options->concat_pages
 
814
      && (force
 
815
          || (new_page_options->roll_fed_media
 
816
              != old_page_options->roll_fed_media)
 
817
          || new_page_size_x != old_page_size_x
 
818
          || page_size_y != old_page_options->page_size [1]))
 
819
    emit_quality_rollfed_size (job_options, new_page_options,
 
820
                               page_size_y, image_height_px);
 
821
 
 
822
  /* WHY DON'T WE SET MARGIN (ESC i d ...)? */
 
823
 
 
824
  /* Set pixel data transfer compression */
 
825
  if (force) {
 
826
    if (job_options->pixel_xfer == RLE) {
 
827
      putchar ('M'); putchar (0x02);
 
828
    }
 
829
  }
 
830
  /* Emit number of raster lines to follow if using BIP */
 
831
  if (job_options->pixel_xfer == BIP) {
 
832
    unsigned image_height_px = lrint (page_size_y * vres / 72.0);
 
833
    putchar (ESC); putchar (0x2a); putchar (0x27);
 
834
    putchar (image_height_px & 0xff);
 
835
    putchar ((image_height_px >> 8) & 0xff);
 
836
  }
 
837
}
 
838
 
 
839
/** mirror [i] = bit mirror image of i.
 
840
 * I.e., (mirror [i] >> j) & 1 ==  (i >> (7 - j)) & 1 for 0 <= j <= 7
 
841
 */
 
842
const unsigned char mirror [0x100] = {
 
843
  0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
 
844
  0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
 
845
  0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
 
846
  0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
 
847
  0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
 
848
  0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
 
849
  0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
 
850
  0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
 
851
  0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
 
852
  0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
 
853
  0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
 
854
  0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
 
855
  0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
 
856
  0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
 
857
  0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
 
858
  0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
 
859
  0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
 
860
  0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
 
861
  0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
 
862
  0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
 
863
  0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
 
864
  0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
 
865
  0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
 
866
  0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
 
867
  0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
 
868
  0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
 
869
  0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
 
870
  0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
 
871
  0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
 
872
  0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
 
873
  0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
 
874
  0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
 
875
};
 
876
 
 
877
/**
 
878
 * Generate a buffer of pixel data ready to emit.
 
879
 * Requirement: buflen + right_padding_bytes
 
880
 *              + (shift > 0 ? 1 : 0) <= bytes_per_line
 
881
 * @param in_buffer           Buffer containing raster data in
 
882
 *                            left-to-right order
 
883
 * @param out_buffer          Buffer for returning generated line in
 
884
 *                            right-to-left order; must be
 
885
 *                            bytes_per_line long
 
886
 * @param buflen              in_buffer length
 
887
 * @param bytes_per_line      Number of pixel bytes to generate
 
888
 * @param right_padding_bytes Number of zero bytes to pad
 
889
 *                            with to the right of pixels
 
890
 * @param shift               Number of bits to shift left
 
891
 *                            If do_mirror is false and shift < 0
 
892
 *                            Then shift right -shift bits
 
893
 * @param do_mirror           Mirror in_buffer pixel data
 
894
 * @param xormask             The XOR mask for negative printing
 
895
 * @return                    0 if entire line is empty (zeros)
 
896
 *                            nonzero if line contains nonzero pixels
 
897
 */
 
898
inline int
 
899
generate_emit_line (unsigned char* in_buffer,
 
900
                    unsigned char* out_buffer,
 
901
                    int buflen,
 
902
                    unsigned char bytes_per_line,
 
903
                    int right_padding_bytes,
 
904
                    int shift,
 
905
                    int do_mirror,
 
906
                    unsigned char xormask) {
 
907
#ifdef DEBUG
 
908
  if (debug)
 
909
    fprintf (stderr, "DEBUG: generate_emit_line "
 
910
             "(in_buffer=%0x, out_buffer=%0x, "
 
911
             "buflen=%d, bytes_per_line=%d, right_padding_bytes=%d, "
 
912
             "shift=%d, do_mirror=%d, xormask=%0x)\n",
 
913
             in_buffer, out_buffer, buflen, bytes_per_line,
 
914
             right_padding_bytes, shift, do_mirror, xormask);
 
915
#endif
 
916
  /* Generate right padding zero bytes */
 
917
  memset (out_buffer, xormask, right_padding_bytes);
 
918
  unsigned int nonzero = 0;
 
919
  int j = right_padding_bytes;
 
920
  /* Copy pixel data from in_buffer to out_buffer, */
 
921
  /* shifted and mirrored if required              */
 
922
  unsigned int box = 0; /* Box for shifting pixel data left */
 
923
  int i;
 
924
  if (do_mirror)
 
925
    if (shift) {
 
926
      for (i = 0; i < buflen; i++) {
 
927
        unsigned int data = in_buffer [i]; nonzero |= data;
 
928
        box |= data << shift;
 
929
        out_buffer [j++] = (box & 0xff) ^ xormask;
 
930
        box >>= 8;
 
931
      }
 
932
      out_buffer [j++] = box & 0xff;
 
933
    } else
 
934
      for (i = 0; i < buflen; i++) {
 
935
        unsigned char data = in_buffer [i]; nonzero |= data;
 
936
        out_buffer [j++] = data ^ xormask;
 
937
      }
 
938
  else
 
939
    if (shift) {
 
940
      if (buflen > 0) {
 
941
        if (shift < 0) {
 
942
          box = in_buffer [buflen - 1] >> -shift; nonzero |= box;
 
943
          shift += 8;
 
944
        } else {
 
945
          box = in_buffer [buflen - 1] << shift; nonzero |= box;
 
946
          out_buffer [j++] = (mirror [box & 0xff]) ^ xormask;
 
947
          box >>= 8;
 
948
        }
 
949
        for (i = buflen - 2; i >= 0; i--) {
 
950
          unsigned data = in_buffer [i]; nonzero |= data;
 
951
          box |= data << shift;
 
952
          out_buffer [j++] = (mirror [box & 0xff]) ^ xormask;
 
953
          box >>= 8;
 
954
        }
 
955
        out_buffer [j++] = (mirror [box & 0xff]) ^ xormask;
 
956
      }
 
957
    } else
 
958
      for (i = buflen - 1; i >= 0; i--) {
 
959
        unsigned char data = in_buffer [i]; nonzero |= data;
 
960
        out_buffer [j++] = (mirror [data]) ^ xormask;
 
961
      }
 
962
  /* Generate left padding bytes */
 
963
  memset (out_buffer + j, xormask, bytes_per_line - j);
 
964
  return nonzero != 0;
 
965
}
 
966
 
 
967
/**
 
968
 * Emit lines waiting in RLE buffer.
 
969
 * Resets global variable rle_buffer_next to rle_buffer,
 
970
 * and lines_waiting to zero.
 
971
 * @param job_options   Job options
 
972
 * @param page_options  Page options
 
973
 */
 
974
inline void
 
975
flush_rle_buffer (job_options_t* job_options,
 
976
                  page_options_t* page_options) {
 
977
#ifdef DEBUG
 
978
  if (debug)
 
979
    fprintf (stderr, "DEBUG: flush_rle_buffer (): "
 
980
             "lines_waiting = %d\n",
 
981
             lines_waiting);
 
982
#endif
 
983
  if (lines_waiting > 0) {
 
984
    if (job_options->label_preamble)
 
985
      emit_quality_rollfed_size (job_options, page_options,
 
986
                                 page_options->page_size [1],
 
987
                                 lines_waiting);
 
988
    xfer_t pixel_xfer = job_options->pixel_xfer;
 
989
    int bytes_per_line = job_options->bytes_per_line;
 
990
    switch (pixel_xfer) {
 
991
    case RLE: {
 
992
      size_t dummy
 
993
        = fwrite (rle_buffer, sizeof (char), rle_buffer_next - rle_buffer, stdout);
 
994
      break;
 
995
    }
 
996
    case ULP:
 
997
    case BIP: {
 
998
      unsigned char* p = rle_buffer;
 
999
      unsigned emitted_lines = 0;
 
1000
      while (rle_buffer_next - p > 0) {
 
1001
        if (pixel_xfer == ULP) {
 
1002
          putchar ('g'); putchar (0x00); putchar (bytes_per_line);
 
1003
        }
 
1004
        int emitted = 0;
 
1005
        int linelen;
 
1006
        switch (*p++) {
 
1007
        case 'G':
 
1008
          linelen = *p++;
 
1009
          linelen += ((int)(*p++)) << 8;
 
1010
          while (linelen > 0) {
 
1011
            signed char l = *p++; linelen--;
 
1012
            if (l < 0) { /* emit repeated data */
 
1013
              char data = *p++; linelen--;
 
1014
              emitted -= l; emitted++;
 
1015
              for (; l <= 0; l++) putchar (data);
 
1016
            } else { /* emit the l + 1 following bytes of data */
 
1017
              size_t dummy = fwrite (p, sizeof (char), l + 1, stdout);
 
1018
              p += l; p++;
 
1019
              linelen -= l; linelen--;
 
1020
              emitted += l; emitted++;
 
1021
            }
 
1022
          }
 
1023
          if (emitted > bytes_per_line)
 
1024
            fprintf (stderr,
 
1025
                     "ERROR: Emitted %d > %d bytes for one pixel line!\n",
 
1026
                     emitted, bytes_per_line);
 
1027
          /* No break; fall through to next case: */
 
1028
        case 'Z':
 
1029
          for (; emitted < bytes_per_line; emitted++) putchar (0x00);
 
1030
          break;
 
1031
        default:
 
1032
          fprintf (stderr, "ERROR: Unknown RLE flag at %p: '0x%02x'\n",
 
1033
                   p - 1, (int)*(p - 1));
 
1034
        }
 
1035
        emitted_lines++;
 
1036
      }
 
1037
#ifdef DEBUG
 
1038
  if (debug)
 
1039
    fprintf (stderr, "DEBUG: emitted %d lines\n", emitted_lines);
 
1040
#endif
 
1041
      break;
 
1042
    }
 
1043
    default:
 
1044
      fprintf (stderr, "ERROR: Unknown pixel transfer mode: '%d'\n",
 
1045
               pixel_xfer);
 
1046
    }
 
1047
    rle_buffer_next = rle_buffer;
 
1048
    lines_waiting = 0;
 
1049
  }
 
1050
}
 
1051
 
 
1052
/**
 
1053
 * Ensure sufficient memory available in rle buffer.
 
1054
 * If rle buffer needs to be extended, global variables rle_buffer and
 
1055
 * rle_buffer_next might be altered.
 
1056
 * @param job_options   Job options
 
1057
 * @param page_options  Page options
 
1058
 * @param bytes         Number of bytes required.
 
1059
 */
 
1060
inline void
 
1061
ensure_rle_buf_space (job_options_t* job_options,
 
1062
                      page_options_t* page_options,
 
1063
                      unsigned bytes) {
 
1064
  unsigned long nextpos = rle_buffer_next - rle_buffer;
 
1065
  if (nextpos + bytes > rle_alloced) {
 
1066
    /* Exponential size increase avoids too frequent reallocation */
 
1067
    unsigned long new_alloced = rle_alloced * 2 + 0x4000;
 
1068
#ifdef DEBUG
 
1069
  if (debug)
 
1070
    fprintf (stderr, "DEBUG: ensure_rle_buf_space (bytes=%d): "
 
1071
             "increasing rle_buffer from %d to %d\n",
 
1072
             bytes,
 
1073
             rle_alloced * sizeof (char),
 
1074
             new_alloced * sizeof (char));
 
1075
#endif
 
1076
    void* p = NULL;
 
1077
    if (new_alloced <= job_options->rle_alloc_max) {
 
1078
      if (rle_buffer)
 
1079
        p = (unsigned char*) realloc (rle_buffer, new_alloced * sizeof (char));
 
1080
      else
 
1081
        p = (unsigned char*) malloc (new_alloced * sizeof (char));
 
1082
    }
 
1083
    if (p) {
 
1084
      rle_buffer = p;
 
1085
      rle_buffer_next = rle_buffer + nextpos;
 
1086
      rle_alloced = new_alloced;
 
1087
    } else { /* Gain memory by flushing buffer to printer */
 
1088
      flush_rle_buffer (job_options, page_options);
 
1089
      if (rle_buffer_next - rle_buffer + bytes > rle_alloced) {
 
1090
        fprintf (stderr,
 
1091
                 "ERROR: Out of memory when attempting to increase RLE "
 
1092
                 "buffer from %ld to %ld bytes\n",
 
1093
                 rle_alloced * sizeof (char),
 
1094
                 new_alloced * sizeof (char));
 
1095
        exit (-1);
 
1096
      }
 
1097
    }
 
1098
  }
 
1099
}
 
1100
 
 
1101
/** @def APPEND_MIXED_BYTES
 
1102
 * Macro for appending mixed-bytes run to rle_buffer */
 
1103
/** @def APPEND_REPEATED_BYTE
 
1104
 * Macro for appending repeated-byte run to rle_buffer */
 
1105
/**
 
1106
 * Store buffer data in rle buffer using run-length encoding.
 
1107
 * @param job_options   Job options
 
1108
 * @param page_options  Page options
 
1109
 * @param buf           Buffer containing data to store
 
1110
 * @param buf_len       Length of buffer
 
1111
 *
 
1112
 * Global variable rle_buffer_next is a pointer into buffer for holding RLE data.
 
1113
 * Must have room for at least 3 + buf_len + buf_len/128 + 1
 
1114
 * bytes (ensured by reallocation).
 
1115
 * On return, rle_buffer_next points to first unused buffer byte.
 
1116
 *
 
1117
 * This implementation enjoys the property that
 
1118
 * the resulting RLE is at most buf_len + buf_len/128 + 1 bytes
 
1119
 * long, because:
 
1120
 * # a repeated-byte run has a repeat factor of at least 3
 
1121
 * # two mixed-bytes runs never follow directly after each other,
 
1122
 *   unless the first one is 128 bytes long
 
1123
 * The first property ensures that a repeated-run output sequence is
 
1124
 * always at least 1 byte shorter than the input sequence it
 
1125
 * represents.  This combined with the second property means that only
 
1126
 * - a terminating mixed-bytes run, and
 
1127
 * - a mixed-bytes run of 128 bytes
 
1128
 * can cause the RLE representation to be longer (by 1 byte) than the
 
1129
 * corresponding input sequence in buf.
 
1130
 */
 
1131
inline void
 
1132
RLE_store_line (job_options_t* job_options,
 
1133
                page_options_t* page_options,
 
1134
                const unsigned char* buf, unsigned buf_len) {
 
1135
  ensure_rle_buf_space (job_options, page_options,
 
1136
                        4 + buf_len + buf_len / 128);
 
1137
  unsigned char* rle_next = rle_buffer_next + 3;
 
1138
  /* Make room for 3 initial meta data bytes, */
 
1139
  /* written when actual length is known      */
 
1140
  const unsigned char* buf_end = buf + buf_len; /* Buffer end */
 
1141
  const unsigned char* mix_start;  /* Start of mixed bytes run */
 
1142
 
 
1143
  const unsigned char* rep_start;  /* End + 1 of mixed bytes run,
 
1144
                                      and start of repeated byte run */
 
1145
  const unsigned char* next;       /* Next byte pointer,
 
1146
                                      and end + 1 of repeated byte run */
 
1147
  unsigned char next_val;          /* Next byte value to consider */
 
1148
  unsigned char rep_val;           /* Repeated byte value */
 
1149
  unsigned char nonzero = 0;       /* OR of all buffer bytes */
 
1150
 
 
1151
#define APPEND_MIXED_BYTES                        \
 
1152
        if (mix_len > 128) mix_len = 128;         \
 
1153
        *rle_next++ = mix_len - 1;                \
 
1154
        memcpy (rle_next, mix_start, mix_len);    \
 
1155
        rle_next += mix_len;
 
1156
#define APPEND_REPEATED_BYTE                      \
 
1157
        unsigned rep_len = next - rep_start;      \
 
1158
        *rle_next++ = (signed char)(1 - rep_len); \
 
1159
        *rle_next++ = rep_val;
 
1160
 
 
1161
  for (mix_start = rep_start = next = buf, rep_val = next_val = *next;
 
1162
       next != buf_end;
 
1163
       next++, next_val = *next) {
 
1164
    /* Loop invariants at this point:
 
1165
     * 1) [mix_start..rep_start - 1] contains mixed bytes waiting
 
1166
     *    to be appended to rle_buffer,
 
1167
     * 2) [rep_start..next - 1] contains repeats of rep_val
 
1168
     *    waiting to be appended to rle_buffer
 
1169
     * 3) If next - rep_start > 2 then mix_start == rep_start
 
1170
     * 4) next - rep_start <= 129
 
1171
     * 5) rep_start - mix_start < 128
 
1172
     * 6) [rle_buffer_next..rle_next - 1] = RLE ([buf..mix_start - 1])
 
1173
     * 7) rep_val = *rep_start
 
1174
     * 8) next_val = *next
 
1175
     */
 
1176
    nonzero |= next_val;
 
1177
    if (next - rep_start >= 129) {
 
1178
      /* RLE cannot represent repeated runs longer than 129 bytes */
 
1179
      APPEND_REPEATED_BYTE;
 
1180
      rep_start += rep_len;
 
1181
      rep_val = *rep_start;
 
1182
      mix_start = rep_start;
 
1183
    }
 
1184
    if (next_val == rep_val) { /* Run of repeated byte values */
 
1185
      if (next - rep_start == 2) {
 
1186
        unsigned mix_len = rep_start - mix_start;
 
1187
        if (mix_len > 0) {
 
1188
          APPEND_MIXED_BYTES;
 
1189
          mix_start = rep_start;
 
1190
        }
 
1191
      }
 
1192
    } else {
 
1193
      if (next - rep_start > 2) { /* End of repeated run found */
 
1194
        APPEND_REPEATED_BYTE;
 
1195
        mix_start = next;
 
1196
      }
 
1197
      rep_start = next;
 
1198
      rep_val = next_val;
 
1199
      unsigned mix_len = rep_start - mix_start;
 
1200
      if (mix_len >= 128) {
 
1201
        /* RLE cannot represent mixed runs longer than 128 bytes */
 
1202
        APPEND_MIXED_BYTES;
 
1203
        mix_start += mix_len;
 
1204
      }
 
1205
    }
 
1206
  }
 
1207
  /* Handle final bytes */
 
1208
  if (next - rep_start > 2) { /* Handle final repeated byte run */
 
1209
    APPEND_REPEATED_BYTE;
 
1210
    mix_start = next;
 
1211
  }
 
1212
  rep_start = next;
 
1213
  unsigned mix_len = rep_start - mix_start;
 
1214
  if (mix_len > 0) { /* Handle any remaining final mixed run */
 
1215
    APPEND_MIXED_BYTES;
 
1216
    mix_start += mix_len;
 
1217
  }
 
1218
  mix_len = rep_start - mix_start;
 
1219
  if (mix_len > 0) { /* Case where final mixed run is 129 bytes */
 
1220
    APPEND_MIXED_BYTES;
 
1221
  }
 
1222
  unsigned rle_len = rle_next - rle_buffer_next - 3;
 
1223
  /* Store rle line meta data (length and (non)zero status) */
 
1224
  if (nonzero) { /* Check for nonempty (no black pixels) line */
 
1225
    rle_buffer_next [0] = 'G';
 
1226
    rle_buffer_next [1] =  rle_len       & 0xff;
 
1227
    rle_buffer_next [2] = (rle_len >> 8) & 0xff;
 
1228
    rle_buffer_next = rle_next;
 
1229
  } else {
 
1230
    rle_buffer_next [0] = 'Z';
 
1231
    rle_buffer_next++;
 
1232
  }
 
1233
  lines_waiting++;
 
1234
  if (lines_waiting >= max_lines_waiting)
 
1235
    flush_rle_buffer (job_options, page_options);
 
1236
}
 
1237
 
 
1238
/**
 
1239
 * Store a number of empty lines in rle_buffer using RLE.
 
1240
 * @param job_options     Job options
 
1241
 * @param page_options    Page options
 
1242
 * @param empty_lines     Number of empty lines to store
 
1243
 * @param xormask         The XOR mask for negative printing
 
1244
 */
 
1245
inline void
 
1246
RLE_store_empty_lines (job_options_t* job_options,
 
1247
                       page_options_t* page_options,
 
1248
                       int empty_lines,
 
1249
                       unsigned char xormask) {
 
1250
  int bytes_per_line = job_options->bytes_per_line;
 
1251
#ifdef DEBUG
 
1252
  if (debug)
 
1253
    fprintf (stderr, "DEBUG: RLE_store_empty_lines (empty_lines=%d, "
 
1254
             "bytes_per_line=%d): lines_waiting = %d\n",
 
1255
             empty_lines, bytes_per_line, lines_waiting);
 
1256
#endif
 
1257
  lines_waiting += empty_lines;
 
1258
  if (xormask) {
 
1259
    int blocks = (bytes_per_line + 127) / 128;
 
1260
    ensure_rle_buf_space (job_options, page_options,
 
1261
                          empty_lines * blocks);
 
1262
    for (; empty_lines--; ) {
 
1263
      *(rle_buffer_next++) = 'G';
 
1264
      *(rle_buffer_next++) = 0x02;
 
1265
      *(rle_buffer_next++) = 0x00;
 
1266
      int rep_len;
 
1267
      for (; bytes_per_line > 0; bytes_per_line -= rep_len) {
 
1268
        rep_len = bytes_per_line;
 
1269
        if (rep_len > 128) rep_len = 128;
 
1270
        *(rle_buffer_next++) = (signed char) (1 - rep_len);
 
1271
        *(rle_buffer_next++) = xormask;
 
1272
      }
 
1273
    }
 
1274
  } else {
 
1275
    ensure_rle_buf_space (job_options, page_options, empty_lines);
 
1276
    for (; empty_lines--; ) *(rle_buffer_next++) = 'Z';
 
1277
  }
 
1278
}
 
1279
 
 
1280
/**
 
1281
 * Emit raster lines for current page.
 
1282
 * @param page          Page number of page to be emitted
 
1283
 * @param job_options   Job options
 
1284
 * @param page_options  Page options
 
1285
 * @param ras           Raster data stream
 
1286
 * @param header        Current page header
 
1287
 * @return              0 on success, nonzero otherwise
 
1288
 */
 
1289
int
 
1290
emit_raster_lines (int page,
 
1291
                   job_options_t* job_options,
 
1292
                   page_options_t* page_options,
 
1293
                   cups_raster_t* ras,
 
1294
                   cups_page_header_t* header) {
 
1295
  unsigned char xormask = (header->NegativePrint ? ~0 : 0);
 
1296
  /* Determine whether we need to mirror the pixel data */
 
1297
  int do_mirror = job_options->software_mirror && page_options->mirror;
 
1298
 
 
1299
  unsigned cupsBytesPerLine = header->cupsBytesPerLine;
 
1300
  unsigned cupsHeight = header->cupsHeight;
 
1301
  unsigned cupsWidth = header->cupsWidth;
 
1302
  int bytes_per_line = job_options->bytes_per_line;
 
1303
  unsigned buflen = cupsBytesPerLine;
 
1304
  /* Make sure buflen can be written as a byte */
 
1305
  if (buflen > 0xff) buflen = 0xff;
 
1306
  /* Truncate buflen if greater than bytes_per_line */
 
1307
  if (buflen >= bytes_per_line) buflen = bytes_per_line;
 
1308
  /* Calculate extra horizontal spacing pixels if the right side of */
 
1309
  /* ImagingBoundingBox doesn't touch the PageSize box              */
 
1310
  double scale_pt2xpixels = header->HWResolution [0] / 72.0;
 
1311
  unsigned right_spacing_px = 0;
 
1312
  if (header->ImagingBoundingBox [2] != 0) {
 
1313
    unsigned right_distance_pt
 
1314
      = header->PageSize [0] - header->ImagingBoundingBox [2];
 
1315
    if (right_distance_pt != 0)
 
1316
      right_spacing_px = right_distance_pt * scale_pt2xpixels;
 
1317
  }
 
1318
  /* Calculate right_padding_bytes and shift */
 
1319
  int right_padding_bits;
 
1320
  if (job_options->align == CENTER) {
 
1321
    unsigned left_spacing_px = 0;
 
1322
    if (header->ImagingBoundingBox [0] != 0)
 
1323
      left_spacing_px
 
1324
        = header->ImagingBoundingBox [0] * scale_pt2xpixels;
 
1325
    right_padding_bits
 
1326
      = (bytes_per_line * 8
 
1327
         - (left_spacing_px + cupsWidth + right_spacing_px)) / 2
 
1328
      + right_spacing_px;
 
1329
    if (right_padding_bits < 0) right_padding_bits = 0;
 
1330
  } else
 
1331
    right_padding_bits = right_spacing_px;
 
1332
  int right_padding_bytes = right_padding_bits / 8;
 
1333
  int shift = right_padding_bits % 8;
 
1334
  /* If width is not an integral number of bytes, we must shift   */
 
1335
  /* right if we don't mirror, to ensure printing starts leftmost */
 
1336
  if (!do_mirror) shift -= (8 - cupsWidth % 8) % 8;
 
1337
  int shift_positive = (shift > 0 ? 1 : 0);
 
1338
  /* We cannot allow buffer+padding to exceed device width */
 
1339
  if (buflen + right_padding_bytes + shift_positive > bytes_per_line) {
 
1340
#ifdef DEBUG
 
1341
    if (debug) {
 
1342
      fprintf (stderr, "DEBUG: Warning: buflen = %d, right_padding_bytes = %d, "
 
1343
               "shift = %d, bytes_per_line = %d\n",
 
1344
               buflen, right_padding_bytes, shift, bytes_per_line);
 
1345
    }
 
1346
#endif
 
1347
    /* We cannot allow padding to exceed device width */
 
1348
    if (right_padding_bytes + shift_positive > bytes_per_line)
 
1349
      right_padding_bytes = bytes_per_line - shift_positive;
 
1350
    /* Truncate buffer to fit device width */
 
1351
    buflen = bytes_per_line - right_padding_bytes - shift_positive;
 
1352
  }
 
1353
  /* Percentage of page emitted */
 
1354
  int completed = -1;
 
1355
  /* Generate and store empty lines if the top of ImagingBoundingBox */
 
1356
  /* doesn't touch the PageSize box                                  */
 
1357
  double scale_pt2ypixels = header->HWResolution [1] / 72.0;
 
1358
  unsigned top_empty_lines = 0;
 
1359
  unsigned page_size_y = header->PageSize [1];
 
1360
  if (header->ImagingBoundingBox [3] != 0
 
1361
      && (!job_options->concat_pages || page == 1)) {
 
1362
    unsigned top_distance_pt
 
1363
      = page_size_y - header->ImagingBoundingBox [3];
 
1364
    if (top_distance_pt != 0) {
 
1365
      top_empty_lines = lrint (top_distance_pt * scale_pt2ypixels);
 
1366
      empty_lines += top_empty_lines;
 
1367
    }
 
1368
  }
 
1369
  /* Generate and store actual page data */
 
1370
  int y;
 
1371
  for (y = 0; y < cupsHeight; y++) {
 
1372
    /* Feedback to the user */
 
1373
    if ((y & 0x1f) == 0) {
 
1374
      int now_completed = 100 * y / cupsHeight;
 
1375
      if (now_completed > completed) {
 
1376
        completed = now_completed;
 
1377
        fprintf (stderr,
 
1378
                 "INFO: Printing page %d, %d%% complete...\n",
 
1379
                 page, completed);
 
1380
        fflush (stderr);
 
1381
      }
 
1382
    }
 
1383
    /* Read one line of pixels */
 
1384
    if (cupsRasterReadPixels (ras, buffer, cupsBytesPerLine) < 1)
 
1385
      break;  /* Escape if no pixels read */
 
1386
    bool nonempty_line =
 
1387
      generate_emit_line (buffer, emit_line_buffer, buflen, bytes_per_line,
 
1388
                          right_padding_bytes, shift, do_mirror, xormask);
 
1389
    if (nonempty_line) {
 
1390
      if (empty_lines) {
 
1391
        RLE_store_empty_lines
 
1392
          (job_options, page_options, empty_lines, xormask);
 
1393
        empty_lines = 0;
 
1394
      }
 
1395
      RLE_store_line (job_options, page_options,
 
1396
                      emit_line_buffer, bytes_per_line);
 
1397
    } else
 
1398
      empty_lines++;
 
1399
  }
 
1400
 
 
1401
  unsigned image_height_px = lrint (page_size_y * scale_pt2ypixels);
 
1402
  unsigned bot_empty_lines;
 
1403
  if (image_height_px >= top_empty_lines + y)
 
1404
    bot_empty_lines = image_height_px - top_empty_lines - y;
 
1405
  else
 
1406
    bot_empty_lines = 0;
 
1407
  if (bot_empty_lines != 0 && !job_options->concat_pages)
 
1408
    empty_lines += bot_empty_lines;
 
1409
  fprintf (stderr,
 
1410
           "INFO: Printing page %d, 100%% complete.\n",
 
1411
            page);
 
1412
  fflush (stderr);
 
1413
  return 0;
 
1414
}
 
1415
/**
 
1416
 * Process CUPS raster data from input file, emitting printer data on
 
1417
 * stdout.
 
1418
 * @param fd           File descriptor for input file
 
1419
 * @param job_options  Pointer to print options
 
1420
 * @return             0 on success, nonzero otherwise
 
1421
 */
 
1422
int
 
1423
process_rasterdata (int fd, job_options_t* job_options) {
 
1424
  int page = 1;                    /* Page number                   */
 
1425
  cups_raster_t* ras;              /* Raster stream for printing    */
 
1426
  cups_page_header_t header;       /* Current page header           */
 
1427
  int first_page = true;           /* Is this the first page?       */
 
1428
  int more_pages;                  /* Are there more pages left?    */
 
1429
  int bytes_per_line = job_options->bytes_per_line;
 
1430
  page_options_t page_options [2] = {{
 
1431
    CUT_MEDIA_DEFAULT,
 
1432
    MIRROR_DEFAULT,
 
1433
    ROLL_FED_MEDIA_DEFAULT,
 
1434
    RESOLUTION_DEFAULT,
 
1435
    PAGE_SIZE_DEFAULT,
 
1436
    IMAGE_HEIGHT_DEFAULT,
 
1437
    FEED_DEFAULT,
 
1438
    PERFORM_FEED_DEFAULT,}
 
1439
  };                               /* Current & preceding page opts */
 
1440
  page_options_t* new_page_options
 
1441
    = page_options + 0;            /* Options for current page      */
 
1442
  page_options_t* old_page_options
 
1443
    = page_options + 1;            /* Options for preceding page    */
 
1444
  page_options_t* tmp_page_options;/* Temp variable for swapping    */
 
1445
  ras = cupsRasterOpen (fd, CUPS_RASTER_READ);
 
1446
  for (more_pages = cupsRasterReadHeader (ras, &header);
 
1447
       more_pages;
 
1448
       tmp_page_options = old_page_options,
 
1449
         old_page_options = new_page_options,
 
1450
         new_page_options = tmp_page_options,
 
1451
         first_page = false) {
 
1452
    update_page_options (&header, new_page_options);
 
1453
#ifdef DEBUG
 
1454
    if (debug) {
 
1455
      fprintf (stderr, "DEBUG: pixel_xfer = %d\n", job_options->pixel_xfer);
 
1456
      fprintf (stderr, "DEBUG: print_quality_high = %d\n", job_options->print_quality_high);
 
1457
      fprintf (stderr, "DEBUG: half_cut = %d\n", job_options->half_cut);
 
1458
      fprintf (stderr, "DEBUG: bytes_per_line = %d\n", job_options->bytes_per_line);
 
1459
      fprintf (stderr, "DEBUG: align = %d\n", job_options->align);
 
1460
      fprintf (stderr, "DEBUG: software_mirror = %d\n", job_options->software_mirror);
 
1461
      fprintf (stderr, "DEBUG: label_preamble = %d\n", job_options->label_preamble);
 
1462
      fprintf (stderr, "DEBUG: print_density = %d\n", job_options->print_density);
 
1463
      fprintf (stderr, "DEBUG: xfer_mode = %d\n", job_options->xfer_mode);
 
1464
      fprintf (stderr, "DEBUG: concat_pages = %d\n", job_options->concat_pages);
 
1465
      fprintf (stderr, "DEBUG: cut_media = %d\n", new_page_options->cut_media);
 
1466
      fprintf (stderr, "DEBUG: mirror = %d\n", new_page_options->mirror);
 
1467
      fprintf (stderr, "DEBUG: roll_fed_media = %d\n", new_page_options->roll_fed_media);
 
1468
      fprintf (stderr, "DEBUG: resolution = %d x %d\n", new_page_options->resolution [0], new_page_options->resolution [1]);
 
1469
      fprintf (stderr, "DEBUG: page_size = %d x %d\n", new_page_options->page_size [0], new_page_options->page_size [1]);
 
1470
      fprintf (stderr, "DEBUG: image_height = %d\n", new_page_options->image_height);
 
1471
      fprintf (stderr, "DEBUG: feed = %d\n", new_page_options->feed);
 
1472
      fprintf (stderr, "DEBUG: perform_feed = %d\n", new_page_options->perform_feed);
 
1473
      fprintf (stderr, "DEBUG: header->ImagingBoundingBox = [%u, %u, %u, %u]\n",
 
1474
               header.ImagingBoundingBox [0], header.ImagingBoundingBox [1],
 
1475
               header.ImagingBoundingBox [2], header.ImagingBoundingBox [3]);
 
1476
      fprintf (stderr, "DEBUG: header.Margins = [%u, %u]\n",
 
1477
               header.Margins [0], header.Margins [1]);
 
1478
    }
 
1479
#endif
 
1480
    page_prepare (header.cupsBytesPerLine, bytes_per_line);
 
1481
    if (first_page) {
 
1482
      emit_job_cmds (job_options);
 
1483
      emit_page_cmds (job_options, old_page_options,
 
1484
                      new_page_options, first_page);
 
1485
    }
 
1486
    emit_raster_lines (page, job_options, new_page_options, ras, &header);
 
1487
    unsigned char xormask = (header.NegativePrint ? ~0 : 0);
 
1488
    /* Determine whether this is the last page (fetch next)    */
 
1489
    more_pages = cupsRasterReadHeader (ras, &header);
 
1490
    /* Do feeding or ejecting at the end of each page. */
 
1491
    cups_adv_t perform_feed = new_page_options->perform_feed;
 
1492
    if (more_pages) {
 
1493
      if (!job_options->concat_pages) {
 
1494
        RLE_store_empty_lines
 
1495
          (job_options, page_options, empty_lines, xormask);
 
1496
        empty_lines = 0;
 
1497
        flush_rle_buffer (job_options, page_options);
 
1498
        if (perform_feed == CUPS_ADVANCE_PAGE)
 
1499
          putchar (PTC_EJECT);    /* Emit eject marker to force feed   */
 
1500
        else
 
1501
          putchar (PTC_FORMFEED); /* Emit page end marker without feed */
 
1502
      }
 
1503
    } else {
 
1504
      if (!job_options->concat_pages) {
 
1505
        RLE_store_empty_lines
 
1506
          (job_options, page_options, empty_lines, xormask);
 
1507
        empty_lines = 0;
 
1508
        flush_rle_buffer (job_options, page_options);
 
1509
        putchar (PTC_FORMFEED);
 
1510
      } else {
 
1511
        double scale_pt2ypixels = header.HWResolution [1] / 72.0;
 
1512
        unsigned bot_empty_lines
 
1513
          = lrint (header.ImagingBoundingBox [1] * scale_pt2ypixels);
 
1514
        empty_lines = bot_empty_lines;
 
1515
        RLE_store_empty_lines
 
1516
          (job_options, page_options, empty_lines, xormask);
 
1517
        empty_lines = 0;
 
1518
        flush_rle_buffer (job_options, page_options);
 
1519
      }
 
1520
 
 
1521
      /* If special feed or cut at job end, emit commands to that effect */
 
1522
      cups_cut_t cut_media = new_page_options->cut_media;
 
1523
      if (perform_feed == CUPS_ADVANCE_JOB || cut_media == CUPS_CUT_JOB) {
 
1524
        emit_feed_cut_mirror
 
1525
          (perform_feed == CUPS_ADVANCE_PAGE ||
 
1526
           perform_feed == CUPS_ADVANCE_JOB,
 
1527
           new_page_options->feed,
 
1528
           cut_media == CUPS_CUT_PAGE || cut_media == CUPS_CUT_JOB,
 
1529
           new_page_options->mirror == CUPS_TRUE);
 
1530
        /* Emit eject marker */
 
1531
        putchar (PTC_EJECT);
 
1532
      }
 
1533
    }
 
1534
    page_end ();
 
1535
    /* Emit page count according to CUPS requirements */
 
1536
    fprintf (stderr, "PAGE: %d 1\n", page);
 
1537
    page++;
 
1538
  }
 
1539
  return 0;
 
1540
}
 
1541
/**
 
1542
 * Main entry function.
 
1543
 * @param argc  number of command line arguments plus one
 
1544
 * @param argv  command line arguments
 
1545
 * @return      0 if success, nonzero otherwise
 
1546
 */
 
1547
int
 
1548
main (int argc, const char* argv []) {
 
1549
  error_occurred = 0;
 
1550
#ifdef DEBUG
 
1551
  int i;
 
1552
  if (argc > 5)
 
1553
    if (strcasestr (argv [5], "debug") == argv [5]
 
1554
        || strcasestr (argv [5], " debug") != NULL)
 
1555
      debug = true;
 
1556
  struct tms time_start, time_end;
 
1557
  if (debug) {
 
1558
    fprintf (stderr, "DEBUG: args = ");
 
1559
    for (i = 0; i < argc; i++) fprintf (stderr, "%d:'%s' ", i, argv [i]);
 
1560
    fprintf (stderr, "\nDEBUG: environment =\n");
 
1561
    char** envvarbind;
 
1562
    for (envvarbind = environ; *envvarbind; envvarbind++)
 
1563
      fprintf (stderr, "DEBUG:  %s\n", *envvarbind);
 
1564
    times (&time_start);
 
1565
  }
 
1566
#endif
 
1567
 
 
1568
  job_options_t job_options = parse_options (argc, argv);
 
1569
 
 
1570
  int fd = open_input_file (argc, argv);
 
1571
 
 
1572
  int rv = process_rasterdata (fd, &job_options);
 
1573
 
 
1574
#ifdef DEBUG
 
1575
  if (debug) {
 
1576
    times (&time_end);
 
1577
    fprintf (stderr, "DEBUG: User time  System time  (usec)\n");
 
1578
    fprintf (stderr, "DEBUG: %9.3g  %9.3g\n",
 
1579
             (time_end.tms_utime - time_start.tms_utime)
 
1580
             * 1000000.0 / CLOCKS_PER_SEC,
 
1581
             (time_end.tms_stime - time_start.tms_stime)
 
1582
             * 1000000.0 / CLOCKS_PER_SEC);
 
1583
    fprintf (stderr, "DEBUG: Emitted lines: %u\n", emitted_lines);
 
1584
  }
 
1585
#endif
 
1586
 
 
1587
  if (fd != 0) close (fd);
 
1588
 
 
1589
  if (error_occurred) return error_occurred; else return rv;
 
1590
}