CUPS rastertoql filter  1.0.4
Filter for the Brother QL family of label printers
Functions | Variables
cupsbackend.c File Reference

Generic functions making use of CUPS. More...

Functions

int ql_printer_data_send (struct qldriver *ql, const void *data, size_t count, int flush)
 
int cups_ql_next_line_read (struct qldriver *ql, size_t sz, unsigned char buf[sz])
 
int cups_ql_raster_header_read (struct qldriver *ql)
 
static unsigned convert_points_to_pixel (float pts, unsigned resolution)
 
static float convert_points_to_mm (float pts)
 
static float convert_pixel_to_mm (float pixel, unsigned resolution)
 
static void cups_ql_medium_size_quirk (struct qldriver *ql)
 
int ql_raster_limits_get (struct qldriver *ql)
 
static int number_convert (const char *string)
 
static unsigned int attribute_group_value_get (struct qldriver *ql, const char *group_name, const char *attribute_name, unsigned int default_val)
 
static const char * choice_value_get (struct qldriver *ql, const char *kw)
 
static void bytes_per_line_init (struct qldriver *ql)
 
static int printer_type_init (struct qldriver *ql)
 
static void halftone_type_init (struct qldriver *ql)
 
static void red_detection_lower_angle (struct qldriver *ql)
 
static void red_detection_higher_angle (struct qldriver *ql)
 
static void red_detection_lower_saturation (struct qldriver *ql)
 
static void red_detection_lower_value (struct qldriver *ql)
 
static void red_detection_init (struct qldriver *ql)
 
static void leading_bytes_setup (struct qldriver *ql)
 
static void margin_setup (struct qldriver *ql)
 
static void high_resoultion_setup (struct qldriver *ql)
 
static void auto_cutter_setup (struct qldriver *ql)
 
static void auto_power_off_setup (struct qldriver *ql)
 
static void auto_power_on_setup (struct qldriver *ql)
 
int cups_ql_driver_init (struct qldriver *ql)
 
static int cups_ql_job_check_colour (struct qldriver *ql)
 
static int cups_ql_medium_guess (struct qldriver *ql)
 
static int cups_ql_medium_detect (struct qldriver *ql)
 
static void cups_ql_input_raster_warn (struct qldriver *ql)
 
static int cups_ql_input_raster_check (struct qldriver *ql)
 
static int cups_ql_raster_lines_skip (struct qldriver *ql, unsigned lines, size_t cnt)
 
int cups_ql_job_print (struct qldriver *ql)
 
void cups_message_print (const char *level, const char *scope, const char *fn, int ln, const char *format,...)
 

Variables

int terminate
 

Detailed Description

Generic functions making use of CUPS.

Function Documentation

◆ attribute_group_value_get()

static unsigned int attribute_group_value_get ( struct qldriver ql,
const char *  group_name,
const char *  attribute_name,
unsigned int  default_val 
)
static

Generic function to read a value from the PPD

Parameters
[in]qlFull job description
[in]group_nameAttribute group name
[in]attribute_nameAttribute name (can be NULL)
[in]default_valDefault value if the group or the attribute wasn't found
Return values
ValueThe value read from the PPD's group_name / attribute_name
DefaultThe default if the group_name / attribute_name wasn't found

The PPD contains lines in the form:

  * <group name> <attribute name>: "<value>"
  * <group name>: "<value>"

The latter one you can read the <value> with attribute_name set to NULL

◆ auto_cutter_setup()

static void auto_cutter_setup ( struct qldriver ql)
static

Setup the printer's auto cutter capability

Parameters
[in]qlFull job description

◆ auto_power_off_setup()

static void auto_power_off_setup ( struct qldriver ql)
static

Setup the printer's power off feature according to user settings

Parameters
[in]qlFull job description

The power off feature is a little bit anoying. After the programmable idle timout it disconnects from the USB and powers itself off. You can't wake it again remotely.

Note
Only a few of the QL printers seems to support this feature. At least the QL500 doesn't and the QL800 does.

◆ auto_power_on_setup()

static void auto_power_on_setup ( struct qldriver ql)
static

Setup the printer's power on feature according to user settings

Parameters
[in]qlFull job description

If the printer is connected to an external power supply, you can select, if it should switch on immediately, or should wait for manual touching the power button to swich on.

◆ bytes_per_line_init()

static void bytes_per_line_init ( struct qldriver ql)
static

Read in the bytes per line entry

Parameters
[in]qlFull job description

This value is required to "know" the amount of dots the printer's head is capable to print per line. All known print heads are simply monochrome, so 8 dots fits into a byte. And it seems this amount of bytes must always be sent, e.g. independendly of the used medium. Exception seems to be when compression is used. But at 90 bytes (or 196 bytes) and a USB interface, compression makes no sense. That's why some printers do not support compression at all.

◆ choice_value_get()

static const char* choice_value_get ( struct qldriver ql,
const char *  kw 
)
static

Grap a choice from the PPD

Parameters
[in]qlFull job description
[in]kwKeyword
Returns
The selected string

◆ convert_pixel_to_mm()

static float convert_pixel_to_mm ( float  pixel,
unsigned  resolution 
)
static
Parameters
[in]resolutionDots Per Inch (DPI)
Returns
Value in [mm]

◆ convert_points_to_mm()

static float convert_points_to_mm ( float  pts)
static

Convert Postscript Points (1/72 inch) to millimeter

Parameters
[in]ptsPostscript Points to convert
Returns
Value in [mm]

◆ convert_points_to_pixel()

static unsigned convert_points_to_pixel ( float  pts,
unsigned  resolution 
)
static

Convert Postscript Points (1/72 inch) to dots at the given resolution

Parameters
[in]ptsPostscript Points to convert
[in]resolutionDots Per Inch (DPI)
Returns
Dot count

◆ cups_message_print()

void cups_message_print ( const char *  level,
const char *  scope,
const char *  fn,
int  ln,
const char *  format,
  ... 
)

State/error/warning/info reporting function

Parameters
[in]levelVerbosity level of this message
[in]scopeThe message's scope, like it's package name
[in]fnName of the function, this output is from
[in]lnLine number this call is from
[in]formatThe format string. Refer the printf() manual for further details
Note
Do not use this function directly. You should always use the convenience macros caps_print_* instead.

◆ cups_ql_driver_init()

int cups_ql_driver_init ( struct qldriver ql)

Init required information about the printer device

Parameters
[in]qlFull job description
Return values
0On success (currently always)

◆ cups_ql_input_raster_check()

static int cups_ql_input_raster_check ( struct qldriver ql)
static

Basic check if the given raster file matches the printer

Parameters
[in]qlFull job description
Return values
0On success

All these Annoying Warnings should'n occur. If they do, the used PPD is broken.

Precondition
The raster header is valid

For the records (Infos from some "spec-ppd.html" web site):

  • AdvanceDistance: Specifies the number of points to advance roll media after printing.
  • AdvanceMedia: Specifies when to advance the media: 0 = never, 1 = after the file, 2 = after the job, 3 = after the set, and 4 = after the page.
  • CutMedia: Specifies when to cut the media: 0 = never, 1 = after the file, 2 = after the job, 3 = after the set, and 4 = after the page.

◆ cups_ql_input_raster_warn()

static void cups_ql_input_raster_warn ( struct qldriver ql)
static

Warn about an annoying behaviour of pdftopdf and pdftoraster

Parameters
[in]qlFull job description
Attention
pdftopdf tends to apply annoying rotations to your document. If your document is oriented in landscape and would fit to a continuous length label, pdftopdf will rotate your document, because the continuous length label looks like a portrait oriented label to it (for example DK2215: 62 mm width and 1000 mm length). Using the pdfAutoRotate=off print parameter solves this issue.
pdftoraster tends to ignore the PageSize printing parameter and creates an inappropriate raster instead. For example, if your document is a 62 mm x 29 mm landscape oriented label and you want to print it on a continuous length label like the DK2251 roll is, it prefers the DK1209 portrait label roll instead. And creates the raster for it, which isn't what you expect.

◆ cups_ql_job_check_colour()

static int cups_ql_job_check_colour ( struct qldriver ql)
static

Get the raster's colour space and check if it can be printed on this printer and medium

Parameters
[in]qlFull job description
Return values
0On success
-EINVALUnsupported colour format (due to wrong medium or wrong device)
Note
Must be called on every single page (e.g. on each raster header read)
Precondition
A raster header must already be read.

◆ cups_ql_job_print()

int cups_ql_job_print ( struct qldriver ql)

CUPS specific document print routine

Parameters
[in]qlFull job description
Return values
0On success
-EINVALUnsupported raster input format

This function prepares the print. E.g. configure the printer according to the given CUPS raster format.

We need to check the raster header in order to have an idea, what has to be printed (monochrome versus bi-colour). We can check the medium size versus the raster size here to be able to print something.

The routine loops through all pages inside the CUPS raster file and calls the corresponding encoding routine to do the job.

Note
On a termination request we rely on the specific encoding function (cups_ql_colour_page_print() or cups_ql_monochome_page_print()) to return with -ECANCELED, because the routine itself knows how to terminate the print at the printer's side as well
Precondition
All pages in the raster file use the same colour format (e.g. no RGB/grey mix)

◆ cups_ql_medium_detect()

static int cups_ql_medium_detect ( struct qldriver ql)
static

Update the media dependent base settings according to the PPD information

Parameters
[in]qlFull job description
Return values
0On success
-EINVALUnsupported DK roll
Attention
The media_height value can be very large for continuous length tapes!
Note
Can be called prior reading the first raster header
Todo:
Can be called in cups_ql_driver_init() as well

◆ cups_ql_medium_guess()

static int cups_ql_medium_guess ( struct qldriver ql)
static

Guess the medium parameters.

Parameters
[in]qlFull job description
Return values
0On success

In the absence of a DefaultPageSize (to make the other stages work as expected) we still need some information about the medium. Guess it instead based on the given CUPS raster. Hopefully the user knows what he does. Famous last words...

In this case we:

  • expect a continuous length medium
  • we expect a bi-colour medium, if the raster is coloured
  • left margin set to the one for full width medium
Precondition
The header of the CUPS raster must be valid

◆ cups_ql_medium_size_quirk()

static void cups_ql_medium_size_quirk ( struct qldriver ql)
static

Add a quirk to guess the size of the used medium based on the CUPS raster

Parameters
[in,out]qlFull job description

While testing the driver and the CUPS framework, some strange things happened in the printer chain. This quirk was a try to check if it is possible to print from applications to a continuous length medium. Result: no it isn't.

Refer Trouble Shooting for details.

◆ cups_ql_next_line_read()

int cups_ql_next_line_read ( struct qldriver ql,
size_t  sz,
unsigned char  buf[sz] 
)

Read in the next line from the CUPS raster

Parameters
[in,out]qlFull job description
[in]szSize of bytes buf points to
[out]bufWhere to store the raster data
Return values
0On success
-ENODATAMature end of CUPS raster input data

◆ cups_ql_raster_header_read()

int cups_ql_raster_header_read ( struct qldriver ql)

Read in the next header from the CUPS raster file

Parameters
[in,out]qlFull job description
Return values
numberHeader bytes read
0on EOF, negative value on failure, 'errno' is valid in this case

◆ cups_ql_raster_lines_skip()

static int cups_ql_raster_lines_skip ( struct qldriver ql,
unsigned  lines,
size_t  cnt 
)
static

Skip some amount of raster lines

Parameters
[in]qlFull job description
[in]linesHow many lines to skip
[in]cntCount of bytes per line
Return values
0On success
-ENODATAMature end of CUPS raster input data

◆ halftone_type_init()

static void halftone_type_init ( struct qldriver ql)
static

Setup the halftone method for this job

Parameters
[in]qlFull job description

If no defintion is found, it falls back to HT_NONE

Note
If the definition is bad/invalid, this function does not return.

◆ high_resoultion_setup()

static void high_resoultion_setup ( struct qldriver ql)
static

Setup the printer's high resolution capabilities

Parameters
[in]qlFull job description
Todo:
This function still needs to be implemented

◆ leading_bytes_setup()

static void leading_bytes_setup ( struct qldriver ql)
static

Read in the amount of leading zero bytes

Parameters
[in]qlFull job description

Various printer variants define a different amount of zero bytes leading a printing job. QL500 defines 200 bytes, QL650 defines 350 bytes and a QL800 defines 400 bytes.

◆ margin_setup()

static void margin_setup ( struct qldriver ql)
static

The printers have some margin requirements at top and bottom of a label for continuous length label

Parameters
[in]qlFull job description

These defines only the min and max hardware margins. It is (theoretical) up to the user, to define these margins with each job. It is some kind of micro optimization, because it safes bytes to be sent to the printer if the marging should be larger than the minimum of 3 mm. But I think it is more relevant to make use of this hardware feature for (slow) serial interfaces, than for USB.

So, I think it is easier to setup a specific margin at the top and bottom of the document which extends the 3mm hardware margins by the cost of sending empty lines to the printer to keep these lines empty. Advantage of this approach is both margins can be different. With the hardware solution the top and bottom margins are always the same.

Todo:
Integrate the 3 mm top/bottom margins into the continuous length paper definition?

◆ number_convert()

static int number_convert ( const char *  string)
static

Convert a positive ASCII number ('\0' terminated) into a positive integer

Parameters
[in]stringThe string toconvert
Return values
PositiveThe converted ASCII string
-EINVALString has more characters than a signed int can fit
-EINVALstring seems not contain an ASCII number
-ERANGEASCII number is larger than a signed int
Note
This is more or less a copy of caps_helper_number_convert()

◆ printer_type_init()

static int printer_type_init ( struct qldriver ql)
static

Read in printer type

Parameters
[in]qlFull job description

This information is very important, since various printer variants interprete the same command in a different manner. Some routines rely on this printer type number to do the right things.

◆ ql_printer_data_send()

int ql_printer_data_send ( struct qldriver ql,
const void *  data,
size_t  count,
int  flush 
)

Send data to the printer's stream

Parameters
[in,out]qlFull job description
[in]dataPointer to the to be sent data
[in]countCount of bytes data points to
[in]flush'1' if the stream should be flushed
Return values
0On success
NegativeERRNO from fwrite() call

◆ ql_raster_limits_get()

int ql_raster_limits_get ( struct qldriver ql)
Precondition
The CUPS raster header info must be valid, e.g. cups_ql_raster_header_read() already called
Note
CUPS specific adaption

◆ red_detection_higher_angle()

static void red_detection_higher_angle ( struct qldriver ql)
static

Read in the higher angle to detect a red dot from the PPD

Parameters
[in]qlFull job description

An angle below this value will be dropped

Note
Refer Bi-coloured print for details

◆ red_detection_init()

static void red_detection_init ( struct qldriver ql)
static

Read in the required valued to detect red dots in a CUPS raster

Parameters
[in]qlFull job description
Note
Refer Bi-coloured print for details

◆ red_detection_lower_angle()

static void red_detection_lower_angle ( struct qldriver ql)
static

Read in the lower angle to detect a red dot from the PPD

Parameters
[in]qlFull job description

An angle above this value will be dropped

Note
Refer Bi-coloured print for details

◆ red_detection_lower_saturation()

static void red_detection_lower_saturation ( struct qldriver ql)
static

Read the lower saturation to detect a red dot from the PPD

Parameters
[in]qlFull job description

If the angle defines a red, a saturation below this value will be dropped.

Note
Refer Bi-coloured print for details

◆ red_detection_lower_value()

static void red_detection_lower_value ( struct qldriver ql)
static

Read the lower value to detect a red dot from the PPD

Parameters
[in]qlFull job description

If the angle defines a red, a saturation below this value will be dropped.

Note
Refer Bi-coloured print for details

Variable Documentation

◆ terminate

int terminate

Change to '1' to signal the program should stop