Custom Drawing Functions

Custom drawing lets an application receive the calculated barcode elements and render them with its own drawing or output functions. It is also the recommended method for special devices or output targets that cannot use a standard driver, such as laser marking equipment or OS/400 printers.

TBarCode Library supports two custom drawing methods. An application can either draw the individual barcode elements from their calculated positions and sizes, or process the barcode row by row as a metadata pattern.

Custom drawing callbacks require a valid TBarCode SDK Developer license and are disabled in the demo version. To evaluate them, request a temporary license key from support@tec-it.com. The How to License TBarCode SDK chapter describes how to apply a license.

Choosing a Custom Drawing Method

Method Recommended use
Individual barcode elements Preferred for new integrations and custom output routines that can draw bars, text, rings, hexagons, and colored elements from their calculated geometry
Metadata patterns Suitable for existing pattern-based integrations and devices that process a barcode as rows of modules, bars, and spaces

Common Calling Sequence

Use the following sequence for both custom drawing methods:

  1. Set all barcode properties and data, call BCCreate(), and continue only if it returns ErrOk.
  2. Register the required callbacks, for example with BCSetFuncDrawBar() or BCSetFuncDrawRow().
  3. Optionally use BCSetCBData() to make application-specific data available to the callbacks.
  4. Define the barcode bounding rectangle and call BCDrawCB().

Drawing Individual Barcode Elements

TBarCode Library calculates the position and size of each barcode element and passes this information to the registered callback. The application can then draw the element with its own graphics or output functions.

Register the callbacks required by the supported barcode types:

  • BCSetFuncDrawBar() handles normal bars, dots, and modules.
  • BCSetFuncDrawColoredBar() handles the colored Swiss cross in Swiss QR Code.
  • BCSetFuncDrawText() handles the human-readable text.
  • BCSetFuncDrawRing() handles MaxiCode finder rings.
  • BCSetFuncDrawHexagon() handles MaxiCode hexagons.

Register all callbacks needed for the barcode types and options used by the application. For example, an application that displays human-readable text must also provide a text callback.

C/C++ Sample: Receiving Individual Elements

The following example receives the position and size of every bar or module and writes the values to the console. Replace printf() with the drawing or output function required by the application. The example assumes that BCCreate(pBC) has already returned ErrOk.

#include <stdio.h>

ERRCODE CALLBACK PrintBarGeometry(
    VOID*, HDC, DOUBLE x, DOUBLE y, DOUBLE width, DOUBLE height)
{
    printf("Bar: x=%f, y=%f, width=%f, height=%f\n",
           x, y, width, height);
    return ErrOk;
}

ERRCODE RunElementCallbacks(t_BarCode* pBC)
{
    RECT rect = {0, 30000, 50000, 0}; // 50 x 30 mm
    ERRCODE eCode = BCSetFuncDrawBar(pBC, PrintBarGeometry);
    if (eCode != ErrOk)
        return eCode;

    return BCDrawCB(pBC, NULL, &rect);
}

Processing Barcode Rows as Metadata Patterns

Use BCSetFuncDrawRow() when the output target processes a barcode as rows of modules, bars, and spaces. The row callback is invoked once for each barcode row. Call BCGetMetaData() inside that callback to read the current row pattern. The metadata is valid only during the callback.

C/C++ Sample: Reading Row Patterns

The following example reads and prints each metadata pattern while its row callback is running. It assumes that BCCreate(pBC) has already returned ErrOk.

#include <stdio.h>

ERRCODE CALLBACK PrintRowPattern(
    VOID*, t_BarCode* pBC, HDC, HDC,
    DOUBLE, DOUBLE, DOUBLE, DOUBLE)
{
    LPCSTR pattern = BCGetMetaData(pBC);
    if (pattern != NULL)
        printf("%s\n", pattern);
    return ErrOk;
}

ERRCODE RunRowCallback(t_BarCode* pBC)
{
    RECT rect = {0, 30000, 50000, 0}; // 50 x 30 mm
    ERRCODE eCode = BCSetFuncDrawRow(pBC, PrintRowPattern);
    if (eCode != ErrOk)
        return eCode;

    return BCDrawCB(pBC, NULL, &rect);
}

Metadata Pattern Format

TBarCode Library represents a barcode as a device-independent metadata pattern that specifies where to draw bars and spaces.

The pattern uses uppercase and lowercase letters:

  • Uppercase letters represent bars or dots.
  • Lowercase letters represent spaces.
  • The letter itself (A, B, C, and so on) specifies the width of the bar or space.

In this chapter, X denotes the module width. For linear barcodes, it is the width of the narrowest bar or space. For matrix codes, it is the width and height of one module.

Linear and Stacked Barcodes (e.g., PDF417)

For barcodes that use multiple bar or space widths, the callback receives different uppercase or lowercase letters. Each letter corresponds to an entry in the current print ratio. The following table uses 1:2:3:4 as an example.

Width factor Bar Space Actual width
1 A a 1 x X
2 B b 2 x X
3 C c 3 x X
4 D d 4 x X

The actual width factors depend on the current print ratio. If a print ratio defines additional factors, the pattern continues with E and e and the following letters.

Each barcode symbology has a predefined print ratio, which the user can adjust. Code 39, for example, uses 1:3:1:3:

  • A: 1 x X
  • B: 3 x X
  • a: 1 x X
  • b: 3 x X

Use BCGetRatioString, BCGetRatioHint, BCGetCountBars, and BCGetCountSpaces to query the ratio and the number of bar and space widths for a symbology.

2D Matrix Codes (Data Matrix, QR Code®, Aztec Code, etc.)

Two-dimensional matrix codes consist of several rows. TBarCode Library passes the pattern for each row separately to the registered row callback, which draws that barcode row.

The row pattern uses uppercase letters for black modules and lowercase letters for white modules. A represents a black module, and a represents a white module.

Metadata pattern for a Data Matrix symbol

The example shows Data Matrix. QR Code and Aztec Code use the same pattern principle.

About Drawing

The pattern contains no absolute sizes. Matrix modules represented by A and a have the same width and height, X. Adjust X to the dot or pixel size of the target device to minimize printing tolerances.

Postal Codes with Bars of Different Height

Unlike other linear barcodes, many postal symbologies use bars of different heights rather than bars of different widths. The callback receives digits instead of letters.

Each digit represents one bar followed by one space. All bars and spaces have a width of 1 x X, but the bar heights differ. Depending on the symbology, the pattern contains two, three, or four different digits.

Barcodes with Two Different Heights

These barcodes use long and short bars with the same baseline. Both grow upwards:

  • 0: long bar
  • 1: short bar

US Postal pattern with long and short bars

Barcodes with Three Different Heights

These barcodes use full-height bars and short bars that grow either downwards from the top or upwards from the baseline:

  • 0: full-height bar
  • 1: short bar growing downwards
  • 2: short bar growing upwards

Pharmacode Two-Track pattern with three bar heights

Barcodes with Four Different Heights

These barcodes use full-height bars, ascenders, descenders, and centered tracker bars:

  • 0: full-height bar (Full)
  • 1: medium bar growing downwards (Ascender)
  • 2: medium bar growing upwards (Descender)
  • 3: short centered bar (Tracker)

Australian Postal pattern with four bar heights

About Drawing

The pattern contains no absolute sizes. A bar is defined by its height and its distance from the upper edge, both expressed as percentages of a full-height bar. Each table entry lists height / distance from upper edge.

Barcode types Digit 0 Digit 1 Digit 2 Digit 3
US Postal, CEPNet, Planet 100% / 0% 38.5% / 61.5% - -
Pharmacode Two-Track 100% / 0% 50% / 50% 50% / 0% -
Australian Postal 100% / 0% 62% / 0% 62% / 38% 24% / 38%
Royal Mail 4-State, KIX 100% / 0% 62.5% / 0% 62.5% / 37.5% 25% / 37.5%
Intelligent Mail® Barcode, DAFT, Japanese Postal 100% / 0% 66.7% / 0% 66.7% / 33.3% 33.3% / 33.3%
Drawing Barcodes with Multiple Heights

Control Patterns

In addition to letters and digits, a metadata pattern can contain control bytes.

Protruding Bars for EAN and UPC Codes

Control byte Hexadecimal Meaning
254 0xFE Begin a section with long, protruding bars
255 0xFF End the section with protruding bars
253 0xFD Begin an add-on section that continues to the end of the symbol

EAN-8, EAN-13, UPC-A, and UPC-E contain protruding bars at the beginning, middle, and end of the symbol. Control byte 254 begins a protruding-bar section; control byte 255 ends it. The following bars use their normal height. Protruding bars extend downwards by approximately half the height of the human-readable text. By default, TBarCode Library determines the additional length automatically. Use BCSetNotchHeight() (Notch Height) to adjust this length.

Control byte 253 begins an add-on section. Add-on bars leave space for the text above the symbol and align at the bottom with the protruding bars.

EAN-8 symbol with a five-digit add-on

Incrementing and Decrementing Bar Width for EAN and UPC Codes

Control byte Hexadecimal Meaning
252 0xFC Begin bar-width increment
251 0xFB End bar-width increment
250 0xFA Begin bar-width decrement
249 0xF9 End bar-width decrement

EAN and UPC specifications require some bars to be wider and others to be narrower. The control bytes above mark the corresponding sections in the metadata pattern.

See the applicable EAN or UPC specification for details.

Search documentation

Search in
More scopes
Additional scopes

All contents