CAPS Universe documentation  1.0.4
All you need to know to be successful
Macros | Functions
encode_method_1030.c File Reference

Implementation of the '1030' encoding mode used by Brother printers. More...

Macros

#define pDEBUG(x, ...)
 
#define WHITE_BYTE   0x00
 

Functions

static void hl_c1030_line_append (struct cm1030_line *c, uint8_t byte)
 
static void hl_c1030_line_mark_empty (struct cm1030_line *c)
 
static void hl_c1030_line_mark_equal (struct cm1030_line *c)
 
static void hl_c1030_overflow_append (struct cm1030_line *c, unsigned value)
 
static void hl_c1030_repeat_edit_append (struct cm1030_line *c, unsigned offset, unsigned count, uint8_t pattern)
 
static void hl_c1030_substitute_edit_append (struct cm1030_line *c, unsigned offset, unsigned count, const uint8_t pattern[count])
 
static bool hl_c1030_line_check_if_empty (size_t cnt, const uint8_t line[cnt])
 
static ssize_t hl_c1030_edit_find_next_with_ref (size_t cnt, const uint8_t line[cnt], const uint8_t reference[cnt])
 
static ssize_t hl_c1030_edit_find_next (size_t cnt, const uint8_t line[cnt])
 
static size_t hl_c1030_line_shorten (size_t cnt, const uint8_t line[cnt], const uint8_t last[cnt])
 
void hl_c1030_line_edit (struct cm1030_line *c, size_t cnt, const uint8_t line[cnt], const uint8_t *last)
 
int hl_c1030_block_flush (struct cm1030_band *block, FILE *outstream)
 
int hl_c1030_block_line_add (struct cm1030_band *block, const struct cm1030_line *line, FILE *outstream)
 
int hl_c1030_block_pad (struct cm1030_band *block, unsigned missing_line_cnt, FILE *outstream)
 
void hl_c1030_block_init (struct cm1030_band *block)
 
void hl_c1030_block_exit (struct cm1030_band *block)
 

Detailed Description

Read the corresponding header file for further information about this encoding method.

The printer wants the data to be print as:

If the input data doesn't match the printer's data polarity, set the WHITE_BYTE to 0xFF instead.

Macro Definition Documentation

◆ pDEBUG

#define pDEBUG (   x,
  ... 
)

◆ WHITE_BYTE

#define WHITE_BYTE   0x00

Define the byte value of eight white dots (e.g. not to print)

Function Documentation

◆ hl_c1030_line_append()

static void hl_c1030_line_append ( struct cm1030_line c,
uint8_t  byte 
)
static

Append a single byte to the end of the line data buffer

Parameters
[in,out]cCompression output buffer
[in]byteThe byte to append to the end of the line data buffer

◆ hl_c1030_line_mark_empty()

static void hl_c1030_line_mark_empty ( struct cm1030_line c)
static

Mark the current line as empty

Parameters
[in,out]cCompression output buffer

This is one of two special cases: the complete line is empty (e.g. nothing to print) and thus, needs only a single byte as a marker. This single byte is 0xff (C1030_LINE_IS_EMPTY).

◆ hl_c1030_line_mark_equal()

static void hl_c1030_line_mark_equal ( struct cm1030_line c)
static

Mark the current line as equal to the previous one

Parameters
[in,out]cCompression output buffer

This is one of two special cases: the complete line is equal to the previous one and thus, needs only a single byte as a marker. This single byte is 0x00 (C1030_LINE_IS_EQUAL).

◆ hl_c1030_overflow_append()

static void hl_c1030_overflow_append ( struct cm1030_line c,
unsigned  value 
)
static

Append an overflow value to the line buffer

Parameters
[in,out]cCompression output buffer
[in]valueOverflow value

An overflow value is a value which is larger then the first byte in the 'edit' can include. An overflow value is encoded into a sequence of bytes. A byte of 0xff signals more bytes follows. The sequence terminates if a byte less than 0xff is found.

E.g.:

   value = 0 -> <0x00>
   value = 10 -> <0x0a>
   value = 255 -> <0xff> <0x00>
   value = 256 -> <0xff> <0x01>
   value = 512 -> <0xff> <0xff> <0x02>

This overflow value is used to form the 'offset' and 'count' values in the 'edits'

Precondition
The value encoded in the first byte must already be substracted!

◆ hl_c1030_repeat_edit_append()

static void hl_c1030_repeat_edit_append ( struct cm1030_line c,
unsigned  offset,
unsigned  count,
uint8_t  pattern 
)
static

Append a repeating pattern edit to the line data buffer

Parameters
[in,out]cCompression output buffer
[in]offsetOffset where to begin to write the pattern to (relativ to the last 'edit' entrie's result)
[in]countHow often the pattern should be repeated
[in]patternThe pattern to repeat

A repeating pattern delta looks like this:

 7654 3210 [[offset overflow][count overflow]] pattern-byte
 1ooc cccc
    ^_^^^^_ (Part of) 'count'
  ^^_______ (Part of) 'offset'
Precondition
count must be at least 2 (due to encoding)

◆ hl_c1030_substitute_edit_append()

static void hl_c1030_substitute_edit_append ( struct cm1030_line c,
unsigned  offset,
unsigned  count,
const uint8_t  pattern[count] 
)
static

Append a substitute pattern edit to the line data buffer

Parameters
[in,out]cCompression output buffer
[in]offsetOffset where to begin to write the pattern to (relativ to the last 'edit' entrie's result)
[in]countHow often the pattern should be repeated
[in]patternThe pattern to substitute

A repeating pattern delta looks like this:

 7654 3210 [[offset overflow][count overflow]] pattern-byte…
 0ooo occc
       ^^^_ (Part of) 'count'
  ^^^_^____ (Part of) 'offset'
Precondition
count must be at least 1 (due to encoding)

◆ hl_c1030_line_check_if_empty()

static bool hl_c1030_line_check_if_empty ( size_t  cnt,
const uint8_t  line[cnt] 
)
static

Check if a line is empty, e.g. nothing to print

Parameters
[in]cntCount of bytes in *line
[in]lineThe line data to check
Return values
trueNothing to print
falseLine contains something to print

If all bits in the line are '0' the line has nothing to print and can be skipped instead. An empty line can be encoded with a single byte at the begin of the line data (0xff for the count of following 'edit' entries).

◆ hl_c1030_edit_find_next_with_ref()

static ssize_t hl_c1030_edit_find_next_with_ref ( size_t  cnt,
const uint8_t  line[cnt],
const uint8_t  reference[cnt] 
)
static

Find best method to edit the next bytes in the line buffer

Parameters
[in]cntRemaining bytes in line and reference
[in]lineWhere to start in the current line
[in]referenceWhere to start in the reference line
Return values
>0byte count to substitute
0nothing to be done
<0byte count to repeat (use as absolute :) )

Some constraints we must consider:

  • a repeating pattern makes sense only by at least 2 repeats
  • a substitution uses at least 1 byte, but in this case it expands to two bytes
Precondition
The bytes in *line and *reference are expected as different.
The right border should be already skipped if all bytes are blank.

◆ hl_c1030_edit_find_next()

static ssize_t hl_c1030_edit_find_next ( size_t  cnt,
const uint8_t  line[cnt] 
)
static

Find best method to compress the next bytes in the line buffer

Parameters
[in]cntRemaining bytes in line
[in]lineWhere to start in the current line
Return values
>0byte count to substitute
0nothing to be done
<0byte count to repeat (use as absolute :) )

Some constraints we must consider:

  • a repeating pattern makes sense only by at least 2 repeats
  • a substitution uses at least 1 byte, but in this case it expands to two bytes

◆ hl_c1030_line_shorten()

static size_t hl_c1030_line_shorten ( size_t  cnt,
const uint8_t  line[cnt],
const uint8_t  last[cnt] 
)
static

Trim the line to the active content

Parameters
[in]cntLength in bytes of line and last
[in]lineLine to shorten
[in]lastLast line as reference
Returns
Length in bytes of the active content

It makes no sense to search for 'edits' in the line if trailing bytes are the same than the previous line. To consider this case it complicates the algorithm. So, it is easier to trim the line prior beginning to search for 'edits' in it.

Here an example of a bad encoding:

 prev: …0xff 0xff 0xff 0xe0 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00…
 curr: …0xff 0xff 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00…
                  ^^^^_ from here on a (useless) substitute or repeat up to the end was encoded

By trimming the line to the active content, the line looks like this:

 prev: …0xff 0xff 0xff 0xe0
 curr: …0xff 0xff 0x00 0x00

…and the 'edit' encoding was really improved.

Precondition
The line must not be empty!
The line must not be equal to the previous one!

◆ hl_c1030_line_edit()

void hl_c1030_line_edit ( struct cm1030_line c,
size_t  cnt,
const uint8_t  line[cnt],
const uint8_t *  last 
)

Edit one full line as best as possible

Parameters
[in,out]cCompression output buffer
[in]cntCount of bytes with active pixel in both lines
[in]lineLine to achieve
[in]lastPrevious line (can be NULL)

This function creates all required 'edits' to form the current line inside the printer with the help/reference of the previous (and already existing inside the printer) line. It handles special cases, where the current line is empty (all pixel white) or where the current line is identical to the previous line. To avoid useless encodings (full substitute or repeat until the end) it then first shrinks the length of the line to the really required one (by comparing the current and previous line content) backwards from the end. And then starts the 'edit' based encoding.

If a line has no predecessor (e.g. last is NULL) the first approach was to encode it against an empty line. This seemed to solve some visual artefacts on the paper. But there are still some artefacts with vertical lines, where this approach fails. As a result, if there is no reference line the full line must be encoded.

◆ hl_c1030_block_flush()

int hl_c1030_block_flush ( struct cm1030_band band,
FILE *  outstream 
)

Flush out the current transfer block

Parameters
[in]bandBand info
[in,out]outstreamThe stream to send the printer data to
Return values
0On success
-errnoIf the data flushing to the printer has failed

This flushes the data out to the printer with a leading PCL command of the form:

  • 'band->bused_cnt' as an integer ASCII number (variable length)
  • the char 'w' (one byte)
  • 'band->blines' as a binary word in big endian (one word, e.g. two bytes)

...and then appends the corresponding dot data to it.

Note
'Flushing' here means only to write the accumulated line encoding data to the printer's stream. It doesn't mean, the printer receives this data immediately. The real stream flush should happen when processing of the current page finishes.
Precondition
Currently at most C1030_MAX_BYTES_IN_ONE_BLOCK should be in the buffer. More this function cannot handle.

◆ hl_c1030_block_line_add()

int hl_c1030_block_line_add ( struct cm1030_band block,
const struct cm1030_line line,
FILE *  outstream 
)

Add one line of dot data to the data block

Parameters
[in]blockThe data block to add the line to
[in]lineLine info
[in,out]outstreamThe stream to send the printer data to
Return values
0On success
-errnoIf the data flushing to the printer's stream has failed
-EAGAINAdd the line again, because the block was flushed

This function tries to add the given line data to the block data until the max block size limit of C1030_MAX_BYTES_IN_ONE_BLOCK is hit. If hit, it flushes the already accumulated band data into a valid transfer block of data via hl_c1030_block_flush().

Note
In case the already accumulated data hits the block size limit, the line gets ignored and must be added again.

◆ hl_c1030_block_pad()

int hl_c1030_block_pad ( struct cm1030_band block,
unsigned  missing_line_cnt,
FILE *  outstream 
)

Pad the current data block to the full band line count

Parameters
[in]blockCurrent block data info
[in]missing_line_cntLines to add to pad the current band
[in,out]outstreamThe stream to send the printer data to
Return values
0On success
-errnoIf the data flushing to the printer's stream has failed

The printer only prints in bands of n lines. Bands with less than these n lines are skipped entirely (and silently). This hurts at the bottom edge of a page, where the vertical dot count might not be a multiple of these n lines.

This function pads the current data block up to these n lines on demand with empty lines. It must be called once at the end of each page if you know your last band has less lines than these n lines.

Postcondition
A call to hl_c1030_block_flush()

◆ hl_c1030_block_init()

void hl_c1030_block_init ( struct cm1030_band block)

Init the printer data block as a preparation

Parameters
[in,out]blockPrinter data block info

◆ hl_c1030_block_exit()

void hl_c1030_block_exit ( struct cm1030_band block)

Free resources allocated when processing

Parameters
[in]blockPrinter data block info