Skip to content
Michael Billington edited this page Dec 15, 2019 · 11 revisions

Although computers understand Unicode, receipt printers do not. This page documents the features which are available in escpos-php to print non-ASCII characters.

If you are writing a simple alphabetic script on a capable printer, then you just need to tell escpos-php which model of printer you have, and it will take care of the rest.

For more complex scripts or where the printer's ESC/POS support is limited, you may need to use a work-around to get usable output.

ESC/POS native

This method is used by default.

Example:

<?php
require __DIR__ . '/vendor/autoload.php';

use Mike42\Escpos\PrintConnectors\FilePrintConnector;
use Mike42\Escpos\CapabilityProfile;
use Mike42\Escpos\Printer;

$profile = CapabilityProfile::load("default");
$connector = new FilePrintConnector("php://stdout");

$printer = new Printer($connector, $profile);
$printer -> text("Pchnąć w tę łódź jeża lub ośm skrzyń fig.\n");
$printer -> cut();
$printer -> close();

How it works:

  1. Each printer has glyphs from a number of legacy code pages, numbered 0-255 on the printer. The exact mapping varies considerably between printers.
  2. The developer finds out which code pages their printer supports, and checks that they are listed correctly in the ESC/POS printer database. There is information about adding a printer here.
  3. In PHP code, the matching profile is loaded into a CapabilityProfile object. The default profile is used if none is specified.
  4. UTF-8 text is then passed to $printer -> text('...'), and the library will convert it character-by-character.

Compatibility:

  • This works for most European languages, and is configured out-of-the box to match the code pages present on common Epson-branded printers.
  • Printers which have an uncertain code page mapping (eg. not listed correctly in the receipt printer database) will not produce usable output outside of ASCII text.
  • If a printer does not have the glyphs that you are trying to use, then this method will not work.
  • If there is not a 1-1 relationship between characters and glyphs in your script, then this method will not produce usable output. This includes scripts which require the use of presentation forms, composing characters or bi-directional text (eg. Thai, Khmer, Indian scripts, Arabic).

Example uses

UnifontPrintBuffer

This is an experimental feature which utilities GNU Unifont instead of the fonts that are built into the printer. This implementation is specific to Unifont, and does not currently allow you to utilize arbitrary bitmap fonts.

You can download unifont here. You need to locate unifont-12.1.03.tar.gz, and extract font/precompiled/unifont-12.1.03.hex.

Example:

<?php

require __DIR__ . '/../vendor/autoload.php';

use Mike42\Escpos\PrintConnectors\FilePrintConnector;
use Mike42\Escpos\Printer;
use Mike42\Escpos\Experimental\Unifont\UnifontPrintBuffer;

$connector = new FilePrintConnector("/dev/usb/lp0");
$printer = new Printer($connector);

// Use Unifont to render text
$unifontBuffer = new UnifontPrintBuffer("/usr/share/unifont/unifont.hex");
$printer -> setPrintBuffer($unifontBuffer);

// Most simple example
$printer->text("Hello World\n");
$printer->cut();
$printer->close();

How it works:

  • GNU Unifont is an 8x16 bitmap font with a large collection of glyphs. We switch the printer to use a "user-defined" code page, then switch the printer to use "Font B", which is 9x17 on many common printers. Glyphs are then cycled through the user-defined font as required. The method is described in this blog post.

Compatibility:

  • The printer must support custom fonts, and must have a "Font B" that is close to 8x16 resolution. Glyphs will appear cut off or excessively spaced on other printers.
  • Glyphs are printed based only on their code point, which makes this method unsuitable for more complex scripts. The implementation of combining marks is being tracked at issue #815.
  • The size, style and spacing of the font is not typical of receipt printer fonts. A derived font called Thermal Sans Mono is being developed to overcome this.

Example uses:

Via external tools

This library can print images, and you can render arbitrary text to an image with the help of other tools. This is often the best way to render more complex scripts.

This example uses wkhtmltoimage and Noto Sans Sinhala font to render Sinhalese text to an image, to eventually print with escpos-php. This tool allows the use of arbitrary fonts, and has good support for contextual forms, text direction, and combining characters.

It starts with a "Hello World" HTML file which references the font at the correct size:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>title</title>

    <style>
      @font-face {
        font-family: 'Noto Sans Sinhala Bold';
        font-style: normal;
        font-weight: 700;
        src: url('fonts/NotoSansSinhala-Bold.ttf') format('truetype');
      }
      body {
        font-size: 24px;
        font-weight: 700;
        font-family: 'Noto Sans Sinhala Bold'
      }
    </style>
  </head>
  <body>හෙලෝ වර්ල්ඩ්</body>
</html>

This displays in the browser like this:

image

It can be rendered to a small image on the command-line -- note that the width of 576 pixels is calculated from the printer specifications.

wkhtmltoimage --width 576 test.html test.pbm

The output image is pure black & white. The PBM format is used because it's very close to the format that is eventually used to print:

test

And our library here can print images just fine:

<?php
require __DIR__ . '/vendor/autoload.php';
use Mike42\Escpos\EscposImage;
use Mike42\Escpos\PrintConnectors\FilePrintConnector;

use Mike42\Escpos\Printer;

$connector = new FilePrintConnector("/dev/usb/lp0");
$printer = new Printer($connector);
$img = EscposImage::load("test.pbm");
$printer -> bitImage($img);
$printer -> cut();
$printer -> close();

Which creates a receipt like this:

2019-09-example

No formatting can be applied to this text from escpos-php, but the good thing is that this can be easily extended to formatting more complex things-

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>title</title>

    <style>
      @font-face {
        font-family: 'Noto Sans Sinhala Bold';
        font-style: normal;
        font-weight: 700;
        src: url('fonts/NotoSansSinhala-Bold.ttf') format('truetype');
      }
      body {
        font-size: 24px;
        font-weight: 700;
        font-family: 'Noto Sans Sinhala Bold'
      }
    </style>
  </head>
  <body>
    <table style="width: 100%">
      <tr>
        <td>හෙලෝ</td>
        <td style="float: right">20.00</td>
      </tr>
      <tr>
        <td>වර්ල්ඩ්</td>
        <td style="float: right">30.00</td>
      </tr>
    </table>
  </body>
</html>

test2

Compatibility and tips:

  • This method is suitable only for higher-density printers, such an Epson TM-series thermal printer.
  • This is much slower than sending text to the printer directly, and the text will have artifacts from being converted to black & white.
  • To avoid falling back on system fonts, you can place the font on disk and load it with a relative path.

Example uses:

ImagePrintBuffer

Example:

<?php
require __DIR__ . '/vendor/autoload.php';
use Mike42\Escpos\CapabilityProfile;
use Mike42\Escpos\Printer;
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
use Mike42\Escpos\PrintBuffers\ImagePrintBuffer;


$profile = CapabilityProfile::load("default");
$buffer = new ImagePrintBuffer();
$connector = new FilePrintConnector("php://stdout");
$printer = new Printer($connector, $profile);
$printer -> setPrintBuffer($buffer);
$printer -> text("Glāžšķūņa rūķīši dzērumā čiepj Baha koncertflīģeļu vākus\n");
$printer -> cut();
$printer -> close();

How it works:

  • TBD

Compatibility:

  • TBD

Example uses:

  • #29 - Latvian
Clone this wiki locally