Collection of macros and functions shared by all QLxxx printer drivers.
More...
Go to the source code of this file.
|
| static struct ql_drv * | to_ql_drv (void *d) |
| |
| void | sliding_halftone_get (struct halftone_converter *cnv) |
| |
| void | sliding_halftone_put (struct halftone_converter *cnv) |
| |
| void | halftone_line_no_dither (struct halftone_converter *cnv) |
| |
| void | halftone_line_ordered (struct halftone_converter *cnv) |
| |
| void | halftone_line_with_error_diffusion (struct halftone_converter *cnv) |
| |
| void | move_in_next_line (struct halftone_converter *cnv, const struct caps_dot_grey raw[cnv->pixel_count]) |
| |
| void | move_in_empty_line (struct halftone_converter *cnv, conv_type val) |
| |
| int | ql_dk_information_get (struct dk_roll_types *medium, const char *name) |
| |
| int | ql_reset (struct ql_drv *t) __wur |
| |
| int | ql_page_print (struct ql_drv *t) __wur |
| |
| int | ql_last_page_print (struct ql_drv *t) __wur |
| |
| int | ql_invalidate_and_initialize (struct ql_drv *t) __wur |
| |
| int | ql_status_request (struct ql_drv *t, unsigned char buffer[32]) __wur |
| |
| void | ql_driver_halftone_selection_setup (struct ql_drv *t, struct caps_ppd_base *base) |
| |
| void | ql_driver_power_selection_setup (struct ql_drv *t, struct caps_ppd_base *base) |
| |
| void | ql_driver_bi_colour_medium_selection_setup (struct ql_drv *t, struct caps_ppd_base *base) |
| |
| void | ql_driver_base_setup (struct ql_drv *t) |
| |
| int | ql_numerical_setting_read (struct ql_drv *t, const char *section, const char *keyword) |
| |
| int | ql_job_header_generate (struct ql_drv *t) |
| |
| int | ql_driver_send (struct ql_drv *t, size_t count, const void *data, int flush) __wur |
| |
| int | ql_driver_data_send (struct ql_drv *t, size_t count, const void *data, int flush) __wur |
| |
| void | ql_driver_raster_crop (struct ql_drv *t) |
| |
| int | ql_page_header_generate (struct ql_drv *t, int first_page) __wur |
| |
| int | ql_auto_powerdown (struct ql_drv *t, unsigned short time_out) __wur |
| |
| int | ql_auto_powerup (struct ql_drv *t, unsigned short mode) __wur |
| |
| static void | transform_to_monochrome (size_t input_cnt, const conv_type input[input_cnt], unsigned char *data) |
| |
| static unsigned | pts_to_pixel (double pts, unsigned resolution) |
| |
| static unsigned | mm_to_pixel (unsigned mm, unsigned resolution) |
| |
| static double | pts_to_mm (double pts) |
| |
| static double | mm_to_pts (double mm) |
| |
| static double | pixel_to_mm (unsigned pixel, unsigned resolution) |
| |
| enum ql_half_tone | ql_driver_job_halftone_get (struct ql_drv *t) |
| |
| void | ql_driver_job_bi_colour_medium_get (struct ql_drv *t) |
| |
| int | ql_monochome_page_print (struct ql_drv *t) |
| |
- Copyright
- GNU General Public License 2 or later
- Author
- Jürgen Borleis
- Warning
- Use as experimental
◆ caps_print_debug
| #define caps_print_debug |
( |
|
fmt, |
|
|
|
... |
|
) |
| |
◆ ARRAY_SIZE
| #define ARRAY_SIZE |
( |
|
x | ) |
(sizeof(x)/sizeof(x[0])) |
◆ DOTS_TO_BYTES
| #define DOTS_TO_BYTES |
( |
|
x | ) |
((x + 7U) / 8U) |
Convert an amount of (monochrome) dots into its corresponding amount of bytes and round up
◆ DOTS_TO_WORDS
| #define DOTS_TO_WORDS |
( |
|
x | ) |
((x + 15U) / 16U) |
Convert an amount of (monochrome) dots into its corresponding amount of shorts and round up
◆ BIT
| #define BIT |
( |
|
x | ) |
(1 << (x)) |
Just a little helper to write more readable code
| #define _ |
( |
|
string | ) |
(string) |
◆ NLS_
| #define NLS_ |
( |
|
string | ) |
(string) |
◆ COLOUR_VAL_DARK
| #define COLOUR_VAL_DARK 0x00 |
Value of black. The minimal value of a byte
◆ COLOUR_VAL_BRIGHT
| #define COLOUR_VAL_BRIGHT 0xff |
Value of white. The maximal value of a byte
◆ PRINT_DOT_VAL
| #define PRINT_DOT_VAL 0x00 |
The value of a to be printed dot
◆ DEFAULT_QL_LINE_SIZE
| #define DEFAULT_QL_LINE_SIZE 90 |
The generic count of bytes of one line of these QL printers
- Note
- This is valid only for a couple types of these printers. It should be set in the PPD instead.
◆ QL_MEDIA_TYPE_CONTINUOUS
| #define QL_MEDIA_TYPE_CONTINUOUS 0xa |
◆ QL_MEDIA_TYPE_DIE_CUT
| #define QL_MEDIA_TYPE_DIE_CUT 0xb |
◆ QL_QUALITY_PRINT
| #define QL_QUALITY_PRINT 0x40 /* never use while bi-colour printing (according to the datasheet) */ |
◆ QL_FAST_PRINT
| #define QL_FAST_PRINT 0x00 /* always use with bi-colour printing (according to the datasheet) */ |
◆ QL_MAX_SELECTIONS
| #define QL_MAX_SELECTIONS 10 |
This is just a short-cut to simplify the addition of selections to the printer description
It is used to reserve a static selection table, which can be extended on demand at run-time.
◆ QL_FIRST_PAGE
◆ QL_NEXT_PAGE
◆ conv_type
◆ ql_half_tone
Half tone method to be used for the raster
| Enumerator |
|---|
| QL_UNKNOWN | not defined, or use some kind of default (let the user select one)
|
| QL_NONE | Don't use any kind of half tone method
|
| QL_ORDERED | Use an ordered half tone method
|
| QL_ERROR_DIFFUSION | Use the error diffusion half tone method (Floyd-Steinberg)
|
◆ dk_caps
| Enumerator |
|---|
| DK_CAP_UNKNOWN | |
| DK_CAP_CONTINUOUS | |
| DK_CAP_DIE_CUT | |
| DK_CAP_RED | additionally red colour possible
|
◆ to_ql_drv()
| static struct ql_drv * to_ql_drv |
( |
void * |
d | ) |
|
|
inlinestatic |
Convert the anonymous pointer from the libcapsdriver into our information collection
- Parameters
-
| [in] | d | Anonymous structure pointer |
- Returns
- Pointer to our struct ql_drv
◆ sliding_halftone_get()
Prepare the sliding line buffers
- Parameters
-
| [in,out] | cnv | The converter structure to initialiaize |
In order to run some kind of dithering we need signed values per pixel which must be larger than the incoming pixels data. Incoming pixels are of type 'unsigned char' with their grey values. Due to this conversion we do not need to honor any kind of saturation while calculating the dithered output.
- Note
- Does not return in case of memory failure
- Precondition
- halftone_converter::pixel_count must be already set and not '0'
◆ sliding_halftone_put()
Clean up image processing via sliding line buffers
- Parameters
-
| [in,out] | cnv | The converter structure to destroy |
◆ halftone_line_no_dither()
◆ halftone_line_ordered()
◆ halftone_line_with_error_diffusion()
◆ move_in_next_line()
Move in the next line with raw raster data into the process
- Parameters
-
| [in,out] | cnv | The converter structure to destroy |
| [in] | raw | Buffer with raw pixel data (grey scale) in bytes |
Throw away the content of the current top line, move all lines below one line up and fill the bottom line with new content from the given raw line.
Currently there are only two lines in the calculation buffer, so "moving" means "swapping" instead.
The byte based pixel data is copied into the sliding half tone structure and gets converted to signed short to be able run the half tone algorithm afterwards.
- Note
- In order to be able to calculate the bottom line of the image, you need to input an empty line instead. Empty means: it must contain a value, which isn't printed. Refer move_in_empty_line() for details
- Precondition
- raw must point to a buffer with halftone_converter::pixel_count bytes.
◆ move_in_empty_line()
Move in an empty line into the process
- Parameters
-
| [in,out] | cnv | The converter structure to use |
| [in] | val | 'Empty' value (0…255) |
'Empty' means val must have a value which should not print anything. For example COLOUR_VAL_BRIGHT.
◆ ql_dk_information_get()
| int ql_dk_information_get |
( |
struct dk_roll_types * |
medium, |
|
|
const char * |
name |
|
) |
| |
Retrieve settings/information about a specific DK roll/cassette
- Parameters
-
| [out] | medium | The settings for the DK roll named by name |
| [in] | name | The DK roll name the settings should be retrieved for |
- Return values
-
| 0 | On success, *medium is valid |
| -EINVAL | Roll with the given name not found |
DK rolls can inherit settings from other rolls. This routine walks through the table and uses the dk_roll_types::like member to re-use their settings.
◆ ql_reset()
| int ql_reset |
( |
struct ql_drv * |
t | ) |
|
Initialize/reset the printer
- Parameters
-
| [in] | t | Full job description |
- Return values
-
This command can also be used every time to terminate a current print
- Note
- To be sent once at the beginning of a print job (according to the manual)
◆ ql_page_print()
| int ql_page_print |
( |
struct ql_drv * |
t | ) |
|
Finish the current page
- Parameters
-
| [in] | t | Full job description |
- Return values
-
This code is to be sent after a page.
It seems, this command is only to be sent, if more than one page in one job should be printed. If the job contains only one page, the ql_last_page_print() is enough to do the right thing.
- Note
- To be sent at the end of a page's raster, if it isn't the last page to be print (according to the manual)
◆ ql_last_page_print()
| int ql_last_page_print |
( |
struct ql_drv * |
t | ) |
|
Finish the current print job
- Parameters
-
| [in] | t | Full job description |
- Return values
-
This code is to be sent after the last page to finish the whole print job.
- Note
- To be sent at the end of a page's raster, if it is the last page of the job (according to the manual)
◆ ql_invalidate_and_initialize()
| int ql_invalidate_and_initialize |
( |
struct ql_drv * |
t | ) |
|
Start a new print job from the printer's point of view
- Parameters
-
| [in] | t | Full job description |
- Return values
-
To be sent at the beginning of a new print job or if the current processing has to be stopped at the printer's side.
From the datasheet: "If data transmission is to be stopped midway, send
the “initialize” command after sending the “invalidate” command for the
appropriate number of bytes to return to the receiving state, where the print
buffer is cleared."
- Note
- invalidate means the specified amount of zero bytes
-
initialize means the *ESC,@* command in ql_reset()
-
To be sent once at the beginning of a print job (according to the manual)
◆ ql_status_request()
| int ql_status_request |
( |
struct ql_drv * |
t, |
|
|
unsigned char |
buffer[32] |
|
) |
| |
Request and read status from printer.
- Parameters
-
| [in] | t | Full job description |
| [out] | buffer | Storage for the 32 status bytes read from the printer |
- Return values
-
| 0 | Status read successfully |
| -ENODATA | No status information from the printer. buffer content is invalid |
| -ENODEV | If the printer is gone in the meanwhile. This is serious! |
| -errno | All error values from ql_driver_data_send(). They are serious! |
Some run-time experiences:
- the printer reports always the inserted cassette, even if the cover is opened (QL800 tested)
- if no cassette is inserted, it returns 0x00 as the 'media_type' and width and length as 0.
- whenever an error occur, the report is marked as an error report (field 'status_type')
- if the cover is closed but whithout an inserted cassette the report isn't marked as an error report
- it seems, the 'automatic status notification mode' works differently. At my side it didn't work at all
- Precondition
- Printer must be idle
◆ ql_driver_halftone_selection_setup()
Add the power feature control selections to the printer description based on INI settings
- Parameters
-
| [in] | t | Full job description |
| [in,out] | base | Add selections to this printer description on demand |
◆ ql_driver_power_selection_setup()
Add the power feature control selections to the printer description based on INI settings
- Parameters
-
| [in] | t | Full job description |
| [in,out] | base | Add selections to this printer description on demand |
Uses the INI boolean key powerctl in section [features] to setup a possible power setting of the printer. In this case, selections defining these features will be added to the printer description PPD.
◆ ql_driver_bi_colour_medium_selection_setup()
| void ql_driver_bi_colour_medium_selection_setup |
( |
struct ql_drv * |
t, |
|
|
struct caps_ppd_base * |
base |
|
) |
| |
Add bi-colour medium selection to the printer description based on INI settings
- Parameters
-
| [in] | t | Full job description |
| [in,out] | base | Add selections to this printer description on demand |
The bi-colour capability of the loaded cassette cannot be detected. It must be selected by the user. This function adds a corresponding selection to the printer description, if the printer has bi-colour capabilities.
- Precondition
- Printer's colour capabilities must be already set (by calling ql_driver_colour_from_INI() first)
◆ ql_driver_base_setup()
| void ql_driver_base_setup |
( |
struct ql_drv * |
t | ) |
|
Read in the main INI file settings for the driver
- Parameters
-
| [in] | t | Full job description |
◆ ql_numerical_setting_read()
| int ql_numerical_setting_read |
( |
struct ql_drv * |
t, |
|
|
const char * |
section, |
|
|
const char * |
keyword |
|
) |
| |
Helper to read in a positive integer INI setting
- Parameters
-
| [in,out] | t | Full job description |
| [in] | section | Name of the section, the setting should be read from |
| [in] | keyword | The keyword/setting to read in |
- Return values
-
| Positive | The setting read from the INI |
| -ENODATA | No setting found |
| -EINVAL | Setting found, but doesn't look like an ASCII number |
| -ERANGE | Setting contains an invalid number for an 'int' |
◆ ql_job_header_generate()
| int ql_job_header_generate |
( |
struct ql_drv * |
t | ) |
|
Send the heading commands to setup the printer prior a print job
- Parameters
-
| [in] | t | Full job description |
Called once per print job at the beginning
◆ ql_driver_send()
| int ql_driver_send |
( |
struct ql_drv * |
t, |
|
|
size_t |
count, |
|
|
const void * |
data, |
|
|
int |
flush |
|
) |
| |
Send some data to the printer's stream
- Parameters
-
| [in,out] | t | Full job description |
| [in] | count | Count of bytes data points to |
| [in] | data | Pointer to the to be sent data |
| [in] | flush | '1' if the stream should be flushed |
- Return values
-
| 0 | Data buffered (and send, if flush is nonzero) |
| -EINVAL | Printer device is unsuitable for writing |
| -EBADF | Really bad internal failure |
| -EFAULT | Really bad internal failure made by the caller |
| -EIO | Low-level I/O error |
- Note
- It seems to me, if this call returns with an error code the data wasn't sent.
◆ ql_driver_data_send()
| int ql_driver_data_send |
( |
struct ql_drv * |
t, |
|
|
size_t |
count, |
|
|
const void * |
data, |
|
|
int |
flush |
|
) |
| |
Send some data to the printer's stream or the development/debugging file
- Parameters
-
| [in,out] | t | Full job description |
| [in] | count | Count of bytes data points to |
| [in] | data | Pointer to the to be sent data |
| [in] | flush | '1' if the stream should be flushed |
- Return values
-
| 0 | Data buffered (and send, if flush is nonzero) |
| -EINVAL | Printer device is unsuitable for writing |
| -EBADF | Really bad internal failure |
| -EFAULT | Really bad internal failure made by the caller |
| -EIO | Low-level I/O error |
This sends the real printer data to the printer's stream like ql_driver_send() does, but of the debug option –writeto is in use, it writes it to the file instead.
This is for debugging/development purposes, to extract the generated wire data and check its content and format. It is required this way, since the driver depends on interactive data exchange with the printer and if something went wrong, there is no other easy to use chance to see the data in this case.
- Todo:
- Write a printer emulator instead.
◆ ql_driver_raster_crop()
| void ql_driver_raster_crop |
( |
struct ql_drv * |
t | ) |
|
Crop the input raster to meet the printer's expectations/requirements
- Parameters
-
| [in] | t | Full job description |
The printer device has some - hmm, lets it call - interesting requirements about the print data it accepts. Continuous labels are easy, but pre-cut labels aren't. In order to ensure the printer always cuts inbetween two pre-cut labels, we need to tweak the amount of lines to be print.
Read how_the_driver_deals_with_margins about details.
◆ ql_page_header_generate()
| int ql_page_header_generate |
( |
struct ql_drv * |
t, |
|
|
int |
first_page |
|
) |
| |
- Parameters
-
- Return values
-
| 0 | On success |
| -ENODEV | Device seems gone (e.g. channel to the next stage is gone) |
Called once per page at the beginning
- Note
- In case of -ENODEV it makes no sense trying to send any further data or commands
- Precondition
- The ql_job::trim member must be up to date, e.g. its content matches the current raster page header
- Todo:
Deal with QL_FAST_PRINT/QL_QUALITY_PRINT for monochrome use case
Do the QL_QUALITY_PRINT and QL_HIGH_RESOLUTION bits depend on each other?
Deal with auto cut setting and when to cut (and if the printer has a cutter). To make it simple: only "cut at end" and "cut each" should be supported
◆ ql_auto_powerdown()
| int ql_auto_powerdown |
( |
struct ql_drv * |
t, |
|
|
unsigned short |
time_out |
|
) |
| |
Set the printer's auto power down behaviour if it is idle
- Parameters
-
| [in] | t | Full job description |
| [in] | time_out | Time out when idle to enter power down mode |
time_out can be:
- 0x0000: disable auto power off
- 0x0001: auto power off after 10 minutes
- 0x0002: auto power off after 20 minutes
- 0x0003: auto power off after 30 minutes
- 0x0004: auto power off after 40 minutes
- 0x0005: auto power off after 50 minutes
- 0x0006: auto power off after 60 minutes
If the printer enters the power off mode, it disconnects itself from the USB and can be re-enabled only manually with its local power button. This is a really bad idea for remotly used printers.
- Note
- This command is reverse-engineered, it isn't listed in the programming manual
-
The big endian format for the subcommand's data (here
time_val) is guessed only. All other printer commands use little endian for multibyte parameter. So, the command's data might have a different format/content than listed here
◆ ql_auto_powerup()
| int ql_auto_powerup |
( |
struct ql_drv * |
t, |
|
|
unsigned short |
mode |
|
) |
| |
Set the printer's power up behaviour when connecting to external power
- Parameters
-
| [in] | t | Full job description |
| [in] | mode | Power On mode |
mode can be:
- 0x0000 Keep offline when connecting to external power
- 0x0001 Go online when connecting to external power
- Note
- This command is reverse-engineered, it isn't listed in the programming manual
-
The big endian format for the subcommand's data (here
mode) is guessed only. All other commands use little endian for multibyte parameter. So, the command's data might have a different format/content than listed here
◆ transform_to_monochrome()
| static void transform_to_monochrome |
( |
size_t |
input_cnt, |
|
|
const conv_type |
input[input_cnt], |
|
|
unsigned char * |
data |
|
) |
| |
|
inlinestatic |
Convert an array of signed shorts into a monochrome pattern (one conv_type into one bit)
- Parameters
-
| [in] | input_cnt | Count of pixel in input |
| [in] | input | Where to get the quantized input data from |
| [out] | data | Where to store the converted monochrome output data to |
Let the compiler optimize it when used.
- Note
- Since the printer prints from right to left, the input pattern gets mirrored(!) here. First pixel printed (at the right border) is the MSB of the first byte
- Precondition
- PRINT_DOT_VAL means: print a dot, everything else means: do not print a dot, e.g. the input data must already be quantized
-
input and data must point to different memories (no overlap, no side effects)
-
input_cnt must be a multiple of 8
◆ pts_to_pixel()
| static unsigned pts_to_pixel |
( |
double |
pts, |
|
|
unsigned |
resolution |
|
) |
| |
|
inlinestatic |
Convert Postscript [pts] (1/72 inch) to [dots] at the given resolution
- Parameters
-
| [in] | pts | Postscript Points to convert |
| [in] | resolution | Dots Per Inch (DPI) |
- Returns
- Dot count
◆ mm_to_pixel()
| static unsigned mm_to_pixel |
( |
unsigned |
mm, |
|
|
unsigned |
resolution |
|
) |
| |
|
inlinestatic |
Convert millimeter [mm] to [dots] at the given resolution
- Parameters
-
| [in] | mm | Millimeter to convert |
| [in] | resolution | Dots Per Inch (DPI) |
- Returns
- Dot count
◆ pts_to_mm()
| static double pts_to_mm |
( |
double |
pts | ) |
|
|
inlinestatic |
Convert Postscript [pts] (1/72 inch) to [mm]
- Parameters
-
| [in] | pts | Postscript Points to convert |
- Returns
- Value in [mm]
◆ mm_to_pts()
| static double mm_to_pts |
( |
double |
mm | ) |
|
|
inlinestatic |
Convert millimeter [mm] to points [pts]
- Parameters
-
| [in] | mm | Millimeter to convert |
- Returns
- Length in [pts]
◆ pixel_to_mm()
| static double pixel_to_mm |
( |
unsigned |
pixel, |
|
|
unsigned |
resolution |
|
) |
| |
|
inlinestatic |
Convert an amount of pixel at a specific resolution into [millimeter]
- Parameters
-
| [in] | pixel | Pixel count to convert |
| [in] | resolution | Dots Per Inch (DPI) |
- Returns
- Value in [mm]
◆ ql_driver_job_halftone_get()
◆ ql_driver_job_bi_colour_medium_get()
| void ql_driver_job_bi_colour_medium_get |
( |
struct ql_drv * |
t | ) |
|
Get the current job related selection for the bi-colour medium capabilities
- Parameters
-
| [in] | t | Full job description |
The bi-colour capability cannot be detected at runtime. So the user mus select it on a per job base to enable bi-colour print. This function checks the current selection and modifies ql_drv::bi_colour_medium_present accordingly.
◆ ql_monochome_page_print()
| int ql_monochome_page_print |
( |
struct ql_drv * |
t | ) |
|
Convert the current page into the printer's wire data format
- Parameters
-
| [in] | t | Full job description |
- Return values
-
| 0 | On success |
| -EINVAL | Unsupported raster input format |
| -ECANCELED | Termination request from outerspace |
The routine loops through all lines of the current page and converts them into the printer's monochrome wire format
- Note
- The ql_trim::top_keep amount of lines of the input raster is printed.
-
In case of an error or a termination request, the print job gets terminated at the printer's side as well.
- Precondition
- The format was already checked, e.g. it fits into the printer's media.