flutter_zpl_generator 2.0.0 copy "flutter_zpl_generator: ^2.0.0" to clipboard
flutter_zpl_generator: ^2.0.0 copied to clipboard

A comprehensive Flutter package for generating ZPL (Zebra Programming Language) labels with Labelary API integration and live preview capabilities.

Flutter ZPL Generator #

A comprehensive Flutter package for generating ZPL (Zebra Programming Language) labels with industry-first TTF font conversion, automatic image-to-ZPL conversion capabilities, and a mathematically robust 12-column grid layout engine.

pub package popularity likes


📑 Table of Contents #

  1. Component Demos & Previews
  2. What Makes This Package Special
  3. Quick Start
  4. The Layout Engine (Visuals)
  5. Images & Fonts
  6. The Data Engine
  7. Hardware & Enterprise Control
  8. Developer Experience & Examples
  9. Related Projects

📸 Component Demos & Previews #

The library boasts an unparalleled set of components, beautifully simulated inside Flutter using the ZplPreview widget via the Labelary REST API:

Text & Fonts Barcodes & Data Matrix
Graphics & Shapes Responsive 12-Unit Grid Layout
Image Dithering Algorithms

🌟 What Makes This Package Special #

📐 Robust Native Layout Architecture #

  • ZplGridRow & ZplGridCol: Build complex receipt layouts utilizing a proportional 12-unit grid container with offset spacing capabilities instead of brittle raw ^FO (Field Origin) numbers.
  • Natural Configuration Flow: ZplConfiguration propagates correctly down to children natively, accurately calculating ZplAlignment.right or ZplAlignment.center based on printWidth.

🔤 TTF to ZPL Font Conversion (First in Flutter!) #

  • Convert any TrueType font to ZPL format and upload custom fonts directly to your Zebra printer's memory.
  • Use your brand fonts in labels for perfect consistency!
  • No more limitations to basic printer fonts.

💯 Unrivaled ZPL Component Coverage #

  • Included shapes: ZplBox, ZplGraphicCircle (^GC), ZplGraphicEllipse (^GE), ZplGraphicDiagonalLine (^GD).
  • Reverse Print Support (^FR): Easily achieve stunning white-on-black UI elements utilizing reversePrint: true.
  • Native Support for DataMatrix (^BX), EAN-13 (^BE), UPC-A (^BU), Code 128 (^BC), Code 39 (^B3), and QR Codes (^BQ).
  • ZplRaw Support: An escape hatch that lets you cleanly inject highly specific/legacy raw strings (e.g., ^MD darkness or RFID triggers).

🖼️ Live Flutter Preview #

  • The ZplPreview widget hooks up directly to Labelary endpoints recursively respecting the generator state for immediate real-time feedback visually in Flutter while you code.
  • Alternatively, you can run the ZplNativePreview widget which operates completely 100% offline leveraging CustomPainter to natively reconstruct elements!

Important Disclosure: The native preview (ZplNativePreview) provides a highly performant offline UI mapping capability. However, ZPL is ultimately a hardware execution language. Thus, while it maps boundaries correctly, it will incredibly rarely map 100% visually identically to the final printer firmware output due to nuances in built-in Zebra TTF rendering logic, line kerning, dot inflation, and physical ribbon tracking.


🚀 Quick Start #

Basic Label Generation #

import 'package:flutter_zpl_generator/flutter_zpl_generator.dart';

// Create ZPL commands and pass the configuration natively
final generator = ZplGenerator(
  config: const ZplConfiguration(
    printWidth: 406, // 2 inches at 203 DPI
    labelLength: 203, // 1 inch at 203 DPI
    printDensity: ZplPrintDensity.d8, // 8 dpmm / 203 DPI
  ),
  commands: [
    // Simple text handling
    ZplText(x: 20, y: 20, text: 'Hello World!'),
    
    // Barcode Support
    ZplBarcode(
      x: 20, y: 60, 
      height: 50, 
      data: '12345',
      type: ZplBarcodeType.code128,
      printInterpretationLine: true,
    ),
  ],
);

// Generate ZPL string 
// (Async required if parsing external images or TTF fonts!)
final zplString = await generator.build();
print(zplString);
// Output: ^XA^LL203^PR8^JMB^FO20,20^A0N,,...^XZ

🏗️ The Layout Engine (Visuals) #

A massive advantage over writing raw strings is abstracting raw X/Y origins via container-based bounds checks.

The 12-Unit Grid (ZplGridRow) #

Create responsive horizontal layouts easily without manually calculating X-offsets.

ZplGridRow(
  y: 355,
  children: [
    ZplGridCol(
      width: 6, // 50% width bounds
      offset: 0,
      child: ZplText(text: 'LEFT COLUMN', alignment: ZplAlignment.left),
    ),
    ZplGridCol(
      width: 6, // 50% width bounds
      child: ZplText(text: 'RIGHT COLUMN', alignment: ZplAlignment.right),
    ),
  ],
)

Advanced Tabular Data (ZplTable) #

ZplTable(
  y: 780,
  columnWidths: [5, 2, 2, 3], // The 12-unit layout
  borderThickness: 2,
  cellPadding: 6,
  headers: [
    ZplTableHeader('Product', alignment: ZplAlignment.left),
    ZplTableHeader('Qty', alignment: ZplAlignment.center),
    ZplTableHeader('Price', alignment: ZplAlignment.right),
  ],
  data: [
    ['Widget Pro', '2', '\$15.00'],
    ['Gadget XL', '1', '\$42.50'],
  ],
)

Graphic Shapes & Escapes #

// Shapes
ZplGraphicCircle(x: 20, y: 310, diameter: 100, borderThickness: 2)
ZplGraphicEllipse(x: 260, y: 485, width: 80, height: 100, borderThickness: 2)

// Diagonal Lines
ZplGraphicDiagonalLine(
  x: 20, y: 665,
  width: 150, height: 120,
  borderThickness: 3, orientation: 'R', // Or 'L'
)

// Inverted Reverse Print (White Text, Black box)
ZplBox(x: 20, y: 620, width: 772, height: 50, borderThickness: 50)
ZplText(
  x: 20, y: 630,
  text: 'WHITE ON BLACK',
  reversePrint: true, // Output ^FR
)

// The Raw Escape Hatch
ZplRaw(command: '^FO20,880^A0N,24,20^FDInject anything directly!^FS')

Conditional Printing (ZplConditional) #

Sometimes you want to show or hide entire layout sections natively based on condition flags (e.g. hasDiscount, showSerialNumber).

Instead of writing messy ternary operators inside Dart lists if (true) myObj,, we've introduced ZplConditional mapping. If condition: false, it safely outputs an empty string, and gracefully returns 0 layout height so surrounding containers like ZplColumn immediately collapse the missing element without rendering any blank gaps!

final generator = ZplGenerator(
  commands: [
    ZplText(text: 'Product: Widget'),
    ZplConditional(
      condition: product.hasDiscount, // If false, the below command is skipped AND collapses safely in columns
      child: ZplText(text: 'SALE: \${product.discount}% OFF', reversePrint: true),
    ),
    ZplBarcode(data: product.sku, type: ZplBarcodeType.code128),
  ],
)

🎨 Images & Fonts #

Convert Images to ZPL Graphics #

Transform any image (PNG, JPEG, GIF) into ZPL graphics that can be embedded directly in your labels:

// Convert to ZPL graphics
final zplGraphics = await LabelaryService.convertImageToGraphic(
  imageBytes,
  'logo.png',
  outputFormat: LabelaryGraphicOutputFormat.zpl,
  blackThreshold: 128 // Auto-Dithering
);

Advanced Image Dithering (Pristine Graphics) #

v2.0 splits image commands into three explicit shapes. Use ZplImageDownload + ZplImageRecall for the Link-OS-safe flow (~DG before ^XA, ^XG inside). All three dithering algorithms are supported on the ZplImageDownload.

// v2.0 Link-OS-safe: download pre-^XA, recall in-format.
commands: [
  ZplImageDownload(
    image: bytes,
    graphicName: 'LOGO_FS',
    ditheringAlgorithm: ZplDitheringAlgorithm.floydSteinberg,
  ),
  const ZplImageRecall(x: 20, y: 20, graphicName: 'LOGO_FS'),

  ZplImageDownload(
    image: bytes,
    graphicName: 'LOGO_ATK',
    ditheringAlgorithm: ZplDitheringAlgorithm.atkinson,
  ),
  const ZplImageRecall(x: 20, y: 150, graphicName: 'LOGO_ATK'),

  ZplImageDownload(
    image: bytes,
    graphicName: 'LOGO_THR',
    ditheringAlgorithm: ZplDitheringAlgorithm.threshold,
  ),
  const ZplImageRecall(x: 20, y: 280, graphicName: 'LOGO_THR'),
]

Use autoLabelLengthFromFirstImage: true on ZplGenerator to auto-emit ^LL equal to the first download's rendered height.

ACS Image Compression (^GFA, one-shot desktop firmware) #

For desktop / stationary firmware and single-use images, ZplImageInline emits ^FO + ^GFA inside the format with ACS run-length encoding (~60-90% smaller wire). Not recommended on Link-OS mobile; see doc/mobile-printer-guide.md.

commands: [
  ZplImageInline(
    x: 20, y: 20,
    image: highResPhotoBytes, // emits ^GFA with ACS body
  ),
]

Import Custom Fonts to Your Printer #

Upload TrueType fonts to the printer's memory via the control-phase ZplFontUpload. Reference the font on any ZplText via customFont:.

import 'package:flutter_zpl_generator/flutter_zpl_generator.dart';

// Load the TTF once.
final roboto = await ZplFontUpload.fromAsset(
  'assets/fonts/Roboto-Regular.ttf',
  'R', // single letter identifier
);

final generator = ZplGenerator(
  config: const ZplConfiguration(printWidth: 406, labelLength: 609),
  commands: [
    roboto, // ~DY upload emitted BEFORE ^XA
    ZplText(
      x: 50, y: 100,
      text: 'Custom Font Text!',
      customFont: roboto,
      fontHeight: 25,
    ),
  ],
);

final zpl = await generator.build();

💾 The Data Engine #

Data Binding & Templating Engine #

In logistics and production environments, you shouldn't compile identical labels from scratch 10,000 times. ZplTemplate enables you to cache the heavy geometry and image rendering algorithms once, unlocking blistering fast synchronous label generations.

  1. Design the layout using {{variable}} placements in standard commands.
  2. Init the template once globally.
  3. Bind synchronous data maps aggressively in a loop.
// 1. Initial Setup
final template = ZplTemplate(
  ZplGenerator(
    config: const ZplConfiguration(printWidth: 406, labelLength: 203),
    commands: [
      ZplText(x: 10, y: 10, text: 'Hello {{name}}'),
      ZplText(x: 10, y: 50, text: 'Price: \${{price}}'),
      ZplBarcode(x: 10, y: 90, height: 50, data: '{{barcode}}', type: ZplBarcodeType.code128),
    ],
  )
);

// 2. Compile geometry & imagery ONCE 
await template.init();

// 3. Loop generating thousands of labels instantly
for (var dataMap in customers) {
    // Zero layout/AST overhead, pure native string replacement
    final rawZplPayload = template.bindSync(dataMap);
    printer.print(rawZplPayload);
}

Auto-Increment Serialization (^SN) #

When printing many identical layout labels but with increasing/decreasing ID numbers (e.g. SN-001, SN-002, SN-003), sending a new payload for every single label is highly inefficient.

Instead, you can combine ZplPrintQuantity with a ZplText configured for hardware serialization. The printer will calculate and index the variable numbers internally!

final generator = ZplGenerator(
  config: const ZplConfiguration(printWidth: 406, labelLength: 203),
  commands: [
    // This looks like static text, but we attach a 'serialization' config to it
    ZplText(
      x: 10, 
      y: 10, 
      text: 'SN-001', // Your starting value
      serialization: const ZplSerialConfig(
        increment: 1,      // +1 per label copy 
        leadingZeros: true // Keep it exactly 3 digits long ('001' -> '002' -> '003')
      ),
    ),
    
    // We only send 1 print job over Wi-Fi, but the printer hardware will 
    // eject 10 labels counting up to 'SN-010' automatically!
    ZplPrintQuantity(quantity: 10),
  ],
);

⚙️ Hardware & Enterprise Control #

Production Print Configurations (^PQ) #

Purpose: In production environments, you often need to print multiple copies of the exact same label without transmitting the entire payload over Wi-Fi/Bluetooth multiple times. ZplPrintQuantity safely delegates the responsibility of duplicating the label directly to the printer's internal memory buffer.

Placement Guidelines: You can append ZplPrintQuantity anywhere inside the commands: list. It will safely execute hardware features natively before the label officially terminates (^XZ).

final generator = ZplGenerator(
  config: const ZplConfiguration(printWidth: 406, labelLength: 203),
  commands: [
    ZplText(x: 10, y: 10, text: 'Product Label'),
    
    // You can place this command anywhere in the 'commands' array!
    // This offloads the work to the printer hardware itself:
    // "Print 50 copies of this label, and physically pause after every 10."
    ZplPrintQuantity(quantity: 50, pauseInterval: 10),
  ],
);

Enterprise RFID Tag Encoding (^RF / ^RS) #

Generate "Smart Labels" by leveraging Zebra's dual-hardware printers (like the ZT411 RFID). You can encode the tiny silicon microchip hidden inside the label at the exact same time you print the visual ink barcodes!

final generator = ZplGenerator(
  config: ZplConfiguration(printWidth: 406, labelLength: 203),
  commands: [
    // 1. Tell the printer what hardware protocol to run (EPC Class 1 Gen 2)
    ZplRfidSetup(tagType: 8),

    // 2. Blast your payload onto the actual RFID Antenna using HEX!
    // (This encodes 11112222 directly into the EPC bank block 3)
    ZplRfidWrite(
      data: '11112222',
      operation: RfidOperation.write,
      format: RfidDataFormat.hex,
      startingBlock: 3, 
      byteCount: 4,
      memoryBank: RfidMemoryBank.epc,
    ),

    // 3. Normal printing logic is executed in parallel!
    ZplText(x: 10, y: 10, text: 'This text gets printed with ink!'),
    ZplBarcode(x: 10, y: 50, data: '11112222', type: ZplBarcodeType.code128),
  ],
);

Note: When using RfidDataFormat.hex, the library strictly asserts that your payload only contains completely valid [0-9A-Fa-f] characters to prevent silent printer-locking failures.

Network & Infrastructure Commands #

Zebra printers operating in warehouses and production environments often require programmatic network configuration (Wi-Fi, Bluetooth, SMTP, SNMP). flutter_zpl_generator exposes a complete suite of network administration commands that gracefully format ZPL configurations without interfering with visual layout math.

These commands physically configure the hardware state. They seamlessly return 0 for layout calculations, meaning you can place them anywhere in the commands list!

final generator = ZplGenerator(
  config: ZplConfiguration(printWidth: 406, labelLength: 203),
  commands: [
    // 1. Establish printer networking rules on boot
    ZplNetworkSettings(
      device: 1, 
      ip: '192.168.1.100', 
      mask: '255.255.255.0', 
      gateway: '192.168.1.1',
      timeout: 300,
      arp: 'Y',
    ),
    
    // 2. Configure standard SNMP telemetry
    ZplNetworkSnmp(
      name: 'DockDoor_Printer_01',
      location: 'Warehouse_A',
      getCommunity: 'public',
    ),
    
    // 3. Connect safely to a target network ID
    ZplNetworkConnect(networkId: 'WLAN_INT_01'),

    // Print regular graphics below...
    ZplText(x: 10, y: 10, text: 'Hello ZPL Networking!'),
  ],
);

Available Configuration Classes:

  • ZplNetworkBoot (^NB) — Check interval for boot blocks.
  • ZplNetworkDevice (^NC) — Set primary network device.
  • ZplNetworkConnect (~NC) — Connect to a secondary network.
  • ZplNetworkSettings (^ND) — Change network parameters.
  • ZplNetworkId (^NI) — Assign a Network ID number string.
  • ZplNetworkSnmp (^NN) — Configure SNMP params.
  • ZplNetworkPrimaryDevice (^NP) — Set primary connection physical device.
  • ZplNetworkPrintersTransparentAll (~NR) — Set all network printers transparent.
  • ZplNetworkWiredSettings (^NS) — Wired network settings fallback.
  • ZplNetworkPrinterTransparentCurrent (~NT) — Set current printer transparent.
  • ZplNetworkSmtp (^NT) — Configure SMTP email rules.
  • ZplNetworkPasswordTimeout (^NW) — Password active countdown timer.

💻 Developer Experience & Examples #

Live Preview Details (Labelary Integration) #

You can preview the receipt in pseudo-real-time simply by wrapping your generator reference mathematically natively.

class LabelPreviewScreen extends StatelessWidget {
  
  final generator = ZplGenerator(
      config: const ZplConfiguration(printWidth: 406, labelLength: 203),
      commands: [ ... ]
  );

  @override
  Widget build(BuildContext context) {
    return ZplPreview(
      generator: generator, // Hot-reloads on Widget Rebuild automatically!
    );
  }
}

If you prefer to hit the REST API directly for PDFs or native assets:

final response = await LabelaryService.renderFromGenerator(
  generator,
  outputFormat: LabelaryOutputFormat.pdf,
);

// Write bytes to disk
await File('label.pdf').writeAsBytes(response.data);

Complete Use-Case: Complex Retail Receipt #

Combine the 12-Unit Grid, Tables, and Barcodes to generate a fully formatted receipt effortlessly.

import 'package:flutter_zpl_generator/flutter_zpl_generator.dart';

final generator = ZplGenerator(
  config: const ZplConfiguration(
    printWidth: 576, // 203 DPI standard receipt
    labelLength: 1200,
    printDensity: ZplPrintDensity.d8,
  ),
  commands: [
    // Header
    ZplText(x: 0, y: 30, text: 'RECEIPT', fontHeight: 50, fontWidth: 45),
    ZplText(x: 0, y: 100, text: 'Receipt number: 117 - 44332'),
    ZplText(x: 0, y: 130, text: 'Date of purchase: December 8, 2023'),

    // Company & Bill To (Side-by-side using 12-unit Grid system)
    ZplGridRow(
      y: 200,
      children: [
        ZplGridCol(
          width: 6, // 50% width
          child: ZplColumn(
            children: [
              ZplText(text: 'Big Machinery, LLC', fontHeight: 25, fontWidth: 22),
              ZplText(text: '3345, Diamond St, Orange City, ST 9987', fontHeight: 18, fontWidth: 16),
            ],
          ),
        ),
        ZplGridCol(
          width: 6, // 50% width
          child: ZplColumn(
            children: [
              ZplText(text: 'Bill To', fontHeight: 25, fontWidth: 22),
              ZplText(text: 'Doe John', fontHeight: 18, fontWidth: 16),
            ],
          ),
        ),
      ],
    ),

    // Items table
    ZplTable(
      y: 360,
      columnWidths: [6, 2, 2, 2], // 12-column grid mapping
      borderThickness: 2,
      cellPadding: 6,
      headers: [
        ZplTableHeader('Item', alignment: ZplAlignment.left, fontHeight: 22, fontWidth: 20),
        ZplTableHeader('Qty', alignment: ZplAlignment.center, fontHeight: 22, fontWidth: 20),
        ZplTableHeader('Unit', alignment: ZplAlignment.center, fontHeight: 22, fontWidth: 20),
        ZplTableHeader('Total', alignment: ZplAlignment.center, fontHeight: 22, fontWidth: 20),
      ],
      data: [
        ['Fuel Plastic Jug (10 gal)', '01', '\$34.00', '\$34.00'],
        ['Gas Hose (5 feet)', '01', '\$15.00', '\$15.00'],
        ['Aluminum Screw (4 in)', '100', '\$0.87', '\$87.00'],
      ],
      dataFontHeight: 18,
      dataFontWidth: 16,
    ),

    // Totals
    ZplText(x: 50, y: 580, text: 'Subtotal: \$136.00', fontHeight: 22, fontWidth: 20),
    ZplText(x: 50, y: 650, text: 'Tax (12%): \$16.32', fontHeight: 20, fontWidth: 18),
    ZplSeparator(y: 685, thickness: 2, paddingLeft: 50, paddingRight: 50),
    ZplText(x: 50, y: 710, text: 'Total: \$152.32', fontHeight: 26, fontWidth: 24),

    // Footer with QR code
    ZplSeparator(y: 760, thickness: 1),
    ZplText(x: 0, y: 785, text: 'Scan for digital receipt:', alignment: ZplAlignment.center),
    ZplBarcode(
      x: 0, y: 815,
      data: 'https://receipt.example.com/117-44332',
      type: ZplBarcodeType.qrCode,
      height: 120,
      alignment: ZplAlignment.center,
    ),
  ],
);

final zpl = await generator.build();
print(zpl);

1
likes
160
points
144
downloads

Documentation

API reference

Publisher

verified publishertritoone.com

Weekly Downloads

A comprehensive Flutter package for generating ZPL (Zebra Programming Language) labels with Labelary API integration and live preview capabilities.

Repository (GitHub)
View/report issues

Topics

#zpl #labels #printing #zebra #barcode

License

MIT (license)

Dependencies

barcode, barcode_widget, flutter, hex, http, image

More

Packages that depend on flutter_zpl_generator