1
/* rastertoptch is a filter to convert CUPS raster data into a Brother
2
* P-touch label printer command byte stream.
4
* Copyright (c) 2006 Arne John Glenstrup <panic@itu.dk>
6
* This file is part of ptouch-driver
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.
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.
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
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.
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.
35
* @author Arne John Glenstrup <panic@itu.dk>
39
* The filter is invoked thus:
41
* rastertoptch job user title copies options [filename]
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)
56
* Available options (default values in [brackets]):
58
* @param PixelXfer=ULP|RLE|BIP Use uncompressed line printing (ULP),
59
* run-length encoding (RLE) or bit
60
* image printing (BIP) when emitting
62
* @param PrintQuality=High|Fast Use high quality or fast printing [High]
63
* @param HalfCut Perform half-cut (crack & peel) when
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)
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.
84
* LabelPreamble should usually not be used for the PT series printers.
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.
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.
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
102
* <h3>Job-related commands</h3>
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>
121
* <h3>Page-related commands</h3>
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>
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
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>
152
* <td>Print buffer data without ejecting.</td></tr>
153
* <tr><td>SUB (1a)</td>
155
* <td>Print buffer data and ejects.</td></tr>
158
* <h3>Line-related commands</h3>
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.
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
178
* <h3>Compressed-data-related commands (RLE)</h3>
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>
185
* <td>#1 < 0: Print compressed</td>
186
* <td>#2 should be printed 1-#1 times</td></tr>
188
* #1 is represented as a 2-complement signed integer.
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.
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.
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,
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
235
* <h2>Tape characteristics</h2>
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>
249
* - Pixels bytes sent are printed from right to left, with bit 7
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.
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
313
#include <cups/raster.h>
314
#include <cups/cups.h>
320
# define memcpy(d, s, n) bcopy ((s), (d), (n))
324
# include <stdbool.h>
330
typedef unsigned char _Bool;
336
# define __bool_true_false_are_defined 1
342
#include <sys/times.h>
345
/** Number of emitted lines */
346
unsigned emitted_lines = 0;
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
356
/** ASCII escape value */
360
* Pixel transfer mode type.
363
ULP, /**< Uncompressed line printing */
364
RLE, /**< Run-length encoding */
365
BIP, /**< Bit image printing */
369
* Pixel data alignment type.
371
typedef enum {RIGHT, CENTER} align_t;
373
/** Flag signalling whether any errors were encountered. */
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 */
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;
393
/** Macro for obtaining integer option values. */
394
#define OBTAIN_INT_OPTION(name, var, min, max) \
396
= cupsGetOption (name, num_options, cups_options); \
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; \
411
/** Macro for obtaining boolean option values. */
412
#define OBTAIN_BOOL_OPTION(name, var) \
414
= cupsGetOption (name, num_options, cups_options); \
415
if (cups_option) options.var = true; \
417
= cupsGetOption ("no"name, num_options, cups_options); \
418
if (cups_option) options.var = false; \
421
* Struct type for holding all the job options.
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 */
438
* Struct type for holding current page options.
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 */
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]
459
parse_options (int argc, const char* argv []) {
460
job_options_t options = {
462
PRINT_QUALITY_HIGH_DEFAULT,
464
BYTES_PER_LINE_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,
473
if (argc < 6) return options;
475
cups_option_t* cups_options = NULL;
477
= cupsParseOptions (argv [5], num_options, &cups_options);
478
const char* cups_option
479
= cupsGetOption ("PixelXfer", num_options, cups_options);
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;
488
fprintf (stderr, "ERROR: Unknown PicelXfer '%s', "
489
"must be RLE, BIP or ULP\n", cups_option);
494
= cupsGetOption ("PrintQuality", num_options, cups_options);
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;
501
fprintf (stderr, "ERROR: Unknown PrintQuality '%s', "
502
"must be High or Fast\n", cups_option);
506
OBTAIN_BOOL_OPTION ("HalfCut", half_cut);
507
OBTAIN_INT_OPTION ("BytesPerLine", bytes_per_line,
508
1, BYTES_PER_LINE_MAX);
510
= cupsGetOption ("Align", num_options, cups_options);
512
if (strcasecmp (cups_option, "Right") == 0)
513
options.align = RIGHT;
514
else if (strcasecmp (cups_option, "Center") == 0)
515
options.align = CENTER;
517
fprintf (stderr, "ERROR: Unknown Align '%s', "
518
"must be Right or Center\n", cups_option);
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);
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
543
open_input_file (int argc, const char* argv []) {
546
if ((fd = open (argv[6], O_RDONLY)) < 0) {
547
perror ("ERROR: Unable to open raster file - ");
557
* Update page_options with information found in header.
558
* @param header CUPS page header
559
* @param page_options page options to be updated
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;
578
void cancel_job (int signal);
580
* Prepare for a new page by setting up signalling infrastructure and
582
* @param cups_buffer_size Required size of CUPS raster line buffer
583
* @param device_buffer_size Required size of device pixel line buffer
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;
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);
600
signal (SIGTERM, cancel_job);
603
/* Allocate line buffer */
604
buffer = malloc (cups_buffer_size);
605
emit_line_buffer = malloc (device_buffer_size);
606
if (!buffer || !emit_line_buffer) {
609
"ERROR: Cannot allocate memory for raster line buffer\n");
615
* Clean up signalling and memory after emitting a page
619
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
620
struct sigaction action;
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);
631
signal (SIGTERM, SIG_IGN);
633
/* Release line buffer memory */
635
free (emit_line_buffer);
642
cancel_job (int signal) {
643
/* Emit page end & eject marker */
646
if (rle_buffer) free (rle_buffer);
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
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;
662
case 1: case 2: case 3: case 4: case 5:
663
putchar (ESC); putchar ('i'); putchar ('D'); putchar (density);
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);
672
/* Emit half cut selection command if required */
673
if (job_options->half_cut) {
674
putchar (ESC); putchar ('i'); putchar ('K'); putchar (0x04);
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
686
emit_feed_cut_mirror (bool do_feed, unsigned feed,
689
/* Determine feed nibble */
690
unsigned feed_nibble;
692
feed_nibble = lrint (feed / 2.6 + 2.4); /* one suggested conversion */
693
if (feed_nibble > 31) feed_nibble = 31;
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);
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
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) {
726
"ERROR: Page width (%umm) exceeds 255mm\n",
728
tape_width_mm = 0xff;
730
/* Get tape height in mm */
731
unsigned tape_height_mm;
735
tape_height_mm = lrint (page_size_y * MM_PER_PT);
736
if (tape_height_mm > 0xff) {
738
"ERROR: Page height (%umm) exceeds 255mm; use continuous tape (MediaType=roll)\n",
740
tape_height_mm = 0xff;
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);
751
* Emit printer command codes at start of page for options that have
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
760
emit_page_cmds (job_options_t* job_options,
761
page_options_t* old_page_options,
762
page_options_t* new_page_options,
764
int tape_width_mm = -1;
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];
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) {
781
"ERROR: Page width (%umm) exceeds 255mm\n",
783
tape_width_mm = 0xff;
785
/* Emit printer commands */
786
putchar (ESC); putchar ('i'); putchar ('c');
788
putchar (0x84); putchar (0x00); putchar (tape_width_mm & 0xff);
789
putchar (0x00); putchar (0x00);
791
putchar (0x86); putchar (0x09); putchar (tape_width_mm & 0xff);
792
putchar (0x00); putchar (0x01);
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;
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
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);
822
/* WHY DON'T WE SET MARGIN (ESC i d ...)? */
824
/* Set pixel data transfer compression */
826
if (job_options->pixel_xfer == RLE) {
827
putchar ('M'); putchar (0x02);
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);
839
/** mirror [i] = bit mirror image of i.
840
* I.e., (mirror [i] >> j) & 1 == (i >> (7 - j)) & 1 for 0 <= j <= 7
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,
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
899
generate_emit_line (unsigned char* in_buffer,
900
unsigned char* out_buffer,
902
unsigned char bytes_per_line,
903
int right_padding_bytes,
906
unsigned char xormask) {
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);
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 */
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;
932
out_buffer [j++] = box & 0xff;
934
for (i = 0; i < buflen; i++) {
935
unsigned char data = in_buffer [i]; nonzero |= data;
936
out_buffer [j++] = data ^ xormask;
942
box = in_buffer [buflen - 1] >> -shift; nonzero |= box;
945
box = in_buffer [buflen - 1] << shift; nonzero |= box;
946
out_buffer [j++] = (mirror [box & 0xff]) ^ xormask;
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;
955
out_buffer [j++] = (mirror [box & 0xff]) ^ xormask;
958
for (i = buflen - 1; i >= 0; i--) {
959
unsigned char data = in_buffer [i]; nonzero |= data;
960
out_buffer [j++] = (mirror [data]) ^ xormask;
962
/* Generate left padding bytes */
963
memset (out_buffer + j, xormask, bytes_per_line - j);
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
975
flush_rle_buffer (job_options_t* job_options,
976
page_options_t* page_options) {
979
fprintf (stderr, "DEBUG: flush_rle_buffer (): "
980
"lines_waiting = %d\n",
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],
988
xfer_t pixel_xfer = job_options->pixel_xfer;
989
int bytes_per_line = job_options->bytes_per_line;
990
switch (pixel_xfer) {
993
= fwrite (rle_buffer, sizeof (char), rle_buffer_next - rle_buffer, stdout);
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);
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);
1019
linelen -= l; linelen--;
1020
emitted += l; emitted++;
1023
if (emitted > bytes_per_line)
1025
"ERROR: Emitted %d > %d bytes for one pixel line!\n",
1026
emitted, bytes_per_line);
1027
/* No break; fall through to next case: */
1029
for (; emitted < bytes_per_line; emitted++) putchar (0x00);
1032
fprintf (stderr, "ERROR: Unknown RLE flag at %p: '0x%02x'\n",
1033
p - 1, (int)*(p - 1));
1039
fprintf (stderr, "DEBUG: emitted %d lines\n", emitted_lines);
1044
fprintf (stderr, "ERROR: Unknown pixel transfer mode: '%d'\n",
1047
rle_buffer_next = rle_buffer;
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.
1061
ensure_rle_buf_space (job_options_t* job_options,
1062
page_options_t* page_options,
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;
1070
fprintf (stderr, "DEBUG: ensure_rle_buf_space (bytes=%d): "
1071
"increasing rle_buffer from %d to %d\n",
1073
rle_alloced * sizeof (char),
1074
new_alloced * sizeof (char));
1077
if (new_alloced <= job_options->rle_alloc_max) {
1079
p = (unsigned char*) realloc (rle_buffer, new_alloced * sizeof (char));
1081
p = (unsigned char*) malloc (new_alloced * sizeof (char));
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) {
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));
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 */
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
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.
1117
* This implementation enjoys the property that
1118
* the resulting RLE is at most buf_len + buf_len/128 + 1 bytes
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.
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 */
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 */
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;
1161
for (mix_start = rep_start = next = buf, rep_val = next_val = *next;
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
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;
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;
1189
mix_start = rep_start;
1193
if (next - rep_start > 2) { /* End of repeated run found */
1194
APPEND_REPEATED_BYTE;
1199
unsigned mix_len = rep_start - mix_start;
1200
if (mix_len >= 128) {
1201
/* RLE cannot represent mixed runs longer than 128 bytes */
1203
mix_start += mix_len;
1207
/* Handle final bytes */
1208
if (next - rep_start > 2) { /* Handle final repeated byte run */
1209
APPEND_REPEATED_BYTE;
1213
unsigned mix_len = rep_start - mix_start;
1214
if (mix_len > 0) { /* Handle any remaining final mixed run */
1216
mix_start += mix_len;
1218
mix_len = rep_start - mix_start;
1219
if (mix_len > 0) { /* Case where final mixed run is 129 bytes */
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;
1230
rle_buffer_next [0] = 'Z';
1234
if (lines_waiting >= max_lines_waiting)
1235
flush_rle_buffer (job_options, page_options);
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
1246
RLE_store_empty_lines (job_options_t* job_options,
1247
page_options_t* page_options,
1249
unsigned char xormask) {
1250
int bytes_per_line = job_options->bytes_per_line;
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);
1257
lines_waiting += empty_lines;
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;
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;
1275
ensure_rle_buf_space (job_options, page_options, empty_lines);
1276
for (; empty_lines--; ) *(rle_buffer_next++) = 'Z';
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
1290
emit_raster_lines (int page,
1291
job_options_t* job_options,
1292
page_options_t* page_options,
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;
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;
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)
1324
= header->ImagingBoundingBox [0] * scale_pt2xpixels;
1326
= (bytes_per_line * 8
1327
- (left_spacing_px + cupsWidth + right_spacing_px)) / 2
1329
if (right_padding_bits < 0) right_padding_bits = 0;
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) {
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);
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;
1353
/* Percentage of page emitted */
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;
1369
/* Generate and store actual page data */
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;
1378
"INFO: Printing page %d, %d%% complete...\n",
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) {
1391
RLE_store_empty_lines
1392
(job_options, page_options, empty_lines, xormask);
1395
RLE_store_line (job_options, page_options,
1396
emit_line_buffer, bytes_per_line);
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;
1406
bot_empty_lines = 0;
1407
if (bot_empty_lines != 0 && !job_options->concat_pages)
1408
empty_lines += bot_empty_lines;
1410
"INFO: Printing page %d, 100%% complete.\n",
1416
* Process CUPS raster data from input file, emitting printer data on
1418
* @param fd File descriptor for input file
1419
* @param job_options Pointer to print options
1420
* @return 0 on success, nonzero otherwise
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] = {{
1433
ROLL_FED_MEDIA_DEFAULT,
1436
IMAGE_HEIGHT_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);
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);
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]);
1480
page_prepare (header.cupsBytesPerLine, bytes_per_line);
1482
emit_job_cmds (job_options);
1483
emit_page_cmds (job_options, old_page_options,
1484
new_page_options, first_page);
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;
1493
if (!job_options->concat_pages) {
1494
RLE_store_empty_lines
1495
(job_options, page_options, empty_lines, xormask);
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 */
1501
putchar (PTC_FORMFEED); /* Emit page end marker without feed */
1504
if (!job_options->concat_pages) {
1505
RLE_store_empty_lines
1506
(job_options, page_options, empty_lines, xormask);
1508
flush_rle_buffer (job_options, page_options);
1509
putchar (PTC_FORMFEED);
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);
1518
flush_rle_buffer (job_options, page_options);
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);
1535
/* Emit page count according to CUPS requirements */
1536
fprintf (stderr, "PAGE: %d 1\n", page);
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
1548
main (int argc, const char* argv []) {
1553
if (strcasestr (argv [5], "debug") == argv [5]
1554
|| strcasestr (argv [5], " debug") != NULL)
1556
struct tms time_start, time_end;
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");
1562
for (envvarbind = environ; *envvarbind; envvarbind++)
1563
fprintf (stderr, "DEBUG: %s\n", *envvarbind);
1564
times (&time_start);
1568
job_options_t job_options = parse_options (argc, argv);
1570
int fd = open_input_file (argc, argv);
1572
int rv = process_rasterdata (fd, &job_options);
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);
1587
if (fd != 0) close (fd);
1589
if (error_occurred) return error_occurred; else return rv;