rastertoptch.c File Reference

This filter processes CUPS raster data, converting it into a byte stream on stdout suitable for sending directly to a label printer of the Brother P-touch family. More...

#include <config.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <math.h>
#include <cups/raster.h>
#include <cups/cups.h>
#include <stdbool.h>


Data Structures

struct  job_options_t
 Struct type for holding all the job options. More...
struct  page_options_t
 Struct type for holding current page options. More...

Defines

#define PIXEL_XFER_DEFAULT   RLE
 Default pixel transfer method.
#define PRINT_QUALITY_HIGH_DEFAULT   true
 Default print quality.
#define HALF_CUT_DEFAULT   false
 Default half cut mode.
#define BYTES_PER_LINE_MAX   255
 Maximum number of bytes per line.
#define BYTES_PER_LINE_DEFAULT   90
 Default number of bytes per line.
#define ALIGN_DEFAULT   RIGHT
 Default pixel data alignment on narrow tapes.
#define PRINT_DENSITY_MAX   5
 Maximum print density value.
#define PRINT_DENSITY_DEFAULT   0
 Default print density value (1: light, .
#define TRANSFER_MODE_DEFAULT   -1
 Transfer mode default ??? (-1 = don't set).
#define SOFTWARE_MIRROR_DEFAULT   false
 Driver pixel data mirroring default.
#define LABEL_PREAMBLE_DEFAULT   false
 Label preamble emitting default.
#define CONCAT_PAGES_DEFAULT   false
 Interlabel margin removal default.
#define RLE_ALLOC_MAX_DEFAULT   1000000
 RLE buffer maximum memory usage.
#define MIRROR_DEFAULT   false
 Mirror printing default.
#define NEGATIVE_DEFAULT   false
 Negative printing default.
#define CUT_MEDIA_DEFAULT   CUPS_CUT_NONE
 Cut media mode default.
#define ROLL_FED_MEDIA_DEFAULT   true
 Roll fed media default.
#define RESOLUTION_DEFAULT   { 300, 300 }
 Device resolution default in DPI.
#define PAGE_SIZE_DEFAULT   { 176, 142 }
 Page size default in PostScript points.
#define IMAGE_HEIGHT_DEFAULT   0
 Image size default in pixels.
#define FEED_DEFAULT   0
 Feed amount default.
#define PERFORM_FEED_DEFAULT   CUPS_ADVANCE_NONE
 When to perform feed default.
#define MM_PER_PT   (25.4 / 72.0)
 Length of a PostScript point in mm.
#define PTC_EJECT   0x1a
 Printer code: Eject.
#define PTC_FORMFEED   0x0c
 Printer code: Form feed.
#define ESC   0x1b
 ASCII escape value.
#define OBTAIN_INT_OPTION(name, var, min, max)
 Macro for obtaining integer option values.
#define OBTAIN_BOOL_OPTION(name, var)
 Macro for obtaining boolean option values.
#define APPEND_MIXED_BYTES
 Macro for appending mixed-bytes run to rle_buffer.
#define APPEND_REPEATED_BYTE
 Macro for appending repeated-byte run to rle_buffer.

Enumerations

enum  xfer_t { ULP, RLE, BIP }
 Pixel transfer mode type. More...
enum  align_t { RIGHT, CENTER }
 Pixel data alignment type.

Functions

job_options_t parse_options (int argc, const char *argv[])
 Parse options given in command line argument 5.
int open_input_file (int argc, const char *argv[])
 Determine input stream and open it.
void update_page_options (cups_page_header_t *header, page_options_t *page_options)
 Update page_options with information found in header.
void cancel_job (int signal)
 Cancel print job.
void page_prepare (unsigned cups_buffer_size, unsigned device_buffer_size)
 Prepare for a new page by setting up signalling infrastructure and memory allocation.
void page_end ()
 Clean up signalling and memory after emitting a page.
void emit_job_cmds (job_options_t *job_options)
 Emit printer command codes at start of print job.
void emit_feed_cut_mirror (bool do_feed, unsigned feed, bool do_cut, bool do_mirror)
 Emit feed, cut and mirror command codes.
void emit_quality_rollfed_size (job_options_t *job_options, page_options_t *page_options, unsigned page_size_y, unsigned image_height_px)
 Emit quality, roll fed media, and label size command codes.
void emit_page_cmds (job_options_t *job_options, page_options_t *old_page_options, page_options_t *new_page_options, bool force)
 Emit printer command codes at start of page for options that have changed.
int generate_emit_line (unsigned char *in_buffer, unsigned char *out_buffer, int buflen, unsigned char bytes_per_line, int right_padding_bytes, int shift, int do_mirror, unsigned char xormask)
 Generate a buffer of pixel data ready to emit.
void flush_rle_buffer (job_options_t *job_options, page_options_t *page_options)
 Emit lines waiting in RLE buffer.
void ensure_rle_buf_space (job_options_t *job_options, page_options_t *page_options, unsigned bytes)
 Ensure sufficient memory available in rle buffer.
void RLE_store_line (job_options_t *job_options, page_options_t *page_options, const unsigned char *buf, unsigned buf_len)
 Store buffer data in rle buffer using run-length encoding.
void RLE_store_empty_lines (job_options_t *job_options, page_options_t *page_options, int empty_lines, unsigned char xormask)
 Store a number of empty lines in rle_buffer using RLE.
int emit_raster_lines (int page, job_options_t *job_options, page_options_t *page_options, cups_raster_t *ras, cups_page_header_t *header)
 Emit raster lines for current page.
int process_rasterdata (int fd, job_options_t *job_options)
 Process CUPS raster data from input file, emitting printer data on stdout.
int main (int argc, const char *argv[])
 Main entry function.

Variables

int error_occurred
 Flag signalling whether any errors were encountered.
unsigned char * buffer
 CUPS Raster line buffer.
unsigned char * emit_line_buffer
 Buffer holding line data to emit to the printer.
unsigned char * rle_buffer = NULL
 Buffer holding RLE line data to emit to the printer.
unsigned char * rle_buffer_next = NULL
 Pointer to first free pos in rle_buffer.
unsigned long rle_alloced = 0
 Size of rle_buffer.
int empty_lines = 0
 Number of empty lines (input data only zeros) waiting to be stored.
unsigned lines_waiting = 0
 Number of pixel lines waiting to be emitted.
unsigned max_lines_waiting = INT_MAX
 Threshold for flushing waiting lines to printer.
const unsigned char mirror [0x100]
 mirror [i] = bit mirror image of i.

Detailed Description

This filter processes CUPS raster data, converting it into a byte stream on stdout suitable for sending directly to a label printer of the Brother P-touch family.

Version:
1.1
Author:
Arne John Glenstrup <panic@itu.dk>
Date:
2006

Invocation

The filter is invoked thus:

rastertoptch job user title copies options [filename]

Parameters:
printer The name of the printer queue (ignored)
job The numeric job ID (ignored)
user The string from the originating-user-name (ignored)
title The string from the job-name attribute (ignored)
copies The number of copies to be printed (ignored)
options String representations of the job template parameters, separated by spaces. Boolean attributes are provided as "name" for true values and "noname" for false values. All other attributes are provided as "name=value" for single-valued attributes and "name=value1,value2,...,valueN" for set attributes
filename The request file (if omitted, read from stdin)
Available options (default values in [brackets]):

Parameters:
PixelXfer=ULP|RLE|BIP Use uncompressed line printing (ULP), run-length encoding (RLE) or bit image printing (BIP) when emitting pixel data [ULP]
PrintQuality=High|Fast Use high quality or fast printing [High]
HalfCut Perform half-cut (crack & peel) when cutting [noHalfCut]
BytesPerLine=N Emit N bytes per line [90]
Align=Right|Center Pixel data alignment on tape [Right]
PrintDensity=1|...|5 Print density level: 1=light, 5=dark
ConcatPages Output all pages in one page [noConcatPages]
RLEMemMax Maximum memory used for RLE buffer [1000000]
SoftwareMirror Make the filter mirror pixel data if MirrorPrint is requested [noSoftwareMirror]
LabelPreamble Emit preamble containing print quality, roll/label type, tape width, label height, and pixel lines [noLabelPreamble]
Debug Emit diagnostic output to stderr [noDebug] (only if compiled with DEBUG set)
Information about media type, resolution, mirror print, negative print, cut media, advance distance (feed) is extracted from the CUPS raster page headers given in the input stream. The MediaType page header field can be either "roll" or "labels" for continuous tape or pre-cut labels, respectively.

LabelPreamble should usually not be used for the PT series printers.

Output

Each invocation of this filter is one job, containing a number of pages, each page containing a number of lines, each line consisting of a number of pixel bytes.

Output consists of job-related printer initialisation commands, followed by a number of pages, each page consisting of page-related commands, followed by raster line data. Each page is followed by a finish page or (after the final page) finish job command.

The following printer command language, printer, and tape information has been deduced from many sources, but is not official Brother documentation and may thus contain errors. Please send any corrections based on actual experience with these printers to the maintainer.

Job-related commands

Byte sequenceFunctionDescription
ESC @ (1b 40) InitialiseClear print buffer
ESC i D # (1b 69 44 ##) Set print density bit 0-3: 0=no change, 1-5=density level
ESC i K # (1b 69 4b ##) Set half cut bit 2: 0=full cut, 1=half cut
ESC i R ## (1b 69 52 ##) Set transfer mode ##: ?: 1=?
M ## (4d ##) Set compression ##: Compression type: 2=RLE

Page-related commands

Byte sequenceFunctionDescription
ESC i c #1 #2 #3 NUL #4
(1b 63 #1 #2 #3 00 #4)
Set width & resolution 360x360DPI: #1 #2 #4 = 0x84 0x00 0x00
360x720DPI: #1 #2 #4 = 0x86 0x09 0x01
#3: Tape width in mm
ESC i M #
(1b 69 4d ##)
Set mode bit 0-4: Feed amount (default=large): 0-7=none, 8-11=small, 12-25=medium, 26-31=large
bit 6: Auto cut/cut mark (default=on): 0=off, 1=on
bit 7: Mirror print (default=off): 0=off, 1=on. (note that it seems that QL devices do not reverse the data stream themselves, but rely on the driver doing it!)
ESC i z #1 #2 #3 #4 #5 #6 NUL NUL NUL NUL
(1b 69 7a #1 #2 #3 #4 #5 #6 00 00 00 00)
Set media & quality #1, bit 6: Print quality: 0=fast, 1=high
#2, bit 0: Media type: 0=continuous roll, 1=pre-cut labels
#3: Tape width in mm
#4: Label height in mm (0 for continuous roll)
#5 #6: Page consists of N=#5+256*#6 pixel lines
ESC i d #1 #2
(1b 69 64 #1 #2)
Set margin Set size of right(?) margin to N=#1+256*#2 pixels
FF (0c) Form feed Print buffer data without ejecting.
SUB (1a) Eject Print buffer data and ejects.

Line-related commands

Byte sequenceFunctionDescription
G #1 #2 ...data...
(47 #1 #2 ...data...)
Send raster line data consists of N=#1+256*#2 bytes of RLE compressed raster data.
Z (5a) Advance tapePrint 1 empty line
g #1 #2 ...data...
(67 #1 #2 ...data...)
Send raster line data consists of N=#2 bytes of uncompressed raster data.
ESC * ' #1 #2 ...data...
(1b 2a 27 #1 #2 ...data...)
Bit image printing (BIP) Print N=#1+256*#2 lines of 24 pixels; data consists of 3*N bytes

Compressed-data-related commands (RLE)

Byte sequenceFunctionDescription
#1 ...data... #1 >= 0: Print uncompressed data consists of 1+#1 uncompressed bytes
#1 #2 #1 < 0: Print compressed #2 should be printed 1-#1 times
#1 is represented as a 2-complement signed integer.

Printer model characteristics

The following table lists for each model what kind of cutter it has (manual, auto, half cut), what kind of pixel data transfer mode it requires, its resolution, number of print head pixels, number of bytes of pixel data that must be transmitted per line (regardless of actual tape width!), and what kinds of tape it can take.

For PC models, pixel data must be centered, so narrow tapes require padding raster data with zero bits on each side. For QL models, labels are left-aligned, so pixel data must be right aligned, so narrow tapes require padding raster data with zero bits at the end.

For PC-PT, only the central 24 pixels (= 3,4mm!) can be used for pixel-based graphics. It might be possible to print several strips of 24 pixels side-by side by issuing CR and line-positioning commands. That is currently not supported, let alone attempted, with this driver.

Model Cutter XferDPIPixelsBytesTape
QL-500 manual ULP30072090DK12-62mm
QL-550 auto ULP30072090DK12-62mm
QL-650TD auto ULP30072090DK12-62mm
PT-PC auto BIP1801283TZ6-24mm
PT-18R auto RLE18012816TZ6-18mm
PT-550A auto RLE18012816TZ6-36mm
PT-1500PCmanual RLE18011214TZ6-24mm
PT-1950 auto RLE18012816TZ6-18mm
PT-1950VPauto RLE18011214TZ6-18mm
PT-1960 auto RLE1809612TZ6-18mm
PT-2420PCmanual RLE18012816TZ6-24mm
PT-2450DXauto RLE18012816TZ6-24mm
PT-2500PCauto RLE18012816TZ6-24mm
PT-2600 auto RLE18012816TZ,AV6-24mm
PT-2610 auto RLE18012816TZ,AV6-24mm
PT-3600 auto/halfRLE36038448TZ,AV6-36mm
PT-9200DXauto/halfRLE36038448TZ6-36mm
PT-9200PCauto/halfRLE36038448TZ6-36mm
PT-9400 auto/halfRLE36038448TZ6-36mm
PT-9500PCauto/halfRLE360
360x720
38448TZ,AV6-36mm
PT-9600 auto/halfRLE36038448TZ,AV6-36mm

Tape characteristics

Tape width Print area MarginsDPI
62mm61.0mm720pixels0.5mm300
36mm27.1mm384pixels4.5mm360
24mm18.0mm128pixels3mm180
18mm12.0mm85pixels3mm180
12mm8.0mm57pixels2mm180
9mm6.9mm49pixels1mm180
6mm3.9mm28pixels1mm180

Notes


Define Documentation

#define APPEND_MIXED_BYTES
 

Value:

if (mix_len > 128) mix_len = 128;         \
        *rle_next++ = mix_len - 1;                \
        memcpy (rle_next, mix_start, mix_len);    \
        rle_next += mix_len;
Macro for appending mixed-bytes run to rle_buffer.

#define APPEND_REPEATED_BYTE
 

Value:

unsigned rep_len = next - rep_start;      \
        *rle_next++ = (signed char)(1 - rep_len); \
        *rle_next++ = rep_val;
Macro for appending repeated-byte run to rle_buffer.

#define OBTAIN_BOOL_OPTION name,
var   ) 
 

Value:

cups_option                                              \
    = cupsGetOption (name, num_options, cups_options);     \
  if (cups_option) options.var = true;                     \
  cups_option                                              \
    = cupsGetOption ("no"name, num_options, cups_options); \
  if (cups_option) options.var = false;                    \
Macro for obtaining boolean option values.

#define OBTAIN_INT_OPTION name,
var,
min,
max   ) 
 

Value:

cups_option                                                   \
    = cupsGetOption (name, num_options, cups_options);          \
  if (cups_option) {                                            \
    errno = 0;                                                  \
    char* rest;                                                 \
    long int var = strtol (cups_option, &rest, 0);              \
    if (errno || *rest != '\0' || rest == cups_option           \
        || var < min || var > max) {                            \
      fprintf (stderr, "ERROR: " name " '%s', "                 \
               "must be an integer N, where %ld <= N <= %ld\n", \
               cups_option, (long) min, (long) max);            \
      error_occurred = 1;                                       \
    } else                                                      \
      options.var = var;                                        \
  }
Macro for obtaining integer option values.

#define PRINT_DENSITY_DEFAULT   0
 

Default print density value (1: light, .

.., 5:dark, 0: no change)


Enumeration Type Documentation

enum xfer_t
 

Pixel transfer mode type.

Enumerator:
ULP  Uncompressed line printing.
RLE  Run-length encoding.
BIP  Bit image printing.

Function Documentation

void emit_feed_cut_mirror bool  do_feed,
unsigned  feed,
bool  do_cut,
bool  do_mirror
[inline]
 

Emit feed, cut and mirror command codes.

Parameters:
do_feed Emit codes to actually feed
feed Feed size
do_cut Emit codes to actually cut
do_mirror Emit codes to mirror print

void emit_job_cmds job_options_t job_options  ) 
 

Emit printer command codes at start of print job.

This function does not emit P-touch page specific codes.

Parameters:
job_options Job options

void emit_page_cmds job_options_t job_options,
page_options_t old_page_options,
page_options_t new_page_options,
bool  force
 

Emit printer command codes at start of page for options that have changed.

Parameters:
job_options Job options
old_page_options Page options for preceding page
new_page_options Page options for page to be printed
force Ignore old_page_options and emit commands for selecting all options in new_page_options

void emit_quality_rollfed_size job_options_t job_options,
page_options_t page_options,
unsigned  page_size_y,
unsigned  image_height_px
 

Emit quality, roll fed media, and label size command codes.

Parameters:
job_options Current job options
page_options Current page options
page_size_y Page size (height) in pt
image_height_px Number of pixel lines in current page

int emit_raster_lines int  page,
job_options_t job_options,
page_options_t page_options,
cups_raster_t *  ras,
cups_page_header_t *  header
 

Emit raster lines for current page.

Parameters:
page Page number of page to be emitted
job_options Job options
page_options Page options
ras Raster data stream
header Current page header
Returns:
0 on success, nonzero otherwise

void ensure_rle_buf_space job_options_t job_options,
page_options_t page_options,
unsigned  bytes
[inline]
 

Ensure sufficient memory available in rle buffer.

If rle buffer needs to be extended, global variables rle_buffer and rle_buffer_next might be altered.

Parameters:
job_options Job options
page_options Page options
bytes Number of bytes required.

void flush_rle_buffer job_options_t job_options,
page_options_t page_options
[inline]
 

Emit lines waiting in RLE buffer.

Resets global variable rle_buffer_next to rle_buffer, and lines_waiting to zero.

Parameters:
job_options Job options
page_options Page options

int generate_emit_line unsigned char *  in_buffer,
unsigned char *  out_buffer,
int  buflen,
unsigned char  bytes_per_line,
int  right_padding_bytes,
int  shift,
int  do_mirror,
unsigned char  xormask
[inline]
 

Generate a buffer of pixel data ready to emit.

Requirement: buflen + right_padding_bytes + (shift > 0 ? 1 : 0) <= bytes_per_line

Parameters:
in_buffer Buffer containing raster data in left-to-right order
out_buffer Buffer for returning generated line in right-to-left order; must be bytes_per_line long
buflen in_buffer length
bytes_per_line Number of pixel bytes to generate
right_padding_bytes Number of zero bytes to pad with to the right of pixels
shift Number of bits to shift left If do_mirror is false and shift < 0 Then shift right -shift bits
do_mirror Mirror in_buffer pixel data
xormask The XOR mask for negative printing
Returns:
0 if entire line is empty (zeros) nonzero if line contains nonzero pixels

int main int  argc,
const char *  argv[]
 

Main entry function.

Parameters:
argc number of command line arguments plus one
argv command line arguments
Returns:
0 if success, nonzero otherwise

int open_input_file int  argc,
const char *  argv[]
 

Determine input stream and open it.

If there are 6 command line arguments, argv[6] is taken to be the input file name otherwise stdin is used. This funtion exits the program on error.

Parameters:
argc number of command line arguments plus one
argv command line arguments
Returns:
file descriptor for the opened input stream

void page_prepare unsigned  cups_buffer_size,
unsigned  device_buffer_size
 

Prepare for a new page by setting up signalling infrastructure and memory allocation.

Parameters:
cups_buffer_size Required size of CUPS raster line buffer
device_buffer_size Required size of device pixel line buffer

job_options_t parse_options int  argc,
const char *  argv[]
 

Parse options given in command line argument 5.

Parameters:
argc number of command line arguments plus one
argv command line arguments
Returns:
options, where each option set to its default value if not specified in argv [5]

int process_rasterdata int  fd,
job_options_t job_options
 

Process CUPS raster data from input file, emitting printer data on stdout.

Parameters:
fd File descriptor for input file
job_options Pointer to print options
Returns:
0 on success, nonzero otherwise

void RLE_store_empty_lines job_options_t job_options,
page_options_t page_options,
int  empty_lines,
unsigned char  xormask
[inline]
 

Store a number of empty lines in rle_buffer using RLE.

Parameters:
job_options Job options
page_options Page options
empty_lines Number of empty lines to store
xormask The XOR mask for negative printing

void RLE_store_line job_options_t job_options,
page_options_t page_options,
const unsigned char *  buf,
unsigned  buf_len
[inline]
 

Store buffer data in rle buffer using run-length encoding.

Parameters:
job_options Job options
page_options Page options
buf Buffer containing data to store
buf_len Length of buffer
Global variable rle_buffer_next is a pointer into buffer for holding RLE data. Must have room for at least 3 + buf_len + buf_len/128 + 1 bytes (ensured by reallocation). On return, rle_buffer_next points to first unused buffer byte.

This implementation enjoys the property that the resulting RLE is at most buf_len + buf_len/128 + 1 bytes long, because: # a repeated-byte run has a repeat factor of at least 3 # two mixed-bytes runs never follow directly after each other, unless the first one is 128 bytes long The first property ensures that a repeated-run output sequence is always at least 1 byte shorter than the input sequence it represents. This combined with the second property means that only

  • a terminating mixed-bytes run, and
  • a mixed-bytes run of 128 bytes can cause the RLE representation to be longer (by 1 byte) than the corresponding input sequence in buf.

void update_page_options cups_page_header_t *  header,
page_options_t page_options
 

Update page_options with information found in header.

Parameters:
header CUPS page header
page_options page options to be updated

Variable Documentation

const unsigned char mirror[0x100]
 

mirror [i] = bit mirror image of i.

I.e., (mirror [i] >> j) & 1 == (i >> (7 - j)) & 1 for 0 <= j <= 7


Generated on Mon May 1 23:27:05 2006 for Ptouch-driver by  doxygen 1.4.6