Class EscPosBuilder

java.lang.Object
io.github.chkrishnatej.rp3200.EscPosBuilder

public final class EscPosBuilder extends Object
Fluent builder that produces the raw ESC/POS bytes for one receipt.

This is the low-level API. ReceiptTemplate is built on top of it; use whichever reads better, or mix them with ReceiptTemplate.renderInto(EscPosBuilder, Object).

Example


 byte[] bytes = new EscPosBuilder(PrinterProfile.RP3200_80MM)
         .center().size(TextSize.DOUBLE).bold(true).line("MY SHOP")
         .resetStyle().line("Anna Nagar, Chennai")
         .left().separator('=')
         .row(Columns.parse("*,4r,10r"), "Masala Tea", "2", "40.00")
         .separator()
         .center().qr("upi://pay?pa=shop@upi&am=40.00")
         .feed(2)
         .cut()
         .openDrawer()
         .build();          // send these bytes to rp3200-agent
 

Behaviour

  • State persists like on the printer itself: alignment and style stay active until changed. (Templates differ: there every line starts fresh.)
  • Alignment only takes effect at the start of a line (an ESC/POS rule). Calling center() in the middle of a line applies from the next line.
  • Block elements - separator(), row(Columns, String...), qr(String), barcode(String), feed(int), cut() and openDrawer() - first finish any unfinished text line.
  • Text is sanitised: control characters are removed (data can never inject printer commands), replacements from the PrinterProfile are applied (e.g. the Rupee sign becomes "Rs."), and characters outside the code page print as ?.
  • Errors: invalid arguments (bad QR size, non-ASCII barcode, columns wider than the paper, ...) throw IllegalArgumentException immediately.

Besides the bytes, the builder keeps a plain-text preview() of the receipt, which is handy for logging and for unit-testing receipts without a printer.

Not thread-safe: create one builder per receipt; builders are cheap.

See Also:
  • Field Details

    • DEFAULT_BARCODE_HEIGHT

      public static final int DEFAULT_BARCODE_HEIGHT
      Barcode height used when none is given (dots; 8 dots = 1 mm).
      See Also:
    • DEFAULT_QR_SIZE

      public static final int DEFAULT_QR_SIZE
      QR module size used when none is given (1..16; 6 gives a ~25 mm code for a UPI link).
      See Also:
  • Constructor Details

    • EscPosBuilder

      public EscPosBuilder(PrinterProfile profile)
      Starts a new receipt. The output begins with a printer reset (ESC @), a switch out of Chinese double-byte mode (FS .) and the profile's code page (ESC t), so every receipt starts from a known state regardless of what was printed before.
      Parameters:
      profile - the printer/paper profile, e.g. PrinterProfile.RP3200_80MM
      Throws:
      NullPointerException - if profile is null
  • Method Details

    • profile

      public PrinterProfile profile()
      Returns the profile this builder was created with.
      Returns:
      the printer/paper profile
    • lineWidth

      public int lineWidth()
      Returns how many characters of the current text size fit on one line, e.g. 48 for normal and 24 for TextSize.DOUBLE text on 80 mm paper.
      Returns:
      characters per line at the current size
    • align

      public EscPosBuilder align(Align a)
      Sets the alignment for this and all following lines. If the current line already has text, the new alignment applies from the next line.
      Parameters:
      a - the alignment
      Returns:
      this builder, for chaining
    • left

      public EscPosBuilder left()
      Shortcut for align(Align.LEFT).
      Returns:
      this builder, for chaining
    • center

      public EscPosBuilder center()
      Shortcut for align(Align.CENTER).
      Returns:
      this builder, for chaining
    • right

      public EscPosBuilder right()
      Shortcut for align(Align.RIGHT).
      Returns:
      this builder, for chaining
    • bold

      public EscPosBuilder bold(boolean on)
      Switches bold (emphasised) printing on or off for the following text.
      Parameters:
      on - true for bold
      Returns:
      this builder, for chaining
    • underline

      public EscPosBuilder underline(boolean on)
      Switches underlining on or off for the following text.
      Parameters:
      on - true to underline
      Returns:
      this builder, for chaining
    • invert

      public EscPosBuilder invert(boolean on)
      Switches reverse printing (white text on a black background) on or off.
      Parameters:
      on - true for white on black
      Returns:
      this builder, for chaining
    • size

      public EscPosBuilder size(TextSize s)
      Sets the character size for the following text. Wide sizes halve lineWidth().
      Parameters:
      s - the size
      Returns:
      this builder, for chaining
    • style

      public EscPosBuilder style(Style s)
      Sets bold, underline, invert and size in one call.
      Parameters:
      s - the complete style, e.g. Style.PLAIN.withBold(true)
      Returns:
      this builder, for chaining
    • resetStyle

      public EscPosBuilder resetStyle()
      Returns to plain, normal-size text. Alignment is not changed.
      Returns:
      this builder, for chaining
    • text

      public EscPosBuilder text(String text)
      Prints text in the current style without ending the line. Each \n in the text starts a new line. Text longer than a line is wrapped by the printer itself.
      Parameters:
      text - the text; null or empty prints nothing
      Returns:
      this builder, for chaining
    • line

      public EscPosBuilder line(String text)
      Prints text in the current style and ends the line. Same as text(text).newline().
      Parameters:
      text - the text; null or empty prints a blank line
      Returns:
      this builder, for chaining
    • newline

      public EscPosBuilder newline()
      Ends the current line (LF). On an empty line this prints a blank line.
      Returns:
      this builder, for chaining
    • separator

      public EscPosBuilder separator()
      Prints a full-width line of dashes in the current style.
      Returns:
      this builder, for chaining
    • separator

      public EscPosBuilder separator(char c)
      Prints a full-width line of the given character, e.g. '='. The width follows the current text size.
      Parameters:
      c - the character to repeat
      Returns:
      this builder, for chaining
    • row

      public EscPosBuilder row(Columns columns, String... cells)
      Prints one table row using the current style. A cell that is too long is word-wrapped inside its own column, so a long item name simply takes two lines while the other columns stay put. Alignment is ignored for rows (they always span the full width).
      
       Columns cols = Columns.parse("*,4r,10r");
       b.row(cols, "Item", "Qty", "Amount");
       b.row(cols, "Masala Tea", "2", "40.00");
       
      Parameters:
      columns - the layout, see Columns.parse(String)
      cells - one value per column; missing trailing cells and null print empty
      Returns:
      this builder, for chaining
      Throws:
      IllegalArgumentException - if there are more cells than columns, or the columns do not fit the line
    • row

      public EscPosBuilder row(Columns columns, List<List<Style.Segment>> cells)
      Like row(Columns, String...), but each cell is a list of styled segments, so a cell can mix styles - e.g. a bold total next to a normal label.
      
       Style bold = Style.PLAIN.withBold(true);
       b.row(Columns.parse("*,12r"), List.of(
               List.of(new Style.Segment("TOTAL", bold)),
               List.of(new Style.Segment("1029.00", bold))));
       
      Parameters:
      columns - the layout, see Columns.parse(String)
      cells - one list of segments per column
      Returns:
      this builder, for chaining
      Throws:
      IllegalArgumentException - if there are more cells than columns, or the columns do not fit the line
    • qr

      public EscPosBuilder qr(String data)
      Prints a QR code with the default module size (6) at the current alignment. See qr(String, int).
      Parameters:
      data - the content, e.g. a UPI payment link
      Returns:
      this builder, for chaining
      Throws:
      IllegalArgumentException - if data is empty or too long
    • qr

      public EscPosBuilder qr(String data, int moduleSize)
      Prints a QR code (model 2, error correction level M) at the current alignment.
      Parameters:
      data - the content, e.g. "upi://pay?pa=shop@upi&am=40.00"; encoded as UTF-8, at most 2953 bytes
      moduleSize - size of one QR module in dots, 1..16. 6 gives a code of about 25 mm for a typical UPI link; use 4-5 for long data, 8 for easy scanning
      Returns:
      this builder, for chaining
      Throws:
      IllegalArgumentException - if data is empty or too long, or the size is out of range
    • barcode

      public EscPosBuilder barcode(String data)
      Prints a CODE128 barcode at the default height (80 dots) with the text below it. See barcode(String, int).
      Parameters:
      data - printable ASCII, e.g. "INV-2024-0042"
      Returns:
      this builder, for chaining
      Throws:
      IllegalArgumentException - if the data is empty, not printable ASCII or too long for the paper
    • barcode

      public EscPosBuilder barcode(String data, int heightDots)
      Prints a CODE128 barcode (the most compact 1D code for bill numbers) at the current alignment, with the human-readable text below it. For long data the bars are made thinner automatically so the code still fits the paper.
      Parameters:
      data - printable ASCII only (space to ~); about 20 characters fit on 80 mm paper at normal bar width, about 45 with thin bars
      heightDots - bar height in dots, 1..255 (8 dots = 1 mm)
      Returns:
      this builder, for chaining
      Throws:
      IllegalArgumentException - if the data is empty, not printable ASCII or too long for the paper
    • feed

      public EscPosBuilder feed(int lines)
      Feeds blank lines. Finishes the current text line first.
      Parameters:
      lines - number of blank lines, 0..255
      Returns:
      this builder, for chaining
      Throws:
      IllegalArgumentException - if lines is out of range
    • cut

      public EscPosBuilder cut()
      Feeds the paper up to the cutter and makes a full cut. Usually the last command of a receipt (add feed(int) before it for extra bottom margin).
      Returns:
      this builder, for chaining
    • partialCut

      public EscPosBuilder partialCut()
      Feeds the paper up to the cutter and makes a partial cut: the receipt stays attached by a small hinge and is torn off by hand.
      Returns:
      this builder, for chaining
    • openDrawer

      public EscPosBuilder openDrawer()
      Opens the cash drawer connected to the printer's RJ11 port, using pin 2 (the usual wiring). Harmless when no drawer is connected.
      Returns:
      this builder, for chaining
    • openDrawer

      public EscPosBuilder openDrawer(int pin)
      Opens the cash drawer using connector pin 2 or pin 5. Try pin 5 if pin 2 does nothing.
      Parameters:
      pin - 2 or 5
      Returns:
      this builder, for chaining
      Throws:
      IllegalArgumentException - for any other pin
    • raw

      public EscPosBuilder raw(byte... bytes)
      Appends bytes exactly as given, for printer features this builder does not cover. The builder does not track what these bytes change (style, alignment), so reset anything you change afterwards.
      Parameters:
      bytes - raw ESC/POS bytes
      Returns:
      this builder, for chaining
    • build

      public byte[] build()
      Returns the ESC/POS bytes to send to the printer, e.g. as the body of an application/octet-stream HTTP response. An unfinished last line is terminated so it is not left in the printer's buffer. The builder stays usable; calling build() again returns everything written so far.
      Returns:
      a new array with the complete receipt
    • preview

      public String preview()
      Returns a plain-text picture of the receipt, one line per printed line. Alignment, columns and wrapping are exact; bold/underline are not visible, double-width text is shown with spaces between letters, and QR codes, barcodes, cuts and the drawer appear as [QR: ...], [BARCODE: ...], [cut] and [open drawer].
      Returns:
      the preview text, ending with a newline
    • toString

      public String toString()
      Returns a short description of the builder (line width and bytes written so far).
      Overrides:
      toString in class Object
      Returns:
      a debug string