forked from Wavyzz/dolibarr
wip ticket printer
This commit is contained in:
@@ -166,6 +166,24 @@ if ($action == 'testprinter' && $user->admin) {
|
|||||||
$action = '';
|
$action = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($action == 'testtemplate' && $user->admin) {
|
||||||
|
$error=0;
|
||||||
|
// if (empty($printerid)) {
|
||||||
|
// $error++;
|
||||||
|
// setEventMessages($langs->trans("PrinterIdEmpty"), null, 'errors');
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (! $error) {
|
||||||
|
// // test
|
||||||
|
// $ret = $printer->sendTestToPrinter($printerid);
|
||||||
|
// if ($ret == 0) {
|
||||||
|
setEventMessages($langs->trans("TestTemplateToPrinter", $printername), null);
|
||||||
|
// } else {
|
||||||
|
// setEventMessages($printer->error, $printer->errors, 'errors');
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
$action = '';
|
||||||
|
}
|
||||||
|
|
||||||
if ($action == 'updatetemplate' && $user->admin) {
|
if ($action == 'updatetemplate' && $user->admin) {
|
||||||
$error=0;
|
$error=0;
|
||||||
@@ -190,6 +208,29 @@ if ($action == 'updatetemplate' && $user->admin) {
|
|||||||
$action = '';
|
$action = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($action == 'addtemplate' && $user->admin) {
|
||||||
|
$error=0;
|
||||||
|
$db->begin();
|
||||||
|
if (empty($templatename)) {
|
||||||
|
$error++;
|
||||||
|
setEventMessages($langs->trans("TemplateNameEmpty"), null, 'errors');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $error) {
|
||||||
|
$result= $printer->addTemplate($templatename, $template);
|
||||||
|
if ($result > 0) $error++;
|
||||||
|
|
||||||
|
if (! $error) {
|
||||||
|
$db->commit();
|
||||||
|
setEventMessages($langs->trans("TemplateAdded", $templatename), null);
|
||||||
|
} else {
|
||||||
|
$db->rollback();
|
||||||
|
dol_print_error($db);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$action = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* View
|
* View
|
||||||
@@ -345,7 +386,7 @@ if ($mode == 'template' && $user->admin) {
|
|||||||
dol_fiche_head($head, $mode, $langs->trans("ModuleSetup"), 0, 'technic');
|
dol_fiche_head($head, $mode, $langs->trans("ModuleSetup"), 0, 'technic');
|
||||||
|
|
||||||
print $langs->trans("ReceiptPrinterTemplateDesc")."<br><br>\n";
|
print $langs->trans("ReceiptPrinterTemplateDesc")."<br><br>\n";
|
||||||
print '<table class="noborder" width="100%">'."\n";
|
print '<table class="noborder centpercent">'."\n";
|
||||||
print '<tr class="liste_titre">';
|
print '<tr class="liste_titre">';
|
||||||
print '<th>'.$langs->trans("Name").'</th>';
|
print '<th>'.$langs->trans("Name").'</th>';
|
||||||
print '<th>'.$langs->trans("Template").'</th>';
|
print '<th>'.$langs->trans("Template").'</th>';
|
||||||
@@ -359,8 +400,7 @@ if ($mode == 'template' && $user->admin) {
|
|||||||
setEventMessages($printer->error, $printer->errors, 'errors');
|
setEventMessages($printer->error, $printer->errors, 'errors');
|
||||||
} else {
|
} else {
|
||||||
$max = count($printer->listprinterstemplates);
|
$max = count($printer->listprinterstemplates);
|
||||||
for ($line=0; $line < $max; $line++)
|
for ($line=0; $line < $max; $line++) {
|
||||||
{
|
|
||||||
print '<tr class="oddeven">';
|
print '<tr class="oddeven">';
|
||||||
if ($action=='edittemplate' && $printer->listprinterstemplates[$line]['rowid']==$templateid) {
|
if ($action=='edittemplate' && $printer->listprinterstemplates[$line]['rowid']==$templateid) {
|
||||||
print '<input type="hidden" name="templateid" value="'.$printer->listprinterstemplates[$line]['rowid'].'">';
|
print '<input type="hidden" name="templateid" value="'.$printer->listprinterstemplates[$line]['rowid'].'">';
|
||||||
@@ -392,6 +432,14 @@ if ($mode == 'template' && $user->admin) {
|
|||||||
|
|
||||||
print '</table>';
|
print '</table>';
|
||||||
if ($action!='edittemplate') {
|
if ($action!='edittemplate') {
|
||||||
|
print '<input type="hidden" name="templateid" value="'.$printer->listprinterstemplates[$line]['rowid'].'">';
|
||||||
|
print '<td><input size="50" type="text" name="templatename" value="'.$printer->listprinterstemplates[$line]['name'].'"></td>';
|
||||||
|
print '<td><textarea name="template" wrap="soft" cols="120" rows="12">'.$printer->listprinterstemplates[$line]['template'].'</textarea>';
|
||||||
|
print '</td>';
|
||||||
|
print '<td></td>';
|
||||||
|
print '<td></td>';
|
||||||
|
print '<td></td>';
|
||||||
|
|
||||||
print '<div class="center"><input type="submit" class="button" value="'.dol_escape_htmltag($langs->trans("Add")).'"></div>';
|
print '<div class="center"><input type="submit" class="button" value="'.dol_escape_htmltag($langs->trans("Add")).'"></div>';
|
||||||
} else {
|
} else {
|
||||||
print '<div class="center"><input type="submit" class="button" value="'.dol_escape_htmltag($langs->trans("Save")).'"></div>';
|
print '<div class="center"><input type="submit" class="button" value="'.dol_escape_htmltag($langs->trans("Save")).'"></div>';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Copyright (C) 2015-2018 Frédéric France <frederic.france@free.fr>
|
/* Copyright (C) 2015-2019 Frédéric France <frederic.france@netlogic.fr>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -91,13 +91,19 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once DOL_DOCUMENT_ROOT .'/includes/mike42/escpos-php/Escpos.php';
|
require_once DOL_DOCUMENT_ROOT .'/includes/mike42/escpos-php/autoload.php';
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
use Mike42\Escpos\PrintConnectors\NetworkPrintConnector;
|
||||||
|
use Mike42\Escpos\PrintConnectors\WindowsPrintConnector;
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\EscposImage;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to manage Receipt Printers
|
* Class to manage Receipt Printers
|
||||||
*/
|
*/
|
||||||
class dolReceiptPrinter extends Escpos
|
class dolReceiptPrinter extends Printer
|
||||||
{
|
{
|
||||||
const CONNECTOR_DUMMY = 1;
|
const CONNECTOR_DUMMY = 1;
|
||||||
const CONNECTOR_FILE_PRINT = 2;
|
const CONNECTOR_FILE_PRINT = 2;
|
||||||
@@ -423,6 +429,29 @@ class dolReceiptPrinter extends Escpos
|
|||||||
return $error;
|
return $error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to add a printer template in db
|
||||||
|
*
|
||||||
|
* @param string $name Template name
|
||||||
|
* @param int $template Template
|
||||||
|
* @return int 0 if OK; >0 if KO
|
||||||
|
*/
|
||||||
|
public function addTemplate($name, $template)
|
||||||
|
{
|
||||||
|
global $conf;
|
||||||
|
$error = 0;
|
||||||
|
$sql = 'INSERT INTO '.MAIN_DB_PREFIX.'printer_receipt_template';
|
||||||
|
$sql.= ' (name, template, entity) VALUES ("'.$this->db->escape($name).'"';
|
||||||
|
$sql.= ', "'.$this->db->escape($template).'", '.$conf->entity.')';
|
||||||
|
$resql = $this->db->query($sql);
|
||||||
|
if (! $resql) {
|
||||||
|
$error++;
|
||||||
|
$this->errors[] = $this->db->lasterror;
|
||||||
|
}
|
||||||
|
return $error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to Update a printer template in db
|
* Function to Update a printer template in db
|
||||||
*
|
*
|
||||||
@@ -458,16 +487,17 @@ class dolReceiptPrinter extends Escpos
|
|||||||
{
|
{
|
||||||
global $conf;
|
global $conf;
|
||||||
$error = 0;
|
$error = 0;
|
||||||
$img = new EscposImage(DOL_DOCUMENT_ROOT .'/theme/common/dolibarr_logo_bw.png');
|
$img = EscposImage::load(DOL_DOCUMENT_ROOT .'/theme/common/dolibarr_logo_bw.png');
|
||||||
|
//$this->profile = CapabilityProfile::load("TM-T88IV");
|
||||||
$ret = $this->initPrinter($printerid);
|
$ret = $this->initPrinter($printerid);
|
||||||
if ($ret>0) {
|
if ($ret>0) {
|
||||||
setEventMessages($this->error, $this->errors, 'errors');
|
setEventMessages($this->error, $this->errors, 'errors');
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
$this->printer->graphics($img);
|
$this->printer->bitImage($img);
|
||||||
$this->printer->text("Hello World!\n");
|
$this->printer->text("Hello World!\n");
|
||||||
$testStr = "Testing 123";
|
$testStr = "1234567890";
|
||||||
$this->printer->qrCode($testStr);
|
$this->printer->barcode($testStr);
|
||||||
$this->printer->text("Most simple example\n");
|
$this->printer->text("Most simple example\n");
|
||||||
$this->printer->feed();
|
$this->printer->feed();
|
||||||
$this->printer->cut();
|
$this->printer->cut();
|
||||||
@@ -687,7 +717,7 @@ class dolReceiptPrinter extends Escpos
|
|||||||
$this->connector = 'CONNECTOR_UNKNOWN';
|
$this->connector = 'CONNECTOR_UNKNOWN';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
$this->printer = new Escpos($this->connector);
|
$this->printer = new Printer($this->connector, $this->profile);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$this->errors[] = $e->getMessage();
|
$this->errors[] = $e->getMessage();
|
||||||
$error++;
|
$error++;
|
||||||
|
|||||||
4
htdocs/includes/mike42/escpos-php/.coveralls.yml
Normal file
4
htdocs/includes/mike42/escpos-php/.coveralls.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
service_name: travis-ci
|
||||||
|
coverage_clover: build/logs/clover.xml
|
||||||
|
json_path: build/logs/coveralls-upload.json
|
||||||
|
|
||||||
4
htdocs/includes/mike42/escpos-php/.gitignore
vendored
4
htdocs/includes/mike42/escpos-php/.gitignore
vendored
@@ -10,3 +10,7 @@ doc/doxygen_sqlite3.db
|
|||||||
|
|
||||||
# composer files
|
# composer files
|
||||||
vendor/
|
vendor/
|
||||||
|
|
||||||
|
# other build files
|
||||||
|
build/*
|
||||||
|
*.phar
|
||||||
|
|||||||
46
htdocs/includes/mike42/escpos-php/.travis.yml
Normal file
46
htdocs/includes/mike42/escpos-php/.travis.yml
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
---
|
||||||
|
dist: trusty
|
||||||
|
sudo: required
|
||||||
|
|
||||||
|
language: php
|
||||||
|
|
||||||
|
php:
|
||||||
|
- 5.4
|
||||||
|
- 5.5
|
||||||
|
- 5.6
|
||||||
|
- 7.0
|
||||||
|
- 7.1
|
||||||
|
- 7.2
|
||||||
|
- nightly
|
||||||
|
- hhvm-3.21
|
||||||
|
- hhvm-nightly
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
allow_failures:
|
||||||
|
- php: nightly
|
||||||
|
- php: hhvm-nightly
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- sudo apt-get -qq update
|
||||||
|
- sudo apt-get install -y imagemagick ghostscript
|
||||||
|
|
||||||
|
install:
|
||||||
|
- composer install
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
# Install 'imagick' plugin
|
||||||
|
- bash -c 'if [[ $TRAVIS_PHP_VERSION != hhvm* ]]; then printf "\n" | pecl install imagick; fi'
|
||||||
|
# Directory for coverage report
|
||||||
|
- mkdir -p build/logs/
|
||||||
|
|
||||||
|
script:
|
||||||
|
# Check code style
|
||||||
|
- php vendor/bin/phpcs --standard=psr2 src/ -n
|
||||||
|
# Run tests
|
||||||
|
- php vendor/bin/phpunit --coverage-clover build/logs/clover.xml
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
# Upload coverage statistics to coveralls service after test
|
||||||
|
- wget -c -nc https://github.com/satooshi/php-coveralls/releases/download/v1.0.1/coveralls.phar
|
||||||
|
- php coveralls.phar -v
|
||||||
|
...
|
||||||
65
htdocs/includes/mike42/escpos-php/CONTRIBUTING.md
Normal file
65
htdocs/includes/mike42/escpos-php/CONTRIBUTING.md
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# How to contribute
|
||||||
|
|
||||||
|
This project is open to many different types of contribution. You can help with improving the documentation and examples, sharing your insights on the issue tracker, adding fixes to the code, providing test cases, or just [writing about your hardware setup that you use](https://github.com/mike42/escpos-php/issues/new).
|
||||||
|
|
||||||
|
## Issue tracker
|
||||||
|
|
||||||
|
Open issues of all sorts are tracked on the [issue tracker](https://github.com/mike42/escpos-php/issues). Please check [the FAQ](https://github.com/mike42/escpos-php/blob/development/doc/FAQ.md) before you post, and practice good [bug tracker etiquette](https://bugzilla.mozilla.org/page.cgi?id=etiquette.html) to keep it running smoothly.
|
||||||
|
|
||||||
|
Issues are [loosely categorised](https://github.com/mike42/escpos-php/labels), and will stay open while there is still something that can be resolved.
|
||||||
|
|
||||||
|
Anybody may add to the discussion on the bug tracker. Just be sure to add new questions as separate issues, and to avoid commenting on closed issues.
|
||||||
|
|
||||||
|
## Submitting changes
|
||||||
|
|
||||||
|
Code changes may be submitted as a "[pull request](https://help.github.com/articles/about-pull-requests/)" at [mike42/escpos-php](https://github.com/mike42/escpos-php). The description should include some information about how the change improves the library.
|
||||||
|
|
||||||
|
The project is MIT-licensed (see [LICENSE.md](https://github.com/mike42/escpos-php/blob/development/LICENSE.md) for details). You are not required to assign copyright in order to submit changes, but you do need to agree for your code to be distributed under this license in order for it to be accepted.
|
||||||
|
|
||||||
|
### Documentation changes
|
||||||
|
|
||||||
|
The official documentaton is also located in the main repository, under the [doc/](https://github.com/mike42/escpos-php/tree/development/doc) folder.
|
||||||
|
|
||||||
|
You are welcome to post any suggested improvements as pull requests.
|
||||||
|
|
||||||
|
### Release process
|
||||||
|
|
||||||
|
Once a pull request is accepted, it usually appears in a release a few days later.
|
||||||
|
|
||||||
|
Branches:
|
||||||
|
|
||||||
|
- "development" is the most recent code, possibly containing unreleased fixes
|
||||||
|
- "master" contains the most recently released code (old versions are not maintained).
|
||||||
|
|
||||||
|
The release process for your changes is:
|
||||||
|
|
||||||
|
- Changes are submitted via pull request to the shared "development" branch.
|
||||||
|
- A new release is staged on the "master" branch via another pull request, and then tagged.
|
||||||
|
|
||||||
|
## Code style
|
||||||
|
|
||||||
|
This project uses the [PSR-2 standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) for all PHP source code.
|
||||||
|
|
||||||
|
## Testing and CI
|
||||||
|
|
||||||
|
The tests are executed on [Travis CI](https://travis-ci.org/mike42/escpos-php) over PHP 5.4, 5.5, 5.6, 7.0, 7.1 and 7.2, plus the latest LTS version of HHVM, 3.21. Older versions of PHP are not supported in current releases.
|
||||||
|
|
||||||
|
For development, it's suggested that you load `imagick`, `gd` and `Xdebug` PHP exensions, and install `composer`.
|
||||||
|
|
||||||
|
Fetch a copy of this code and load dependencies with composer:
|
||||||
|
|
||||||
|
git clone https://github.com/mike42/escpos-php
|
||||||
|
cd escpos-php/
|
||||||
|
composer install
|
||||||
|
|
||||||
|
Execute unit tests via `phpunit`:
|
||||||
|
|
||||||
|
php vendor/bin/phpunit --coverage-text
|
||||||
|
|
||||||
|
Code style can be checked via [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer):
|
||||||
|
|
||||||
|
php vendor/bin/phpcs --standard=psr2 src/ -n
|
||||||
|
|
||||||
|
The developer docs are built with [doxygen](https://github.com/doxygen/doxygen). Re-build them to check for documentation warnings:
|
||||||
|
|
||||||
|
make -C doc clean && make -C doc
|
||||||
25
htdocs/includes/mike42/escpos-php/CONTRIBUTORS.md
Normal file
25
htdocs/includes/mike42/escpos-php/CONTRIBUTORS.md
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# escpos-php contributors
|
||||||
|
|
||||||
|
This file contains a list of people who have made contributions of
|
||||||
|
code which appear in the public repository of escpos-php.
|
||||||
|
|
||||||
|
Main repository: [mike42/escpos-php](https://github.com/mike42/escpos-php) ([online contributor list](https://github.com/mike42/escpos-php/graphs/contributors))
|
||||||
|
|
||||||
|
- [Michael Billington](https://github.com/mike42)
|
||||||
|
- [Alif Maulana El Fattah Nataly](https://github.com/alif25r)
|
||||||
|
- [Mareks Sudniks](https://github.com/marech)
|
||||||
|
- [matiasgaston](https://github.com/matiasgaston)
|
||||||
|
- [Mike Stivala](https://github.com/brndwgn)
|
||||||
|
- [Nicholas Long](https://github.com/longsview)
|
||||||
|
- [Evandro Araújo](https://github.com/evsar3)
|
||||||
|
|
||||||
|
Via fork: [wdoyle/EpsonESCPOS-PHP](https://github.com/wdoyle/EpsonESCPOS-PHP):
|
||||||
|
|
||||||
|
- [Warren Doyle](https://github.com/wdoyle)
|
||||||
|
|
||||||
|
Via fork: [ronisaha/php-esc-pos](https://github.com/ronisaha/php-esc-pos):
|
||||||
|
|
||||||
|
- [Roni Saha](https://github.com/ronisaha)
|
||||||
|
- [Gergely Radics](https://github.com/Gerifield)
|
||||||
|
- [vharo](https://github.com/vharo)
|
||||||
|
|
||||||
@@ -1,853 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* escpos-php, a Thermal receipt printer library, for use with
|
|
||||||
* ESC/POS compatible printers.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014-2015 Michael Billington <michael.billington@gmail.com>,
|
|
||||||
* incorporating modifications by:
|
|
||||||
* - Roni Saha <roni.cse@gmail.com>
|
|
||||||
* - Gergely Radics <gerifield@ustream.tv>
|
|
||||||
* - Warren Doyle <w.doyle@fuelled.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
|
||||||
* This class generates ESC/POS printer control commands for compatible printers.
|
|
||||||
* See README.md for a summary of compatible printers and supported commands, and
|
|
||||||
* basic usage.
|
|
||||||
*
|
|
||||||
* See example/demo.php for a detailed print-out demonstrating the range of commands
|
|
||||||
* implemented in this project.
|
|
||||||
*
|
|
||||||
* Note that some functions have not been implemented:
|
|
||||||
* - Set paper sensors
|
|
||||||
* - Select print colour
|
|
||||||
*
|
|
||||||
* Please direct feature requests, bug reports and contributions to escpos-php
|
|
||||||
* on Github:
|
|
||||||
* - https://github.com/mike42/escpos-php
|
|
||||||
*/
|
|
||||||
require_once(dirname(__FILE__) . "/src/EscposImage.php");
|
|
||||||
require_once(dirname(__FILE__) . "/src/PrintBuffer.php");
|
|
||||||
require_once(dirname(__FILE__) . "/src/EscposPrintBuffer.php");
|
|
||||||
require_once(dirname(__FILE__) . "/src/PrintConnector.php");
|
|
||||||
require_once(dirname(__FILE__) . "/src/WindowsPrintConnector.php");
|
|
||||||
require_once(dirname(__FILE__) . "/src/FilePrintConnector.php");
|
|
||||||
require_once(dirname(__FILE__) . "/src/NetworkPrintConnector.php");
|
|
||||||
require_once(dirname(__FILE__) . "/src/AbstractCapabilityProfile.php");
|
|
||||||
require_once(dirname(__FILE__) . "/src/DefaultCapabilityProfile.php");
|
|
||||||
require_once(dirname(__FILE__) . "/src/SimpleCapabilityProfile.php");
|
|
||||||
require_once(dirname(__FILE__) . "/src/EposTepCapabilityProfile.php");
|
|
||||||
require_once(dirname(__FILE__) . "/src/StarCapabilityProfile.php");
|
|
||||||
require_once(dirname(__FILE__) . "/src/P822DCapabilityProfile.php");
|
|
||||||
require_once(dirname(__FILE__) . "/src/CodePage.php");
|
|
||||||
require_once(dirname(__FILE__) . "/src/ImagePrintBuffer.php");
|
|
||||||
|
|
||||||
class Escpos {
|
|
||||||
/* ASCII codes */
|
|
||||||
const NUL = "\x00";
|
|
||||||
const LF = "\x0a";
|
|
||||||
const ESC = "\x1b";
|
|
||||||
const FS = "\x1c";
|
|
||||||
const FF = "\x0c";
|
|
||||||
const GS = "\x1d";
|
|
||||||
const DLE = "\x10";
|
|
||||||
const EOT = "\x04";
|
|
||||||
|
|
||||||
/* Barcode types */
|
|
||||||
const BARCODE_UPCA = 65;
|
|
||||||
const BARCODE_UPCE = 66;
|
|
||||||
const BARCODE_JAN13 = 67;
|
|
||||||
const BARCODE_JAN8 = 68;
|
|
||||||
const BARCODE_CODE39 = 69;
|
|
||||||
const BARCODE_ITF = 70;
|
|
||||||
const BARCODE_CODABAR = 71;
|
|
||||||
const BARCODE_CODE93 = 72;
|
|
||||||
const BARCODE_CODE128 = 73;
|
|
||||||
|
|
||||||
/* Barcode HRI (human-readable interpretation) text position */
|
|
||||||
const BARCODE_TEXT_NONE = 0;
|
|
||||||
const BARCODE_TEXT_ABOVE = 1;
|
|
||||||
const BARCODE_TEXT_BELOW = 2;
|
|
||||||
|
|
||||||
/* Cut types */
|
|
||||||
const CUT_FULL = 65;
|
|
||||||
const CUT_PARTIAL = 66;
|
|
||||||
|
|
||||||
/* Fonts */
|
|
||||||
const FONT_A = 0;
|
|
||||||
const FONT_B = 1;
|
|
||||||
const FONT_C = 2;
|
|
||||||
|
|
||||||
/* Image sizing options */
|
|
||||||
const IMG_DEFAULT = 0;
|
|
||||||
const IMG_DOUBLE_WIDTH = 1;
|
|
||||||
const IMG_DOUBLE_HEIGHT = 2;
|
|
||||||
|
|
||||||
/* Justifications */
|
|
||||||
const JUSTIFY_LEFT = 0;
|
|
||||||
const JUSTIFY_CENTER = 1;
|
|
||||||
const JUSTIFY_RIGHT = 2;
|
|
||||||
|
|
||||||
/* Print mode constants */
|
|
||||||
const MODE_FONT_A = 0;
|
|
||||||
const MODE_FONT_B = 1;
|
|
||||||
const MODE_EMPHASIZED = 8;
|
|
||||||
const MODE_DOUBLE_HEIGHT = 16;
|
|
||||||
const MODE_DOUBLE_WIDTH = 32;
|
|
||||||
const MODE_UNDERLINE = 128;
|
|
||||||
|
|
||||||
/* QR code error correction levels */
|
|
||||||
const QR_ECLEVEL_L = 0;
|
|
||||||
const QR_ECLEVEL_M = 1;
|
|
||||||
const QR_ECLEVEL_Q = 2;
|
|
||||||
const QR_ECLEVEL_H = 3;
|
|
||||||
|
|
||||||
/* QR code models */
|
|
||||||
const QR_MODEL_1 = 1;
|
|
||||||
const QR_MODEL_2 = 2;
|
|
||||||
const QR_MICRO = 3;
|
|
||||||
|
|
||||||
/* Printer statuses */
|
|
||||||
const STATUS_PRINTER = 1;
|
|
||||||
const STATUS_OFFLINE_CAUSE = 2;
|
|
||||||
const STATUS_ERROR_CAUSE = 3;
|
|
||||||
const STATUS_PAPER_ROLL = 4;
|
|
||||||
const STATUS_INK_A = 7;
|
|
||||||
const STATUS_INK_B = 6;
|
|
||||||
const STATUS_PEELER = 8;
|
|
||||||
|
|
||||||
/* Underline */
|
|
||||||
const UNDERLINE_NONE = 0;
|
|
||||||
const UNDERLINE_SINGLE = 1;
|
|
||||||
const UNDERLINE_DOUBLE = 2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var PrintBuffer The printer's output buffer.
|
|
||||||
*/
|
|
||||||
private $buffer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var PrintConnector
|
|
||||||
* @CHANGE
|
|
||||||
*/
|
|
||||||
protected $connector;
|
|
||||||
// private $connector;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var AbstractCapabilityProfile
|
|
||||||
*/
|
|
||||||
private $profile;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int Current character code table
|
|
||||||
*/
|
|
||||||
private $characterTable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new print object
|
|
||||||
*
|
|
||||||
* @param PrintConnector $connector The PrintConnector to send data to. If not set, output is sent to standard output.
|
|
||||||
* @param AbstractCapabilityProfile $profile Supported features of this printer. If not set, the DefaultCapabilityProfile will be used, which is suitable for Epson printers.
|
|
||||||
* @throws InvalidArgumentException
|
|
||||||
*/
|
|
||||||
function __construct(PrintConnector $connector = null, AbstractCapabilityProfile $profile = null) {
|
|
||||||
if(is_null($connector)) {
|
|
||||||
if(php_sapi_name() == 'cli') {
|
|
||||||
$connector = new FilePrintConnector("php://stdout");
|
|
||||||
} else {
|
|
||||||
throw new InvalidArgumentException("Argument passed to Escpos::__construct() must implement interface PrintConnector, null given.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Set connector */
|
|
||||||
$this -> connector = $connector;
|
|
||||||
|
|
||||||
/* Set capability profile */
|
|
||||||
if($profile === null) {
|
|
||||||
$profile = DefaultCapabilityProfile::getInstance();
|
|
||||||
}
|
|
||||||
$this -> profile = $profile;
|
|
||||||
/* Set buffer */
|
|
||||||
$buffer = new EscposPrintBuffer();
|
|
||||||
$this -> buffer = null;
|
|
||||||
$this -> setPrintBuffer($buffer);
|
|
||||||
$this -> initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Print a barcode.
|
|
||||||
*
|
|
||||||
* @param string $content The information to encode.
|
|
||||||
* @param int $type The barcode standard to output. If not specified, `Escpos::BARCODE_CODE39` will be used. Note that some barcode formats only support specific lengths or sets of characters.
|
|
||||||
* @throws InvalidArgumentException Where the length or characters used in $content is invalid for the requested barcode format.
|
|
||||||
*/
|
|
||||||
function barcode($content, $type = self::BARCODE_CODE39) {
|
|
||||||
/* Validate input */
|
|
||||||
self::validateInteger($type, 65, 73, __FUNCTION__, "Barcode type");
|
|
||||||
$len = strlen($content);
|
|
||||||
switch($type) {
|
|
||||||
case self::BARCODE_UPCA:
|
|
||||||
self::validateInteger($len, 11, 12, __FUNCTION__, "UPCA barcode content length");
|
|
||||||
self::validateStringRegex($content, __FUNCTION__, "/^[0-9]{11,12}$/", "UPCA barcode content");
|
|
||||||
break;
|
|
||||||
case self::BARCODE_UPCE:
|
|
||||||
self::validateIntegerMulti($len, array(array(6, 8), array(11, 12)), __FUNCTION__, "UPCE barcode content length");
|
|
||||||
self::validateStringRegex($content, __FUNCTION__, "/^([0-9]{6,8}|[0-9]{11,12})$/", "UPCE barcode content");
|
|
||||||
break;
|
|
||||||
case self::BARCODE_JAN13:
|
|
||||||
self::validateInteger($len, 12, 13, __FUNCTION__, "JAN13 barcode content length");
|
|
||||||
self::validateStringRegex($content, __FUNCTION__, "/^[0-9]{12,13}$/", "JAN13 barcode content");
|
|
||||||
break;
|
|
||||||
case self::BARCODE_JAN8:
|
|
||||||
self::validateInteger($len, 7, 8, __FUNCTION__, "JAN8 barcode content length");
|
|
||||||
self::validateStringRegex($content, __FUNCTION__, "/^[0-9]{7,8}$/", "JAN8 barcode content");
|
|
||||||
break;
|
|
||||||
case self::BARCODE_CODE39:
|
|
||||||
self::validateInteger($len, 1, 255, __FUNCTION__, "CODE39 barcode content length"); // 255 is a limitation of the "function b" command, not the barcode format.
|
|
||||||
self::validateStringRegex($content, __FUNCTION__, "/^([0-9A-Z \$\%\+\-\.\/]+|\*[0-9A-Z \$\%\+\-\.\/]+\*)$/", "CODE39 barcode content");
|
|
||||||
break;
|
|
||||||
case self::BARCODE_ITF:
|
|
||||||
self::validateInteger($len, 2, 255, __FUNCTION__, "ITF barcode content length"); // 255 is a limitation of the "function b" command, not the barcode format.
|
|
||||||
self::validateStringRegex($content, __FUNCTION__, "/^([0-9]{2})+$/", "ITF barcode content");
|
|
||||||
break;
|
|
||||||
case self::BARCODE_CODABAR:
|
|
||||||
self::validateInteger($len, 1, 255, __FUNCTION__, "Codabar barcode content length"); // 255 is a limitation of the "function b" command, not the barcode format.
|
|
||||||
self::validateStringRegex($content, __FUNCTION__, "/^[A-Da-d][0-9\$\+\-\.\/\:]+[A-Da-d]$/", "Codabar barcode content");
|
|
||||||
break;
|
|
||||||
case self::BARCODE_CODE93:
|
|
||||||
self::validateInteger($len, 1, 255, __FUNCTION__, "Code93 barcode content length"); // 255 is a limitation of the "function b" command, not the barcode format.
|
|
||||||
self::validateStringRegex($content, __FUNCTION__, "/^[\\x00-\\x7F]+$/", "Code93 barcode content");
|
|
||||||
break;
|
|
||||||
case self::BARCODE_CODE128:
|
|
||||||
self::validateInteger($len, 1, 255, __FUNCTION__, "Code128 barcode content length"); // 255 is a limitation of the "function b" command, not the barcode format.
|
|
||||||
// The CODE128 encoder is quite complex, so only a very basic header-check is applied here.
|
|
||||||
self::validateStringRegex($content, __FUNCTION__, "/^\{[A-C][\\x00-\\x7F]+$/", "Code128 barcode content");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(!$this -> profile -> getSupportsBarcodeB()) {
|
|
||||||
// A simpler barcode command which supports fewer codes
|
|
||||||
self::validateInteger($type, 65, 71, __FUNCTION__);
|
|
||||||
$this -> connector -> write(self::GS . "k" . chr($type - 65) . $content . self::NUL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// More advanced function B, used in preference
|
|
||||||
$this -> connector -> write(self::GS . "k" . chr($type) . chr(strlen($content)) . $content);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Print an image, using the older "bit image" command. This creates padding on the right of the image,
|
|
||||||
* if its width is not divisible by 8.
|
|
||||||
*
|
|
||||||
* Should only be used if your printer does not support the graphics() command.
|
|
||||||
*
|
|
||||||
* @param EscposImage $img The image to print
|
|
||||||
* @param EscposImage $size Size modifier for the image.
|
|
||||||
*/
|
|
||||||
function bitImage(EscposImage $img, $size = self::IMG_DEFAULT) {
|
|
||||||
self::validateInteger($size, 0, 3, __FUNCTION__);
|
|
||||||
$header = self::dataHeader(array($img -> getWidthBytes(), $img -> getHeight()), true);
|
|
||||||
$this -> connector -> write(self::GS . "v0" . chr($size) . $header);
|
|
||||||
$this -> connector -> write($img -> toRasterFormat());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close the underlying buffer. With some connectors, the
|
|
||||||
* job will not actually be sent to the printer until this is called.
|
|
||||||
*/
|
|
||||||
function close() {
|
|
||||||
$this -> connector -> finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cut the paper.
|
|
||||||
*
|
|
||||||
* @param int $mode Cut mode, either Escpos::CUT_FULL or Escpos::CUT_PARTIAL. If not specified, `Escpos::CUT_FULL` will be used.
|
|
||||||
* @param int $lines Number of lines to feed
|
|
||||||
*/
|
|
||||||
function cut($mode = self::CUT_FULL, $lines = 3) {
|
|
||||||
// TODO validation on cut() inputs
|
|
||||||
$this -> connector -> write(self::GS . "V" . chr($mode) . chr($lines));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Print and feed line / Print and feed n lines.
|
|
||||||
*
|
|
||||||
* @param int $lines Number of lines to feed
|
|
||||||
*/
|
|
||||||
function feed($lines = 1) {
|
|
||||||
self::validateInteger($lines, 1, 255, __FUNCTION__);
|
|
||||||
if($lines <= 1) {
|
|
||||||
$this -> connector -> write(self::LF);
|
|
||||||
} else {
|
|
||||||
$this -> connector -> write(self::ESC . "d" . chr($lines));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Some printers require a form feed to release the paper. On most printers, this
|
|
||||||
* command is only useful in page mode, which is not implemented in this driver.
|
|
||||||
*/
|
|
||||||
function feedForm() {
|
|
||||||
$this -> connector -> write(self::FF);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Print and reverse feed n lines.
|
|
||||||
*
|
|
||||||
* @param int $lines number of lines to feed. If not specified, 1 line will be fed.
|
|
||||||
*/
|
|
||||||
function feedReverse($lines = 1) {
|
|
||||||
self::validateInteger($lines, 1, 255, __FUNCTION__);
|
|
||||||
$this -> connector -> write(self::ESC . "e" . chr($lines));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return number
|
|
||||||
*/
|
|
||||||
function getCharacterTable() {
|
|
||||||
return $this -> characterTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return PrintBuffer
|
|
||||||
*/
|
|
||||||
function getPrintBuffer() {
|
|
||||||
return $this -> buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return PrintConnector
|
|
||||||
*/
|
|
||||||
function getPrintConnector() {
|
|
||||||
return $this -> connector;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return AbstractCapabilityProfile
|
|
||||||
*/
|
|
||||||
function getPrinterCapabilityProfile() {
|
|
||||||
return $this -> profile;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $type The type of status to request
|
|
||||||
* @return stdClass Class containing requested status, or null if either no status was received, or your print connector is unable to read from the printer.
|
|
||||||
*/
|
|
||||||
function getPrinterStatus($type = self::STATUS_PRINTER) {
|
|
||||||
self::validateIntegerMulti($type, array(array(1, 4), array(6, 8)), __FUNCTION__);
|
|
||||||
// Determine which flags we are looking for
|
|
||||||
$statusFlags = array(
|
|
||||||
self::STATUS_PRINTER => array(
|
|
||||||
4 => "pulseHigh", // connector pin 3, see pulse().
|
|
||||||
8 => "offline",
|
|
||||||
32 => "waitingForOnlineRecovery",
|
|
||||||
64 => "feedButtonPressed"
|
|
||||||
),
|
|
||||||
self::STATUS_OFFLINE_CAUSE => array(
|
|
||||||
4 => "coverOpen",
|
|
||||||
8 => "paperManualFeed",
|
|
||||||
32 => "paperEnd",
|
|
||||||
64 => "errorOccurred"
|
|
||||||
),
|
|
||||||
self::STATUS_ERROR_CAUSE => array(
|
|
||||||
4 => "recoverableError",
|
|
||||||
8 => "autocutterError",
|
|
||||||
32 => "unrecoverableError",
|
|
||||||
64 => "autorecoverableError"
|
|
||||||
),
|
|
||||||
self::STATUS_PAPER_ROLL => array(
|
|
||||||
4 => "paperNearEnd",
|
|
||||||
32 => "paperNotPresent"
|
|
||||||
),
|
|
||||||
self::STATUS_INK_A => array(
|
|
||||||
4 => "inkNearEnd",
|
|
||||||
8 => "inkEnd",
|
|
||||||
32 => "inkNotPresent",
|
|
||||||
64 => "cleaning"
|
|
||||||
),
|
|
||||||
self::STATUS_INK_B => array(
|
|
||||||
4 => "inkNearEnd",
|
|
||||||
8 => "inkEnd",
|
|
||||||
32 => "inkNotPresent"
|
|
||||||
),
|
|
||||||
self::STATUS_PEELER => array(
|
|
||||||
4 => "labelWaitingForRemoval",
|
|
||||||
32 => "labelPaperNotDetected"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$flags = $statusFlags[$type];
|
|
||||||
// Clear any previous statuses which haven't been read yet
|
|
||||||
$f = $this -> connector -> read(1);
|
|
||||||
// Make request
|
|
||||||
$reqC = chr($type);
|
|
||||||
switch($type) {
|
|
||||||
// Special cases: These are two-character requests
|
|
||||||
case self::STATUS_INK_A:
|
|
||||||
$reqC = chr(7) . chr(1);
|
|
||||||
break;
|
|
||||||
case self::STATUS_INK_B:
|
|
||||||
$reqC = chr(7) . chr(2);
|
|
||||||
break;
|
|
||||||
case self::STATUS_PEELER:
|
|
||||||
$reqC = chr(8) . chr(3);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$this -> connector -> write(self::DLE . self::EOT . $reqC);
|
|
||||||
// Wait for single-character response
|
|
||||||
$f = $this -> connector -> read(1);
|
|
||||||
$i = 0;
|
|
||||||
while($f === false && $i < 50000) {
|
|
||||||
usleep(100);
|
|
||||||
$f = $this -> connector -> read(1);
|
|
||||||
$i++;
|
|
||||||
}
|
|
||||||
if($f === false) {
|
|
||||||
// Timeout
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
$ret = new stdClass();
|
|
||||||
foreach($flags as $num => $name) {
|
|
||||||
$ret -> $name = (ord($f) & $num) != 0;
|
|
||||||
}
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Print an image to the printer.
|
|
||||||
*
|
|
||||||
* Size modifiers are:
|
|
||||||
* - IMG_DEFAULT (leave image at original size)
|
|
||||||
* - IMG_DOUBLE_WIDTH
|
|
||||||
* - IMG_DOUBLE_HEIGHT
|
|
||||||
*
|
|
||||||
* See the example/ folder for detailed examples.
|
|
||||||
*
|
|
||||||
* The function bitImage() takes the same parameters, and can be used if
|
|
||||||
* your printer doesn't support the newer graphics commands.
|
|
||||||
*
|
|
||||||
* @param EscposImage $img The image to print.
|
|
||||||
* @param int $size Output size modifier for the image.
|
|
||||||
*/
|
|
||||||
function graphics(EscposImage $img, $size = self::IMG_DEFAULT) {
|
|
||||||
self::validateInteger($size, 0, 3, __FUNCTION__);
|
|
||||||
$imgHeader = self::dataHeader(array($img -> getWidth(), $img -> getHeight()), true);
|
|
||||||
$tone = '0';
|
|
||||||
$colors = '1';
|
|
||||||
$xm = (($size & self::IMG_DOUBLE_WIDTH) == self::IMG_DOUBLE_WIDTH) ? chr(2) : chr(1);
|
|
||||||
$ym = (($size & self::IMG_DOUBLE_HEIGHT) == self::IMG_DOUBLE_HEIGHT) ? chr(2) : chr(1);
|
|
||||||
$header = $tone . $xm . $ym . $colors . $imgHeader;
|
|
||||||
$this -> wrapperSendGraphicsData('0', 'p', $header . $img -> toRasterFormat());
|
|
||||||
$this -> wrapperSendGraphicsData('0', '2');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize printer. This resets formatting back to the defaults.
|
|
||||||
*/
|
|
||||||
function initialize() {
|
|
||||||
$this -> connector -> write(self::ESC . "@");
|
|
||||||
$this -> characterTable = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a pulse, for opening a cash drawer if one is connected.
|
|
||||||
* The default settings should open an Epson drawer.
|
|
||||||
*
|
|
||||||
* @param int $pin 0 or 1, for pin 2 or pin 5 kick-out connector respectively.
|
|
||||||
* @param int $on_ms pulse ON time, in milliseconds.
|
|
||||||
* @param int $off_ms pulse OFF time, in milliseconds.
|
|
||||||
*/
|
|
||||||
function pulse($pin = 0, $on_ms = 120, $off_ms = 240) {
|
|
||||||
self::validateInteger($pin, 0, 1, __FUNCTION__);
|
|
||||||
self::validateInteger($on_ms, 1, 511, __FUNCTION__);
|
|
||||||
self::validateInteger($off_ms, 1, 511, __FUNCTION__);
|
|
||||||
$this -> connector -> write(self::ESC . "p" . chr($pin + 48) . chr($on_ms / 2) . chr($off_ms / 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Print the given data as a QR code on the printer.
|
|
||||||
*
|
|
||||||
* @param string $content The content of the code. Numeric data will be more efficiently compacted.
|
|
||||||
* @param int $ec Error-correction level to use. One of Escpos::QR_ECLEVEL_L (default), Escpos::QR_ECLEVEL_M, Escpos::QR_ECLEVEL_Q or Escpos::QR_ECLEVEL_H. Higher error correction results in a less compact code.
|
|
||||||
* @param int $size Pixel size to use. Must be 1-16 (default 3)
|
|
||||||
* @param int $model QR code model to use. Must be one of Escpos::QR_MODEL_1, Escpos::QR_MODEL_2 (default) or Escpos::QR_MICRO (not supported by all printers).
|
|
||||||
*/
|
|
||||||
function qrCode($content, $ec = self::QR_ECLEVEL_L, $size = 3, $model = self::QR_MODEL_2) {
|
|
||||||
self::validateString($content, __FUNCTION__);
|
|
||||||
self::validateInteger($ec, 0, 3, __FUNCTION__);
|
|
||||||
self::validateInteger($size, 1, 16, __FUNCTION__);
|
|
||||||
self::validateInteger($model, 1, 3, __FUNCTION__);
|
|
||||||
if($content == "") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(!$this -> profile -> getSupportsQrCode()) {
|
|
||||||
// TODO use software rendering via phpqrcode instead
|
|
||||||
throw new Exception("QR codes are not supported on your printer.");
|
|
||||||
}
|
|
||||||
$cn = '1'; // Code type for QR code
|
|
||||||
// Select model: 1, 2 or micro.
|
|
||||||
$this -> wrapperSend2dCodeData(chr(65), $cn, chr(48 + $model) . chr(0));
|
|
||||||
// Set dot size.
|
|
||||||
$this -> wrapperSend2dCodeData(chr(67), $cn, chr($size));
|
|
||||||
// Set error correction level: L, M, Q, or H
|
|
||||||
$this -> wrapperSend2dCodeData(chr(69), $cn, chr(48 + $ec));
|
|
||||||
// Send content & print
|
|
||||||
$this -> wrapperSend2dCodeData(chr(80), $cn, $content, '0');
|
|
||||||
$this -> wrapperSend2dCodeData(chr(81), $cn, '', '0');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Switch character table (code page) manually. Used in conjunction with textRaw() to
|
|
||||||
* print special characters which can't be encoded automatically.
|
|
||||||
*
|
|
||||||
* @param int $table The table to select. Available code tables are model-specific.
|
|
||||||
*/
|
|
||||||
function selectCharacterTable($table = 0) {
|
|
||||||
self::validateInteger($table, 0, 255, __FUNCTION__);
|
|
||||||
$supported = $this -> profile -> getSupportedCodePages();
|
|
||||||
if(!isset($supported[$table])) {
|
|
||||||
throw new InvalidArgumentException("There is no code table $table allowed by this printer's capability profile.");
|
|
||||||
}
|
|
||||||
$this -> characterTable = $table;
|
|
||||||
if($this -> profile -> getSupportsStarCommands()) {
|
|
||||||
/* Not an ESC/POS command: STAR printers stash all the extra code pages under a different command. */
|
|
||||||
$this -> connector -> write(self::ESC . self::GS . "t" . chr($table));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$this -> connector -> write(self::ESC . "t" . chr($table));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Select print mode(s).
|
|
||||||
*
|
|
||||||
* Several MODE_* constants can be OR'd together passed to this function's `$mode` argument. The valid modes are:
|
|
||||||
* - MODE_FONT_A
|
|
||||||
* - MODE_FONT_B
|
|
||||||
* - MODE_EMPHASIZED
|
|
||||||
* - MODE_DOUBLE_HEIGHT
|
|
||||||
* - MODE_DOUBLE_WIDTH
|
|
||||||
* - MODE_UNDERLINE
|
|
||||||
*
|
|
||||||
* @param int $mode The mode to use. Default is Escpos::MODE_FONT_A, with no special formatting. This has a similar effect to running initialize().
|
|
||||||
*/
|
|
||||||
function selectPrintMode($mode = self::MODE_FONT_A) {
|
|
||||||
$allModes = self::MODE_FONT_B | self::MODE_EMPHASIZED | self::MODE_DOUBLE_HEIGHT | self::MODE_DOUBLE_WIDTH | self::MODE_UNDERLINE;
|
|
||||||
if(!is_integer($mode) || $mode < 0 || ($mode & $allModes) != $mode) {
|
|
||||||
throw new InvalidArgumentException("Invalid mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
$this -> connector -> write(self::ESC . "!" . chr($mode));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set barcode height.
|
|
||||||
*
|
|
||||||
* @param int $height Height in dots. If not specified, 8 will be used.
|
|
||||||
*/
|
|
||||||
function setBarcodeHeight($height = 8) {
|
|
||||||
self::validateInteger($height, 1, 255, __FUNCTION__);
|
|
||||||
$this -> connector -> write(self::GS . "h" . chr($height));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the position for the Human Readable Interpretation (HRI) of barcode characters.
|
|
||||||
*
|
|
||||||
* @param position $position. Use Escpos::BARCODE_TEXT_NONE to hide the text (default), or any combination of Escpos::BARCODE_TEXT_TOP and Escpos::BARCODE_TEXT_BOTTOM flags to display the text.
|
|
||||||
*/
|
|
||||||
function setBarcodeTextPosition($position = self::BARCODE_TEXT_NONE) {
|
|
||||||
self::validateInteger($position, 0, 3, __FUNCTION__, "Barcode text position");
|
|
||||||
$this -> connector -> write(self::GS . "H" . chr($position));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Turn double-strike mode on/off.
|
|
||||||
*
|
|
||||||
* @param boolean $on true for double strike, false for no double strike
|
|
||||||
*/
|
|
||||||
function setDoubleStrike($on = true) {
|
|
||||||
self::validateBoolean($on, __FUNCTION__);
|
|
||||||
$this -> connector -> write(self::ESC . "G". ($on ? chr(1) : chr(0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Turn emphasized mode on/off.
|
|
||||||
*
|
|
||||||
* @param boolean $on true for emphasis, false for no emphasis
|
|
||||||
*/
|
|
||||||
function setEmphasis($on = true) {
|
|
||||||
self::validateBoolean($on, __FUNCTION__);
|
|
||||||
$this -> connector -> write(self::ESC . "E". ($on ? chr(1) : chr(0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Select font. Most printers have two fonts (Fonts A and B), and some have a third (Font C).
|
|
||||||
*
|
|
||||||
* @param int $font The font to use. Must be either Escpos::FONT_A, Escpos::FONT_B, or Escpos::FONT_C.
|
|
||||||
*/
|
|
||||||
function setFont($font = self::FONT_A) {
|
|
||||||
self::validateInteger($font, 0, 2, __FUNCTION__);
|
|
||||||
$this -> connector -> write(self::ESC . "M" . chr($font));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Select justification.
|
|
||||||
*
|
|
||||||
* @param int $justification One of Escpos::JUSTIFY_LEFT, Escpos::JUSTIFY_CENTER, or Escpos::JUSTIFY_RIGHT.
|
|
||||||
*/
|
|
||||||
function setJustification($justification = self::JUSTIFY_LEFT) {
|
|
||||||
self::validateInteger($justification, 0, 2, __FUNCTION__);
|
|
||||||
$this -> connector -> write(self::ESC . "a" . chr($justification));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attach a different print buffer to the printer. Buffers are responsible for handling text output to the printer.
|
|
||||||
*
|
|
||||||
* @param PrintBuffer $buffer The buffer to use.
|
|
||||||
* @throws InvalidArgumentException Where the buffer is already attached to a different printer.
|
|
||||||
*/
|
|
||||||
function setPrintBuffer(PrintBuffer $buffer) {
|
|
||||||
if($buffer === $this -> buffer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if($buffer -> getPrinter() != null) {
|
|
||||||
throw new InvalidArgumentException("This buffer is already attached to a printer.");
|
|
||||||
}
|
|
||||||
if($this -> buffer !== null) {
|
|
||||||
$this -> buffer -> setPrinter(null);
|
|
||||||
}
|
|
||||||
$this -> buffer = $buffer;
|
|
||||||
$this -> buffer -> setPrinter($this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set black/white reverse mode on or off. In this mode, text is printed white on a black background.
|
|
||||||
*
|
|
||||||
* @param boolean $on True to enable, false to disable.
|
|
||||||
*/
|
|
||||||
function setReverseColors($on = true) {
|
|
||||||
self::validateBoolean($on, __FUNCTION__);
|
|
||||||
$this -> connector -> write(self::GS . "B" . ($on ? chr(1) : chr(0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the size of text, as a multiple of the normal size.
|
|
||||||
*
|
|
||||||
* @param int $widthMultiplier Multiple of the regular height to use (range 1 - 8)
|
|
||||||
* @param int $heightMultiplier Multiple of the regular height to use (range 1 - 8)
|
|
||||||
*/
|
|
||||||
function setTextSize($widthMultiplier, $heightMultiplier) {
|
|
||||||
self::validateInteger($widthMultiplier, 1, 8, __FUNCTION__);
|
|
||||||
self::validateInteger($heightMultiplier, 1, 8, __FUNCTION__);
|
|
||||||
$c = pow(2,4) * ($widthMultiplier - 1) + ($heightMultiplier - 1);
|
|
||||||
$this -> connector -> write(self::GS . "!" . chr($c));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set underline for printed text.
|
|
||||||
*
|
|
||||||
* Argument can be true/false, or one of UNDERLINE_NONE,
|
|
||||||
* UNDERLINE_SINGLE or UNDERLINE_DOUBLE.
|
|
||||||
*
|
|
||||||
* @param int $underline Either true/false, or one of Escpos::UNDERLINE_NONE, Escpos::UNDERLINE_SINGLE or Escpos::UNDERLINE_DOUBLE. Defaults to Escpos::UNDERLINE_SINGLE.
|
|
||||||
*/
|
|
||||||
function setUnderline($underline = self::UNDERLINE_SINGLE) {
|
|
||||||
/* Map true/false to underline constants */
|
|
||||||
if($underline === true) {
|
|
||||||
$underline = self::UNDERLINE_SINGLE;
|
|
||||||
} else if($underline === false) {
|
|
||||||
$underline = self::UNDERLINE_NONE;
|
|
||||||
}
|
|
||||||
/* Set the underline */
|
|
||||||
self::validateInteger($underline, 0, 2, __FUNCTION__);
|
|
||||||
$this -> connector -> write(self::ESC . "-". chr($underline));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add text to the buffer.
|
|
||||||
*
|
|
||||||
* Text should either be followed by a line-break, or feed() should be called
|
|
||||||
* after this to clear the print buffer.
|
|
||||||
*
|
|
||||||
* @param string $str Text to print
|
|
||||||
*/
|
|
||||||
function text($str = "") {
|
|
||||||
self::validateString($str, __FUNCTION__);
|
|
||||||
$this -> buffer -> writeText((string)$str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add text to the buffer without attempting to interpret chararacter codes.
|
|
||||||
*
|
|
||||||
* Text should either be followed by a line-break, or feed() should be called
|
|
||||||
* after this to clear the print buffer.
|
|
||||||
*
|
|
||||||
* @param string $str Text to print
|
|
||||||
*/
|
|
||||||
function textRaw($str = "") {
|
|
||||||
self::validateString($str, __FUNCTION__);
|
|
||||||
$this -> buffer -> writeTextRaw((string)$str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper for GS ( k, to calculate and send correct data length.
|
|
||||||
*
|
|
||||||
* @param string $fn Function to use
|
|
||||||
* @param string $cn Output code type. Affects available data
|
|
||||||
* @param string $data Data to send.
|
|
||||||
* @param string $m Modifier/variant for function. Often '0' where used.
|
|
||||||
* @throws InvalidArgumentException Where the input lengths are bad.
|
|
||||||
*/
|
|
||||||
private function wrapperSend2dCodeData($fn, $cn, $data = '', $m = '') {
|
|
||||||
if(strlen($m) > 1 || strlen($cn) != 1 || strlen($fn) != 1) {
|
|
||||||
throw new InvalidArgumentException("wrapperSend2dCodeData: cn and fn must be one character each.");
|
|
||||||
}
|
|
||||||
$header = $this -> intLowHigh(strlen($data) + strlen($m) + 2, 2);
|
|
||||||
$this -> connector -> write(self::GS . "(k" . $header . $cn . $fn . $m . $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper for GS ( L, to calculate and send correct data length.
|
|
||||||
*
|
|
||||||
* @param string $m Modifier/variant for function. Usually '0'.
|
|
||||||
* @param string $fn Function number to use, as character.
|
|
||||||
* @param string $data Data to send.
|
|
||||||
* @throws InvalidArgumentException Where the input lengths are bad.
|
|
||||||
*/
|
|
||||||
private function wrapperSendGraphicsData($m, $fn, $data = '') {
|
|
||||||
if(strlen($m) != 1 || strlen($fn) != 1) {
|
|
||||||
throw new InvalidArgumentException("wrapperSendGraphicsData: m and fn must be one character each.");
|
|
||||||
}
|
|
||||||
$header = $this -> intLowHigh(strlen($data) + 2, 2);
|
|
||||||
$this -> connector -> write(self::GS . "(L" . $header . $m . $fn . $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert widths and heights to characters. Used before sending graphics to set the size.
|
|
||||||
*
|
|
||||||
* @param array $inputs
|
|
||||||
* @param boolean $long True to use 4 bytes, false to use 2
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private static function dataHeader(array $inputs, $long = true) {
|
|
||||||
$outp = array();
|
|
||||||
foreach($inputs as $input) {
|
|
||||||
if($long) {
|
|
||||||
$outp[] = Escpos::intLowHigh($input, 2);
|
|
||||||
} else {
|
|
||||||
self::validateInteger($input, 0 , 255, __FUNCTION__);
|
|
||||||
$outp[] = chr($input);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return implode("", $outp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate two characters for a number: In lower and higher parts, or more parts as needed.
|
|
||||||
* @param int $int Input number
|
|
||||||
* @param int $length The number of bytes to output (1 - 4).
|
|
||||||
*/
|
|
||||||
private static function intLowHigh($input, $length) {
|
|
||||||
$maxInput = (256 << ($length * 8) - 1);
|
|
||||||
self::validateInteger($length, 1, 4, __FUNCTION__);
|
|
||||||
self::validateInteger($input, 0, $maxInput, __FUNCTION__);
|
|
||||||
$outp = "";
|
|
||||||
for($i = 0; $i < $length; $i++) {
|
|
||||||
$outp .= chr($input % 256);
|
|
||||||
$input = (int)($input / 256);
|
|
||||||
}
|
|
||||||
return $outp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Throw an exception if the argument given is not a boolean
|
|
||||||
*
|
|
||||||
* @param boolean $test the input to test
|
|
||||||
* @param string $source the name of the function calling this
|
|
||||||
*/
|
|
||||||
protected static function validateBoolean($test, $source) {
|
|
||||||
if(!($test === true || $test === false)) {
|
|
||||||
throw new InvalidArgumentException("Argument to $source must be a boolean");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Throw an exception if the argument given is not an integer within the specified range
|
|
||||||
*
|
|
||||||
* @param int $test the input to test
|
|
||||||
* @param int $min the minimum allowable value (inclusive)
|
|
||||||
* @param int $max the maximum allowable value (inclusive)
|
|
||||||
* @param string $source the name of the function calling this
|
|
||||||
* @param string $argument the name of the invalid parameter
|
|
||||||
*/
|
|
||||||
protected static function validateInteger($test, $min, $max, $source, $argument = "Argument") {
|
|
||||||
self::validateIntegerMulti($test, array(array($min, $max)), $source, $argument);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Throw an exception if the argument given is not an integer within one of the specified ranges
|
|
||||||
*
|
|
||||||
* @param int $test the input to test
|
|
||||||
* @param arrray $ranges array of two-item min/max ranges.
|
|
||||||
* @param string $source the name of the function calling this
|
|
||||||
* @param string $source the name of the function calling this
|
|
||||||
* @param string $argument the name of the invalid parameter
|
|
||||||
*/
|
|
||||||
protected static function validateIntegerMulti($test, array $ranges, $source, $argument = "Argument") {
|
|
||||||
if(!is_integer($test)) {
|
|
||||||
throw new InvalidArgumentException("$argument given to $source must be a number, but '$test' was given.");
|
|
||||||
}
|
|
||||||
$match = false;
|
|
||||||
foreach($ranges as $range) {
|
|
||||||
$match |= $test >= $range[0] && $test <= $range[1];
|
|
||||||
}
|
|
||||||
if(!$match) {
|
|
||||||
// Put together a good error "range 1-2 or 4-6"
|
|
||||||
$rangeStr = "range ";
|
|
||||||
for($i = 0; $i < count($ranges); $i++) {
|
|
||||||
$rangeStr .= $ranges[$i][0] . "-" . $ranges[$i][1];
|
|
||||||
if($i == count($ranges) - 1) {
|
|
||||||
continue;
|
|
||||||
} else if($i == count($ranges) - 2) {
|
|
||||||
$rangeStr .= " or ";
|
|
||||||
} else {
|
|
||||||
$rangeStr .= ", ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new InvalidArgumentException("$argument given to $source must be in $rangeStr, but $test was given.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Throw an exception if the argument given can't be cast to a string
|
|
||||||
*
|
|
||||||
* @param string $test the input to test
|
|
||||||
* @param string $source the name of the function calling this
|
|
||||||
* @param string $argument the name of the invalid parameter
|
|
||||||
*/
|
|
||||||
protected static function validateString($test, $source, $argument = "Argument") {
|
|
||||||
if (is_object($test) && !method_exists($test, '__toString')) {
|
|
||||||
throw new InvalidArgumentException("$argument to $source must be a string");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static function validateStringRegex($test, $source, $regex, $argument = "Argument") {
|
|
||||||
if(preg_match($regex, $test) === 0) {
|
|
||||||
throw new InvalidArgumentException("$argument given to $source is invalid. It should match regex '$regex', but '$test' was given.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,7 @@
|
|||||||
escpos-php, a Thermal receipt printer library, for use with
|
MIT License
|
||||||
ESC/POS compatible printers.
|
|
||||||
|
|
||||||
Copyright (c) 2014-15 Michael Billington <michael.billington@gmail.com>,
|
Copyright (c) 2014-2016 Michael Billington, incorporating modifications by others.
|
||||||
incorporating modifications by:
|
See CONTRIBUTORS.md for a full list.
|
||||||
- Roni Saha <roni.cse@gmail.com>
|
|
||||||
- Gergely Radics <gerifield@ustream.tv>
|
|
||||||
- Warren Doyle <w.doyle@fuelled.co>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -13,10 +9,10 @@ in the Software without restriction, including without limitation the rights
|
|||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all
|
||||||
copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
@@ -24,4 +20,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
||||||
|
|||||||
@@ -1,73 +1,14 @@
|
|||||||
ESC/POS Print Driver for PHP
|
# ESC/POS Print Driver for PHP
|
||||||
============================
|
[](https://travis-ci.org/mike42/escpos-php) [](https://packagist.org/packages/mike42/escpos-php)
|
||||||
|
[](https://packagist.org/packages/mike42/escpos-php)
|
||||||
|
[](https://packagist.org/packages/mike42/escpos-php)
|
||||||
|
[](https://coveralls.io/github/mike42/escpos-php?branch=development)
|
||||||
|
|
||||||
This project implements a subset of Epson's ESC/POS protocol for thermal receipt printers. It allows you to generate and print receipts with basic formatting, cutting, and barcodes on a compatible printer.
|
This project implements a subset of Epson's ESC/POS protocol for thermal receipt printers. It allows you to generate and print receipts with basic formatting, cutting, and barcodes on a compatible printer.
|
||||||
|
|
||||||
The library was developed to add drop-in support for receipt printing to any PHP app, including web-based point-of-sale (POS) applications.
|
The library was developed to add drop-in support for receipt printing to any PHP app, including web-based point-of-sale (POS) applications.
|
||||||
|
|
||||||
Basic usage
|
## Compatibility
|
||||||
-----------
|
|
||||||
A "hello world" receipt can be generated easily (Call this `hello-world.php`):
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
require_once(dirname(__FILE__) . "/Escpos.php");
|
|
||||||
$printer = new Escpos();
|
|
||||||
$printer -> text("Hello World!\n");
|
|
||||||
$printer -> cut();
|
|
||||||
$printer -> close();
|
|
||||||
```
|
|
||||||
This would be printed as:
|
|
||||||
```
|
|
||||||
# Networked printer
|
|
||||||
php hello-world.php | nc 10.x.x.x. 9100
|
|
||||||
# Local printer
|
|
||||||
php hello-world.php > /dev/...
|
|
||||||
# Windows local printer
|
|
||||||
php hello-world.php > foo.txt
|
|
||||||
net use LPT1 \\server\printer
|
|
||||||
copy foo.txt LPT1
|
|
||||||
del foo.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
From your web app, you could pass the output directly to a socket if your printer is networked:
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
require_once(dirname(__FILE__) . "/Escpos.php");
|
|
||||||
$connector = new NetworkPrintConnector("10.x.x.x", 9100);
|
|
||||||
$printer = new Escpos($connector);
|
|
||||||
$printer -> text("Hello World!\n");
|
|
||||||
$printer -> cut();
|
|
||||||
$printer -> close();
|
|
||||||
```
|
|
||||||
|
|
||||||
Or to a local printer:
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
require_once(dirname(__FILE__) . "/Escpos.php");
|
|
||||||
$connector = new FilePrintConnector("/dev/ttyS0");
|
|
||||||
$printer = new Escpos($connector);
|
|
||||||
$printer -> text("Hello World!\n");
|
|
||||||
$printer -> cut();
|
|
||||||
$printer -> close();
|
|
||||||
```
|
|
||||||
|
|
||||||
### Basic workflow
|
|
||||||
The library should be initialised with a PrintConnector, which will pass on the data to your printer.
|
|
||||||
Use the table under "Compatibility", or the examples below to choose the appropriate connector for your
|
|
||||||
platform & interface. If no connector is specified, then standard output is used.
|
|
||||||
|
|
||||||
When you have finished using the print object, call `close()` to finalize any data transfers.
|
|
||||||
|
|
||||||
### Tips & examples
|
|
||||||
On Linux, your printer device file will be somewhere like `/dev/lp0` (parallel), `/dev/usb/lp1` (USB), `/dev/ttyUSB0` (USB-Serial), `/dev/ttyS0` (serial).
|
|
||||||
|
|
||||||
On Windows, the device files will be along the lines of `LPT1` (parallel) or `COM1` (serial). Use the `WindowsPrintConnector` to tap into system printing on Windows (eg. [Windows USB](https://github.com/mike42/escpos-php/tree/master/example/interface/windows-usb.php), [SMB](https://github.com/mike42/escpos-php/tree/master/example/interface/smb.php) or [Windows LPT](https://github.com/mike42/escpos-php/tree/master/example/interface/windows-lpt.php)) - this submits print jobs via a queue rather than communicating directly with the printer.
|
|
||||||
|
|
||||||
A complete real-world receipt can be found in the code of [Auth](https://github.com/mike42/Auth) in [ReceiptPrinter.php](https://github.com/mike42/Auth/blob/master/lib/misc/ReceiptPrinter.php). It includes justification, boldness, and a barcode.
|
|
||||||
|
|
||||||
Other examples are located in the [example/](https://github.com/mike42/escpos-php/blob/master/example/) directory.
|
|
||||||
|
|
||||||
Compatibility
|
|
||||||
-------------
|
|
||||||
|
|
||||||
### Interfaces and operating systems
|
### Interfaces and operating systems
|
||||||
This driver is known to work with the following OS/interface combinations:
|
This driver is known to work with the following OS/interface combinations:
|
||||||
@@ -115,43 +56,276 @@ This driver is known to work with the following OS/interface combinations:
|
|||||||
<td>No</td>
|
<td>No</td>
|
||||||
<td><a href="https://github.com/mike42/escpos-php/tree/master/example/interface/smb.php">Yes</a></td>
|
<td><a href="https://github.com/mike42/escpos-php/tree/master/example/interface/smb.php">Yes</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>CUPS hosted</th>
|
||||||
|
<td><a href="https://github.com/mike42/escpos-php/tree/master/example/interface/cups.php">Yes</a></td>
|
||||||
|
<td><a href="https://github.com/mike42/escpos-php/tree/master/example/interface/cups.php">Yes</a></td>
|
||||||
|
<td>No</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
### Printers
|
### Printers
|
||||||
Many thermal receipt printers support ESC/POS to some degree. This driver has been known to work with:
|
Many thermal receipt printers support ESC/POS to some degree. This driver has been known to work with:
|
||||||
|
|
||||||
|
- 3nStar RPT-008
|
||||||
|
- Approx APPPOS80AM
|
||||||
|
- AURES ODP-333
|
||||||
|
- AURES ODP-500
|
||||||
|
- Bematech-4200-TH
|
||||||
|
- Bematech LR2000E
|
||||||
|
- Birch PRP-085III
|
||||||
|
- Bixolon SRP-350III
|
||||||
|
- Bixolon SRP-350Plus
|
||||||
|
- Black Copper BC-85AC
|
||||||
|
- CHD TH-305N
|
||||||
|
- Citizen CBM1000-II
|
||||||
|
- Citizen CT-S310II
|
||||||
|
- Dapper-Geyi Q583P
|
||||||
|
- Daruma DR800
|
||||||
|
- DR-MP200 (manufacturer unknown)
|
||||||
- EPOS TEP 220M
|
- EPOS TEP 220M
|
||||||
|
- Elgin i9
|
||||||
|
- Epson EU-T332C
|
||||||
|
- Epson FX-890 (requires `feedForm()` to release paper).
|
||||||
|
- Epson TM-T20
|
||||||
|
- Epson TM-T20II
|
||||||
|
- Epson TM-T70
|
||||||
|
- Epson TM-T70II
|
||||||
|
- Epson TM-T81
|
||||||
|
- Epson TM-T82II
|
||||||
|
- Epson TM-T88II
|
||||||
- Epson TM-T88III
|
- Epson TM-T88III
|
||||||
- Epson TM-T88IV
|
- Epson TM-T88IV
|
||||||
- Epson TM-T70
|
- Epson TM-T88V
|
||||||
- Epson TM-T82II
|
|
||||||
- Epson TM-T20
|
|
||||||
- Epson TM-T70II
|
|
||||||
- Epson TM-U220
|
- Epson TM-U220
|
||||||
- Epson FX-890 (requires `feedForm()` to release paper).
|
- Epson TM-U295 (requires `release()` to release slip).
|
||||||
- Okipos 80 Plus III
|
- Epson TM-U590 and TM-U590P
|
||||||
|
- Equal (EQ-IT-001) POS-58
|
||||||
|
- Everycom EC-58
|
||||||
|
- Excelvan HOP-E200
|
||||||
|
- Excelvan HOP-E58
|
||||||
|
- Excelvan HOP-E801
|
||||||
|
- Gainscha GP-2120TF
|
||||||
|
- Gainscha GP-5890x (Also marketed as EC Line 5890x)
|
||||||
|
- Gainscha GP-U80300I (Also marketed as gprinter GP-U80300I)
|
||||||
|
- gprinter GP-U80160I
|
||||||
|
- HOIN HOP-H58
|
||||||
|
- Ithaca iTherm 28
|
||||||
|
- Hasar HTP 250
|
||||||
|
- Metapace T-1
|
||||||
|
- Metapace T-25
|
||||||
|
- Nexa PX700
|
||||||
|
- Nyear NP100
|
||||||
|
- OKI RT322
|
||||||
|
- OKI 80 Plus III
|
||||||
|
- Orient BTP-R580
|
||||||
- P-822D
|
- P-822D
|
||||||
|
- P85A-401 (make unknown)
|
||||||
|
- Partner Tech RP320
|
||||||
|
- POSLIGNE ODP200H-III-G
|
||||||
|
- QPOS Q58M
|
||||||
|
- Rongta RP326US
|
||||||
|
- Rongta RP58-U
|
||||||
|
- Rongta RP80USE
|
||||||
|
- SAM4S GIANT-100DB
|
||||||
|
- Senor TP-100
|
||||||
|
- Sewoo SLK-TS400
|
||||||
|
- SEYPOS PRP-96
|
||||||
- SEYPOS PRP-300 (Also marketed as TYSSO PRP-300)
|
- SEYPOS PRP-300 (Also marketed as TYSSO PRP-300)
|
||||||
|
- SNBC BTP-R880NPIII
|
||||||
|
- Solux SX-TP-88300
|
||||||
|
- Sicar POS-80
|
||||||
|
- Silicon SP-201 / RP80USE
|
||||||
|
- SPRT SP-POS88V
|
||||||
|
- Star BSC10
|
||||||
|
- Star TSP100 ECO
|
||||||
|
- Star TSP100III FuturePRNT
|
||||||
- Star TSP-650
|
- Star TSP-650
|
||||||
- Star TUP-592
|
- Star TUP-592
|
||||||
|
- TVS RP45 Shoppe
|
||||||
|
- Venus V248T
|
||||||
|
- Xeumior SM-8330
|
||||||
|
- Xprinter F-900
|
||||||
|
- Xprinter XP-365B
|
||||||
|
- Xprinter XP-58 Series
|
||||||
|
- Xprinter XP-80C
|
||||||
|
- Xprinter XP-90
|
||||||
|
- XPrinter XP-Q20011
|
||||||
- Xprinter XP-Q800
|
- Xprinter XP-Q800
|
||||||
- Zijang NT-58H
|
- Zjiang NT-58H
|
||||||
- Zijang ZJ-5870
|
- Zjiang ZJ-5870
|
||||||
- Zijang ZJ-5890T (Marketed as POS 5890T)
|
- Zjiang ZJ-5890 (Also sold as POS-5890 by many vendors; ZJ-5890K, ZJ-5890T also work).
|
||||||
|
- Zjiang ZJ-8220 (Also marketed as Excelvan ZJ-8220)
|
||||||
|
- Zjiang ZJ-8250
|
||||||
|
|
||||||
If you use any other printer with this code, please let me know so I can add it to the list.
|
If you use any other printer with this code, please [let us know](https://github.com/mike42/escpos-php/issues/new) so that it can be added to the list.
|
||||||
|
|
||||||
Available methods
|
## Basic usage
|
||||||
-----------------
|
|
||||||
|
|
||||||
### __construct(PrintConnector $connector, AbstractCapabilityProfile $profile)
|
### Include the library
|
||||||
|
|
||||||
|
#### Composer
|
||||||
|
If you are using composer, then add `mike42/escpos-php` as a dependency:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
composer require mike42/escpos-php
|
||||||
|
```
|
||||||
|
|
||||||
|
In this case, you would include composer's auto-loader at the top of your source files:
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
require __DIR__ . '/vendor/autoload.php';
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Manually
|
||||||
|
If you don't have composer available, then simply download the code and include `autoload.php`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/mike42/escpos-php vendor/mike42/escpos-php
|
||||||
|
```
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
require __DIR__ . '/vendor/mike42/escpos-php/autoload.php';
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Requirements
|
||||||
|
|
||||||
|
To maintain compatibility with as many systems as possible, this driver has few
|
||||||
|
hard dependencies:
|
||||||
|
|
||||||
|
- PHP 5.4 or above.
|
||||||
|
- `mbstring` extension, since the driver accepts UTF-8 encoding.
|
||||||
|
|
||||||
|
It is also suggested that you install either `imagick` or `gd`, so that you can
|
||||||
|
print images.
|
||||||
|
|
||||||
|
A number of optional packages can be added to enable more specific features. These
|
||||||
|
are described in the "suggest" section of [composer.json](https://github.com/mike42/escpos-php/tree/master/composer.json).
|
||||||
|
|
||||||
|
### The 'Hello World' receipt
|
||||||
|
|
||||||
|
To make use of this driver, your server (where PHP is installed) must be able to communicate with your printer. Start by generating a simple receipt and sending it to your printer using the command-line.
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
/* Call this file 'hello-world.php' */
|
||||||
|
require __DIR__ . '/vendor/autoload.php';
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
|
$printer = new Printer($connector);
|
||||||
|
$printer -> text("Hello World!\n");
|
||||||
|
$printer -> cut();
|
||||||
|
$printer -> close();
|
||||||
|
```
|
||||||
|
|
||||||
|
Some examples are below for common interfaces.
|
||||||
|
|
||||||
|
Communicate with a printer with an Ethernet interface using `netcat`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
php hello-world.php | nc 10.x.x.x. 9100
|
||||||
|
```
|
||||||
|
|
||||||
|
A USB local printer connected with `usblp` on Linux has a device file (Includes USB-parallel interfaces):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
php hello-world.php > /dev/usb/lp0
|
||||||
|
```
|
||||||
|
|
||||||
|
A computer installed into the local `cups` server is accessed through `lp` or `lpr`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
php hello-world.php > foo.txt
|
||||||
|
lpr -o raw -H localhost -P printer foo.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
A local or networked printer on a Windows computer is mapped in to a file, and generally requires you to share the printer first:
|
||||||
|
|
||||||
|
```
|
||||||
|
php hello-world.php > foo.txt
|
||||||
|
net use LPT1 \\server\printer
|
||||||
|
copy foo.txt LPT1
|
||||||
|
del foo.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
If you have troubles at this point, then you should consult your OS and printer system documentation to try to find a working print command.
|
||||||
|
|
||||||
|
### Using a PrintConnector
|
||||||
|
|
||||||
|
To print receipts from PHP, use the most applicable [PrintConnector](https://github.com/mike42/escpos-php/tree/master/src/Mike42/Escpos/PrintConnectors) for your setup. The connector simply provides the plumbing to get data to the printer.
|
||||||
|
|
||||||
|
For example, a `NetworkPrintConnector` accepts an IP address and port:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use Mike42\Escpos\PrintConnectors\NetworkPrintConnector;
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
$connector = new NetworkPrintConnector("10.x.x.x", 9100);
|
||||||
|
$printer = new Printer($connector);
|
||||||
|
try {
|
||||||
|
// ... Print stuff
|
||||||
|
} finally {
|
||||||
|
$printer -> close();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
While a serial printer might use:
|
||||||
|
```php
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
$connector = new FilePrintConnector("/dev/ttyS0");
|
||||||
|
$printer = new Printer($connector);
|
||||||
|
```
|
||||||
|
|
||||||
|
For each OS/interface combination that's supported, there are examples in the compatibility section of how a `PrintConnector` would be constructed. If you can't get a `PrintConnector` to work, then be sure to include the working print command in bug.
|
||||||
|
|
||||||
|
### Using a CapabilityProfile
|
||||||
|
|
||||||
|
Support for commands and code pages varies between printer vendors and models. By default, the driver will accept UTF-8, and output commands that are suitable for Epson TM-series printers.
|
||||||
|
|
||||||
|
When trying out a new brand of printer, it's a good idea to use the "simple" `CapabilityProfile`, which instructs the driver to avoid the use of advanced features (generally simpler image handling, ASCII-only text).
|
||||||
|
|
||||||
|
```php
|
||||||
|
use Mike42\Escpos\PrintConnectors\WindowsPrintConnector;
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
$profile = CapabilityProfile::load("simple");
|
||||||
|
$connector = new WindowsPrintConnector("smb://computer/printer");
|
||||||
|
$printer = new Printer($connector, $profile);
|
||||||
|
```
|
||||||
|
|
||||||
|
As another example, Star-branded printers use different commands:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use Mike42\Escpos\PrintConnectors\WindowsPrintConnector;
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
$profile = CapabilityProfile::load("SP2000")
|
||||||
|
$connector = new WindowsPrintConnector("smb://computer/printer");
|
||||||
|
$printer = new Printer($connector, $profile);
|
||||||
|
```
|
||||||
|
|
||||||
|
For a list of available profiles, or to have support for your printer improved, please see the upstream [receipt-print-hq/escpos-printer-db](https://github.com/receipt-print-hq/escpos-printer-db) project.
|
||||||
|
|
||||||
|
### Tips & examples
|
||||||
|
On Linux, your printer device file will be somewhere like `/dev/lp0` (parallel), `/dev/usb/lp1` (USB), `/dev/ttyUSB0` (USB-Serial), `/dev/ttyS0` (serial).
|
||||||
|
|
||||||
|
On Windows, the device files will be along the lines of `LPT1` (parallel) or `COM1` (serial). Use the `WindowsPrintConnector` to tap into system printing on Windows (eg. [Windows USB](https://github.com/mike42/escpos-php/tree/master/example/interface/windows-usb.php), [SMB](https://github.com/mike42/escpos-php/tree/master/example/interface/smb.php) or [Windows LPT](https://github.com/mike42/escpos-php/tree/master/example/interface/windows-lpt.php)) - this submits print jobs via a queue rather than communicating directly with the printer.
|
||||||
|
|
||||||
|
A complete real-world receipt can be found in the code of [Auth](https://github.com/mike42/Auth) in [ReceiptPrinter.php](https://github.com/mike42/Auth/blob/master/lib/misc/ReceiptPrinter.php). It includes justification, boldness, and a barcode.
|
||||||
|
|
||||||
|
Other examples are located in the [example/](https://github.com/mike42/escpos-php/blob/master/example/) directory.
|
||||||
|
|
||||||
|
## Available methods
|
||||||
|
|
||||||
|
### __construct(PrintConnector $connector, CapabilityProfile $profile)
|
||||||
Construct new print object.
|
Construct new print object.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- `PrintConnector $connector`: The PrintConnector to send data to. If not set, output is sent to standard output.
|
- `PrintConnector $connector`: The PrintConnector to send data to.
|
||||||
- `AbstractCapabilityProfile $profile` Supported features of this printer. If not set, the DefaultCapabilityProfile will be used, which is suitable for Epson printers.
|
- `CapabilityProfile $profile` Supported features of this printer. If not set, the "default" CapabilityProfile will be used, which is suitable for Epson printers.
|
||||||
|
|
||||||
See [example/interface/]("https://github.com/mike42/escpos-php/tree/master/example/interface/) for ways to open connections for different platforms and interfaces.
|
See [example/interface/](https://github.com/mike42/escpos-php/tree/master/example/interface/) for ways to open connections for different platforms and interfaces.
|
||||||
|
|
||||||
### barcode($content, $type)
|
### barcode($content, $type)
|
||||||
Print a barcode.
|
Print a barcode.
|
||||||
@@ -159,7 +333,7 @@ Print a barcode.
|
|||||||
Parameters:
|
Parameters:
|
||||||
|
|
||||||
- `string $content`: The information to encode.
|
- `string $content`: The information to encode.
|
||||||
- `int $type`: The barcode standard to output. If not specified, `Escpos::BARCODE_CODE39` will be used.
|
- `int $type`: The barcode standard to output. If not specified, `Printer::BARCODE_CODE39` will be used.
|
||||||
|
|
||||||
Currently supported barcode standards are (depending on your printer):
|
Currently supported barcode standards are (depending on your printer):
|
||||||
|
|
||||||
@@ -181,7 +355,7 @@ Cut the paper.
|
|||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
|
|
||||||
- `int $mode`: Cut mode, either `Escpos::CUT_FULL` or `Escpos::CUT_PARTIAL`. If not specified, `Escpos::CUT_FULL` will be used.
|
- `int $mode`: Cut mode, either `Printer::CUT_FULL` or `Printer::CUT_PARTIAL`. If not specified, `Printer::CUT_FULL` will be used.
|
||||||
- `int $lines`: Number of lines to feed before cutting. If not specified, 3 will be used.
|
- `int $lines`: Number of lines to feed before cutting. If not specified, 3 will be used.
|
||||||
|
|
||||||
### feed($lines)
|
### feed($lines)
|
||||||
@@ -219,17 +393,29 @@ A minimal example:
|
|||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
<?php
|
||||||
$img = new EscposImage("logo.png");
|
$img = EscposImage::load("logo.png");
|
||||||
$printer -> graphics($img);
|
$printer -> graphics($img);
|
||||||
```
|
```
|
||||||
|
|
||||||
See the [example/](https://github.com/mike42/escpos-php/blob/master/example/) folder for detailed examples.
|
See the [example/](https://github.com/mike42/escpos-php/blob/master/example/) folder for detailed examples.
|
||||||
|
|
||||||
The function [bitImage()](#bitimageescposimage-image-size) takes the same parameters, and can be used if your printer doesn't support the newer graphics commands.
|
The function [bitImage()](#bitimageescposimage-image-size) takes the same parameters, and can be used if your printer doesn't support the newer graphics commands. As an additional fallback, the `bitImageColumnFormat()` function is also provided.
|
||||||
|
|
||||||
### initialize()
|
### initialize()
|
||||||
Initialize printer. This resets formatting back to the defaults.
|
Initialize printer. This resets formatting back to the defaults.
|
||||||
|
|
||||||
|
### pdf417Code($content, $width, $heightMultiplier, $dataColumnCount, $ec, $options)
|
||||||
|
Print a two-dimensional data code using the PDF417 standard.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `string $content`: Text or numbers to store in the code
|
||||||
|
- `number $width`: Width of a module (pixel) in the printed code. Default is 3 dots.
|
||||||
|
- `number $heightMultiplier`: Multiplier for height of a module. Default is 3 times the width.
|
||||||
|
- `number $dataColumnCount`: Number of data columns to use. 0 (default) is to auto-calculate. Smaller numbers will result in a narrower code, making larger pixel sizes possible. Larger numbers require smaller pixel sizes.
|
||||||
|
- `real $ec`: Error correction ratio, from 0.01 to 4.00. Default is 0.10 (10%).
|
||||||
|
- `number $options`: Standard code `Printer::PDF417_STANDARD` with start/end bars, or truncated code `Printer::PDF417_TRUNCATED` with start bars only.
|
||||||
|
|
||||||
### pulse($pin, $on_ms, $off_ms)
|
### pulse($pin, $on_ms, $off_ms)
|
||||||
Generate a pulse, for opening a cash drawer if one is connected. The default settings (0, 120, 240) should open an Epson drawer.
|
Generate a pulse, for opening a cash drawer if one is connected. The default settings (0, 120, 240) should open an Epson drawer.
|
||||||
|
|
||||||
@@ -243,16 +429,16 @@ Parameters:
|
|||||||
Print the given data as a QR code on the printer.
|
Print the given data as a QR code on the printer.
|
||||||
|
|
||||||
- `string $content`: The content of the code. Numeric data will be more efficiently compacted.
|
- `string $content`: The content of the code. Numeric data will be more efficiently compacted.
|
||||||
- `int $ec` Error-correction level to use. One of `Escpos::QR_ECLEVEL_L` (default), `Escpos::QR_ECLEVEL_M`, `Escpos::QR_ECLEVEL_Q` or `Escpos::QR_ECLEVEL_H`. Higher error correction results in a less compact code.
|
- `int $ec` Error-correction level to use. One of `Printer::QR_ECLEVEL_L` (default), `Printer::QR_ECLEVEL_M`, `Printer::QR_ECLEVEL_Q` or `Printer::QR_ECLEVEL_H`. Higher error correction results in a less compact code.
|
||||||
- `int $size`: Pixel size to use. Must be 1-16 (default 3)
|
- `int $size`: Pixel size to use. Must be 1-16 (default 3)
|
||||||
- `int $model`: QR code model to use. Must be one of `Escpos::QR_MODEL_1`, `Escpos::QR_MODEL_2` (default) or `Escpos::QR_MICRO` (not supported by all printers).
|
- `int $model`: QR code model to use. Must be one of `Printer::QR_MODEL_1`, `Printer::QR_MODEL_2` (default) or `Printer::QR_MICRO` (not supported by all printers).
|
||||||
|
|
||||||
### selectPrintMode($mode)
|
### selectPrintMode($mode)
|
||||||
Select print mode(s).
|
Select print mode(s).
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
|
|
||||||
- `int $mode`: The mode to use. Default is `Escpos::MODE_FONT_A`, with no special formatting. This has a similar effect to running `initialize()`.
|
- `int $mode`: The mode to use. Default is `Printer::MODE_FONT_A`, with no special formatting. This has a similar effect to running `initialize()`.
|
||||||
|
|
||||||
Several MODE_* constants can be OR'd together passed to this function's `$mode` argument. The valid modes are:
|
Several MODE_* constants can be OR'd together passed to this function's `$mode` argument. The valid modes are:
|
||||||
|
|
||||||
@@ -270,6 +456,20 @@ Parameters:
|
|||||||
|
|
||||||
- `int $height`: Height in dots. If not specified, 8 will be used.
|
- `int $height`: Height in dots. If not specified, 8 will be used.
|
||||||
|
|
||||||
|
### setBarcodeWidth($width)
|
||||||
|
Set barcode bar width.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `int $width`: Bar width in dots. If not specified, 3 will be used. Values above 6 appear to have no effect.
|
||||||
|
|
||||||
|
### setColor($color)
|
||||||
|
Select print color - on printers that support multiple colors.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `int $color`: Color to use. Must be either `Printer::COLOR_1` (default), or `Printer::COLOR_2`
|
||||||
|
|
||||||
### setDoubleStrike($on)
|
### setDoubleStrike($on)
|
||||||
Turn double-strike mode on/off.
|
Turn double-strike mode on/off.
|
||||||
|
|
||||||
@@ -289,14 +489,40 @@ Select font. Most printers have two fonts (Fonts A and B), and some have a third
|
|||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
|
|
||||||
- `int $font`: The font to use. Must be either `Escpos::FONT_A`, `Escpos::FONT_B`, or `Escpos::FONT_C`.
|
- `int $font`: The font to use. Must be either `Printer::FONT_A`, `Printer::FONT_B`, or `Printer::FONT_C`.
|
||||||
|
|
||||||
### setJustification($justification)
|
### setJustification($justification)
|
||||||
Select justification.
|
Select justification.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
|
|
||||||
- `int $justification`: One of `Escpos::JUSTIFY_LEFT`, `Escpos::JUSTIFY_CENTER`, or `Escpos::JUSTIFY_RIGHT`.
|
- `int $justification`: One of `Printer::JUSTIFY_LEFT`, `Printer::JUSTIFY_CENTER`, or `Printer::JUSTIFY_RIGHT`.
|
||||||
|
|
||||||
|
### setLineSpacing($height)
|
||||||
|
|
||||||
|
Set the height of the line.
|
||||||
|
|
||||||
|
Some printers will allow you to overlap lines with a smaller line feed.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `int $height`: The height of each line, in dots. If not set, the printer will reset to its default line spacing.
|
||||||
|
|
||||||
|
### setPrintLeftMargin($margin)
|
||||||
|
|
||||||
|
Set print area left margin. Reset to default with `Printer::initialize()`.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `int $margin`: The left margin to set on to the print area, in dots.
|
||||||
|
|
||||||
|
### setPrintWidth($width)
|
||||||
|
|
||||||
|
Set print area width. This can be used to add a right margin to the print area. Reset to default with `Printer::initialize()`.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
- `int $width`: The width of the page print area, in dots.
|
||||||
|
|
||||||
### setReverseColors($on)
|
### setReverseColors($on)
|
||||||
Set black/white reverse mode on or off. In this mode, text is printed white on a black background.
|
Set black/white reverse mode on or off. In this mode, text is printed white on a black background.
|
||||||
@@ -318,7 +544,7 @@ Set underline for printed text.
|
|||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
|
|
||||||
- `int $underline`: Either `true`/`false`, or one of `Escpos::UNDERLINE_NONE`, `Escpos::UNDERLINE_SINGLE` or `Escpos::UNDERLINE_DOUBLE`. Defaults to `Escpos::UNDERLINE_SINGLE`.
|
- `int $underline`: Either `true`/`false`, or one of `Printer::UNDERLINE_NONE`, `Printer::UNDERLINE_SINGLE` or `Printer::UNDERLINE_DOUBLE`. Defaults to `Printer::UNDERLINE_SINGLE`.
|
||||||
|
|
||||||
### text($str)
|
### text($str)
|
||||||
Add text to the buffer. Text should either be followed by a line-break, or `feed()` should be called after this.
|
Add text to the buffer. Text should either be followed by a line-break, or `feed()` should be called after this.
|
||||||
@@ -327,26 +553,37 @@ Parameters:
|
|||||||
|
|
||||||
- `string $str`: The string to print.
|
- `string $str`: The string to print.
|
||||||
|
|
||||||
Further notes
|
# Further notes
|
||||||
-------------
|
|
||||||
Posts I've written up for people who are learning how to use receipt printers:
|
Posts I've written up for people who are learning how to use receipt printers:
|
||||||
|
|
||||||
* [What is ESC/POS, and how do I use it?](http://mike.bitrevision.com/blog/what-is-escpos-and-how-do-i-use-it), which documents the output of test.php.
|
* [What is ESC/POS, and how do I use it?](https://mike42.me/blog/what-is-escpos-and-how-do-i-use-it), which documents the output of `example/demo.php`.
|
||||||
* [Setting up an Epson receipt printer](http://mike.bitrevision.com/blog/2014-20-26-setting-up-an-epson-receipt-printer)
|
* [Setting up an Epson receipt printer](https://mike42.me/blog/2014-20-26-setting-up-an-epson-receipt-printer)
|
||||||
* [Getting a USB receipt printer working on Linux](http://mike.bitrevision.com/blog/2015-03-getting-a-usb-receipt-printer-working-on-linux)
|
* [Getting a USB receipt printer working on Linux](https://mike42.me/blog/2015-03-getting-a-usb-receipt-printer-working-on-linux)
|
||||||
|
|
||||||
Other versions
|
# Development
|
||||||
--------------
|
|
||||||
Some forks of this project have been developed by others for specific use cases. Improvements from the following projects have been incorporated into escpos-php:
|
|
||||||
|
|
||||||
- [wdoyle/EpsonESCPOS-PHP](https://github.com/wdoyle/EpsonESCPOS-PHP)
|
This code is MIT licensed, and you are encouraged to contribute any modifications back to the project.
|
||||||
- [ronisaha/php-esc-pos](https://github.com/ronisaha/php-esc-pos)
|
|
||||||
|
|
||||||
Vendor documentation
|
For development, it's suggested that you load `imagick`, `gd` and `Xdebug` PHP exensions, and install `composer`.
|
||||||
--------------------
|
|
||||||
Epson notes that not all of its printers support all ESC/POS features, and includes a table in their documentation:
|
|
||||||
|
|
||||||
* [FAQ about ESC/POS from Epson](http://content.epson.de/fileadmin/content/files/RSD/downloads/escpos.pdf)
|
The tests are executed on [Travis CI](https://travis-ci.org/mike42/escpos-php) over PHP 5.4, 5.5, 5.6, 7.0, 7.1 and 7.2, plus the latest LTS version of HHVM, 3.21. Older versions of PHP are not supported in current releases.
|
||||||
|
|
||||||
Note that many printers produced by other vendors use the same standard, and are compatible by varying degrees.
|
Fetch a copy of this code and load dependencies with composer:
|
||||||
|
|
||||||
|
git clone https://github.com/mike42/escpos-php
|
||||||
|
cd escpos-php/
|
||||||
|
composer install
|
||||||
|
|
||||||
|
Execute unit tests via `phpunit`:
|
||||||
|
|
||||||
|
php vendor/bin/phpunit --coverage-text
|
||||||
|
|
||||||
|
This project uses the PSR-2 standard, which can be checked via [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer):
|
||||||
|
|
||||||
|
php vendor/bin/phpcs --standard=psr2 src/ -n
|
||||||
|
|
||||||
|
The developer docs are build with [doxygen](https://github.com/doxygen/doxygen). Re-build them to check for documentation warnings:
|
||||||
|
|
||||||
|
make -C doc clean && make -C doc
|
||||||
|
|
||||||
|
Pull requests and bug reports welcome.
|
||||||
|
|||||||
26
htdocs/includes/mike42/escpos-php/autoload.php
Normal file
26
htdocs/includes/mike42/escpos-php/autoload.php
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Users who do not have 'composer' to manage dependencies, include this
|
||||||
|
* file to provide auto-loading of the classes in this library.
|
||||||
|
*/
|
||||||
|
spl_autoload_register ( function ($class) {
|
||||||
|
/*
|
||||||
|
* PSR-4 autoloader, based on PHP Framework Interop Group snippet (Under MIT License.)
|
||||||
|
* https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-examples.md
|
||||||
|
*/
|
||||||
|
$prefix = "Mike42\\";
|
||||||
|
$base_dir = __DIR__ . "/src/Mike42/";
|
||||||
|
|
||||||
|
/* Only continue for classes in this namespace */
|
||||||
|
$len = strlen ( $prefix );
|
||||||
|
if (strncmp ( $prefix, $class, $len ) !== 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Require the file if it exists */
|
||||||
|
$relative_class = substr ( $class, $len );
|
||||||
|
$file = $base_dir . str_replace ( '\\', '/', $relative_class ) . '.php';
|
||||||
|
if (file_exists ( $file )) {
|
||||||
|
require $file;
|
||||||
|
}
|
||||||
|
} );
|
||||||
@@ -1,36 +1,38 @@
|
|||||||
{
|
{
|
||||||
"name": "mike42/escpos-php",
|
"name": "mike42/escpos-php",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"description": "Thermal receipt printer library, for use with ESC/POS compatible printers",
|
"description": "PHP receipt printer library for use with ESC/POS-compatible thermal and impact printers",
|
||||||
"homepage": "https://github.com/mike42/escpos-php",
|
"homepage": "https://github.com/mike42/escpos-php",
|
||||||
"keywords": ["receipt", "print", "escpos", "ESC-POS", "driver"],
|
"keywords": ["receipt", "print", "escpos", "ESC-POS", "driver"],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Michael Billington",
|
"name": "Michael Billington",
|
||||||
"email": "michael.billington@gmail.com"
|
"email": "michael.billington@gmail.com"
|
||||||
},
|
}
|
||||||
{
|
],
|
||||||
"name": "Roni Saha",
|
"config": {
|
||||||
"email": "roni.cse@gmail.com"
|
"platform": {
|
||||||
},
|
"php": "5.4.0"
|
||||||
{
|
}
|
||||||
"name": "Gergely Radics",
|
},
|
||||||
"email": "gerifield@ustream.tv"
|
"require": {
|
||||||
},
|
"php": ">=5.4.0",
|
||||||
{
|
"ext-mbstring": "*"
|
||||||
"name": "Warren Doyle",
|
},
|
||||||
"email": "w.doyle@fuelled.co"
|
"suggest": {
|
||||||
},
|
"guzzlehttp/guzzle": "Allows the use of the ApiConnector to send print jobs over HTTP.",
|
||||||
{
|
"ext-imagick": "Will be used for image printing if present. Required for PDF printing or use of custom fonts.",
|
||||||
"name": "vharo",
|
"ext-gd": "Used for image printing if present."
|
||||||
"email": "vharo@geepok.com"
|
},
|
||||||
}
|
"require-dev": {
|
||||||
],
|
"phpunit/phpunit": "^4.8",
|
||||||
"require": {
|
"squizlabs/php_codesniffer": "^3.2",
|
||||||
"php": ">=5.3.0"
|
"guzzlehttp/guzzle": "^5.3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"autoload": {
|
||||||
"phpunit/phpunit": "4.5.*"
|
"psr-4": {
|
||||||
}
|
"Mike42\\": "src/Mike42"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
615
htdocs/includes/mike42/escpos-php/composer.lock
generated
615
htdocs/includes/mike42/escpos-php/composer.lock
generated
File diff suppressed because it is too large
Load Diff
142
htdocs/includes/mike42/escpos-php/doc/FAQ.md
Normal file
142
htdocs/includes/mike42/escpos-php/doc/FAQ.md
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
# Frequently Asked Questions (FAQ)
|
||||||
|
|
||||||
|
## Can I print to File Format X with this?
|
||||||
|
|
||||||
|
If you are trying to generate XPS, PDF or DOCX or HTML files from PHP, then you are most likely in the wrong place.
|
||||||
|
|
||||||
|
The purpose of this driver it to generate binary ESC/POS code, which is understood by many embedded thermal receipt and impact printers.
|
||||||
|
|
||||||
|
## I have Printer X. Can I use this driver?
|
||||||
|
|
||||||
|
If the printer understands ESC/POS, and you know how to get raw binary data to it, then yes. Otherwise, no.
|
||||||
|
|
||||||
|
The [list of printers that are known to work](https://github.com/mike42/escpos-php/blob/development/README.md#printers) is crowd-sourced. We appreciate it when developers try out the driver, then [file information on the bug tracker](https://github.com/mike42/escpos-php/issues/new) with some information about which features worked on their model of printer.
|
||||||
|
|
||||||
|
To see how well your printer works, first check that it supports ESC/POS, then begin by attempting to send the text "Hello World" to your printer on the command-line, from the computer that will run PHP.
|
||||||
|
|
||||||
|
Once you solve this, [try to do the same from PHP](https://github.com/mike42/escpos-php/blob/development/README.md#basic-usage) using the default profile. Further details are in the [README](https://github.com/mike42/escpos-php/blob/development/README.md) file.
|
||||||
|
|
||||||
|
## Can you add support for Printer X?
|
||||||
|
|
||||||
|
Features vary between printers, so we collaborate on an ESC/POS printer compatibility database to collect known differences: [receipt-print-hq/escpos-printer-db](https://github.com/receipt-print-hq/escpos-printer-db).
|
||||||
|
|
||||||
|
If you encounter garbage output when you try to print images or special characters, then please submit a test page and a link to vendor documentation to the `escpos-printer-db` project, so that support can be improved for future versions.
|
||||||
|
|
||||||
|
## I have a printer that does not understand ESC/POS. Can I use this driver?
|
||||||
|
|
||||||
|
No. The purpose of this driver it to generate binary ESC/POS code. If your printer doesn't understand that, then this code wont be much use to you.
|
||||||
|
|
||||||
|
Some printers do have an emulation mode for ESC/POS. The vendor docs will tell if this is the case, and how to enable it.
|
||||||
|
|
||||||
|
## Why do I get this error when I try to print?
|
||||||
|
|
||||||
|
Start by testing that you can send text to your printer outside of escpos-php. The examples linked to in the README are commented with some commands to get you started.
|
||||||
|
|
||||||
|
Generally, initial setup problems seem to have one of these causes:
|
||||||
|
|
||||||
|
1. You are writing to the wrong place. Writing to `LPT1` does not output to parallel port on Linux, and `/dev/ttyS0` is not a serial printer on Windows.
|
||||||
|
2. The printer has not been set up to accept printing the way you expect. This means permissions on Linux, network printers being configured, and shared printers having user accounts and firewalls set up correctly on the print server.
|
||||||
|
3. Your printer actually doesn't work (rare but possible).
|
||||||
|
|
||||||
|
To be clear, these are not escpos-php issues: No amount of PHP code can set up your printer for you. Instead, the driver relies on developers determining how their setup is going to work before using a connector to transport data to their printer.
|
||||||
|
|
||||||
|
Once you have a working command to send text to your printer (from the PHP server), you are ready to use escpos-php. You can try to use a PrintConnector now, based on your operating system and printer interface. A table is located in the README to help you select the right one.
|
||||||
|
|
||||||
|
The connectors are-
|
||||||
|
|
||||||
|
- `FilePrintConnector` and `NetworkPrintConnector` directly use files or network sockets.
|
||||||
|
- `WindowsPrintConnector` and `CupsPrintConnector` tie in with Windows and Unix system printing.
|
||||||
|
- `DummyPrintConnector` does not connect to a real printer, and can be used to save ESC/POS receipts to a database, for example.
|
||||||
|
|
||||||
|
At this point, you might find that the way you would like to print is not supported by escpos-php. You can post your printing command as a feature request on the issue tracker.
|
||||||
|
|
||||||
|
Lastly, you may run in to the final common trap:
|
||||||
|
|
||||||
|
4. Your PHP is not running with the same sort of permissions as your login account. Again, no amount of PHP code can fix this. For example, on LAMP, your `www-data` user needs to be in the `lp` group, while on WAMP, `Local Service` account may run in to problems. SELinux and firewalls are also worth a look.
|
||||||
|
|
||||||
|
When printing fails, you can expect a PHP Exception that explains what went wrong. They are all clues:
|
||||||
|
|
||||||
|
- `Warning: copy(\\pc\printer): failed to open stream: Permission denied`
|
||||||
|
- `/dev/usb/lp0: Permission denied`
|
||||||
|
- `User name or password is incorrect`
|
||||||
|
|
||||||
|
Ensure that while you are developing, you configure PHP to show error messages, so that you can see these problems.
|
||||||
|
|
||||||
|
Please file a bug if you think that there is a specific situation which escpos-php could provide better error messages for.
|
||||||
|
|
||||||
|
## Can I print over the network?
|
||||||
|
|
||||||
|
Certainly, as long as your printer is available over the network.
|
||||||
|
|
||||||
|
- `NetworkPrintConnector` will speak directly to an Ethernet-connected printer on port 9100.
|
||||||
|
|
||||||
|
For USB or Serial printers, you need to install the printer on a computer and then share it, so that it becomes network-accessible.
|
||||||
|
|
||||||
|
- `WindowsPrintConnector` will connect to Windows shared printers from Windows or Linux (Linux users will need Samba).
|
||||||
|
- `CupsPrintConnector` will connect to CUPS-shared printers from Linux or Mac.
|
||||||
|
|
||||||
|
Always start by testing your shared printer setup outside of escpos-php. The examples linked to in the README are commented with some example commands to get you started. Typically, networks, firewalls and permissions need to be set up.
|
||||||
|
|
||||||
|
Once you have a working command to send text to your printer (from the PHP server), you are ready to use escpos-php.
|
||||||
|
|
||||||
|
If you have any issues at this stage, please ask on the issue tracker, and include the commands that you used to verify your setup.
|
||||||
|
|
||||||
|
## Can I print from my server on the Internet?
|
||||||
|
|
||||||
|
Since PHP is a server-side language, escpos-php is a server-side print library. The driver is able to transport data between a server and a printer in a few different ways, all of them server-side. For example, you may print to a USB printer *connected to the server running PHP*, or an Ethernet printer *on a network accessible to the server*.
|
||||||
|
|
||||||
|
Many developers dream of having an application that is hosted on the public Internet, with POS terminals accessing it, and printing via a web browser. Because the webserver cannot see the printer in this sort of setup, a server-side print driver is not much use.
|
||||||
|
|
||||||
|
Because of this, there are no cut-and-paste recipes available, but here are two top-level approaches you could take:
|
||||||
|
|
||||||
|
1. Architect your application so that the server can see your printer
|
||||||
|
2. Use an application which runs client-side to deliver print data instead
|
||||||
|
|
||||||
|
### Option 1: Allow the server to print
|
||||||
|
|
||||||
|
Server-side printing is viable if the server can get to the printer. Here are some ways it could work:
|
||||||
|
|
||||||
|
- Run your server on the LAN instead, and read the section above about printing over the network
|
||||||
|
- Set up a VPN so that your cloud-hosted server can also access the LAN
|
||||||
|
- Expose the printer via some other secure tunnel to the server, via SSH or TLS
|
||||||
|
|
||||||
|
Please do your own research to determine how these may apply to your setup- the escpos-php issue tracker is not a place where you should be requesting network support.
|
||||||
|
|
||||||
|
### Option 2: Use client software to print
|
||||||
|
|
||||||
|
If you aren't able to set up some network infrastructure to implement the above, then you cannot use a server-side print driver.
|
||||||
|
|
||||||
|
Here are some browser-based printing tools which you may like to consider instead.
|
||||||
|
|
||||||
|
- Use system printing with a vendor driver, and some good `@media print` CSS
|
||||||
|
- [Chrome Raw Print](https://github.com/receipt-print-hq/chrome-raw-print) app
|
||||||
|
- [qz](https://qz.io/)
|
||||||
|
- [ePOS-Device SDK for JavaScript](https://reference.epson-biz.com/modules/ref_epos_device_js_en/index.php?content_id=139). Requires network interface card that supports ePOS (UB-E04/R04)
|
||||||
|
|
||||||
|
Please direct queries about client-side printing products to the appropriate project.
|
||||||
|
|
||||||
|
## Why is image printing slow?
|
||||||
|
|
||||||
|
Three things tend to slow down the image processing:
|
||||||
|
|
||||||
|
1. Slow PHP code
|
||||||
|
2. Data link
|
||||||
|
3. The printer itself
|
||||||
|
|
||||||
|
First, ensure you have the Imagick plugin loaded. The driver will avoid a slower image processing implementation once you've got it.
|
||||||
|
|
||||||
|
Next, connect over a faster interface. Serial printers have a low bit-rate, and the printer spends a lot of time waiting for data. If you have USB or Ethernet, then use it (note: storing graphics to the printer memory is not currently implemented).
|
||||||
|
|
||||||
|
Lastly, the printer will go faster if you use less pixels. Since images are two-dimensional, scaling down by 50% removes 75% of the pixels. The driver can then print at a half the density, so that your lower resolution image appears the same size when printed.
|
||||||
|
|
||||||
|
## How can I get the status of the printer?
|
||||||
|
|
||||||
|
This feature is not implemented, but a solution for some Epson printers is planned.
|
||||||
|
|
||||||
|
Only `FilePrintConnector` or `NetworkPrintConnector` will support reading from the printer, ensure that you migrate to those if you would like these features.
|
||||||
|
|
||||||
|
## How do I produce this complex layout?
|
||||||
|
|
||||||
|
ESC/POS "page mode" is not currently supported, which would allow some printers to render some more complex layouts natively
|
||||||
|
|
||||||
|
Since the output is raster anyway, it is suggested that you render your output to an image and print that instead. The driver supports PDF printing via Imagick, and an example that uses `wkhtmltoimage` is available in the repository.
|
||||||
@@ -1,9 +1,20 @@
|
|||||||
html: ../Escpos.php escpos.conf
|
html: escpos.doxyfile
|
||||||
doxygen escpos.conf
|
# Compile
|
||||||
|
doxygen escpos.doxyfile
|
||||||
|
# Filter out warnings on README.md- doxygen cannot handle image links that
|
||||||
|
# are used there: [](https://example.com/image)
|
||||||
|
sed -i '/README.md\:/d' warnings.log
|
||||||
|
# Show warnings log
|
||||||
|
cat warnings.log
|
||||||
|
# Return failure if there were any doc warnings
|
||||||
|
[ ! -s warnings.log ]
|
||||||
|
|
||||||
latex: html
|
latex: html
|
||||||
# Do nothing
|
# Do nothing
|
||||||
|
|
||||||
clean:
|
xml: html
|
||||||
rm --preserve-root -Rf html latex doxygen_sqlite3.db
|
xsltproc xml/combine.xslt xml/index.xml > all.xml
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm --preserve-root -Rf html latex xml doxygen_sqlite3.db all.xml warnings.log
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
# This tag specifies the encoding used for all characters in the config file
|
# This tag specifies the encoding used for all characters in the config file
|
||||||
# that follow. The default is UTF-8 which is also the encoding used for all text
|
# that follow. The default is UTF-8 which is also the encoding used for all text
|
||||||
# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
|
# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
|
||||||
# built into libc) for the transcoding. See https://www.gnu.org/software/libiconv
|
# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
|
||||||
# for the list of possible encodings.
|
# for the list of possible encodings.
|
||||||
# The default value is: UTF-8.
|
# The default value is: UTF-8.
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ PROJECT_BRIEF =
|
|||||||
# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
|
# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
|
||||||
# to the output directory.
|
# to the output directory.
|
||||||
|
|
||||||
PROJECT_LOGO = ../example/images/escpos-php-small.png
|
PROJECT_LOGO = ../example/resources/escpos-php-small.png
|
||||||
|
|
||||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
|
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
|
||||||
# into which the generated documentation will be written. If a relative path is
|
# into which the generated documentation will be written. If a relative path is
|
||||||
@@ -741,7 +741,7 @@ WARN_FORMAT = "$file:$line: $text"
|
|||||||
# messages should be written. If left blank the output is written to standard
|
# messages should be written. If left blank the output is written to standard
|
||||||
# error (stderr).
|
# error (stderr).
|
||||||
|
|
||||||
WARN_LOGFILE =
|
WARN_LOGFILE = warnings.log
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Configuration options related to the input files
|
# Configuration options related to the input files
|
||||||
@@ -753,12 +753,12 @@ WARN_LOGFILE =
|
|||||||
# spaces.
|
# spaces.
|
||||||
# Note: If this tag is empty the current directory is searched.
|
# Note: If this tag is empty the current directory is searched.
|
||||||
|
|
||||||
INPUT = ../Escpos.php ../src/ ../README.md
|
INPUT = ../src ../README.md ./
|
||||||
|
|
||||||
# This tag can be used to specify the character encoding of the source files
|
# This tag can be used to specify the character encoding of the source files
|
||||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||||
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
|
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
|
||||||
# documentation (see: https://www.gnu.org/software/libiconv) for the list of
|
# documentation (see: http://www.gnu.org/software/libiconv) for the list of
|
||||||
# possible encodings.
|
# possible encodings.
|
||||||
# The default value is: UTF-8.
|
# The default value is: UTF-8.
|
||||||
|
|
||||||
@@ -773,13 +773,13 @@ INPUT_ENCODING = UTF-8
|
|||||||
# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
|
# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
|
||||||
# *.qsf, *.as and *.js.
|
# *.qsf, *.as and *.js.
|
||||||
|
|
||||||
FILE_PATTERNS =
|
FILE_PATTERNS = *.php *.md
|
||||||
|
|
||||||
# The RECURSIVE tag can be used to specify whether or not subdirectories should
|
# The RECURSIVE tag can be used to specify whether or not subdirectories should
|
||||||
# be searched for input files as well.
|
# be searched for input files as well.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
RECURSIVE = NO
|
RECURSIVE = YES
|
||||||
|
|
||||||
# The EXCLUDE tag can be used to specify files and/or directories that should be
|
# The EXCLUDE tag can be used to specify files and/or directories that should be
|
||||||
# excluded from the INPUT source files. This way you can easily exclude a
|
# excluded from the INPUT source files. This way you can easily exclude a
|
||||||
@@ -950,7 +950,7 @@ SOURCE_TOOLTIPS = YES
|
|||||||
# If the USE_HTAGS tag is set to YES then the references to source code will
|
# If the USE_HTAGS tag is set to YES then the references to source code will
|
||||||
# point to the HTML generated by the htags(1) tool instead of doxygen built-in
|
# point to the HTML generated by the htags(1) tool instead of doxygen built-in
|
||||||
# source browser. The htags tool is part of GNU's global source tagging system
|
# source browser. The htags tool is part of GNU's global source tagging system
|
||||||
# (see https://www.gnu.org/software/global/global.html). You will need version
|
# (see http://www.gnu.org/software/global/global.html). You will need version
|
||||||
# 4.8.6 or higher.
|
# 4.8.6 or higher.
|
||||||
#
|
#
|
||||||
# To use it do the following:
|
# To use it do the following:
|
||||||
@@ -1820,7 +1820,7 @@ MAN_LINKS = NO
|
|||||||
# captures the structure of the code including all documentation.
|
# captures the structure of the code including all documentation.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
GENERATE_XML = NO
|
GENERATE_XML = YES
|
||||||
|
|
||||||
# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
|
# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
|
||||||
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
|
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
|
||||||
@@ -23,4 +23,4 @@ Each example prints to standard output, so either edit the print connector, or r
|
|||||||
- `print-from-html.php` - Runs `wkhtmltoimage` to convert HTML to an image, and then prints the image. (This is very slow)
|
- `print-from-html.php` - Runs `wkhtmltoimage` to convert HTML to an image, and then prints the image. (This is very slow)
|
||||||
- `character-tables.php` - Prints a compact character code table for each available character set. Used to debug incorrect output from `character-encodings.php`.
|
- `character-tables.php` - Prints a compact character code table for each available character set. Used to debug incorrect output from `character-encodings.php`.
|
||||||
- `print-from-pdf.php` - Loads a PDF and prints each page in a few different ways (very slow as well)
|
- `print-from-pdf.php` - Loads a PDF and prints each page in a few different ways (very slow as well)
|
||||||
|
- `rawbt-receipt` (.php & .html) - Demonstration of Back and Front for integration between the site and the Android application “RawBT - Printer Driver for Android”
|
||||||
|
|||||||
@@ -1,181 +1,207 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once (dirname ( __FILE__ ) . "/../Escpos.php");
|
require __DIR__ . '/../autoload.php';
|
||||||
$printer = new Escpos ();
|
use Mike42\Escpos\Printer;
|
||||||
$printer->setBarcodeHeight ( 40 );
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
|
||||||
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
|
$printer = new Printer($connector);
|
||||||
|
|
||||||
|
/* Height and width */
|
||||||
|
$printer->selectPrintMode(Printer::MODE_DOUBLE_HEIGHT | Printer::MODE_DOUBLE_WIDTH);
|
||||||
|
$printer->text("Height and bar width\n");
|
||||||
|
$printer->selectPrintMode();
|
||||||
|
$heights = array(1, 2, 4, 8, 16, 32);
|
||||||
|
$widths = array(1, 2, 3, 4, 5, 6, 7, 8);
|
||||||
|
$printer -> text("Default look\n");
|
||||||
|
$printer->barcode("ABC", Printer::BARCODE_CODE39);
|
||||||
|
|
||||||
|
foreach($heights as $height) {
|
||||||
|
$printer -> text("\nHeight $height\n");
|
||||||
|
$printer->setBarcodeHeight($height);
|
||||||
|
$printer->barcode("ABC", Printer::BARCODE_CODE39);
|
||||||
|
}
|
||||||
|
foreach($widths as $width) {
|
||||||
|
$printer -> text("\nWidth $width\n");
|
||||||
|
$printer->setBarcodeWidth($width);
|
||||||
|
$printer->barcode("ABC", Printer::BARCODE_CODE39);
|
||||||
|
}
|
||||||
|
$printer->feed();
|
||||||
|
// Set to something sensible for the rest of the examples
|
||||||
|
$printer->setBarcodeHeight(40);
|
||||||
|
$printer->setBarcodeWidth(2);
|
||||||
|
|
||||||
/* Text position */
|
/* Text position */
|
||||||
$printer->selectPrintMode ( Escpos::MODE_DOUBLE_HEIGHT | Escpos::MODE_DOUBLE_WIDTH );
|
$printer->selectPrintMode(Printer::MODE_DOUBLE_HEIGHT | Printer::MODE_DOUBLE_WIDTH);
|
||||||
$printer->text ( "Text position\n" );
|
$printer->text("Text position\n");
|
||||||
$printer->selectPrintMode ();
|
$printer->selectPrintMode();
|
||||||
$hri = array (
|
$hri = array (
|
||||||
Escpos::BARCODE_TEXT_NONE => "No text",
|
Printer::BARCODE_TEXT_NONE => "No text",
|
||||||
Escpos::BARCODE_TEXT_ABOVE => "Above",
|
Printer::BARCODE_TEXT_ABOVE => "Above",
|
||||||
Escpos::BARCODE_TEXT_BELOW => "Below",
|
Printer::BARCODE_TEXT_BELOW => "Below",
|
||||||
Escpos::BARCODE_TEXT_ABOVE | Escpos::BARCODE_TEXT_BELOW => "Both"
|
Printer::BARCODE_TEXT_ABOVE | Printer::BARCODE_TEXT_BELOW => "Both"
|
||||||
);
|
);
|
||||||
foreach ( $hri as $position => $caption ) {
|
foreach ($hri as $position => $caption) {
|
||||||
$printer->text ( $caption . "\n" );
|
$printer->text($caption . "\n");
|
||||||
$printer->setBarcodeTextPosition ( $position );
|
$printer->setBarcodeTextPosition($position);
|
||||||
$printer->barcode ( "012345678901", Escpos::BARCODE_JAN13 );
|
$printer->barcode("012345678901", Printer::BARCODE_JAN13);
|
||||||
$printer->feed ();
|
$printer->feed();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Barcode types */
|
/* Barcode types */
|
||||||
$standards = array (
|
$standards = array (
|
||||||
Escpos::BARCODE_UPCA => array (
|
Printer::BARCODE_UPCA => array (
|
||||||
"title" => "UPC-A",
|
"title" => "UPC-A",
|
||||||
"caption" => "Fixed-length numeric product barcodes.",
|
"caption" => "Fixed-length numeric product barcodes.",
|
||||||
"example" => array (
|
"example" => array (
|
||||||
array (
|
array (
|
||||||
"caption" => "12 char numeric including (wrong) check digit.",
|
"caption" => "12 char numeric including (wrong) check digit.",
|
||||||
"content" => "012345678901"
|
"content" => "012345678901"
|
||||||
),
|
),
|
||||||
array (
|
array (
|
||||||
"caption" => "Send 11 chars to add check digit automatically.",
|
"caption" => "Send 11 chars to add check digit automatically.",
|
||||||
"content" => "01234567890"
|
"content" => "01234567890"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Escpos::BARCODE_UPCE => array (
|
Printer::BARCODE_UPCE => array (
|
||||||
"title" => "UPC-E",
|
"title" => "UPC-E",
|
||||||
"caption" => "Fixed-length numeric compact product barcodes.",
|
"caption" => "Fixed-length numeric compact product barcodes.",
|
||||||
"example" => array (
|
"example" => array (
|
||||||
array (
|
array (
|
||||||
"caption" => "6 char numeric - auto check digit & NSC",
|
"caption" => "6 char numeric - auto check digit & NSC",
|
||||||
"content" => "123456"
|
"content" => "123456"
|
||||||
),
|
),
|
||||||
array (
|
array (
|
||||||
"caption" => "7 char numeric - auto check digit",
|
"caption" => "7 char numeric - auto check digit",
|
||||||
"content" => "0123456"
|
"content" => "0123456"
|
||||||
),
|
),
|
||||||
array (
|
array (
|
||||||
"caption" => "8 char numeric",
|
"caption" => "8 char numeric",
|
||||||
"content" => "01234567"
|
"content" => "01234567"
|
||||||
),
|
),
|
||||||
array (
|
array (
|
||||||
"caption" => "11 char numeric - auto check digit",
|
"caption" => "11 char numeric - auto check digit",
|
||||||
"content" => "01234567890"
|
"content" => "01234567890"
|
||||||
),
|
),
|
||||||
array (
|
array (
|
||||||
"caption" => "12 char numeric including (wrong) check digit",
|
"caption" => "12 char numeric including (wrong) check digit",
|
||||||
"content" => "012345678901"
|
"content" => "012345678901"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Escpos::BARCODE_JAN13 => array (
|
Printer::BARCODE_JAN13 => array (
|
||||||
"title" => "JAN13/EAN13",
|
"title" => "JAN13/EAN13",
|
||||||
"caption" => "Fixed-length numeric barcodes.",
|
"caption" => "Fixed-length numeric barcodes.",
|
||||||
"example" => array (
|
"example" => array (
|
||||||
array (
|
array (
|
||||||
"caption" => "12 char numeric - auto check digit",
|
"caption" => "12 char numeric - auto check digit",
|
||||||
"content" => "012345678901"
|
"content" => "012345678901"
|
||||||
),
|
),
|
||||||
array (
|
array (
|
||||||
"caption" => "13 char numeric including (wrong) check digit",
|
"caption" => "13 char numeric including (wrong) check digit",
|
||||||
"content" => "0123456789012"
|
"content" => "0123456789012"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Escpos::BARCODE_JAN8 => array (
|
Printer::BARCODE_JAN8 => array (
|
||||||
"title" => "JAN8/EAN8",
|
"title" => "JAN8/EAN8",
|
||||||
"caption" => "Fixed-length numeric barcodes.",
|
"caption" => "Fixed-length numeric barcodes.",
|
||||||
"example" => array (
|
"example" => array (
|
||||||
array (
|
array (
|
||||||
"caption" => "7 char numeric - auto check digit",
|
"caption" => "7 char numeric - auto check digit",
|
||||||
"content" => "0123456"
|
"content" => "0123456"
|
||||||
),
|
),
|
||||||
array (
|
array (
|
||||||
"caption" => "8 char numeric including (wrong) check digit",
|
"caption" => "8 char numeric including (wrong) check digit",
|
||||||
"content" => "01234567"
|
"content" => "01234567"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Escpos::BARCODE_CODE39 => array (
|
Printer::BARCODE_CODE39 => array (
|
||||||
"title" => "Code39",
|
"title" => "Code39",
|
||||||
"caption" => "Variable length alphanumeric w/ some special chars.",
|
"caption" => "Variable length alphanumeric w/ some special chars.",
|
||||||
"example" => array (
|
"example" => array (
|
||||||
array (
|
array (
|
||||||
"caption" => "Text, numbers, spaces",
|
"caption" => "Text, numbers, spaces",
|
||||||
"content" => "ABC 012"
|
"content" => "ABC 012"
|
||||||
),
|
),
|
||||||
array (
|
array (
|
||||||
"caption" => "Special characters",
|
"caption" => "Special characters",
|
||||||
"content" => "$%+-./"
|
"content" => "$%+-./"
|
||||||
),
|
),
|
||||||
array (
|
array (
|
||||||
"caption" => "Extra char (*) Used as start/stop",
|
"caption" => "Extra char (*) Used as start/stop",
|
||||||
"content" => "*TEXT*"
|
"content" => "*TEXT*"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Escpos::BARCODE_ITF => array (
|
Printer::BARCODE_ITF => array (
|
||||||
"title" => "ITF",
|
"title" => "ITF",
|
||||||
"caption" => "Variable length numeric w/even number of digits,\nas they are encoded in pairs.",
|
"caption" => "Variable length numeric w/even number of digits,\nas they are encoded in pairs.",
|
||||||
"example" => array (
|
"example" => array (
|
||||||
array (
|
array (
|
||||||
"caption" => "Numeric- even number of digits",
|
"caption" => "Numeric- even number of digits",
|
||||||
"content" => "0123456789"
|
"content" => "0123456789"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Escpos::BARCODE_CODABAR => array (
|
Printer::BARCODE_CODABAR => array (
|
||||||
"title" => "Codabar",
|
"title" => "Codabar",
|
||||||
"caption" => "Varaible length numeric with some allowable\nextra characters. ABCD/abcd must be used as\nstart/stop characters (one at the start, one\nat the end) to distinguish between barcode\napplications.",
|
"caption" => "Varaible length numeric with some allowable\nextra characters. ABCD/abcd must be used as\nstart/stop characters (one at the start, one\nat the end) to distinguish between barcode\napplications.",
|
||||||
"example" => array (
|
"example" => array (
|
||||||
array (
|
array (
|
||||||
"caption" => "Numeric w/ A A start/stop. ",
|
"caption" => "Numeric w/ A A start/stop. ",
|
||||||
"content" => "A012345A"
|
"content" => "A012345A"
|
||||||
),
|
),
|
||||||
array (
|
array (
|
||||||
"caption" => "Extra allowable characters",
|
"caption" => "Extra allowable characters",
|
||||||
"content" => "A012$+-./:A"
|
"content" => "A012$+-./:A"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Escpos::BARCODE_CODE93 => array (
|
Printer::BARCODE_CODE93 => array (
|
||||||
"title" => "Code93",
|
"title" => "Code93",
|
||||||
"caption" => "Variable length- any ASCII is available",
|
"caption" => "Variable length- any ASCII is available",
|
||||||
"example" => array (
|
"example" => array (
|
||||||
array (
|
array (
|
||||||
"caption" => "Text",
|
"caption" => "Text",
|
||||||
"content" => "012abcd"
|
"content" => "012abcd"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Escpos::BARCODE_CODE128 => array (
|
Printer::BARCODE_CODE128 => array (
|
||||||
"title" => "Code128",
|
"title" => "Code128",
|
||||||
"caption" => "Variable length- any ASCII is available",
|
"caption" => "Variable length- any ASCII is available",
|
||||||
"example" => array (
|
"example" => array (
|
||||||
array (
|
array (
|
||||||
"caption" => "Code set A uppercase & symbols",
|
"caption" => "Code set A uppercase & symbols",
|
||||||
"content" => "{A" . "012ABCD"
|
"content" => "{A" . "012ABCD"
|
||||||
),
|
),
|
||||||
array (
|
array (
|
||||||
"caption" => "Code set B general text",
|
"caption" => "Code set B general text",
|
||||||
"content" => "{B" . "012ABCDabcd"
|
"content" => "{B" . "012ABCDabcd"
|
||||||
),
|
),
|
||||||
array (
|
array (
|
||||||
"caption" => "Code set C compact numbers\n Sending chr(21) chr(32) chr(43)",
|
"caption" => "Code set C compact numbers\n Sending chr(21) chr(32) chr(43)",
|
||||||
"content" => "{C" . chr ( 21 ) . chr ( 32 ) . chr ( 43 )
|
"content" => "{C" . chr(21) . chr(32) . chr(43)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$printer->setBarcodeTextPosition ( Escpos::BARCODE_TEXT_BELOW );
|
$printer->setBarcodeTextPosition(Printer::BARCODE_TEXT_BELOW);
|
||||||
foreach ( $standards as $type => $standard ) {
|
foreach ($standards as $type => $standard) {
|
||||||
$printer->selectPrintMode ( Escpos::MODE_DOUBLE_HEIGHT | Escpos::MODE_DOUBLE_WIDTH );
|
$printer->selectPrintMode(Printer::MODE_DOUBLE_HEIGHT | Printer::MODE_DOUBLE_WIDTH);
|
||||||
$printer->text ( $standard ["title"] . "\n" );
|
$printer->text($standard ["title"] . "\n");
|
||||||
$printer->selectPrintMode ();
|
$printer->selectPrintMode();
|
||||||
$printer->text ( $standard ["caption"] . "\n\n" );
|
$printer->text($standard ["caption"] . "\n\n");
|
||||||
foreach ( $standard ["example"] as $id => $barcode ) {
|
foreach ($standard ["example"] as $id => $barcode) {
|
||||||
$printer->setEmphasis ( true );
|
$printer->setEmphasis(true);
|
||||||
$printer->text ( $barcode ["caption"] . "\n" );
|
$printer->text($barcode ["caption"] . "\n");
|
||||||
$printer->setEmphasis ( false );
|
$printer->setEmphasis(false);
|
||||||
$printer->text ( "Content: " . $barcode ["content"] . "\n" );
|
$printer->text("Content: " . $barcode ["content"] . "\n");
|
||||||
$printer->barcode ( $barcode ["content"], $type );
|
$printer->barcode($barcode ["content"], $type);
|
||||||
$printer->feed ();
|
$printer->feed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$printer->cut ();
|
$printer->cut();
|
||||||
$printer->close ();
|
$printer->close();
|
||||||
|
|
||||||
|
|||||||
@@ -1,32 +1,36 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Example print-outs using the older bit image print command */
|
/* Example print-outs using the older bit image print command */
|
||||||
require_once(dirname(__FILE__) . "/../Escpos.php");
|
require __DIR__ . '/../autoload.php';
|
||||||
$printer = new Escpos();
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\EscposImage;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
|
||||||
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
|
$printer = new Printer($connector);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$tux = new EscposImage("resources/tux.png");
|
$tux = EscposImage::load("resources/tux.png", false);
|
||||||
|
|
||||||
$printer -> text("These example images are printed with the older\nbit image print command. You should only use\n\$p -> bitImage() if \$p -> graphics() does not\nwork on your printer.\n\n");
|
$printer -> text("These example images are printed with the older\nbit image print command. You should only use\n\$p -> bitImage() if \$p -> graphics() does not\nwork on your printer.\n\n");
|
||||||
|
|
||||||
$printer -> bitImage($tux);
|
$printer -> bitImage($tux);
|
||||||
$printer -> text("Regular Tux (bit image).\n");
|
$printer -> text("Regular Tux (bit image).\n");
|
||||||
$printer -> feed();
|
$printer -> feed();
|
||||||
|
|
||||||
$printer -> bitImage($tux, Escpos::IMG_DOUBLE_WIDTH);
|
$printer -> bitImage($tux, Printer::IMG_DOUBLE_WIDTH);
|
||||||
$printer -> text("Wide Tux (bit image).\n");
|
$printer -> text("Wide Tux (bit image).\n");
|
||||||
$printer -> feed();
|
$printer -> feed();
|
||||||
|
|
||||||
$printer -> bitImage($tux, Escpos::IMG_DOUBLE_HEIGHT);
|
$printer -> bitImage($tux, Printer::IMG_DOUBLE_HEIGHT);
|
||||||
$printer -> text("Tall Tux (bit image).\n");
|
$printer -> text("Tall Tux (bit image).\n");
|
||||||
$printer -> feed();
|
$printer -> feed();
|
||||||
|
|
||||||
$printer -> bitImage($tux, Escpos::IMG_DOUBLE_WIDTH | Escpos::IMG_DOUBLE_HEIGHT);
|
$printer -> bitImage($tux, Printer::IMG_DOUBLE_WIDTH | Printer::IMG_DOUBLE_HEIGHT);
|
||||||
$printer -> text("Large Tux in correct proportion (bit image).\n");
|
$printer -> text("Large Tux in correct proportion (bit image).\n");
|
||||||
} catch(Exception $e) {
|
} catch (Exception $e) {
|
||||||
/* Images not supported on your PHP, or image file not found */
|
/* Images not supported on your PHP, or image file not found */
|
||||||
$printer -> text($e -> getMessage() . "\n");
|
$printer -> text($e -> getMessage() . "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
$printer -> close();
|
$printer -> close();
|
||||||
?>
|
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Change to the correct path if you copy this example! */
|
/* Change to the correct path if you copy this example! */
|
||||||
require_once(dirname(__FILE__) . "/../Escpos.php");
|
require __DIR__ . '/../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
use Mike42\Escpos\PrintBuffers\EscposPrintBuffer;
|
||||||
|
use Mike42\Escpos\PrintBuffers\ImagePrintBuffer;
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This example builds on character-encodings.php, also providing an image-based rendering.
|
* This example builds on character-encodings.php, also providing an image-based rendering.
|
||||||
* This is quite slow, since a) the buffers are changed dozens of
|
* This is quite slow, since a) the buffers are changed dozens of
|
||||||
* times in the example, and b) It involves sending very wide images, which printers don't like!
|
* times in the example, and b) It involves sending very wide images, which printers don't like!
|
||||||
*
|
*
|
||||||
* There are currently no test cases around the image printing, since it is an experimental feature.
|
* There are currently no test cases around the image printing, since it is an experimental feature.
|
||||||
*
|
*
|
||||||
* It does, however, illustrate the way that more encodings are available when image output is used.
|
* It does, however, illustrate the way that more encodings are available when image output is used.
|
||||||
@@ -14,46 +19,45 @@ require_once(dirname(__FILE__) . "/../Escpos.php");
|
|||||||
include(dirname(__FILE__) . '/resources/character-encoding-test-strings.inc');
|
include(dirname(__FILE__) . '/resources/character-encoding-test-strings.inc');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Enter connector and capability profile
|
// Enter connector and capability profile
|
||||||
$connector = new FilePrintConnector("php://stdout");
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
$profile = DefaultCapabilityProfile::getInstance();
|
$profile = CapabilityProfile::load('default');
|
||||||
$buffers = array(new EscposPrintBuffer(), new ImagePrintBuffer());
|
$buffers = array(new EscposPrintBuffer(), new ImagePrintBuffer());
|
||||||
|
|
||||||
/* Print a series of receipts containing i18n example strings */
|
/* Print a series of receipts containing i18n example strings */
|
||||||
$printer = new Escpos($connector, $profile);
|
$printer = new Printer($connector, $profile);
|
||||||
$printer -> selectPrintMode(Escpos::MODE_DOUBLE_HEIGHT | Escpos::MODE_EMPHASIZED | Escpos::MODE_DOUBLE_WIDTH);
|
$printer -> selectPrintMode(Printer::MODE_DOUBLE_HEIGHT | Printer::MODE_EMPHASIZED | Printer::MODE_DOUBLE_WIDTH);
|
||||||
$printer -> text("Implemented languages\n");
|
$printer -> text("Implemented languages\n");
|
||||||
$printer -> selectPrintMode();
|
$printer -> selectPrintMode();
|
||||||
foreach($inputsOk as $label => $str) {
|
foreach ($inputsOk as $label => $str) {
|
||||||
$printer -> setEmphasis(true);
|
$printer -> setEmphasis(true);
|
||||||
$printer -> text($label . ":\n");
|
$printer -> text($label . ":\n");
|
||||||
$printer -> setEmphasis(false);
|
$printer -> setEmphasis(false);
|
||||||
foreach($buffers as $buffer) {
|
foreach ($buffers as $buffer) {
|
||||||
$printer -> setPrintBuffer($buffer);
|
$printer -> setPrintBuffer($buffer);
|
||||||
$printer -> text($str);
|
$printer -> text($str);
|
||||||
}
|
}
|
||||||
$printer -> setPrintBuffer($buffers[0]);
|
$printer -> setPrintBuffer($buffers[0]);
|
||||||
}
|
}
|
||||||
$printer -> feed();
|
$printer -> feed();
|
||||||
|
|
||||||
$printer -> selectPrintMode(Escpos::MODE_DOUBLE_HEIGHT | Escpos::MODE_EMPHASIZED | Escpos::MODE_DOUBLE_WIDTH);
|
$printer -> selectPrintMode(Printer::MODE_DOUBLE_HEIGHT | Printer::MODE_EMPHASIZED | Printer::MODE_DOUBLE_WIDTH);
|
||||||
$printer -> text("Works in progress\n");
|
$printer -> text("Works in progress\n");
|
||||||
$printer -> selectPrintMode();
|
$printer -> selectPrintMode();
|
||||||
foreach($inputsNotOk as $label => $str) {
|
foreach ($inputsNotOk as $label => $str) {
|
||||||
$printer -> setEmphasis(true);
|
$printer -> setEmphasis(true);
|
||||||
$printer -> text($label . ":\n");
|
$printer -> text($label . ":\n");
|
||||||
$printer -> setEmphasis(false);
|
$printer -> setEmphasis(false);
|
||||||
foreach($buffers as $buffer) {
|
foreach ($buffers as $buffer) {
|
||||||
$printer -> setPrintBuffer($buffer);
|
$printer -> setPrintBuffer($buffer);
|
||||||
$printer -> text($str);
|
$printer -> text($str);
|
||||||
}
|
}
|
||||||
$printer -> setPrintBuffer($buffers[0]);
|
$printer -> setPrintBuffer($buffers[0]);
|
||||||
}
|
}
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
|
|
||||||
/* Close printer */
|
/* Close printer */
|
||||||
$printer -> close();
|
$printer -> close();
|
||||||
} catch(Exception $e) {
|
} catch (Exception $e) {
|
||||||
echo "Couldn't print to this printer: " . $e -> getMessage() . "\n";
|
echo "Couldn't print to this printer: " . $e -> getMessage() . "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,58 +1,60 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Change to the correct path if you copy this example! */
|
/* Change to the correct path if you copy this example! */
|
||||||
require_once(dirname(__FILE__) . "/../Escpos.php");
|
require __DIR__ . '/../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This demonstrates available character encodings. Escpos-php accepts UTF-8,
|
* This demonstrates available character encodings. Escpos-php accepts UTF-8,
|
||||||
* and converts this to lower-level data to the printer. This is a complex area, so be
|
* and converts this to lower-level data to the printer. This is a complex area, so be
|
||||||
* prepared to code a model-specific hack ('CapabilityProfile') for your printer.
|
* prepared to code a model-specific hack ('CapabilityProfile') for your printer.
|
||||||
*
|
*
|
||||||
* If you run into trouble, please file an issue on GitHub, including at a minimum:
|
* If you run into trouble, please file an issue on GitHub, including at a minimum:
|
||||||
* - A UTF-8 test string in the language you're working in, and
|
* - A UTF-8 test string in the language you're working in, and
|
||||||
* - A test print or link to a technical document which lists the available
|
* - A test print or link to a technical document which lists the available
|
||||||
* code pages ('character code tables') for your printer.
|
* code pages ('character code tables') for your printer.
|
||||||
*
|
*
|
||||||
* The DefaultCapabilityProfile works for Espson-branded printers. For other models, you
|
* The DefaultCapabilityProfile works for Espson-branded printers. For other models, you
|
||||||
* must use/create a PrinterCapabilityProfile for your printer containing a list of code
|
* must use/create a PrinterCapabilityProfile for your printer containing a list of code
|
||||||
* page numbers for your printer- otherwise you will get mojibake.
|
* page numbers for your printer- otherwise you will get mojibake.
|
||||||
*
|
*
|
||||||
* If you do not intend to use non-English characters, then use SimpleCapabilityProfile,
|
* If you do not intend to use non-English characters, then use SimpleCapabilityProfile,
|
||||||
* which has only the default encoding, effectively disabling code page changes.
|
* which has only the default encoding, effectively disabling code page changes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
include(dirname(__FILE__) . '/resources/character-encoding-test-strings.inc');
|
include(dirname(__FILE__) . '/resources/character-encoding-test-strings.inc');
|
||||||
try {
|
try {
|
||||||
// Enter connector and capability profile (to match your printer)
|
// Enter connector and capability profile (to match your printer)
|
||||||
$connector = new FilePrintConnector("php://stdout");
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
$profile = DefaultCapabilityProfile::getInstance();
|
$profile = CapabilityProfile::load("default");
|
||||||
|
|
||||||
/* Print a series of receipts containing i18n example strings */
|
/* Print a series of receipts containing i18n example strings */
|
||||||
$printer = new Escpos($connector, $profile);
|
$printer = new Printer($connector, $profile);
|
||||||
$printer -> selectPrintMode(Escpos::MODE_DOUBLE_HEIGHT | Escpos::MODE_EMPHASIZED | Escpos::MODE_DOUBLE_WIDTH);
|
$printer -> selectPrintMode(Printer::MODE_DOUBLE_HEIGHT | Printer::MODE_EMPHASIZED | Printer::MODE_DOUBLE_WIDTH);
|
||||||
$printer -> text("Implemented languages\n");
|
$printer -> text("Implemented languages\n");
|
||||||
$printer -> selectPrintMode();
|
$printer -> selectPrintMode();
|
||||||
foreach($inputsOk as $label => $str) {
|
foreach ($inputsOk as $label => $str) {
|
||||||
$printer -> setEmphasis(true);
|
$printer -> setEmphasis(true);
|
||||||
$printer -> text($label . ":\n");
|
$printer -> text($label . ":\n");
|
||||||
$printer -> setEmphasis(false);
|
$printer -> setEmphasis(false);
|
||||||
$printer -> text($str);
|
$printer -> text($str);
|
||||||
}
|
}
|
||||||
$printer -> feed();
|
$printer -> feed();
|
||||||
|
|
||||||
$printer -> selectPrintMode(Escpos::MODE_DOUBLE_HEIGHT | Escpos::MODE_EMPHASIZED | Escpos::MODE_DOUBLE_WIDTH);
|
$printer -> selectPrintMode(Printer::MODE_DOUBLE_HEIGHT | Printer::MODE_EMPHASIZED | Printer::MODE_DOUBLE_WIDTH);
|
||||||
$printer -> text("Works in progress\n");
|
$printer -> text("Works in progress\n");
|
||||||
$printer -> selectPrintMode();
|
$printer -> selectPrintMode();
|
||||||
foreach($inputsNotOk as $label => $str) {
|
foreach ($inputsNotOk as $label => $str) {
|
||||||
$printer -> setEmphasis(true);
|
$printer -> setEmphasis(true);
|
||||||
$printer -> text($label . ":\n");
|
$printer -> text($label . ":\n");
|
||||||
$printer -> setEmphasis(false);
|
$printer -> setEmphasis(false);
|
||||||
$printer -> text($str);
|
$printer -> text($str);
|
||||||
}
|
}
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
|
|
||||||
/* Close printer */
|
/* Close printer */
|
||||||
$printer -> close();
|
$printer -> close();
|
||||||
} catch(Exception $e) {
|
} catch (Exception $e) {
|
||||||
echo "Couldn't print to this printer: " . $e -> getMessage() . "\n";
|
echo "Couldn't print to this printer: " . $e -> getMessage() . "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,68 +4,72 @@
|
|||||||
* for debugging character-encoding issues: If your printer does not work with
|
* for debugging character-encoding issues: If your printer does not work with
|
||||||
* a built-in capability profile, you need to check its documentation for
|
* a built-in capability profile, you need to check its documentation for
|
||||||
* supported code pages.
|
* supported code pages.
|
||||||
*
|
*
|
||||||
* These are then loaded into a capability profile, which maps code page
|
* These are then loaded into a capability profile, which maps code page
|
||||||
* numbers to iconv encoding names on your particular printer. This script
|
* numbers to iconv encoding names on your particular printer. This script
|
||||||
* will print all configured code pages, so that you can check that the chosen
|
* will print all configured code pages, so that you can check that the chosen
|
||||||
* iconv encoding name matches the actual code page contents.
|
* iconv encoding name matches the actual code page contents.
|
||||||
*
|
*
|
||||||
* If this is correctly set up for your printer, then the driver will try its
|
* If this is correctly set up for your printer, then the driver will try its
|
||||||
* best to map UTF-8 text into these code pages for you, allowing you to accept
|
* best to map UTF-8 text into these code pages for you, allowing you to accept
|
||||||
* arbitrary input from a database, without worrying about encoding it for the printer.
|
* arbitrary input from a database, without worrying about encoding it for the printer.
|
||||||
*/
|
*/
|
||||||
require_once(dirname(__FILE__) . "/../Escpos.php");
|
require __DIR__ . '/../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
|
||||||
// Enter connector and capability profile (to match your printer)
|
// Enter connector and capability profile (to match your printer)
|
||||||
$connector = new FilePrintConnector("php://stdout");
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
$profile = DefaultCapabilityProfile::getInstance();
|
$profile = CapabilityProfile::load("default");
|
||||||
$verbose = false; // Skip tables which iconv wont convert to (ie, only print characters available with UTF-8 input)
|
$verbose = false; // Skip tables which iconv wont convert to (ie, only print characters available with UTF-8 input)
|
||||||
|
|
||||||
/* Print a series of receipts containing i18n example strings - Code below shouldn't need changing */
|
/* Print a series of receipts containing i18n example strings - Code below shouldn't need changing */
|
||||||
$printer = new Escpos($connector, $profile);
|
$printer = new Mike42\Escpos\Printer($connector, $profile);
|
||||||
$codePages = $profile -> getSupportedCodePages();
|
$codePages = $profile -> getCodePages();
|
||||||
$first = true; // Print larger table for first code-page.
|
$first = true; // Print larger table for first code-page.
|
||||||
foreach($codePages as $table => $name) {
|
foreach ($codePages as $table => $page) {
|
||||||
/* Change printer code page */
|
/* Change printer code page */
|
||||||
$printer -> selectCharacterTable(255);
|
$printer -> selectCharacterTable(255);
|
||||||
$printer -> selectCharacterTable($table);
|
$printer -> selectCharacterTable($table);
|
||||||
/* Select & print a label for it */
|
/* Select & print a label for it */
|
||||||
$label = $name;
|
$label = $page -> getId();
|
||||||
if($name === false) {
|
if (!$page -> isEncodable()) {
|
||||||
$label= " (not matched to iconv table)";
|
$label= " (not supported)";
|
||||||
}
|
}
|
||||||
$printer -> setEmphasis(true);
|
$printer -> setEmphasis(true);
|
||||||
$printer -> textRaw("Table $table: $label\n");
|
$printer -> textRaw("Table $table: $label\n");
|
||||||
$printer -> setEmphasis(false);
|
$printer -> setEmphasis(false);
|
||||||
if($name === false && !$verbose) {
|
if (!$page -> isEncodable() && !$verbose) {
|
||||||
continue; // Skip non-recognised
|
continue; // Skip non-recognised
|
||||||
}
|
}
|
||||||
/* Print a table of available characters (first table is larger than subsequent ones */
|
/* Print a table of available characters (first table is larger than subsequent ones */
|
||||||
if($first) {
|
if ($first) {
|
||||||
$first = false;
|
$first = false;
|
||||||
compactCharTable($printer, 1, true);
|
compactCharTable($printer, 1, true);
|
||||||
} else {
|
} else {
|
||||||
compactCharTable($printer);
|
compactCharTable($printer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
$printer -> close();
|
$printer -> close();
|
||||||
|
|
||||||
function compactCharTable($printer, $start = 4, $header = false) {
|
function compactCharTable($printer, $start = 4, $header = false)
|
||||||
/* Output a compact character table for the current encoding */
|
{
|
||||||
$chars = str_repeat(' ', 256);
|
/* Output a compact character table for the current encoding */
|
||||||
for($i = 0; $i < 255; $i++) {
|
$chars = str_repeat(' ', 256);
|
||||||
$chars[$i] = ($i > 32 && $i != 127) ? chr($i) : ' ';
|
for ($i = 0; $i < 255; $i++) {
|
||||||
}
|
$chars[$i] = ($i > 32 && $i != 127) ? chr($i) : ' ';
|
||||||
if($header) {
|
}
|
||||||
$printer -> setEmphasis(true);
|
if ($header) {
|
||||||
$printer -> textRaw(" 0123456789ABCDEF0123456789ABCDEF\n");
|
$printer -> setEmphasis(true);
|
||||||
$printer -> setEmphasis(false);
|
$printer -> textRaw(" 0123456789ABCDEF0123456789ABCDEF\n");
|
||||||
}
|
$printer -> setEmphasis(false);
|
||||||
for($y = $start; $y < 8; $y++) {
|
}
|
||||||
$printer -> setEmphasis(true);
|
for ($y = $start; $y < 8; $y++) {
|
||||||
$printer -> textRaw(strtoupper(dechex($y * 2)) . " ");
|
$printer -> setEmphasis(true);
|
||||||
$printer -> setEmphasis(false);
|
$printer -> textRaw(strtoupper(dechex($y * 2)) . " ");
|
||||||
$printer -> textRaw(substr($chars, $y * 32, 32) . "\n");
|
$printer -> setEmphasis(false);
|
||||||
}
|
$printer -> textRaw(substr($chars, $y * 32, 32) . "\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This demo interacts with an Aures OCD-300 customer display,
|
||||||
|
* showing its support for ESC/POS text encodings.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require __DIR__ . '/../autoload.php';
|
||||||
|
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\Devices\AuresCustomerDisplay;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Device appears as a serial port.
|
||||||
|
*
|
||||||
|
* stat /dev/ttyACM0
|
||||||
|
* sudo usermod -a -G dialout [username]
|
||||||
|
*/
|
||||||
|
$connector = new FilePrintConnector("/dev/ttyACM0");
|
||||||
|
|
||||||
|
// Profile and display
|
||||||
|
$profile = CapabilityProfile::load("OCD-300");
|
||||||
|
$display = new AuresCustomerDisplay($connector, $profile);
|
||||||
|
|
||||||
|
|
||||||
|
// Make a really long test string
|
||||||
|
include(__DIR__ . "/resources/character-encoding-test-strings.inc");
|
||||||
|
$input = "";
|
||||||
|
foreach ($inputsOk as $str) {
|
||||||
|
$input .= $str;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap at a fixed width (as ASCII...), and show the user
|
||||||
|
// what's about to be sent to the printer
|
||||||
|
$wrapped = wordwrap($input, 20);
|
||||||
|
echo($wrapped);
|
||||||
|
|
||||||
|
// Roll out each line with 0.5s delay
|
||||||
|
foreach (explode("\n", $wrapped) as $line) {
|
||||||
|
$display -> feed();
|
||||||
|
$display -> text($line);
|
||||||
|
usleep(500000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finish by showing "Hello World"
|
||||||
|
$display -> clear();
|
||||||
|
$display -> text("Hello World\n");
|
||||||
|
|
||||||
|
// Dont forget to close the device
|
||||||
|
$display -> close();
|
||||||
@@ -8,8 +8,13 @@
|
|||||||
*
|
*
|
||||||
* @author Michael Billington <michael.billington@gmail.com>
|
* @author Michael Billington <michael.billington@gmail.com>
|
||||||
*/
|
*/
|
||||||
require_once(dirname(__FILE__) . "/../Escpos.php");
|
require __DIR__ . '/../autoload.php';
|
||||||
$printer = new Escpos();
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
use Mike42\Escpos\EscposImage;
|
||||||
|
|
||||||
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
|
$printer = new Printer($connector);
|
||||||
|
|
||||||
/* Initialize */
|
/* Initialize */
|
||||||
$printer -> initialize();
|
$printer -> initialize();
|
||||||
@@ -29,132 +34,132 @@ $printer -> cut();
|
|||||||
|
|
||||||
/* Font modes */
|
/* Font modes */
|
||||||
$modes = array(
|
$modes = array(
|
||||||
Escpos::MODE_FONT_B,
|
Printer::MODE_FONT_B,
|
||||||
Escpos::MODE_EMPHASIZED,
|
Printer::MODE_EMPHASIZED,
|
||||||
Escpos::MODE_DOUBLE_HEIGHT,
|
Printer::MODE_DOUBLE_HEIGHT,
|
||||||
Escpos::MODE_DOUBLE_WIDTH,
|
Printer::MODE_DOUBLE_WIDTH,
|
||||||
Escpos::MODE_UNDERLINE);
|
Printer::MODE_UNDERLINE);
|
||||||
for($i = 0; $i < pow(2, count($modes)); $i++) {
|
for ($i = 0; $i < pow(2, count($modes)); $i++) {
|
||||||
$bits = str_pad(decbin($i), count($modes), "0", STR_PAD_LEFT);
|
$bits = str_pad(decbin($i), count($modes), "0", STR_PAD_LEFT);
|
||||||
$mode = 0;
|
$mode = 0;
|
||||||
for($j = 0; $j < strlen($bits); $j++) {
|
for ($j = 0; $j < strlen($bits); $j++) {
|
||||||
if(substr($bits, $j, 1) == "1") {
|
if (substr($bits, $j, 1) == "1") {
|
||||||
$mode |= $modes[$j];
|
$mode |= $modes[$j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$printer -> selectPrintMode($mode);
|
$printer -> selectPrintMode($mode);
|
||||||
$printer -> text("ABCDEFGHIJabcdefghijk\n");
|
$printer -> text("ABCDEFGHIJabcdefghijk\n");
|
||||||
}
|
}
|
||||||
$printer -> selectPrintMode(); // Reset
|
$printer -> selectPrintMode(); // Reset
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
|
|
||||||
/* Underline */
|
/* Underline */
|
||||||
for($i = 0; $i < 3; $i++) {
|
for ($i = 0; $i < 3; $i++) {
|
||||||
$printer -> setUnderline($i);
|
$printer -> setUnderline($i);
|
||||||
$printer -> text("The quick brown fox jumps over the lazy dog\n");
|
$printer -> text("The quick brown fox jumps over the lazy dog\n");
|
||||||
}
|
}
|
||||||
$printer -> setUnderline(0); // Reset
|
$printer -> setUnderline(0); // Reset
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
|
|
||||||
/* Cuts */
|
/* Cuts */
|
||||||
$printer -> text("Partial cut\n(not available on all printers)\n");
|
$printer -> text("Partial cut\n(not available on all printers)\n");
|
||||||
$printer -> cut(Escpos::CUT_PARTIAL);
|
$printer -> cut(Printer::CUT_PARTIAL);
|
||||||
$printer -> text("Full cut\n");
|
$printer -> text("Full cut\n");
|
||||||
$printer -> cut(Escpos::CUT_FULL);
|
$printer -> cut(Printer::CUT_FULL);
|
||||||
|
|
||||||
/* Emphasis */
|
/* Emphasis */
|
||||||
for($i = 0; $i < 2; $i++) {
|
for ($i = 0; $i < 2; $i++) {
|
||||||
$printer -> setEmphasis($i == 1);
|
$printer -> setEmphasis($i == 1);
|
||||||
$printer -> text("The quick brown fox jumps over the lazy dog\n");
|
$printer -> text("The quick brown fox jumps over the lazy dog\n");
|
||||||
}
|
}
|
||||||
$printer -> setEmphasis(false); // Reset
|
$printer -> setEmphasis(false); // Reset
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
|
|
||||||
/* Double-strike (looks basically the same as emphasis) */
|
/* Double-strike (looks basically the same as emphasis) */
|
||||||
for($i = 0; $i < 2; $i++) {
|
for ($i = 0; $i < 2; $i++) {
|
||||||
$printer -> setDoubleStrike($i == 1);
|
$printer -> setDoubleStrike($i == 1);
|
||||||
$printer -> text("The quick brown fox jumps over the lazy dog\n");
|
$printer -> text("The quick brown fox jumps over the lazy dog\n");
|
||||||
}
|
}
|
||||||
$printer -> setDoubleStrike(false);
|
$printer -> setDoubleStrike(false);
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
|
|
||||||
/* Fonts (many printers do not have a 'Font C') */
|
/* Fonts (many printers do not have a 'Font C') */
|
||||||
$fonts = array(
|
$fonts = array(
|
||||||
Escpos::FONT_A,
|
Printer::FONT_A,
|
||||||
Escpos::FONT_B,
|
Printer::FONT_B,
|
||||||
Escpos::FONT_C);
|
Printer::FONT_C);
|
||||||
for($i = 0; $i < count($fonts); $i++) {
|
for ($i = 0; $i < count($fonts); $i++) {
|
||||||
$printer -> setFont($fonts[$i]);
|
$printer -> setFont($fonts[$i]);
|
||||||
$printer -> text("The quick brown fox jumps over the lazy dog\n");
|
$printer -> text("The quick brown fox jumps over the lazy dog\n");
|
||||||
}
|
}
|
||||||
$printer -> setFont(); // Reset
|
$printer -> setFont(); // Reset
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
|
|
||||||
/* Justification */
|
/* Justification */
|
||||||
$justification = array(
|
$justification = array(
|
||||||
Escpos::JUSTIFY_LEFT,
|
Printer::JUSTIFY_LEFT,
|
||||||
Escpos::JUSTIFY_CENTER,
|
Printer::JUSTIFY_CENTER,
|
||||||
Escpos::JUSTIFY_RIGHT);
|
Printer::JUSTIFY_RIGHT);
|
||||||
for($i = 0; $i < count($justification); $i++) {
|
for ($i = 0; $i < count($justification); $i++) {
|
||||||
$printer -> setJustification($justification[$i]);
|
$printer -> setJustification($justification[$i]);
|
||||||
$printer -> text("A man a plan a canal panama\n");
|
$printer -> text("A man a plan a canal panama\n");
|
||||||
}
|
}
|
||||||
$printer -> setJustification(); // Reset
|
$printer -> setJustification(); // Reset
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
|
|
||||||
/* Barcodes - see barcode.php for more detail */
|
/* Barcodes - see barcode.php for more detail */
|
||||||
$printer -> setBarcodeHeight(80);
|
$printer -> setBarcodeHeight(80);
|
||||||
$printer->setBarcodeTextPosition ( Escpos::BARCODE_TEXT_BELOW );
|
$printer->setBarcodeTextPosition(Printer::BARCODE_TEXT_BELOW);
|
||||||
$printer -> barcode("9876");
|
$printer -> barcode("9876");
|
||||||
$printer -> feed();
|
$printer -> feed();
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
|
|
||||||
/* Graphics - this demo will not work on some non-Epson printers */
|
/* Graphics - this demo will not work on some non-Epson printers */
|
||||||
try {
|
try {
|
||||||
$logo = new EscposImage("resources/escpos-php.png");
|
$logo = EscposImage::load("resources/escpos-php.png", false);
|
||||||
$imgModes = array(
|
$imgModes = array(
|
||||||
Escpos::IMG_DEFAULT,
|
Printer::IMG_DEFAULT,
|
||||||
Escpos::IMG_DOUBLE_WIDTH,
|
Printer::IMG_DOUBLE_WIDTH,
|
||||||
Escpos::IMG_DOUBLE_HEIGHT,
|
Printer::IMG_DOUBLE_HEIGHT,
|
||||||
Escpos::IMG_DOUBLE_WIDTH | Escpos::IMG_DOUBLE_HEIGHT
|
Printer::IMG_DOUBLE_WIDTH | Printer::IMG_DOUBLE_HEIGHT
|
||||||
);
|
);
|
||||||
foreach($imgModes as $mode) {
|
foreach ($imgModes as $mode) {
|
||||||
$printer -> graphics($logo, $mode);
|
$printer -> graphics($logo, $mode);
|
||||||
}
|
}
|
||||||
} catch(Exception $e) {
|
} catch (Exception $e) {
|
||||||
/* Images not supported on your PHP, or image file not found */
|
/* Images not supported on your PHP, or image file not found */
|
||||||
$printer -> text($e -> getMessage() . "\n");
|
$printer -> text($e -> getMessage() . "\n");
|
||||||
}
|
}
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
|
|
||||||
/* Bit image */
|
/* Bit image */
|
||||||
try {
|
try {
|
||||||
$logo = new EscposImage("resources/escpos-php.png");
|
$logo = EscposImage::load("resources/escpos-php.png", false);
|
||||||
$imgModes = array(
|
$imgModes = array(
|
||||||
Escpos::IMG_DEFAULT,
|
Printer::IMG_DEFAULT,
|
||||||
Escpos::IMG_DOUBLE_WIDTH,
|
Printer::IMG_DOUBLE_WIDTH,
|
||||||
Escpos::IMG_DOUBLE_HEIGHT,
|
Printer::IMG_DOUBLE_HEIGHT,
|
||||||
Escpos::IMG_DOUBLE_WIDTH | Escpos::IMG_DOUBLE_HEIGHT
|
Printer::IMG_DOUBLE_WIDTH | Printer::IMG_DOUBLE_HEIGHT
|
||||||
);
|
);
|
||||||
foreach($imgModes as $mode) {
|
foreach ($imgModes as $mode) {
|
||||||
$printer -> bitImage($logo, $mode);
|
$printer -> bitImage($logo, $mode);
|
||||||
}
|
}
|
||||||
} catch(Exception $e) {
|
} catch (Exception $e) {
|
||||||
/* Images not supported on your PHP, or image file not found */
|
/* Images not supported on your PHP, or image file not found */
|
||||||
$printer -> text($e -> getMessage() . "\n");
|
$printer -> text($e -> getMessage() . "\n");
|
||||||
}
|
}
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
|
|
||||||
/* QR Code - see also the more in-depth demo at qr-code.php */
|
/* QR Code - see also the more in-depth demo at qr-code.php */
|
||||||
$testStr = "Testing 123";
|
$testStr = "Testing 123";
|
||||||
$models = array(
|
$models = array(
|
||||||
Escpos::QR_MODEL_1 => "QR Model 1",
|
Printer::QR_MODEL_1 => "QR Model 1",
|
||||||
Escpos::QR_MODEL_2 => "QR Model 2 (default)",
|
Printer::QR_MODEL_2 => "QR Model 2 (default)",
|
||||||
Escpos::QR_MICRO => "Micro QR code\n(not supported on all printers)");
|
Printer::QR_MICRO => "Micro QR code\n(not supported on all printers)");
|
||||||
foreach($models as $model => $name) {
|
foreach ($models as $model => $name) {
|
||||||
$printer -> qrCode($testStr, Escpos::QR_ECLEVEL_L, 3, $model);
|
$printer -> qrCode($testStr, Printer::QR_ECLEVEL_L, 3, $model);
|
||||||
$printer -> text("$name\n");
|
$printer -> text("$name\n");
|
||||||
$printer -> feed();
|
$printer -> feed();
|
||||||
}
|
}
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
|
|
||||||
@@ -164,4 +169,3 @@ $printer -> pulse();
|
|||||||
/* Always close the printer! On some PrintConnectors, no actual
|
/* Always close the printer! On some PrintConnectors, no actual
|
||||||
* data is sent until the printer is closed. */
|
* data is sent until the printer is closed. */
|
||||||
$printer -> close();
|
$printer -> close();
|
||||||
?>
|
|
||||||
|
|||||||
@@ -1,32 +1,36 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Print-outs using the newer graphics print command */
|
/* Print-outs using the newer graphics print command */
|
||||||
|
|
||||||
require_once(dirname(__FILE__) . "/../Escpos.php");
|
require __DIR__ . '/../autoload.php';
|
||||||
$printer = new Escpos();
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\EscposImage;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
|
||||||
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
|
$printer = new Printer($connector);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$tux = new EscposImage("resources/tux.png");
|
$tux = EscposImage::load("resources/tux.png", false);
|
||||||
|
|
||||||
$printer -> graphics($tux);
|
$printer -> graphics($tux);
|
||||||
$printer -> text("Regular Tux.\n");
|
$printer -> text("Regular Tux.\n");
|
||||||
$printer -> feed();
|
$printer -> feed();
|
||||||
|
|
||||||
$printer -> graphics($tux, Escpos::IMG_DOUBLE_WIDTH);
|
$printer -> graphics($tux, Printer::IMG_DOUBLE_WIDTH);
|
||||||
$printer -> text("Wide Tux.\n");
|
$printer -> text("Wide Tux.\n");
|
||||||
$printer -> feed();
|
$printer -> feed();
|
||||||
|
|
||||||
$printer -> graphics($tux, Escpos::IMG_DOUBLE_HEIGHT);
|
$printer -> graphics($tux, Printer::IMG_DOUBLE_HEIGHT);
|
||||||
$printer -> text("Tall Tux.\n");
|
$printer -> text("Tall Tux.\n");
|
||||||
$printer -> feed();
|
$printer -> feed();
|
||||||
|
|
||||||
$printer -> graphics($tux, Escpos::IMG_DOUBLE_WIDTH | Escpos::IMG_DOUBLE_HEIGHT);
|
$printer -> graphics($tux, Printer::IMG_DOUBLE_WIDTH | Printer::IMG_DOUBLE_HEIGHT);
|
||||||
$printer -> text("Large Tux in correct proportion.\n");
|
$printer -> text("Large Tux in correct proportion.\n");
|
||||||
|
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
} catch(Exception $e) {
|
} catch (Exception $e) {
|
||||||
/* Images not supported on your PHP, or image file not found */
|
/* Images not supported on your PHP, or image file not found */
|
||||||
$printer -> text($e -> getMessage() . "\n");
|
$printer -> text($e -> getMessage() . "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
$printer -> close();
|
$printer -> close();
|
||||||
?>
|
|
||||||
|
|||||||
19
htdocs/includes/mike42/escpos-php/example/interface/cups.php
Normal file
19
htdocs/includes/mike42/escpos-php/example/interface/cups.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
/* Change to the correct path if you copy this example! */
|
||||||
|
require __DIR__ . '/../../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\CupsPrintConnector;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$connector = new CupsPrintConnector("EPSON_TM-T20");
|
||||||
|
|
||||||
|
/* Print a "Hello world" receipt" */
|
||||||
|
$printer = new Printer($connector);
|
||||||
|
$printer -> text("Hello World!\n");
|
||||||
|
$printer -> cut();
|
||||||
|
|
||||||
|
/* Close printer */
|
||||||
|
$printer -> close();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo "Couldn't print to this printer: " . $e -> getMessage() . "\n";
|
||||||
|
}
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Change to the correct path if you copy this example! */
|
/* Change to the correct path if you copy this example! */
|
||||||
require_once(dirname(__FILE__) . "/../../Escpos.php");
|
require __DIR__ . '/../../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\NetworkPrintConnector;
|
||||||
|
|
||||||
/* Most printers are open on port 9100, so you just need to know the IP
|
/* Most printers are open on port 9100, so you just need to know the IP
|
||||||
* address of your receipt printer, and then fsockopen() it on that port.
|
* address of your receipt printer, and then fsockopen() it on that port.
|
||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
$connector = null;
|
$connector = new NetworkPrintConnector("10.x.x.x", 9100);
|
||||||
//$connector = new NetworkPrintConnector("10.x.x.x", 9100);
|
|
||||||
|
/* Print a "Hello world" receipt" */
|
||||||
/* Print a "Hello world" receipt" */
|
$printer = new Printer($connector);
|
||||||
$printer = new Escpos($connector);
|
$printer -> text("Hello World!\n");
|
||||||
$printer -> text("Hello World!\n");
|
$printer -> cut();
|
||||||
$printer -> cut();
|
|
||||||
|
/* Close printer */
|
||||||
/* Close printer */
|
$printer -> close();
|
||||||
$printer -> close();
|
} catch (Exception $e) {
|
||||||
} catch(Exception $e) {
|
echo "Couldn't print to this printer: " . $e -> getMessage() . "\n";
|
||||||
echo "Couldn't print to this printer: " . $e -> getMessage() . "\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Change to the correct path if you copy this example! */
|
/* Change to the correct path if you copy this example! */
|
||||||
require_once(dirname(__FILE__) . "/../../Escpos.php");
|
require __DIR__ . '/../../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* On Linux, use the usblp module to make your printer available as a device
|
* On Linux, use the usblp module to make your printer available as a device
|
||||||
@@ -14,20 +16,18 @@ require_once(dirname(__FILE__) . "/../../Escpos.php");
|
|||||||
* other drivers are unloading the module.
|
* other drivers are unloading the module.
|
||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
// Enter the device file for your USB printer here
|
// Enter the device file for your USB printer here
|
||||||
$connector = null;
|
$connector = new FilePrintConnector("/dev/usb/lp0");
|
||||||
//$connector = new FilePrintConnector("/dev/usb/lp0");
|
//$connector = new FilePrintConnector("/dev/usb/lp1");
|
||||||
//$connector = new FilePrintConnector("/dev/usb/lp1");
|
//$connector = new FilePrintConnector("/dev/usb/lp2");
|
||||||
//$connector = new FilePrintConnector("/dev/usb/lp2");
|
|
||||||
|
|
||||||
/* Print a "Hello world" receipt" */
|
/* Print a "Hello world" receipt" */
|
||||||
$printer = new Escpos($connector);
|
$printer = new Printer($connector);
|
||||||
$printer -> text("Hello World!\n");
|
$printer -> text("Hello World!\n");
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
|
|
||||||
/* Close printer */
|
/* Close printer */
|
||||||
$printer -> close();
|
$printer -> close();
|
||||||
} catch(Exception $e) {
|
} catch (Exception $e) {
|
||||||
echo "Couldn't print to this printer: " . $e -> getMessage() . "\n";
|
echo "Couldn't print to this printer: " . $e -> getMessage() . "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,51 +1,52 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Change to the correct path if you copy this example! */
|
/* Change to the correct path if you copy this example! */
|
||||||
require_once(dirname(__FILE__) . "/../../Escpos.php");
|
require __DIR__ . '/../../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\WindowsPrintConnector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Install the printer using USB printing support, and the "Generic / Text Only" driver,
|
* Install the printer using USB printing support, and the "Generic / Text Only" driver,
|
||||||
* then share it.
|
* then share it.
|
||||||
*
|
*
|
||||||
* Use a WindowsPrintConnector with the share name to print. This works on either
|
* Use a WindowsPrintConnector with the share name to print. This works on either
|
||||||
* Windows or Linux.
|
* Windows or Linux.
|
||||||
*
|
*
|
||||||
* Troubleshooting: Fire up a command prompt/terminal, and ensure that (if your printer is
|
* Troubleshooting: Fire up a command prompt/terminal, and ensure that (if your printer is
|
||||||
* shared as "Receipt Printer"), the following commands work.
|
* shared as "Receipt Printer"), the following commands work.
|
||||||
*
|
*
|
||||||
* Windows: (use an appropriate "net use" command if you need authentication)
|
* Windows: (use an appropriate "net use" command if you need authentication)
|
||||||
* echo "Hello World" > testfile
|
* echo "Hello World" > testfile
|
||||||
* ## If you need authentication, use "net use" to hook up the printer:
|
* ## If you need authentication, use "net use" to hook up the printer:
|
||||||
* # net use "\\computername\Receipt Printer" /user:Guest
|
* # net use "\\computername\Receipt Printer" /user:Guest
|
||||||
* # net use "\\computername\Receipt Printer" /user:Bob secret
|
* # net use "\\computername\Receipt Printer" /user:Bob secret
|
||||||
* # net use "\\computername\Receipt Printer" /user:workgroup\Bob secret
|
* # net use "\\computername\Receipt Printer" /user:workgroup\Bob secret
|
||||||
* copy testfile "\\computername\Receipt Printer"
|
* copy testfile "\\computername\Receipt Printer"
|
||||||
* del testfile
|
* del testfile
|
||||||
*
|
*
|
||||||
* GNU/Linux:
|
* GNU/Linux:
|
||||||
* # No authentication
|
* # No authentication
|
||||||
* echo "Hello World" | smbclient "//computername/Receipt Printer" -c "print -" -N
|
* echo "Hello World" | smbclient "//computername/Receipt Printer" -c "print -" -N
|
||||||
* # Guest login
|
* # Guest login
|
||||||
* echo "Hello World" | smbclient "//computername/Receipt Printer" -U Guest -c "print -" -N
|
* echo "Hello World" | smbclient "//computername/Receipt Printer" -U Guest -c "print -" -N
|
||||||
* # Basic username/password
|
* # Basic username/password
|
||||||
* echo "Hello World" | smbclient "//computername/Receipt Printer" secret -U "Bob" -c "print -"
|
* echo "Hello World" | smbclient "//computername/Receipt Printer" secret -U "Bob" -c "print -"
|
||||||
* # Including domain name
|
* # Including domain name
|
||||||
* echo "Hello World" | smbclient "//computername/Receipt Printer" secret -U "workgroup\\Bob" -c "print -"
|
* echo "Hello World" | smbclient "//computername/Receipt Printer" secret -U "workgroup\\Bob" -c "print -"
|
||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
// Enter the share name for your printer here, as a smb:// url format
|
// Enter the share name for your printer here, as a smb:// url format
|
||||||
$connector = null;
|
$connector = new WindowsPrintConnector("smb://computername/Receipt Printer");
|
||||||
//$connector = new WindowsPrintConnector("smb://computername/Receipt Printer");
|
//$connector = new WindowsPrintConnector("smb://Guest@computername/Receipt Printer");
|
||||||
//$connector = new WindowsPrintConnector("smb://Guest@computername/Receipt Printer");
|
//$connector = new WindowsPrintConnector("smb://FooUser:secret@computername/workgroup/Receipt Printer");
|
||||||
//$connector = new WindowsPrintConnector("smb://FooUser:secret@computername/workgroup/Receipt Printer");
|
//$connector = new WindowsPrintConnector("smb://User:secret@computername/Receipt Printer");
|
||||||
//$connector = new WindowsPrintConnector("smb://User:secret@computername/Receipt Printer");
|
|
||||||
|
/* Print a "Hello world" receipt" */
|
||||||
/* Print a "Hello world" receipt" */
|
$printer = new Printer($connector);
|
||||||
$printer = new Escpos($connector);
|
$printer -> text("Hello World!\n");
|
||||||
$printer -> text("Hello World!\n");
|
$printer -> cut();
|
||||||
$printer -> cut();
|
|
||||||
|
/* Close printer */
|
||||||
/* Close printer */
|
$printer -> close();
|
||||||
$printer -> close();
|
} catch (Exception $e) {
|
||||||
} catch(Exception $e) {
|
echo "Couldn't print to this printer: " . $e -> getMessage() . "\n";
|
||||||
echo "Couldn't print to this printer: " . $e -> getMessage() . "\n";
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,31 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Change to the correct path if you copy this example! */
|
/* Change to the correct path if you copy this example! */
|
||||||
require_once(dirname(__FILE__) . "/../../Escpos.php");
|
require __DIR__ . '/../../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\WindowsPrintConnector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assuming your printer is available at LPT1,
|
* Assuming your printer is available at LPT1,
|
||||||
* simpy instantiate a WindowsPrintConnector to it.
|
* simpy instantiate a WindowsPrintConnector to it.
|
||||||
*
|
*
|
||||||
* When troubleshooting, make sure you can send it
|
* When troubleshooting, make sure you can send it
|
||||||
* data from the command-line first:
|
* data from the command-line first:
|
||||||
* echo "Hello World" > LPT1
|
* echo "Hello World" > LPT1
|
||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
$connector = null;
|
$connector = new WindowsPrintConnector("LPT1");
|
||||||
//$connector = new WindowsPrintConnector("LPT1");
|
|
||||||
|
// A FilePrintConnector will also work, but on non-Windows systems, writes
|
||||||
// A FilePrintConnector will also work, but on non-Windows systems, writes
|
// to an actual file called 'LPT1' rather than giving a useful error.
|
||||||
// to an actual file called 'LPT1' rather than giving a useful error.
|
// $connector = new FilePrintConnector("LPT1");
|
||||||
// $connector = new FilePrintConnector("LPT1");
|
|
||||||
|
|
||||||
/* Print a "Hello world" receipt" */
|
/* Print a "Hello world" receipt" */
|
||||||
$printer = new Escpos($connector);
|
$printer = new Printer($connector);
|
||||||
$printer -> text("Hello World!\n");
|
$printer -> text("Hello World!\n");
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
|
|
||||||
/* Close printer */
|
/* Close printer */
|
||||||
$printer -> close();
|
$printer -> close();
|
||||||
} catch(Exception $e) {
|
} catch (Exception $e) {
|
||||||
echo "Couldn't print to this printer: " . $e -> getMessage() . "\n";
|
echo "Couldn't print to this printer: " . $e -> getMessage() . "\n";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,34 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Change to the correct path if you copy this example! */
|
/* Change to the correct path if you copy this example! */
|
||||||
require_once(dirname(__FILE__) . "/../../Escpos.php");
|
require __DIR__ . '/../../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\WindowsPrintConnector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Install the printer using USB printing support, and the "Generic / Text Only" driver,
|
* Install the printer using USB printing support, and the "Generic / Text Only" driver,
|
||||||
* then share it (you can use a firewall so that it can only be seen locally).
|
* then share it (you can use a firewall so that it can only be seen locally).
|
||||||
*
|
*
|
||||||
* Use a WindowsPrintConnector with the share name to print.
|
* Use a WindowsPrintConnector with the share name to print.
|
||||||
*
|
*
|
||||||
* Troubleshooting: Fire up a command prompt, and ensure that (if your printer is shared as
|
* Troubleshooting: Fire up a command prompt, and ensure that (if your printer is shared as
|
||||||
* "Receipt Printer), the following commands work:
|
* "Receipt Printer), the following commands work:
|
||||||
*
|
*
|
||||||
* echo "Hello World" > testfile
|
* echo "Hello World" > testfile
|
||||||
* copy testfile "\\%COMPUTERNAME%\Receipt Printer"
|
* copy testfile "\\%COMPUTERNAME%\Receipt Printer"
|
||||||
* del testfile
|
* del testfile
|
||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
// Enter the share name for your USB printer here
|
// Enter the share name for your USB printer here
|
||||||
$connector = null;
|
$connector = null;
|
||||||
//$connector = new WindowsPrintConnector("Receipt Printer");
|
//$connector = new WindowsPrintConnector("Receipt Printer");
|
||||||
|
|
||||||
/* Print a "Hello world" receipt" */
|
/* Print a "Hello world" receipt" */
|
||||||
$printer = new Escpos($connector);
|
$printer = new Printer($connector);
|
||||||
$printer -> text("Hello World!\n");
|
$printer -> text("Hello World!\n");
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
|
|
||||||
/* Close printer */
|
/* Close printer */
|
||||||
$printer -> close();
|
$printer -> close();
|
||||||
} catch(Exception $e) {
|
} catch (Exception $e) {
|
||||||
echo "Couldn't print to this printer: " . $e -> getMessage() . "\n";
|
echo "Couldn't print to this printer: " . $e -> getMessage() . "\n";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
/* Left margin & page width demo. */
|
||||||
|
require __DIR__ . '/../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
|
||||||
|
$connector = new FilePrintConnector("php://stdout"); // Add connector for your printer here.
|
||||||
|
$printer = new Printer($connector);
|
||||||
|
|
||||||
|
/* Line spacing */
|
||||||
|
/*
|
||||||
|
$printer -> setEmphasis(true);
|
||||||
|
$printer -> text("Line spacing\n");
|
||||||
|
$printer -> setEmphasis(false);
|
||||||
|
foreach(array(16, 32, 64, 128, 255) as $spacing) {
|
||||||
|
$printer -> setLineSpacing($spacing);
|
||||||
|
$printer -> text("Spacing $spacing: The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.\n");
|
||||||
|
}
|
||||||
|
$printer -> setLineSpacing(); // Back to default
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Stuff around with left margin */
|
||||||
|
$printer -> setEmphasis(true);
|
||||||
|
$printer -> text("Left margin\n");
|
||||||
|
$printer -> setEmphasis(false);
|
||||||
|
$printer -> text("Default left\n");
|
||||||
|
foreach(array(1, 2, 4, 8, 16, 32, 64, 128, 256, 512) as $margin) {
|
||||||
|
$printer -> setPrintLeftMargin($margin);
|
||||||
|
$printer -> text("left margin $margin\n");
|
||||||
|
}
|
||||||
|
/* Reset left */
|
||||||
|
$printer -> setPrintLeftMargin(0);
|
||||||
|
|
||||||
|
/* Stuff around with page width */
|
||||||
|
$printer -> setEmphasis(true);
|
||||||
|
$printer -> text("Page width\n");
|
||||||
|
$printer -> setEmphasis(false);
|
||||||
|
$printer -> setJustification(Printer::JUSTIFY_RIGHT);
|
||||||
|
$printer -> text("Default width\n");
|
||||||
|
foreach(array(512, 256, 128, 64) as $width) {
|
||||||
|
$printer -> setPrintWidth($width);
|
||||||
|
$printer -> text("page width $width\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Printer shutdown */
|
||||||
|
$printer -> cut();
|
||||||
|
$printer -> close();
|
||||||
|
|
||||||
95
htdocs/includes/mike42/escpos-php/example/pdf417-code.php
Normal file
95
htdocs/includes/mike42/escpos-php/example/pdf417-code.php
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
<?php
|
||||||
|
/* Demonstration of available options on the pdf417Code() command */
|
||||||
|
require __DIR__ . '/../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
|
||||||
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
|
$printer = new Printer($connector);
|
||||||
|
|
||||||
|
// Most simple example
|
||||||
|
title($printer, "PDF417 code demo\n");
|
||||||
|
$testStr = "Testing 123";
|
||||||
|
$printer -> pdf417Code($testStr);
|
||||||
|
$printer -> text("Most simple example\n");
|
||||||
|
$printer -> feed();
|
||||||
|
|
||||||
|
// Demo that alignment is the same as text
|
||||||
|
$printer -> setJustification(Printer::JUSTIFY_CENTER);
|
||||||
|
$printer -> pdf417Code($testStr, 3, 3, 2);
|
||||||
|
$printer -> text("Same content, narrow and centred\n");
|
||||||
|
$printer -> setJustification();
|
||||||
|
$printer -> feed();
|
||||||
|
|
||||||
|
// Demo of error correction
|
||||||
|
title($printer, "Error correction\n");
|
||||||
|
$ec = array(0.1, 0.5, 1.0, 2.0, 4.0);
|
||||||
|
foreach ($ec as $level) {
|
||||||
|
$printer -> pdf417Code($testStr, 3, 3, 0, $level);
|
||||||
|
$printer -> text("Error correction ratio $level\n");
|
||||||
|
$printer -> feed();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change size
|
||||||
|
title($printer, "Pixel size\n");
|
||||||
|
$sizes = array(
|
||||||
|
2 => "(minimum)",
|
||||||
|
3 => "(default)",
|
||||||
|
4 => "",
|
||||||
|
8 => "(maximum)");
|
||||||
|
foreach ($sizes as $size => $label) {
|
||||||
|
$printer -> pdf417Code($testStr, $size);
|
||||||
|
$printer -> text("Module width $size dots $label\n");
|
||||||
|
$printer -> feed();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change height
|
||||||
|
title($printer, "Height multiplier\n");
|
||||||
|
$sizes = array(
|
||||||
|
2 => "(minimum)",
|
||||||
|
3 => "(default)",
|
||||||
|
4 => "",
|
||||||
|
8 => "(maximum)");
|
||||||
|
foreach ($sizes as $size => $label) {
|
||||||
|
$printer -> pdf417Code($testStr, 3, $size);
|
||||||
|
$printer -> text("Height multiplier $size $label\n");
|
||||||
|
$printer -> feed();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chage data column count
|
||||||
|
title($printer, "Data column count\n");
|
||||||
|
$columnCounts = array(
|
||||||
|
0 => "(auto, default)",
|
||||||
|
1 => "",
|
||||||
|
2 => "",
|
||||||
|
3 => "",
|
||||||
|
4 => "",
|
||||||
|
5 => "",
|
||||||
|
30 => "(maximum, doesnt fit!)");
|
||||||
|
foreach ($columnCounts as $columnCount => $label) {
|
||||||
|
$printer -> pdf417Code($testStr, 3, 3, $columnCount);
|
||||||
|
$printer -> text("Column count $columnCount $label\n");
|
||||||
|
$printer -> feed();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change options
|
||||||
|
title($printer, "Options\n");
|
||||||
|
$models = array(
|
||||||
|
Printer::PDF417_STANDARD => "Standard",
|
||||||
|
Printer::PDF417_TRUNCATED => "Truncated");
|
||||||
|
foreach ($models as $model => $name) {
|
||||||
|
$printer -> pdf417Code($testStr, 3, 3, 0, 0.10, $model);
|
||||||
|
$printer -> text("$name\n");
|
||||||
|
$printer -> feed();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cut & close
|
||||||
|
$printer -> cut();
|
||||||
|
$printer -> close();
|
||||||
|
|
||||||
|
function title(Printer $printer, $str)
|
||||||
|
{
|
||||||
|
$printer -> selectPrintMode(Printer::MODE_DOUBLE_HEIGHT | Printer::MODE_DOUBLE_WIDTH);
|
||||||
|
$printer -> text($str);
|
||||||
|
$printer -> selectPrintMode();
|
||||||
|
}
|
||||||
@@ -1,11 +1,20 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once(dirname(__FILE__)."/../Escpos.php");
|
require __DIR__ . '/../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\EscposImage;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
|
||||||
|
$connector = new FilePrintConnector("php://stdout"); // Add connector for your printer here.
|
||||||
|
$printer = new Printer($connector);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Due to its complxity, escpos-php does not support HTML input. To print HTML,
|
* Due to its complxity, escpos-php does not support HTML input. To print HTML,
|
||||||
* either convert it to calls on the Escpos() object, or rasterise the page with
|
* either convert it to calls on the Printer() object, or rasterise the page with
|
||||||
* wkhtmltopdf, an external package which is designed to handle HTML efficiently.
|
* wkhtmltopdf, an external package which is designed to handle HTML efficiently.
|
||||||
*
|
*
|
||||||
* This example is provided to get you started.
|
* This example is provided to get you started: On Debian, first run-
|
||||||
|
*
|
||||||
|
* sudo apt-get install wkhtmltopdf xvfb
|
||||||
*
|
*
|
||||||
* Note: Depending on the height of your pages, it is suggested that you chop it
|
* Note: Depending on the height of your pages, it is suggested that you chop it
|
||||||
* into smaller sections, as printers simply don't have the buffer capacity for
|
* into smaller sections, as printers simply don't have the buffer capacity for
|
||||||
@@ -15,39 +24,63 @@ require_once(dirname(__FILE__)."/../Escpos.php");
|
|||||||
* (550 -> 225 below) and printing w/ Escpos::IMG_DOUBLE_WIDTH | Escpos::IMG_DOUBLE_HEIGHT
|
* (550 -> 225 below) and printing w/ Escpos::IMG_DOUBLE_WIDTH | Escpos::IMG_DOUBLE_HEIGHT
|
||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
/* Set up command */
|
/* Set up command */
|
||||||
$source = "http://en.m.wikipedia.org/wiki/ESC/P";
|
$source = __DIR__ . "/resources/document.html";
|
||||||
$width = 550;
|
$width = 550;
|
||||||
$dest = tempnam(sys_get_temp_dir(), 'escpos') . ".png";
|
$dest = tempnam(sys_get_temp_dir(), 'escpos') . ".png";
|
||||||
$cmd = sprintf("wkhtmltoimage -n -q --width %s %s %s",
|
$command = sprintf(
|
||||||
escapeshellarg($width),
|
"xvfb-run wkhtmltoimage -n -q --width %s %s %s",
|
||||||
escapeshellarg($source),
|
escapeshellarg($width),
|
||||||
escapeshellarg($dest));
|
escapeshellarg($source),
|
||||||
|
escapeshellarg($dest)
|
||||||
/* Run wkhtmltoimage */
|
);
|
||||||
ob_start();
|
|
||||||
system($cmd); // Can also use popen() for better control of process
|
|
||||||
$outp = ob_get_contents();
|
|
||||||
ob_end_clean();
|
|
||||||
if(!file_exists($dest)) {
|
|
||||||
throw new Exception("Command $cmd failed: $outp");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load up the image */
|
/* Test for dependencies */
|
||||||
try {
|
foreach (array("xvfb-run", "wkhtmltoimage") as $cmd) {
|
||||||
$img = new EscposImage($dest);
|
$testCmd = sprintf("which %s", escapeshellarg($cmd));
|
||||||
} catch(Exception $e) {
|
exec($testCmd, $testOut, $testStatus);
|
||||||
unlink($dest);
|
if ($testStatus != 0) {
|
||||||
throw $e;
|
throw new Exception("You require $cmd but it could not be found");
|
||||||
}
|
}
|
||||||
unlink($dest);
|
}
|
||||||
|
|
||||||
/* Print it */
|
|
||||||
$printer = new Escpos(); // Add connector for your printer here.
|
/* Run wkhtmltoimage */
|
||||||
$printer -> bitImage($img); // bitImage() seems to allow larger images than graphics() on the TM-T20.
|
$descriptors = array(
|
||||||
$printer -> cut();
|
1 => array("pipe", "w"),
|
||||||
$printer -> close();
|
2 => array("pipe", "w"),
|
||||||
} catch(Exception $e) {
|
);
|
||||||
echo $e -> getMessage();
|
$process = proc_open($command, $descriptors, $fd);
|
||||||
|
if (is_resource($process)) {
|
||||||
|
/* Read stdout */
|
||||||
|
$outputStr = stream_get_contents($fd[1]);
|
||||||
|
fclose($fd[1]);
|
||||||
|
/* Read stderr */
|
||||||
|
$errorStr = stream_get_contents($fd[2]);
|
||||||
|
fclose($fd[2]);
|
||||||
|
/* Finish up */
|
||||||
|
$retval = proc_close($process);
|
||||||
|
if ($retval != 0) {
|
||||||
|
throw new Exception("Command $cmd failed: $outputStr $errorStr");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Exception("Command '$cmd' failed to start.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load up the image */
|
||||||
|
try {
|
||||||
|
$img = EscposImage::load($dest);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
unlink($dest);
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
unlink($dest);
|
||||||
|
|
||||||
|
/* Print it */
|
||||||
|
$printer -> bitImage($img); // bitImage() seems to allow larger images than graphics() on the TM-T20. bitImageColumnFormat() is another option.
|
||||||
|
$printer -> cut();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo $e -> getMessage();
|
||||||
|
} finally {
|
||||||
|
$printer -> close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once(dirname(__FILE__) . '/../Escpos.php');
|
require __DIR__ . '/../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\ImagickEscposImage;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is three examples in one:
|
* This is three examples in one:
|
||||||
* 1: Print an entire PDF, normal quality.
|
* 1: Print an entire PDF, normal quality.
|
||||||
@@ -9,21 +13,22 @@ require_once(dirname(__FILE__) . '/../Escpos.php');
|
|||||||
|
|
||||||
/* 1: Print an entire PDF, start-to-finish (shorter form of the example) */
|
/* 1: Print an entire PDF, start-to-finish (shorter form of the example) */
|
||||||
$pdf = 'resources/document.pdf';
|
$pdf = 'resources/document.pdf';
|
||||||
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
|
$printer = new Printer($connector);
|
||||||
try {
|
try {
|
||||||
$pages = EscposImage::loadPdf($pdf);
|
$pages = ImagickEscposImage::loadPdf($pdf);
|
||||||
$printer = new Escpos();
|
foreach ($pages as $page) {
|
||||||
foreach($pages as $page) {
|
$printer -> graphics($page);
|
||||||
$printer -> graphics($page);
|
}
|
||||||
}
|
$printer -> cut();
|
||||||
$printer -> cut();
|
} catch (Exception $e) {
|
||||||
$printer -> close();
|
/*
|
||||||
} catch(Exception $e) {
|
|
||||||
/*
|
|
||||||
* loadPdf() throws exceptions if files or not found, or you don't have the
|
* loadPdf() throws exceptions if files or not found, or you don't have the
|
||||||
* imagick extension to read PDF's
|
* imagick extension to read PDF's
|
||||||
*/
|
*/
|
||||||
echo $e -> getMessage() . "\n";
|
echo $e -> getMessage() . "\n";
|
||||||
exit(0);
|
} finally {
|
||||||
|
$printer -> close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -33,11 +38,12 @@ try {
|
|||||||
*
|
*
|
||||||
* Reduce the page width further if necessary: if it extends past the printing area, your prints will be very slow.
|
* Reduce the page width further if necessary: if it extends past the printing area, your prints will be very slow.
|
||||||
*/
|
*/
|
||||||
$printer = new Escpos();
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
|
$printer = new Printer($connector);
|
||||||
$pdf = 'resources/document.pdf';
|
$pdf = 'resources/document.pdf';
|
||||||
$pages = EscposImage::loadPdf($pdf, 260);
|
$pages = ImagickEscposImage::loadPdf($pdf, 260);
|
||||||
foreach($pages as $page) {
|
foreach ($pages as $page) {
|
||||||
$printer -> graphics($page, Escpos::IMG_DOUBLE_HEIGHT | Escpos::IMG_DOUBLE_WIDTH);
|
$printer -> graphics($page, Printer::IMG_DOUBLE_HEIGHT | Printer::IMG_DOUBLE_WIDTH);
|
||||||
}
|
}
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
$printer -> close();
|
$printer -> close();
|
||||||
@@ -51,21 +57,22 @@ $printer -> close();
|
|||||||
*
|
*
|
||||||
* [1]After printing, the pixels are loaded and formatted for the print command you used, so even a raspberry pi can print complex PDF's quickly.
|
* [1]After printing, the pixels are loaded and formatted for the print command you used, so even a raspberry pi can print complex PDF's quickly.
|
||||||
*/
|
*/
|
||||||
$printer = new Escpos();
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
|
$printer = new Printer($connector);
|
||||||
$pdf = 'resources/document.pdf';
|
$pdf = 'resources/document.pdf';
|
||||||
$ser = 'resources/document.z';
|
$ser = 'resources/document.z';
|
||||||
if(!file_exists($ser)) {
|
if (!file_exists($ser)) {
|
||||||
$pages = EscposImage::loadPdf($pdf);
|
$pages = ImagickEscposImage::loadPdf($pdf);
|
||||||
} else {
|
} else {
|
||||||
$pages = unserialize(gzuncompress(file_get_contents($ser)));
|
$pages = unserialize(gzuncompress(file_get_contents($ser)));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($pages as $page) {
|
foreach ($pages as $page) {
|
||||||
$printer -> graphics($page);
|
$printer -> graphics($page);
|
||||||
}
|
}
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
$printer -> close();
|
$printer -> close();
|
||||||
|
|
||||||
if(!file_exists($ser)) {
|
if (!file_exists($ser)) {
|
||||||
file_put_contents($ser, gzcompress(serialize($pages)));
|
file_put_contents($ser, gzcompress(serialize($pages)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Demonstration of available options on the qrCode() command */
|
/* Demonstration of available options on the qrCode() command */
|
||||||
require_once(dirname(__FILE__) . "/../Escpos.php");
|
require __DIR__ . '/../autoload.php';
|
||||||
$printer = new Escpos();
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
|
||||||
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
|
$printer = new Printer($connector);
|
||||||
|
|
||||||
// Most simple example
|
// Most simple example
|
||||||
title($printer, "QR code demo\n");
|
title($printer, "QR code demo\n");
|
||||||
@@ -11,71 +15,72 @@ $printer -> text("Most simple example\n");
|
|||||||
$printer -> feed();
|
$printer -> feed();
|
||||||
|
|
||||||
// Demo that alignment is the same as text
|
// Demo that alignment is the same as text
|
||||||
$printer -> setJustification(Escpos::JUSTIFY_CENTER);
|
$printer -> setJustification(Printer::JUSTIFY_CENTER);
|
||||||
$printer -> qrCode($testStr);
|
$printer -> qrCode($testStr);
|
||||||
$printer -> text("Same example, centred\n");
|
$printer -> text("Same example, centred\n");
|
||||||
$printer -> setJustification();
|
$printer -> setJustification();
|
||||||
$printer -> feed();
|
$printer -> feed();
|
||||||
|
|
||||||
// Demo of numeric data being packed more densly
|
// Demo of numeric data being packed more densly
|
||||||
title($printer, "Data encoding\n");
|
title($printer, "Data encoding\n");
|
||||||
$test = array(
|
$test = array(
|
||||||
"Numeric" => "0123456789012345678901234567890123456789",
|
"Numeric" => "0123456789012345678901234567890123456789",
|
||||||
"Alphanumeric" => "abcdefghijklmnopqrstuvwxyzabcdefghijklmn",
|
"Alphanumeric" => "abcdefghijklmnopqrstuvwxyzabcdefghijklmn",
|
||||||
"Binary" => str_repeat("\0", 40));
|
"Binary" => str_repeat("\0", 40));
|
||||||
foreach($test as $type => $data) {
|
foreach ($test as $type => $data) {
|
||||||
$printer -> qrCode($data);
|
$printer -> qrCode($data);
|
||||||
$printer -> text("$type\n");
|
$printer -> text("$type\n");
|
||||||
$printer -> feed();
|
$printer -> feed();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Demo of error correction
|
// Demo of error correction
|
||||||
title($printer, "Error correction\n");
|
title($printer, "Error correction\n");
|
||||||
$ec = array(
|
$ec = array(
|
||||||
Escpos::QR_ECLEVEL_L => "L",
|
Printer::QR_ECLEVEL_L => "L",
|
||||||
Escpos::QR_ECLEVEL_M => "M",
|
Printer::QR_ECLEVEL_M => "M",
|
||||||
Escpos::QR_ECLEVEL_Q => "Q",
|
Printer::QR_ECLEVEL_Q => "Q",
|
||||||
Escpos::QR_ECLEVEL_H => "H");
|
Printer::QR_ECLEVEL_H => "H");
|
||||||
foreach($ec as $level => $name) {
|
foreach ($ec as $level => $name) {
|
||||||
$printer -> qrCode($testStr, $level);
|
$printer -> qrCode($testStr, $level);
|
||||||
$printer -> text("Error correction $name\n");
|
$printer -> text("Error correction $name\n");
|
||||||
$printer -> feed();
|
$printer -> feed();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change size
|
// Change size
|
||||||
title($printer, "Pixel size\n");
|
title($printer, "Pixel size\n");
|
||||||
$sizes = array(
|
$sizes = array(
|
||||||
1 => "(minimum)",
|
1 => "(minimum)",
|
||||||
2 => "",
|
2 => "",
|
||||||
3 => "(default)",
|
3 => "(default)",
|
||||||
4 => "",
|
4 => "",
|
||||||
5 => "",
|
5 => "",
|
||||||
10 => "",
|
10 => "",
|
||||||
16 => "(maximum)");
|
16 => "(maximum)");
|
||||||
foreach($sizes as $size => $label) {
|
foreach ($sizes as $size => $label) {
|
||||||
$printer -> qrCode($testStr, Escpos::QR_ECLEVEL_L, $size);
|
$printer -> qrCode($testStr, Printer::QR_ECLEVEL_L, $size);
|
||||||
$printer -> text("Pixel size $size $label\n");
|
$printer -> text("Pixel size $size $label\n");
|
||||||
$printer -> feed();
|
$printer -> feed();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change model
|
// Change model
|
||||||
title($printer, "QR model\n");
|
title($printer, "QR model\n");
|
||||||
$models = array(
|
$models = array(
|
||||||
Escpos::QR_MODEL_1 => "QR Model 1",
|
Printer::QR_MODEL_1 => "QR Model 1",
|
||||||
Escpos::QR_MODEL_2 => "QR Model 2 (default)",
|
Printer::QR_MODEL_2 => "QR Model 2 (default)",
|
||||||
Escpos::QR_MICRO => "Micro QR code\n(not supported on all printers)");
|
Printer::QR_MICRO => "Micro QR code\n(not supported on all printers)");
|
||||||
foreach($models as $model => $name) {
|
foreach ($models as $model => $name) {
|
||||||
$printer -> qrCode($testStr, Escpos::QR_ECLEVEL_L, 3, $model);
|
$printer -> qrCode($testStr, Printer::QR_ECLEVEL_L, 3, $model);
|
||||||
$printer -> text("$name\n");
|
$printer -> text("$name\n");
|
||||||
$printer -> feed();
|
$printer -> feed();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cut & close
|
// Cut & close
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
$printer -> close();
|
$printer -> close();
|
||||||
|
|
||||||
function title(Escpos $printer, $str) {
|
function title(Printer $printer, $str)
|
||||||
$printer -> selectPrintMode(Escpos::MODE_DOUBLE_HEIGHT | Escpos::MODE_DOUBLE_WIDTH);
|
{
|
||||||
$printer -> text($str);
|
$printer -> selectPrintMode(Printer::MODE_DOUBLE_HEIGHT | Printer::MODE_DOUBLE_WIDTH);
|
||||||
$printer -> selectPrintMode();
|
$printer -> text($str);
|
||||||
|
$printer -> selectPrintMode();
|
||||||
}
|
}
|
||||||
|
|||||||
76
htdocs/includes/mike42/escpos-php/example/rawbt-receipt.html
Normal file
76
htdocs/includes/mike42/escpos-php/example/rawbt-receipt.html
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>RawBT Integration Demo</title>
|
||||||
|
<meta content="width=device-width, initial-scale=1" name="viewport">
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
|
||||||
|
<style>
|
||||||
|
html {
|
||||||
|
background-color: grey;
|
||||||
|
padding: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
max-width: 640px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 32px;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background-color: #6e89ff;
|
||||||
|
color: white;
|
||||||
|
padding: 16px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
border-left: #6e89ff solid 3px
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #6e89ff;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
a:before{
|
||||||
|
content: '\1F855';
|
||||||
|
margin-right:4px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
// for php demo call
|
||||||
|
function ajax_print(url, btn) {
|
||||||
|
b = $(btn);
|
||||||
|
b.attr('data-old', b.text());
|
||||||
|
b.text('wait');
|
||||||
|
$.get(url, function (data) {
|
||||||
|
window.location.href = data; // main action
|
||||||
|
}).fail(function () {
|
||||||
|
alert("ajax error");
|
||||||
|
}).always(function () {
|
||||||
|
b.text(b.attr('data-old'));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<img src="resources/rawbtlogo.png" alt="black & white picture">
|
||||||
|
<h1>RawBT Integration Demo</h1>
|
||||||
|
<pre>
|
||||||
|
|
||||||
|
window.location.href = ajax_backend_data;
|
||||||
|
|
||||||
|
</pre>
|
||||||
|
<br/>
|
||||||
|
<button onclick="ajax_print('rawbt-receipt.php',this)">RECEIPT</button>
|
||||||
|
|
||||||
|
<p><a href="https://rawbt.ru/">Visit RawBT site</a></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
145
htdocs/includes/mike42/escpos-php/example/rawbt-receipt.php
Normal file
145
htdocs/includes/mike42/escpos-php/example/rawbt-receipt.php
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
<?php
|
||||||
|
require __DIR__ . '/../autoload.php';
|
||||||
|
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\EscposImage;
|
||||||
|
use Mike42\Escpos\PrintConnectors\RawbtPrintConnector;
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$profile = CapabilityProfile::load("POS-5890");
|
||||||
|
|
||||||
|
/* Fill in your own connector here */
|
||||||
|
$connector = new RawbtPrintConnector();
|
||||||
|
|
||||||
|
/* Information for the receipt */
|
||||||
|
$items = array(
|
||||||
|
new item("Example item #1", "4.00"),
|
||||||
|
new item("Another thing", "3.50"),
|
||||||
|
new item("Something else", "1.00"),
|
||||||
|
new item("A final item", "4.45"),
|
||||||
|
);
|
||||||
|
$subtotal = new item('Subtotal', '12.95');
|
||||||
|
$tax = new item('A local tax', '1.30');
|
||||||
|
$total = new item('Total', '14.25', true);
|
||||||
|
/* Date is kept the same for testing */
|
||||||
|
// $date = date('l jS \of F Y h:i:s A');
|
||||||
|
$date = "Monday 6th of April 2015 02:56:25 PM";
|
||||||
|
|
||||||
|
/* Start the printer */
|
||||||
|
$logo = EscposImage::load("resources/rawbtlogo.png", false);
|
||||||
|
$printer = new Printer($connector, $profile);
|
||||||
|
|
||||||
|
|
||||||
|
/* Print top logo */
|
||||||
|
if ($profile->getSupportsGraphics()) {
|
||||||
|
$printer->graphics($logo);
|
||||||
|
}
|
||||||
|
if ($profile->getSupportsBitImageRaster() && !$profile->getSupportsGraphics()) {
|
||||||
|
$printer->bitImage($logo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Name of shop */
|
||||||
|
$printer->setJustification(Printer::JUSTIFY_CENTER);
|
||||||
|
$printer->selectPrintMode(Printer::MODE_DOUBLE_WIDTH);
|
||||||
|
$printer->text("ExampleMart Ltd.\n");
|
||||||
|
$printer->selectPrintMode();
|
||||||
|
$printer->text("Shop No. 42.\n");
|
||||||
|
$printer->feed();
|
||||||
|
|
||||||
|
|
||||||
|
/* Title of receipt */
|
||||||
|
$printer->setEmphasis(true);
|
||||||
|
$printer->text("SALES INVOICE\n");
|
||||||
|
$printer->setEmphasis(false);
|
||||||
|
|
||||||
|
/* Items */
|
||||||
|
$printer->setJustification(Printer::JUSTIFY_LEFT);
|
||||||
|
$printer->setEmphasis(true);
|
||||||
|
$printer->text(new item('', '$'));
|
||||||
|
$printer->setEmphasis(false);
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$printer->text($item->getAsString(32)); // for 58mm Font A
|
||||||
|
}
|
||||||
|
$printer->setEmphasis(true);
|
||||||
|
$printer->text($subtotal->getAsString(32));
|
||||||
|
$printer->setEmphasis(false);
|
||||||
|
$printer->feed();
|
||||||
|
|
||||||
|
/* Tax and total */
|
||||||
|
$printer->text($tax->getAsString(32));
|
||||||
|
$printer->selectPrintMode(Printer::MODE_DOUBLE_WIDTH);
|
||||||
|
$printer->text($total->getAsString(32));
|
||||||
|
$printer->selectPrintMode();
|
||||||
|
|
||||||
|
/* Footer */
|
||||||
|
$printer->feed(2);
|
||||||
|
$printer->setJustification(Printer::JUSTIFY_CENTER);
|
||||||
|
$printer->text("Thank you for shopping\n");
|
||||||
|
$printer->text("at ExampleMart\n");
|
||||||
|
$printer->text("For trading hours,\n");
|
||||||
|
$printer->text("please visit example.com\n");
|
||||||
|
$printer->feed(2);
|
||||||
|
$printer->text($date . "\n");
|
||||||
|
|
||||||
|
/* Barcode Default look */
|
||||||
|
|
||||||
|
$printer->barcode("ABC", Printer::BARCODE_CODE39);
|
||||||
|
$printer->feed();
|
||||||
|
$printer->feed();
|
||||||
|
|
||||||
|
|
||||||
|
// Demo that alignment QRcode is the same as text
|
||||||
|
$printer2 = new Printer($connector); // dirty printer profile hack !!
|
||||||
|
$printer2->setJustification(Printer::JUSTIFY_CENTER);
|
||||||
|
$printer2->qrCode("https://rawbt.ru/mike42", Printer::QR_ECLEVEL_M, 8);
|
||||||
|
$printer2->text("rawbt.ru/mike42\n");
|
||||||
|
$printer2->setJustification();
|
||||||
|
$printer2->feed();
|
||||||
|
|
||||||
|
|
||||||
|
/* Cut the receipt and open the cash drawer */
|
||||||
|
$printer->cut();
|
||||||
|
$printer->pulse();
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo $e->getMessage();
|
||||||
|
} finally {
|
||||||
|
$printer->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A wrapper to do organise item names & prices into columns */
|
||||||
|
|
||||||
|
class item
|
||||||
|
{
|
||||||
|
private $name;
|
||||||
|
private $price;
|
||||||
|
private $dollarSign;
|
||||||
|
|
||||||
|
public function __construct($name = '', $price = '', $dollarSign = false)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
$this->price = $price;
|
||||||
|
$this->dollarSign = $dollarSign;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAsString($width = 48)
|
||||||
|
{
|
||||||
|
$rightCols = 10;
|
||||||
|
$leftCols = $width - $rightCols;
|
||||||
|
if ($this->dollarSign) {
|
||||||
|
$leftCols = $leftCols / 2 - $rightCols / 2;
|
||||||
|
}
|
||||||
|
$left = str_pad($this->name, $leftCols);
|
||||||
|
|
||||||
|
$sign = ($this->dollarSign ? '$ ' : '');
|
||||||
|
$right = str_pad($sign . $this->price, $rightCols, ' ', STR_PAD_LEFT);
|
||||||
|
return "$left$right\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return $this->getAsString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,12 +1,18 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once(dirname(__FILE__) . "/../Escpos.php");
|
require __DIR__ . '/../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\EscposImage;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
|
||||||
|
/* Fill in your own connector here */
|
||||||
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
|
|
||||||
/* Information for the receipt */
|
/* Information for the receipt */
|
||||||
$items = array(
|
$items = array(
|
||||||
new item("Example item #1", "4.00"),
|
new item("Example item #1", "4.00"),
|
||||||
new item("Another thing", "3.50"),
|
new item("Another thing", "3.50"),
|
||||||
new item("Something else", "1.00"),
|
new item("Something else", "1.00"),
|
||||||
new item("A final item", "4.45"),
|
new item("A final item", "4.45"),
|
||||||
);
|
);
|
||||||
$subtotal = new item('Subtotal', '12.95');
|
$subtotal = new item('Subtotal', '12.95');
|
||||||
$tax = new item('A local tax', '1.30');
|
$tax = new item('A local tax', '1.30');
|
||||||
@@ -16,15 +22,15 @@ $total = new item('Total', '14.25', true);
|
|||||||
$date = "Monday 6th of April 2015 02:56:25 PM";
|
$date = "Monday 6th of April 2015 02:56:25 PM";
|
||||||
|
|
||||||
/* Start the printer */
|
/* Start the printer */
|
||||||
$logo = new EscposImage("resources/escpos-php.png");
|
$logo = EscposImage::load("resources/escpos-php.png", false);
|
||||||
$printer = new Escpos();
|
$printer = new Printer($connector);
|
||||||
|
|
||||||
/* Print top logo */
|
/* Print top logo */
|
||||||
$printer -> setJustification(Escpos::JUSTIFY_CENTER);
|
$printer -> setJustification(Printer::JUSTIFY_CENTER);
|
||||||
$printer -> graphics($logo);
|
$printer -> graphics($logo);
|
||||||
|
|
||||||
/* Name of shop */
|
/* Name of shop */
|
||||||
$printer -> selectPrintMode(Escpos::MODE_DOUBLE_WIDTH);
|
$printer -> selectPrintMode(Printer::MODE_DOUBLE_WIDTH);
|
||||||
$printer -> text("ExampleMart Ltd.\n");
|
$printer -> text("ExampleMart Ltd.\n");
|
||||||
$printer -> selectPrintMode();
|
$printer -> selectPrintMode();
|
||||||
$printer -> text("Shop No. 42.\n");
|
$printer -> text("Shop No. 42.\n");
|
||||||
@@ -36,12 +42,12 @@ $printer -> text("SALES INVOICE\n");
|
|||||||
$printer -> setEmphasis(false);
|
$printer -> setEmphasis(false);
|
||||||
|
|
||||||
/* Items */
|
/* Items */
|
||||||
$printer -> setJustification(Escpos::JUSTIFY_LEFT);
|
$printer -> setJustification(Printer::JUSTIFY_LEFT);
|
||||||
$printer -> setEmphasis(true);
|
$printer -> setEmphasis(true);
|
||||||
$printer -> text(new item('', '$'));
|
$printer -> text(new item('', '$'));
|
||||||
$printer -> setEmphasis(false);
|
$printer -> setEmphasis(false);
|
||||||
foreach($items as $item) {
|
foreach ($items as $item) {
|
||||||
$printer -> text($item);
|
$printer -> text($item);
|
||||||
}
|
}
|
||||||
$printer -> setEmphasis(true);
|
$printer -> setEmphasis(true);
|
||||||
$printer -> text($subtotal);
|
$printer -> text($subtotal);
|
||||||
@@ -50,13 +56,13 @@ $printer -> feed();
|
|||||||
|
|
||||||
/* Tax and total */
|
/* Tax and total */
|
||||||
$printer -> text($tax);
|
$printer -> text($tax);
|
||||||
$printer -> selectPrintMode(Escpos::MODE_DOUBLE_WIDTH);
|
$printer -> selectPrintMode(Printer::MODE_DOUBLE_WIDTH);
|
||||||
$printer -> text($total);
|
$printer -> text($total);
|
||||||
$printer -> selectPrintMode();
|
$printer -> selectPrintMode();
|
||||||
|
|
||||||
/* Footer */
|
/* Footer */
|
||||||
$printer -> feed(2);
|
$printer -> feed(2);
|
||||||
$printer -> setJustification(Escpos::JUSTIFY_CENTER);
|
$printer -> setJustification(Printer::JUSTIFY_CENTER);
|
||||||
$printer -> text("Thank you for shopping at ExampleMart\n");
|
$printer -> text("Thank you for shopping at ExampleMart\n");
|
||||||
$printer -> text("For trading hours, please visit example.com\n");
|
$printer -> text("For trading hours, please visit example.com\n");
|
||||||
$printer -> feed(2);
|
$printer -> feed(2);
|
||||||
@@ -69,28 +75,30 @@ $printer -> pulse();
|
|||||||
$printer -> close();
|
$printer -> close();
|
||||||
|
|
||||||
/* A wrapper to do organise item names & prices into columns */
|
/* A wrapper to do organise item names & prices into columns */
|
||||||
class item {
|
class item
|
||||||
private $name;
|
{
|
||||||
private $price;
|
private $name;
|
||||||
private $dollarSign;
|
private $price;
|
||||||
|
private $dollarSign;
|
||||||
|
|
||||||
public function __construct($name = '', $price = '', $dollarSign = false) {
|
public function __construct($name = '', $price = '', $dollarSign = false)
|
||||||
$this -> name = $name;
|
{
|
||||||
$this -> price = $price;
|
$this -> name = $name;
|
||||||
$this -> dollarSign = $dollarSign;
|
$this -> price = $price;
|
||||||
}
|
$this -> dollarSign = $dollarSign;
|
||||||
|
}
|
||||||
public function __toString() {
|
|
||||||
$rightCols = 10;
|
public function __toString()
|
||||||
$leftCols = 38;
|
{
|
||||||
if($this -> dollarSign) {
|
$rightCols = 10;
|
||||||
$leftCols = $leftCols / 2 - $rightCols / 2;
|
$leftCols = 38;
|
||||||
}
|
if ($this -> dollarSign) {
|
||||||
$left = str_pad($this -> name, $leftCols) ;
|
$leftCols = $leftCols / 2 - $rightCols / 2;
|
||||||
|
}
|
||||||
$sign = ($this -> dollarSign ? '$ ' : '');
|
$left = str_pad($this -> name, $leftCols) ;
|
||||||
$right = str_pad($sign . $this -> price, $rightCols, ' ', STR_PAD_LEFT);
|
|
||||||
return "$left$right\n";
|
$sign = ($this -> dollarSign ? '$ ' : '');
|
||||||
}
|
$right = str_pad($sign . $this -> price, $rightCols, ' ', STR_PAD_LEFT);
|
||||||
|
return "$left$right\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
?>
|
|
||||||
|
|||||||
@@ -3,21 +3,22 @@
|
|||||||
* on the default profile, so you can use them to test modified profiles (using the wrong
|
* on the default profile, so you can use them to test modified profiles (using the wrong
|
||||||
* profile for a printer produces mojibake) */
|
* profile for a printer produces mojibake) */
|
||||||
$inputsOk = array(
|
$inputsOk = array(
|
||||||
"Danish" => "Quizdeltagerne spiste jordbær med fløde, mens cirkusklovnen Wolther spillede på xylofon.\n",
|
"Danish" => "Quizdeltagerne spiste jordbær med fløde, mens cirkusklovnen Wolther spillede på xylofon.\n",
|
||||||
"German" => "Falsches Üben von Xylophonmusik quält jeden größeren Zwerg.\n",
|
"German" => "Falsches Üben von Xylophonmusik quält jeden größeren Zwerg.\n",
|
||||||
"Greek" => "Ξεσκεπάζω την ψυχοφθόρα βδελυγμία\n",
|
"Greek" => "Ξεσκεπάζω την ψυχοφθόρα βδελυγμία\n",
|
||||||
"English" => "The quick brown fox jumps over the lazy dog.\n",
|
"English" => "The quick brown fox jumps over the lazy dog.\n",
|
||||||
"Spanish" => "El pingüino Wenceslao hizo kilómetros bajo exhaustiva lluvia y frío, añoraba a su querido cachorro.\n",
|
"Spanish" => "El pingüino Wenceslao hizo kilómetros bajo exhaustiva lluvia y frío, añoraba a su querido cachorro.\n",
|
||||||
"French" => "Le cœur déçu mais l'âme plutôt naïve, Louÿs rêva de crapaüter en canoë au delà des îles, près du mälström où brûlent les novæ.\n",
|
"French" => "Le cœur déçu mais l'âme plutôt naïve, Louÿs rêva de crapaüter en canoë au delà des îles, près du mälström où brûlent les novæ.\n",
|
||||||
"Irish Gaelic" => "D'fhuascail Íosa, Úrmhac na hÓighe Beannaithe, pór Éava agus Ádhaimh.\n",
|
"Irish Gaelic" => "D'fhuascail Íosa, Úrmhac na hÓighe Beannaithe, pór Éava agus Ádhaimh.\n",
|
||||||
"Hungarian" => "Árvíztűrő tükörfúrógép.\n",
|
"Hungarian" => "Árvíztűrő tükörfúrógép.\n",
|
||||||
"Icelandic" => "Kæmi ný öxi hér ykist þjófum nú bæði víl og ádrepa.\n",
|
"Icelandic" => "Kæmi ný öxi hér ykist þjófum nú bæði víl og ádrepa.\n",
|
||||||
"Latvian" => "Glāžšķūņa rūķīši dzērumā čiepj Baha koncertflīģeļu vākus.\n",
|
"Latvian" => "Glāžšķūņa rūķīši dzērumā čiepj Baha koncertflīģeļu vākus.\n",
|
||||||
"Polish" => "Pchnąć w tę łódź jeża lub ośm skrzyń fig.\n",
|
"Polish" => "Pchnąć w tę łódź jeża lub ośm skrzyń fig.\n",
|
||||||
"Russian" => "В чащах юга жил бы цитрус? Да, но фальшивый экземпляр!\n",
|
"Russian" => "В чащах юга жил бы цитрус? Да, но фальшивый экземпляр!\n",
|
||||||
"Turkish" => "Pijamalı hasta, yağız şoföre çabucak güvendi.\n",
|
"Turkish" => "Pijamalı hasta, yağız şoföre çabucak güvendi.\n",
|
||||||
"Japanese (Katakana half-width)" => implode("\n", array("イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム", "ウイノオクヤマ ケフコエテ アサキユメミシ エヒモセスン")) . "\n"
|
"Japanese (Katakana half-width)" => implode("\n", array("イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム", "ウイノオクヤマ ケフコエテ アサキユメミシ エヒモセスン")) . "\n",
|
||||||
);
|
"Vietnamese" => "Tiếng Việt, còn gọi tiếng Việt Nam hay Việt ngữ, là ngôn ngữ của người Việt (người Kinh) và là ngôn ngữ chính thức tại Việt Nam.\n"
|
||||||
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These strings are not expected to print correctly, if at all, even on an Epson printer. This is due to a mix of
|
* These strings are not expected to print correctly, if at all, even on an Epson printer. This is due to a mix of
|
||||||
@@ -26,10 +27,9 @@ $inputsOk = array(
|
|||||||
* They are included here as a collection of things not yet implemented.
|
* They are included here as a collection of things not yet implemented.
|
||||||
*/
|
*/
|
||||||
$inputsNotOk = array(
|
$inputsNotOk = array(
|
||||||
"Thai (No character encoder available)" => "นายสังฆภัณฑ์ เฮงพิทักษ์ฝั่ง ผู้เฒ่าซึ่งมีอาชีพเป็นฅนขายฃวด ถูกตำรวจปฏิบัติการจับฟ้องศาล ฐานลักนาฬิกาคุณหญิงฉัตรชฎา ฌานสมาธิ\n",
|
"Thai (No character encoder available)" => "นายสังฆภัณฑ์ เฮงพิทักษ์ฝั่ง ผู้เฒ่าซึ่งมีอาชีพเป็นฅนขายฃวด ถูกตำรวจปฏิบัติการจับฟ้องศาล ฐานลักนาฬิกาคุณหญิงฉัตรชฎา ฌานสมาธิ\n",
|
||||||
"Japanese (Hiragana)" => implode("\n", array("いろはにほへとちりぬるを", " わかよたれそつねならむ", "うゐのおくやまけふこえて", "あさきゆめみしゑひもせす")) . "\n",
|
"Japanese (Hiragana)" => implode("\n", array("いろはにほへとちりぬるを", " わかよたれそつねならむ", "うゐのおくやまけふこえて", "あさきゆめみしゑひもせす")) . "\n",
|
||||||
"Japanese (Katakana full-width)" => implode("\n", array("イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム", "ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン")) . "\n",
|
"Japanese (Katakana full-width)" => implode("\n", array("イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム", "ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン")) . "\n",
|
||||||
"Arabic (RTL not supported, encoding issues)" => "صِف خَلقَ خَودِ كَمِثلِ الشَمسِ إِذ بَزَغَت — يَحظى الضَجيعُ بِها نَجلاءَ مِعطارِ" . "\n",
|
"Arabic (RTL not supported, encoding issues)" => "صِف خَلقَ خَودِ كَمِثلِ الشَمسِ إِذ بَزَغَت — يَحظى الضَجيعُ بِها نَجلاءَ مِعطارِ" . "\n",
|
||||||
"Hebrew (RTL not supported, line break issues)" => "דג סקרן שט בים מאוכזב ולפתע מצא לו חברה איך הקליטה" . "\n"
|
"Hebrew (RTL not supported, line break issues)" => "דג סקרן שט בים מאוכזב ולפתע מצא לו חברה איך הקליטה" . "\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
BIN
htdocs/includes/mike42/escpos-php/example/resources/tulips.png
Normal file
BIN
htdocs/includes/mike42/escpos-php/example/resources/tulips.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 370 KiB |
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
require __DIR__ . '/../../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
|
||||||
|
$a = "{A012323392982";
|
||||||
|
$b = "{B012323392982";
|
||||||
|
$c = "{C" . chr(01) . chr(23) . chr(23) . chr(39) . chr(29) . chr(82);
|
||||||
|
|
||||||
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
|
$printer = new Printer($connector);
|
||||||
|
$printer -> setJustification(Printer::JUSTIFY_CENTER);
|
||||||
|
$printer -> setBarcodeHeight(48);
|
||||||
|
$printer->setBarcodeTextPosition(Printer::BARCODE_TEXT_BELOW);
|
||||||
|
foreach(array($a, $b, $c) as $item) {
|
||||||
|
$printer -> barcode($item, Printer::BARCODE_CODE128);
|
||||||
|
$printer -> feed(1);
|
||||||
|
}
|
||||||
|
$printer -> cut();
|
||||||
|
$printer -> close();
|
||||||
|
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
require __DIR__ . '/../../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
use Mike42\Escpos\CapabilityProfiles\DefaultCapabilityProfile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This example shows how to send a custom command to the printer
|
||||||
|
*
|
||||||
|
* "ESC ( B" is the barcode function for Epson LX300 series.
|
||||||
|
* This is not part of standard ESC/POS, but it's a good example
|
||||||
|
* of how to send some binary to the driver.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Barcode type is used in this script */
|
||||||
|
const EAN13 = 0;
|
||||||
|
|
||||||
|
/* Barcode properties */
|
||||||
|
$type = EAN13;
|
||||||
|
$content = "0075678164125";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make the command.
|
||||||
|
* This is documented on page A-14 of:
|
||||||
|
* https://files.support.epson.com/pdf/lx300p/lx300pu1.pdf
|
||||||
|
*/
|
||||||
|
$m = chr(EAN13);
|
||||||
|
$n = intLowHigh(strlen($content), 2);
|
||||||
|
$barcodeCommand = Printer::ESC . "G(" . $m . $n . $content;
|
||||||
|
|
||||||
|
/* Send it off as usual */
|
||||||
|
$connector = new FilePrintConnector("php://output");
|
||||||
|
$printer = new Printer($connector);
|
||||||
|
$printer->getPrintConnector()->write($barcodeCommand);
|
||||||
|
$printer->cut();
|
||||||
|
$printer->close();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate two characters for a number: In lower and higher parts, or more parts as needed.
|
||||||
|
*
|
||||||
|
* @param int $input
|
||||||
|
* Input number
|
||||||
|
* @param int $length
|
||||||
|
* The number of bytes to output (1 - 4).
|
||||||
|
*/
|
||||||
|
function intLowHigh($input, $length)
|
||||||
|
{
|
||||||
|
$outp = "";
|
||||||
|
for ($i = 0; $i < $length; $i ++) {
|
||||||
|
$outp .= chr($input % 256);
|
||||||
|
$input = (int) ($input / 256);
|
||||||
|
}
|
||||||
|
return $outp;
|
||||||
|
}
|
||||||
|
?>
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Example of one way you could load a PNG data URI into an EscposImage object
|
||||||
|
* without using a file.
|
||||||
|
*/
|
||||||
|
require __DIR__ . '/../../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
use Mike42\Escpos\ImagickEscposImage;
|
||||||
|
|
||||||
|
// Data URI for a PNG image (red dot from https://en.wikipedia.org/wiki/Data_URI_scheme )
|
||||||
|
$uri = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
|
||||||
|
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
|
||||||
|
9TXL0Y4OHwAAAABJRU5ErkJggg==";
|
||||||
|
|
||||||
|
// Convert data URI to binary data
|
||||||
|
$imageBlob = base64_decode(explode(",", $uri)[1]);
|
||||||
|
|
||||||
|
// Give Imagick a filename with the correct extension to stop it from attempting
|
||||||
|
// to identify the format itself (this avoids CVE-2016–3714)
|
||||||
|
$imagick = new Imagick();
|
||||||
|
$imagick -> setResourceLimit(6, 1); // Prevent libgomp1 segfaults, grumble grumble.
|
||||||
|
$imagick -> readImageBlob($imageBlob, "input.png");
|
||||||
|
|
||||||
|
// Load Imagick straight into an EscposImage object
|
||||||
|
$im = new ImagickEscposImage();
|
||||||
|
$im -> readImageFromImagick($imagick);
|
||||||
|
|
||||||
|
// Do a test print to make sure that this EscposImage object has the right data
|
||||||
|
// (should see a tiny bullet point)
|
||||||
|
$connector = new FilePrintConnector("php://output");
|
||||||
|
$printer = new Printer($connector);
|
||||||
|
$printer -> bitImage($im);
|
||||||
|
$printer -> cut();
|
||||||
|
$printer -> close();
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Example showing how to return binary data back to the user.
|
||||||
|
*
|
||||||
|
* This is intended for the "Star TSP650IIcloudPRNT" printer.
|
||||||
|
*/
|
||||||
|
require __DIR__ . '/../../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\DummyPrintConnector;
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
|
||||||
|
// Make sure you load a Star print connector or you may get gibberish.
|
||||||
|
$connector = new DummyPrintConnector();
|
||||||
|
$profile = CapabilityProfile::load("TSP600");
|
||||||
|
$printer = new Printer($connector);
|
||||||
|
$printer -> text("Hello world!\n");
|
||||||
|
$printer -> cut();
|
||||||
|
|
||||||
|
// Get the data out as a string
|
||||||
|
$data = $connector -> getData();
|
||||||
|
|
||||||
|
// Return it, check the manual for specifics.
|
||||||
|
header('Content-type: application/octet-stream');
|
||||||
|
header('Content-Length: '.strlen($data));
|
||||||
|
echo $data;
|
||||||
|
|
||||||
|
// Close the printer when done.
|
||||||
|
$printer -> close();
|
||||||
@@ -1,11 +1,16 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once(dirname(__FILE__) . "/../../Escpos.php");
|
require __DIR__ . '/../../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
use Mike42\Escpos\CapabilityProfiles\StarCapabilityProfile;
|
||||||
|
use Mike42\Escpos\PrintBuffers\ImagePrintBuffer;
|
||||||
|
|
||||||
/* This example shows the printing of Latvian text on the Star TUP 592 printer */
|
/* This example shows the printing of Latvian text on the Star TUP 592 printer */
|
||||||
$profile = StarCapabilityProfile::getInstance();
|
$profile = StarCapabilityProfile::getInstance();
|
||||||
|
|
||||||
/* Option 1: Native character encoding */
|
/* Option 1: Native character encoding */
|
||||||
$connector = new FilePrintConnector("php://stdout");
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
$printer = new Escpos($connector, $profile);
|
$printer = new Printer($connector, $profile);
|
||||||
$printer -> text("Glāžšķūņa rūķīši dzērumā čiepj Baha koncertflīģeļu vākus\n");
|
$printer -> text("Glāžšķūņa rūķīši dzērumā čiepj Baha koncertflīģeļu vākus\n");
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
$printer -> close();
|
$printer -> close();
|
||||||
@@ -13,9 +18,8 @@ $printer -> close();
|
|||||||
/* Option 2: Image-based output (formatting not available using this output) */
|
/* Option 2: Image-based output (formatting not available using this output) */
|
||||||
$buffer = new ImagePrintBuffer();
|
$buffer = new ImagePrintBuffer();
|
||||||
$connector = new FilePrintConnector("php://stdout");
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
$printer = new Escpos($connector, $profile);
|
$printer = new Printer($connector, $profile);
|
||||||
$printer -> setPrintBuffer($buffer);
|
$printer -> setPrintBuffer($buffer);
|
||||||
$printer -> text("Glāžšķūņa rūķīši dzērumā čiepj Baha koncertflīģeļu vākus\n");
|
$printer -> text("Glāžšķūņa rūķīši dzērumā čiepj Baha koncertflīģeļu vākus\n");
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
$printer -> close();
|
$printer -> close();
|
||||||
?>
|
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once(dirname(__FILE__) . "/../../Escpos.php");
|
require __DIR__ . '/../../autoload.php';
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This example shows how tok send a custom command to the printer-
|
* This example shows how tok send a custom command to the printer-
|
||||||
* The use case here is an Epson TM-T20II and German text.
|
* The use case here is an Epson TM-T20II and German text.
|
||||||
@@ -18,19 +22,18 @@ require_once(dirname(__FILE__) . "/../../Escpos.php");
|
|||||||
|
|
||||||
/* Set up profile & connector */
|
/* Set up profile & connector */
|
||||||
$connector = new FilePrintConnector("php://output");
|
$connector = new FilePrintConnector("php://output");
|
||||||
$profile = DefaultCapabilityProfile::getInstance(); // Works for Epson printers
|
$profile = CapabilityProfile::load("default"); // Works for Epson printers
|
||||||
|
|
||||||
$printer = new Escpos($connector, $profile);
|
$printer = new Printer($connector, $profile);
|
||||||
$cmd = Escpos::ESC . "V" . chr(1); // Try out 90-degree rotation.
|
$cmd = Printer::ESC . "V" . chr(1); // Try out 90-degree rotation.
|
||||||
$printer -> getPrintConnector() -> write($cmd);
|
$printer -> getPrintConnector() -> write($cmd);
|
||||||
$printer -> text("Beispieltext in Deutsch\n");
|
$printer -> text("Beispieltext in Deutsch\n");
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
$printer -> close();
|
$printer -> close();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hex-dump of output confirms that ESC V 1 being sent:
|
* Hex-dump of output confirms that ESC V 1 being sent:
|
||||||
*
|
*
|
||||||
* 0000000 033 @ 033 V 001 B e i s p i e l t e x
|
* 0000000 033 @ 033 V 001 B e i s p i e l t e x
|
||||||
* 0000010 t i n D e u t s c h \n 035 V A
|
* 0000010 t i n D e u t s c h \n 035 V A
|
||||||
* 0000020 003
|
* 0000020 003
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,11 +6,14 @@
|
|||||||
*
|
*
|
||||||
* Use the hardware switch to activate "Two-byte Character Code"
|
* Use the hardware switch to activate "Two-byte Character Code"
|
||||||
*/
|
*/
|
||||||
require_once(dirname(__FILE__) . "/../../Escpos.php");
|
require __DIR__ . '/../../autoload.php';
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
|
||||||
$connector = new FilePrintConnector("php://output");
|
$connector = new FilePrintConnector("php://output");
|
||||||
$profile = SimpleCapabilityProfile::getInstance();
|
$profile = CapabilityProfile::load("simple"); // Works for Epson printers
|
||||||
$printer = new Escpos($connector);
|
$printer = new Printer($connector);
|
||||||
$printer -> text("El pingüino Wenceslao hizo kilómetros bajo exhaustiva lluvia y frío, añoraba a su querido cachorro.\n");
|
$printer -> text("El pingüino Wenceslao hizo kilómetros bajo exhaustiva lluvia y frío, añoraba a su querido cachorro.\n");
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
$printer -> close();
|
$printer -> close();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This is an example of printing chinese text. This is a bit different to other character encodings, because
|
||||||
|
* the printer accepts a 2-byte character encoding (GBK), and formatting is handled differently while in this mode.
|
||||||
|
*
|
||||||
|
* At the time of writing, this is implemented separately as a textChinese() function, until chinese text
|
||||||
|
* can be properly detected and printed alongside other encodings.
|
||||||
|
*/
|
||||||
|
require __DIR__ . '/../../autoload.php';
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
|
||||||
|
$connector = new FilePrintConnector("/dev/usb/lp1");
|
||||||
|
$profile = CapabilityProfile::load("default");
|
||||||
|
|
||||||
|
$printer = new Printer($connector);
|
||||||
|
|
||||||
|
// Example text from #37
|
||||||
|
$printer -> textChinese("艾德蒙 AOC E2450SWH 23.6吋 LED液晶寬螢幕特價$ 19900\n\n");
|
||||||
|
|
||||||
|
// Note that on the printer tested (ZJ5890), the font only contained simplified characters.
|
||||||
|
$printer -> textChinese("示例文本打印机!\n\n");
|
||||||
|
$printer -> close();
|
||||||
@@ -1,11 +1,16 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once(dirname(__FILE__) . "/../../Escpos.php");
|
require __DIR__ . '/../../autoload.php';
|
||||||
$profile = DefaultCapabilityProfile::getInstance();
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
use Mike42\Escpos\PrintBuffers\ImagePrintBuffer;
|
||||||
|
|
||||||
|
$profile = CapabilityProfile::load("default");
|
||||||
// This is a quick demo of currency symbol issues in #39.
|
// This is a quick demo of currency symbol issues in #39.
|
||||||
|
|
||||||
/* Option 1: Native ESC/POS characters, depends on printer and is buggy. */
|
/* Option 1: Native ESC/POS characters, depends on printer and is buggy. */
|
||||||
$connector = new FilePrintConnector("php://stdout");
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
$printer = new Escpos($connector, $profile);
|
$printer = new Printer($connector, $profile);
|
||||||
$printer -> text("€ 9,95\n");
|
$printer -> text("€ 9,95\n");
|
||||||
$printer -> text("£ 9.95\n");
|
$printer -> text("£ 9.95\n");
|
||||||
$printer -> text("$ 9.95\n");
|
$printer -> text("$ 9.95\n");
|
||||||
@@ -16,7 +21,7 @@ $printer -> close();
|
|||||||
/* Option 2: Image-based output (formatting not available using this output). */
|
/* Option 2: Image-based output (formatting not available using this output). */
|
||||||
$buffer = new ImagePrintBuffer();
|
$buffer = new ImagePrintBuffer();
|
||||||
$connector = new FilePrintConnector("php://stdout");
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
$printer = new Escpos($connector, $profile);
|
$printer = new Printer($connector, $profile);
|
||||||
$printer -> setPrintBuffer($buffer);
|
$printer -> setPrintBuffer($buffer);
|
||||||
$printer -> text("€ 9,95\n");
|
$printer -> text("€ 9,95\n");
|
||||||
$printer -> text("£ 9.95\n");
|
$printer -> text("£ 9.95\n");
|
||||||
@@ -34,32 +39,35 @@ $printer -> close();
|
|||||||
are not available in CP437. CP858 has good printer support, but is not
|
are not available in CP437. CP858 has good printer support, but is not
|
||||||
included in all iconv builds.
|
included in all iconv builds.
|
||||||
*/
|
*/
|
||||||
class CustomCapabilityProfile extends SimpleCapabilityProfile {
|
class CustomCapabilityProfile extends CapabilityProfile
|
||||||
function getCustomCodePages() {
|
{
|
||||||
/*
|
function getCustomCodePages()
|
||||||
|
{
|
||||||
|
/*
|
||||||
* Example to print in a specific, user-defined character set
|
* Example to print in a specific, user-defined character set
|
||||||
* on a printer which has been configured to use i
|
* on a printer which has been configured to use i
|
||||||
*/
|
*/
|
||||||
return array(
|
return array(
|
||||||
'CP858' => "ÇüéâäàåçêëèïîìÄÅ" .
|
'CP858' => "ÇüéâäàåçêëèïîìÄÅ" .
|
||||||
"ÉæÆôöòûùÿÖÜø£Ø×ƒ" .
|
"ÉæÆôöòûùÿÖÜø£Ø×ƒ" .
|
||||||
"áíóúñѪº¿®¬½¼¡«»" .
|
"áíóúñѪº¿®¬½¼¡«»" .
|
||||||
"░▒▓│┤ÁÂÀ©╣║╗╝¢¥┐" .
|
"░▒▓│┤ÁÂÀ©╣║╗╝¢¥┐" .
|
||||||
"└┴┬├─┼ãÃ╚╔╩╦╠═╬¤" .
|
"└┴┬├─┼ãÃ╚╔╩╦╠═╬¤" .
|
||||||
"ðÐÊËÈ€ÍÎÏ┘┌█▄¦Ì▀" .
|
"ðÐÊËÈ€ÍÎÏ┘┌█▄¦Ì▀" .
|
||||||
"ÓßÔÒõÕµþÞÚÛÙýݯ´" .
|
"ÓßÔÒõÕµþÞÚÛÙýݯ´" .
|
||||||
" ±‗¾¶§÷¸°¨·¹³²■ ");
|
" ±‗¾¶§÷¸°¨·¹³²■ ");
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSupportedCodePages() {
|
function getSupportedCodePages()
|
||||||
return array(
|
{
|
||||||
0 => 'custom:CP858');
|
return array(
|
||||||
}
|
0 => 'custom:CP858');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$connector = new FilePrintConnector("php://stdout");
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
$profile = CustomCapabilityProfile::getInstance();
|
$profile = CustomCapabilityProfile::getInstance();
|
||||||
$printer = new Escpos($connector, $profile);
|
$printer = new Printer($connector, $profile);
|
||||||
$printer -> text("€ 9,95\n");
|
$printer -> text("€ 9,95\n");
|
||||||
$printer -> text("£ 9.95\n");
|
$printer -> text("£ 9.95\n");
|
||||||
$printer -> text("$ 9.95\n");
|
$printer -> text("$ 9.95\n");
|
||||||
|
|||||||
@@ -7,12 +7,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Adjust these to your environment
|
// Adjust these to your environment
|
||||||
require_once(dirname(__FILE__) . "/../../Escpos.php");
|
require __DIR__ . '/../../autoload.php';
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
|
||||||
$connector = new FilePrintConnector("php://stdout");
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
|
|
||||||
// Start printer
|
// Start printer
|
||||||
$profile = SimpleCapabilityProfile::getInstance();
|
$profile = CapabilityProfile::load("simple");
|
||||||
$printer = new Escpos($connector, $profile);
|
$printer = new Printer($connector, $profile);
|
||||||
|
|
||||||
// A) Raw pound symbol
|
// A) Raw pound symbol
|
||||||
// This is the most likely thing to work, and bypasses all the fancy stuff.
|
// This is the most likely thing to work, and bypasses all the fancy stuff.
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Example of Greek text on the P-822D */
|
/* Example of Greek text on the P-822D */
|
||||||
require_once(dirname(__FILE__) . "/../../Escpos.php");
|
require __DIR__ . '/../../autoload.php';
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
|
||||||
// Setup the printer
|
// Setup the printer
|
||||||
$connector = new FilePrintConnector("php://stdout");
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
$profile = P822DCapabilityProfile::getInstance();
|
$profile = CapabilityProfile::load("P822D");
|
||||||
$printer = new Escpos($connector, $profile);
|
$printer = new Printer($connector, $profile);
|
||||||
|
|
||||||
// Print a Greek pangram
|
// Print a Greek pangram
|
||||||
$text = "Ξεσκεπάζω την ψυχοφθόρα βδελυγμία";
|
$text = "Ξεσκεπάζω την ψυχοφθόρα βδελυγμία";
|
||||||
|
|||||||
@@ -11,48 +11,54 @@
|
|||||||
* Note that image operations are slow. You can and should serialise an EscposImage
|
* Note that image operations are slow. You can and should serialise an EscposImage
|
||||||
* object into some sort of cache if you will re-use the output.
|
* object into some sort of cache if you will re-use the output.
|
||||||
*/
|
*/
|
||||||
require_once (dirname ( __FILE__ ) . "/../../Escpos.php");
|
require __DIR__ . '/../../autoload.php';
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\EscposImage;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
|
||||||
// Paths to images to combine
|
// Paths to images to combine
|
||||||
$img1_path = dirname ( __FILE__ ) . "/../resources/tux.png";
|
$img1_path = dirname(__FILE__) . "/../resources/tux.png";
|
||||||
$img2_path = dirname ( __FILE__ ) . "/../resources/escpos-php.png";
|
$img2_path = dirname(__FILE__) . "/../resources/escpos-php.png";
|
||||||
|
|
||||||
// Set up temp file with .png extension
|
// Set up temp file with .png extension
|
||||||
$tmpf_path = tempnam ( sys_get_temp_dir (), 'escpos-php' );
|
$tmpf_path = tempnam(sys_get_temp_dir(), 'escpos-php');
|
||||||
$imgCombined_path = $tmpf_path . ".png";
|
$imgCombined_path = $tmpf_path . ".png";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Convert, load image, remove temp files
|
// Convert, load image, remove temp files
|
||||||
$cmd = sprintf ("convert %s %s +append %s",
|
$cmd = sprintf(
|
||||||
escapeshellarg ( $img1_path ),
|
"convert %s %s +append %s",
|
||||||
escapeshellarg ( $img2_path ),
|
escapeshellarg($img1_path),
|
||||||
escapeshellarg ( $imgCombined_path ));
|
escapeshellarg($img2_path),
|
||||||
exec($cmd, $outp, $retval);
|
escapeshellarg($imgCombined_path)
|
||||||
if($retval != 0) {
|
);
|
||||||
// Detect and handle command failure
|
exec($cmd, $outp, $retval);
|
||||||
throw new Exception("Command \"$cmd\" returned $retval." . implode("\n", $outp));
|
if ($retval != 0) {
|
||||||
}
|
// Detect and handle command failure
|
||||||
$img = new EscposImage ( $imgCombined_path );
|
throw new Exception("Command \"$cmd\" returned $retval." . implode("\n", $outp));
|
||||||
|
}
|
||||||
|
$img = EscposImage::load($imgCombined_path);
|
||||||
|
|
||||||
// Setup the printer
|
// Setup the printer
|
||||||
$connector = new FilePrintConnector ( "php://stdout" );
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
$profile = DefaultCapabilityProfile::getInstance ();
|
$profile = CapabilityProfile::load("default");
|
||||||
|
|
||||||
// Run the actual print
|
// Run the actual print
|
||||||
$printer = new Escpos ( $connector, $profile );
|
$printer = new Printer($connector, $profile);
|
||||||
try {
|
try {
|
||||||
$printer -> setJustification(Escpos::JUSTIFY_CENTER);
|
$printer -> setJustification(Printer::JUSTIFY_CENTER);
|
||||||
$printer -> graphics($img);
|
$printer -> graphics($img);
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
} finally {
|
} finally {
|
||||||
// Always close the connection
|
// Always close the connection
|
||||||
$printer -> close();
|
$printer -> close();
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
// Print out any errors: Eg. printer connection, image loading & external image manipulation.
|
// Print out any errors: Eg. printer connection, image loading & external image manipulation.
|
||||||
echo $e -> getMessage() . "\n";
|
echo $e -> getMessage() . "\n";
|
||||||
echo $e -> getTraceAsString();
|
echo $e -> getTraceAsString();
|
||||||
} finally {
|
} finally {
|
||||||
unlink ( $imgCombined_path );
|
unlink($imgCombined_path);
|
||||||
unlink ( $tmpf_path );
|
unlink($tmpf_path);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,14 +10,30 @@
|
|||||||
* Requirements are:
|
* Requirements are:
|
||||||
* - imagick extension (For the ImagePrintBuffer, which does not
|
* - imagick extension (For the ImagePrintBuffer, which does not
|
||||||
* support gd at the time of writing)
|
* support gd at the time of writing)
|
||||||
* - Ar-PHP library, available from sourceforge, for the first
|
* - ArPHP 4.0 (release date: Jan 8, 2016), available from SourceForge, for
|
||||||
* part of this example. Drop it in the folder listed below:
|
* handling the layout for this example.
|
||||||
*/
|
*/
|
||||||
require_once(dirname(__FILE__) . "/../../Escpos.php");
|
require __DIR__ . '/../../autoload.php';
|
||||||
require_once(dirname(__FILE__) . "/../../vendor/I18N/Arabic.php");
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
use Mike42\Escpos\PrintBuffers\ImagePrintBuffer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First, convert the text into LTR byte order with joined letters,
|
* Drop Ar-php into the folder listed below:
|
||||||
|
*/
|
||||||
|
require_once(dirname(__FILE__) . "/../../I18N/Arabic.php");
|
||||||
|
$fontPath = dirname(__FILE__) . "/../../I18N/Arabic/Examples/GD/ae_AlHor.ttf";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inputs are some text, line wrapping options, and a font size.
|
||||||
|
*/
|
||||||
|
$textUtf8 = "صِف خَلقَ خَودِ كَمِثلِ الشَمسِ إِذ بَزَغَت — يَحظى الضَجيعُ بِها نَجلاءَ مِعطارِ";
|
||||||
|
$maxChars = 50;
|
||||||
|
$fontSize = 28;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First, convert the text into LTR byte order with line wrapping,
|
||||||
* Using the Ar-PHP library.
|
* Using the Ar-PHP library.
|
||||||
*
|
*
|
||||||
* The Ar-PHP library uses the default internal encoding, and can print
|
* The Ar-PHP library uses the default internal encoding, and can print
|
||||||
@@ -29,19 +45,30 @@ require_once(dirname(__FILE__) . "/../../vendor/I18N/Arabic.php");
|
|||||||
*/
|
*/
|
||||||
mb_internal_encoding("UTF-8");
|
mb_internal_encoding("UTF-8");
|
||||||
$Arabic = new I18N_Arabic('Glyphs');
|
$Arabic = new I18N_Arabic('Glyphs');
|
||||||
$text = "صِف خَلقَ خَودِ كَمِثلِ الشَمسِ إِذ بَزَغَت — يَحظى الضَجيعُ بِها نَجلاءَ مِعطارِ";
|
$textLtr = $Arabic -> utf8Glyphs($textUtf8, $maxChars);
|
||||||
$text = $Arabic -> utf8Glyphs($text);
|
$textLine = explode("\n", $textLtr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up and use the printer
|
* Set up and use an image print buffer with a suitable font
|
||||||
*/
|
*/
|
||||||
$buffer = new ImagePrintBuffer();
|
$buffer = new ImagePrintBuffer();
|
||||||
$profile = EposTepCapabilityProfile::getInstance();
|
$buffer -> setFont($fontPath);
|
||||||
$connector = new FilePrintConnector("php://output");
|
$buffer -> setFontSize($fontSize);
|
||||||
// = WindowsPrintConnector("LPT2");
|
|
||||||
// Windows LPT2 was used in the bug tracker
|
|
||||||
|
|
||||||
$printer = new Escpos($connector, $profile);
|
$profile = CapabilityProfile::load("TEP-200M");
|
||||||
|
$connector = new FilePrintConnector("php://output");
|
||||||
|
// = new WindowsPrintConnector("LPT2");
|
||||||
|
// Windows LPT2 was used in the bug tracker
|
||||||
|
|
||||||
|
$printer = new Printer($connector, $profile);
|
||||||
$printer -> setPrintBuffer($buffer);
|
$printer -> setPrintBuffer($buffer);
|
||||||
$printer -> text($text . "\n");
|
|
||||||
|
$printer -> setJustification(Printer::JUSTIFY_RIGHT);
|
||||||
|
foreach($textLine as $text) {
|
||||||
|
// Print each line separately. We need to do this since Imagick thinks
|
||||||
|
// text is left-to-right
|
||||||
|
$printer -> text($text . "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
$printer -> cut();
|
||||||
$printer -> close();
|
$printer -> close();
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
require __DIR__ . '/../../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
|
||||||
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
|
$profile = CapabilityProfile::load("default");
|
||||||
|
$printer = new Printer($connector, $profile);
|
||||||
|
|
||||||
|
$printer -> text("Μιχάλης Νίκος\n");
|
||||||
|
$printer -> cut();
|
||||||
|
$printer -> close();
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Example of two-color printing, tested on an epson TM-U220 with two-color ribbon installed.
|
||||||
|
*/
|
||||||
|
require __DIR__ . '/../../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
|
||||||
|
$connector = new FilePrintConnector("/dev/usb/lp0");
|
||||||
|
$printer = new Printer($connector);
|
||||||
|
try {
|
||||||
|
$printer -> text("Hello World!\n");
|
||||||
|
$printer -> setColor(Printer::COLOR_2);
|
||||||
|
$printer -> text("Red?!\n");
|
||||||
|
$printer -> setColor(Printer::COLOR_1);
|
||||||
|
$printer -> text("Default color again?!\n");
|
||||||
|
$printer -> cut();
|
||||||
|
} finally {
|
||||||
|
/* Always close the printer! */
|
||||||
|
$printer -> close();
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* Example of dithering used in EscposImage by default, if you have Imagick loaded.
|
||||||
|
*/
|
||||||
|
require __DIR__ . '/../../autoload.php';
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\EscposImage;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
|
||||||
|
$connector = new FilePrintConnector("/dev/usb/lp0");
|
||||||
|
$printer = new Printer($connector);
|
||||||
|
try {
|
||||||
|
/* Load with optimisations enabled. If you have Imagick, this will get you
|
||||||
|
a nicely dithered image, which prints very quickly
|
||||||
|
*/
|
||||||
|
$img1 = EscposImage::load(__DIR__ . '/../resources/tulips.png');
|
||||||
|
$printer -> bitImage($img1);
|
||||||
|
|
||||||
|
/* Load with optimisations disabled, forcing the use of PHP to convert the
|
||||||
|
pixels, which uses a threshold and is much slower.
|
||||||
|
*/
|
||||||
|
$img2 = EscposImage::load(__DIR__ . '/../resources/tulips.png', false);
|
||||||
|
$printer -> bitImage($img2);
|
||||||
|
$printer -> cut();
|
||||||
|
} finally {
|
||||||
|
/* Always close the printer! */
|
||||||
|
$printer -> close();
|
||||||
|
}
|
||||||
@@ -5,33 +5,37 @@
|
|||||||
*
|
*
|
||||||
* @author Michael Billington <michael.billington@gmail.com>
|
* @author Michael Billington <michael.billington@gmail.com>
|
||||||
*/
|
*/
|
||||||
require_once(dirname(__FILE__) . "/../Escpos.php");
|
require __DIR__ . '/../autoload.php';
|
||||||
$printer = new Escpos();
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
|
||||||
|
|
||||||
|
$connector = new FilePrintConnector("php://stdout");
|
||||||
|
$printer = new Printer($connector);
|
||||||
|
|
||||||
/* Initialize */
|
/* Initialize */
|
||||||
$printer -> initialize();
|
$printer -> initialize();
|
||||||
|
|
||||||
/* Text of various (in-proportion) sizes */
|
/* Text of various (in-proportion) sizes */
|
||||||
title($printer, "Change height & width\n");
|
title($printer, "Change height & width\n");
|
||||||
for($i = 1; $i <= 8; $i++) {
|
for ($i = 1; $i <= 8; $i++) {
|
||||||
$printer -> setTextSize($i, $i);
|
$printer -> setTextSize($i, $i);
|
||||||
$printer -> text($i);
|
$printer -> text($i);
|
||||||
}
|
}
|
||||||
$printer -> text("\n");
|
$printer -> text("\n");
|
||||||
|
|
||||||
/* Width changing only */
|
/* Width changing only */
|
||||||
title($printer, "Change width only (height=4):\n");
|
title($printer, "Change width only (height=4):\n");
|
||||||
for($i = 1; $i <= 8; $i++) {
|
for ($i = 1; $i <= 8; $i++) {
|
||||||
$printer -> setTextSize($i, 4);
|
$printer -> setTextSize($i, 4);
|
||||||
$printer -> text($i);
|
$printer -> text($i);
|
||||||
}
|
}
|
||||||
$printer -> text("\n");
|
$printer -> text("\n");
|
||||||
|
|
||||||
/* Height changing only */
|
/* Height changing only */
|
||||||
title($printer, "Change height only (width=4):\n");
|
title($printer, "Change height only (width=4):\n");
|
||||||
for($i = 1; $i <= 8; $i++) {
|
for ($i = 1; $i <= 8; $i++) {
|
||||||
$printer -> setTextSize(4, $i);
|
$printer -> setTextSize(4, $i);
|
||||||
$printer -> text($i);
|
$printer -> text($i);
|
||||||
}
|
}
|
||||||
$printer -> text("\n");
|
$printer -> text("\n");
|
||||||
|
|
||||||
@@ -47,16 +51,15 @@ $printer -> text("Hello world!\n");
|
|||||||
|
|
||||||
/* Very large text */
|
/* Very large text */
|
||||||
title($printer, "Largest possible text:\n");
|
title($printer, "Largest possible text:\n");
|
||||||
$printer -> setTextSize(8,8);
|
$printer -> setTextSize(8, 8);
|
||||||
$printer -> text("Hello\nworld!\n");
|
$printer -> text("Hello\nworld!\n");
|
||||||
|
|
||||||
$printer -> cut();
|
$printer -> cut();
|
||||||
$printer -> close();
|
$printer -> close();
|
||||||
|
|
||||||
function title(Escpos $printer, $text) {
|
function title(Printer $printer, $text)
|
||||||
$printer -> selectPrintMode(Escpos::MODE_EMPHASIZED);
|
{
|
||||||
$printer -> text("\n" . $text);
|
$printer -> selectPrintMode(Printer::MODE_EMPHASIZED);
|
||||||
$printer -> selectPrintMode(); // Reset
|
$printer -> text("\n" . $text);
|
||||||
|
$printer -> selectPrintMode(); // Reset
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
|
||||||
|
|||||||
21
htdocs/includes/mike42/escpos-php/phpunit.xml
Normal file
21
htdocs/includes/mike42/escpos-php/phpunit.xml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<phpunit bootstrap="test/bootstrap.php"
|
||||||
|
timeoutForSmallTests="1"
|
||||||
|
timeoutForMediumTests="10"
|
||||||
|
timeoutForLargeTests="60"
|
||||||
|
verbose="true"
|
||||||
|
|
||||||
|
>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="unit">
|
||||||
|
<directory>test/unit</directory>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="integration">
|
||||||
|
<directory>test/integration</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
<filter>
|
||||||
|
<whitelist processUncoveredFilesFromWhitelist="true">
|
||||||
|
<directory suffix=".php">src</directory>
|
||||||
|
</whitelist>
|
||||||
|
</filter>
|
||||||
|
</phpunit>
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Not all printers support the same subset of available Esc/POS commands. Profiles allow you to specify
|
|
||||||
* which features are available on your printer, so that Escpos is less likely to send unsupported commands.
|
|
||||||
*/
|
|
||||||
abstract class AbstractCapabilityProfile {
|
|
||||||
/**
|
|
||||||
* Sub-classes must be retrieved via getInstance(), so that validation
|
|
||||||
* can be attached to guarantee that dud profiles are not used on an Escpos object.
|
|
||||||
*/
|
|
||||||
protected final function __construct() {
|
|
||||||
// This space intentionally left blank.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If getSupportedCodePages contains custom code pages, their character maps must be provided here.
|
|
||||||
*/
|
|
||||||
abstract function getCustomCodePages();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a map of code page numbers to names for this printer. Names
|
|
||||||
* should match iconv code page names where possible (non-matching names will not be used).
|
|
||||||
*/
|
|
||||||
abstract function getSupportedCodePages();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True to support barcode "function b", false to use only function A.
|
|
||||||
*/
|
|
||||||
abstract function getSupportsBarcodeB();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True for bitImage support, false for no bitImage support.
|
|
||||||
*/
|
|
||||||
abstract function getSupportsBitImage();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True for graphics support, false for no graphics support.
|
|
||||||
*/
|
|
||||||
abstract function getSupportsGraphics();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True for 'STAR original' commands, false for standard ESC/POS only.
|
|
||||||
*/
|
|
||||||
abstract function getSupportsStarCommands();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True if the printer renders its own QR codes, false to send an image.
|
|
||||||
*/
|
|
||||||
abstract function getSupportsQrCode();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return AbstractCapabilityProfile Instance of sub-class.
|
|
||||||
*/
|
|
||||||
public static final function getInstance() {
|
|
||||||
static $profile = null;
|
|
||||||
if ($profile === null) {
|
|
||||||
$profile = new static();
|
|
||||||
}
|
|
||||||
return $profile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,181 +0,0 @@
|
|||||||
<?php
|
|
||||||
abstract class CodePage {
|
|
||||||
/** Code page constants, exported from iconv -l. Can be cut down*/
|
|
||||||
const CP037 = "CP037";
|
|
||||||
const CP038 = "CP038";
|
|
||||||
const CP273 = "CP273";
|
|
||||||
const CP274 = "CP274";
|
|
||||||
const CP275 = "CP275";
|
|
||||||
const CP278 = "CP278";
|
|
||||||
const CP280 = "CP280";
|
|
||||||
const CP281 = "CP281";
|
|
||||||
const CP282 = "CP282";
|
|
||||||
const CP284 = "CP284";
|
|
||||||
const CP285 = "CP285";
|
|
||||||
const CP290 = "CP290";
|
|
||||||
const CP297 = "CP297";
|
|
||||||
const CP367 = "CP367";
|
|
||||||
const CP420 = "CP420";
|
|
||||||
const CP423 = "CP423";
|
|
||||||
const CP424 = "CP424";
|
|
||||||
const CP437 = "CP437";
|
|
||||||
const CP500 = "CP500";
|
|
||||||
const CP737 = "CP737";
|
|
||||||
const CP770 = "CP770";
|
|
||||||
const CP771 = "CP771";
|
|
||||||
const CP772 = "CP772";
|
|
||||||
const CP773 = "CP773";
|
|
||||||
const CP774 = "CP774";
|
|
||||||
const CP775 = "CP775";
|
|
||||||
const CP803 = "CP803";
|
|
||||||
const CP813 = "CP813";
|
|
||||||
const CP819 = "CP819";
|
|
||||||
const CP850 = "CP850";
|
|
||||||
const CP851 = "CP851";
|
|
||||||
const CP852 = "CP852";
|
|
||||||
const CP855 = "CP855";
|
|
||||||
const CP856 = "CP856";
|
|
||||||
const CP857 = "CP857";
|
|
||||||
const CP860 = "CP860";
|
|
||||||
const CP861 = "CP861";
|
|
||||||
const CP862 = "CP862";
|
|
||||||
const CP863 = "CP863";
|
|
||||||
const CP864 = "CP864";
|
|
||||||
const CP865 = "CP865";
|
|
||||||
const CP866 = "CP866";
|
|
||||||
const CP866NAV = "CP866NAV";
|
|
||||||
const CP868 = "CP868";
|
|
||||||
const CP869 = "CP869";
|
|
||||||
const CP870 = "CP870";
|
|
||||||
const CP871 = "CP871";
|
|
||||||
const CP874 = "CP874";
|
|
||||||
const CP875 = "CP875";
|
|
||||||
const CP880 = "CP880";
|
|
||||||
const CP891 = "CP891";
|
|
||||||
const CP901 = "CP901";
|
|
||||||
const CP902 = "CP902";
|
|
||||||
const CP903 = "CP903";
|
|
||||||
const CP904 = "CP904";
|
|
||||||
const CP905 = "CP905";
|
|
||||||
const CP912 = "CP912";
|
|
||||||
const CP915 = "CP915";
|
|
||||||
const CP916 = "CP916";
|
|
||||||
const CP918 = "CP918";
|
|
||||||
const CP920 = "CP920";
|
|
||||||
const CP921 = "CP921";
|
|
||||||
const CP922 = "CP922";
|
|
||||||
const CP930 = "CP930";
|
|
||||||
const CP932 = "CP932";//
|
|
||||||
const CP933 = "CP933";
|
|
||||||
const CP935 = "CP935";
|
|
||||||
const CP936 = "CP936";
|
|
||||||
const CP937 = "CP937";
|
|
||||||
const CP939 = "CP939";
|
|
||||||
const CP949 = "CP949";
|
|
||||||
const CP950 = "CP950";
|
|
||||||
const CP1004 = "CP1004";
|
|
||||||
const CP1008 = "CP1008";
|
|
||||||
const CP1025 = "CP1025";
|
|
||||||
const CP1026 = "CP1026";
|
|
||||||
const CP1046 = "CP1046";
|
|
||||||
const CP1047 = "CP1047";
|
|
||||||
const CP1070 = "CP1070";
|
|
||||||
const CP1079 = "CP1079";
|
|
||||||
const CP1081 = "CP1081";
|
|
||||||
const CP1084 = "CP1084";
|
|
||||||
const CP1089 = "CP1089";
|
|
||||||
const CP1097 = "CP1097";
|
|
||||||
const CP1112 = "CP1112";
|
|
||||||
const CP1122 = "CP1122";
|
|
||||||
const CP1123 = "CP1123";
|
|
||||||
const CP1124 = "CP1124";
|
|
||||||
const CP1125 = "CP1125";
|
|
||||||
const CP1129 = "CP1129";
|
|
||||||
const CP1130 = "CP1130";
|
|
||||||
const CP1132 = "CP1132";
|
|
||||||
const CP1133 = "CP1133";
|
|
||||||
const CP1137 = "CP1137";
|
|
||||||
const CP1140 = "CP1140";
|
|
||||||
const CP1141 = "CP1141";
|
|
||||||
const CP1142 = "CP1142";
|
|
||||||
const CP1143 = "CP1143";
|
|
||||||
const CP1144 = "CP1144";
|
|
||||||
const CP1145 = "CP1145";
|
|
||||||
const CP1146 = "CP1146";
|
|
||||||
const CP1147 = "CP1147";
|
|
||||||
const CP1148 = "CP1148";
|
|
||||||
const CP1149 = "CP1149";
|
|
||||||
const CP1153 = "CP1153";
|
|
||||||
const CP1154 = "CP1154";
|
|
||||||
const CP1155 = "CP1155";
|
|
||||||
const CP1156 = "CP1156";
|
|
||||||
const CP1157 = "CP1157";
|
|
||||||
const CP1158 = "CP1158";
|
|
||||||
const CP1160 = "CP1160";
|
|
||||||
const CP1161 = "CP1161";
|
|
||||||
const CP1162 = "CP1162";
|
|
||||||
const CP1163 = "CP1163";
|
|
||||||
const CP1164 = "CP1164";
|
|
||||||
const CP1166 = "CP1166";
|
|
||||||
const CP1167 = "CP1167";
|
|
||||||
const CP1250 = "CP1250";
|
|
||||||
const CP1251 = "CP1251";
|
|
||||||
const CP1252 = "CP1252";
|
|
||||||
const CP1253 = "CP1253";
|
|
||||||
const CP1254 = "CP1254";
|
|
||||||
const CP1255 = "CP1255";
|
|
||||||
const CP1256 = "CP1256";
|
|
||||||
const CP1257 = "CP1257";
|
|
||||||
const CP1258 = "CP1258";
|
|
||||||
const CP1282 = "CP1282";
|
|
||||||
const CP1361 = "CP1361";
|
|
||||||
const CP1364 = "CP1364";
|
|
||||||
const CP1371 = "CP1371";
|
|
||||||
const CP1388 = "CP1388";
|
|
||||||
const CP1390 = "CP1390";
|
|
||||||
const CP1399 = "CP1399";
|
|
||||||
const CP4517 = "CP4517";
|
|
||||||
const CP4899 = "CP4899";
|
|
||||||
const CP4909 = "CP4909";
|
|
||||||
const CP4971 = "CP4971";
|
|
||||||
const CP5347 = "CP5347";
|
|
||||||
const CP9030 = "CP9030";
|
|
||||||
const CP9066 = "CP9066";
|
|
||||||
const CP9448 = "CP9448";
|
|
||||||
const CP10007 = "CP10007";
|
|
||||||
const CP12712 = "CP12712";
|
|
||||||
const CP16804 = "CP16804";
|
|
||||||
const ISO8859_7 = "ISO_8859-7";
|
|
||||||
const ISO8859_2 = "ISO_8859-2";
|
|
||||||
const ISO8859_15 = "ISO_8859-15";
|
|
||||||
const RK1048 = "RK1048";
|
|
||||||
// Code pages which are not built in
|
|
||||||
// to default iconv on Debian.
|
|
||||||
const CP720 = false;
|
|
||||||
const CP853 = false;
|
|
||||||
const CP858 = false;
|
|
||||||
const CP928 = false;
|
|
||||||
const CP1098 = false;
|
|
||||||
const CP747 = false;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Below code pages appear to be vendor-specific (Star), so iconv wont use them
|
|
||||||
* They are being merged gradually into the StarCapabilityProfile.
|
|
||||||
*/
|
|
||||||
const CP3840 = false;
|
|
||||||
const CP3841 = false;
|
|
||||||
const CP3843 = false;
|
|
||||||
const CP3844 = false;
|
|
||||||
const CP3845 = false;
|
|
||||||
const CP3847 = false;
|
|
||||||
const CP3846 = false;
|
|
||||||
const CP3848 = false;
|
|
||||||
const CP1001 = false;
|
|
||||||
const CP2001 = false;
|
|
||||||
const CP3001 = false;
|
|
||||||
const CP3002 = false;
|
|
||||||
const CP3011 = false;
|
|
||||||
const CP3012 = false;
|
|
||||||
const CP3021 = false;
|
|
||||||
const CP3041 = false;
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* This capability profile matches many recent Epson-branded thermal receipt printers.
|
|
||||||
*
|
|
||||||
* For non-Epson printers, try the SimpleCapabilityProfile.
|
|
||||||
*/
|
|
||||||
class DefaultCapabilityProfile extends AbstractCapabilityProfile {
|
|
||||||
function getCustomCodePages() {
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSupportedCodePages() {
|
|
||||||
/* Character code tables which the printer understands, mapping to known encoding standards we may be able to encode to.
|
|
||||||
*
|
|
||||||
* See CodePage.php for the mapping of these standards to encoding names for use in the backing library.
|
|
||||||
*
|
|
||||||
* Any entry with 'false' means I haven't compared the print-out of the code page to a table.
|
|
||||||
*/
|
|
||||||
return array(
|
|
||||||
0 => CodePage::CP437,
|
|
||||||
1 => CodePage::CP932,
|
|
||||||
2 => CodePage::CP850,
|
|
||||||
3 => CodePage::CP860,
|
|
||||||
4 => CodePage::CP863,
|
|
||||||
5 => CodePage::CP865,
|
|
||||||
6 => false, // Hiragana
|
|
||||||
7 => false, // One-pass printing Kanji characters
|
|
||||||
8 => false, // Page 8 [One-pass printing Kanji characters]
|
|
||||||
11 => CodePage::CP851,
|
|
||||||
12 => CodePage::CP853,
|
|
||||||
13 => CodePage::CP857,
|
|
||||||
14 => CodePage::CP737,
|
|
||||||
15 => CodePage::ISO8859_7,
|
|
||||||
16 => CodePage::CP1252,
|
|
||||||
17 => CodePage::CP866,
|
|
||||||
18 => CodePage::CP852,
|
|
||||||
19 => CodePage::CP858,
|
|
||||||
20 => false, // Thai Character Code 42
|
|
||||||
21 => CodePage::CP874, // Thai Character Code 11
|
|
||||||
22 => false, // Thai Character Code 13
|
|
||||||
23 => false, // Thai Character Code 14
|
|
||||||
24 => false, // Thai Character Code 16
|
|
||||||
25 => false, // Thai Character Code 17
|
|
||||||
26 => false, // Thai Character Code 18
|
|
||||||
30 => false, // TCVN-3: Vietnamese
|
|
||||||
31 => false, // TCVN-3: Vietnamese
|
|
||||||
32 => CodePage::CP720,
|
|
||||||
33 => CodePage::CP775,
|
|
||||||
34 => CodePage::CP855,
|
|
||||||
35 => CodePage::CP861,
|
|
||||||
36 => CodePage::CP862,
|
|
||||||
37 => CodePage::CP864,
|
|
||||||
38 => CodePage::CP869,
|
|
||||||
39 => CodePage::ISO8859_2,
|
|
||||||
40 => CodePage::ISO8859_15,
|
|
||||||
41 => CodePage::CP1098, // PC1098: Farsi
|
|
||||||
42 => CodePage::CP774,
|
|
||||||
43 => CodePage::CP772,
|
|
||||||
44 => CodePage::CP1125,
|
|
||||||
45 => CodePage::CP1250,
|
|
||||||
46 => CodePage::CP1251,
|
|
||||||
47 => CodePage::CP1253,
|
|
||||||
48 => CodePage::CP1254,
|
|
||||||
49 => CodePage::CP1255,
|
|
||||||
50 => CodePage::CP1256,
|
|
||||||
51 => CodePage::CP1257,
|
|
||||||
52 => CodePage::CP1258,
|
|
||||||
53 => CodePage::RK1048,
|
|
||||||
66 => false, // Devanagari
|
|
||||||
67 => false, // Bengali
|
|
||||||
68 => false, // Tamil
|
|
||||||
69 => false, // Telugu
|
|
||||||
70 => false, // Assamese
|
|
||||||
71 => false, // Oriya
|
|
||||||
72 => false, // Kannada
|
|
||||||
73 => false, // Malayalam
|
|
||||||
74 => false, // Gujarati
|
|
||||||
75 => false, // Punjabi
|
|
||||||
82 => false, // Marathi
|
|
||||||
254 => false,
|
|
||||||
255 => false);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSupportsBarcodeB() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSupportsBitImage() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSupportsGraphics() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSupportsStarCommands() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSupportsQrCode() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* escpos-php, a Thermal receipt printer library, for use with
|
|
||||||
* ESC/POS compatible printers.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014-2015 Michael Billington <michael.billington@gmail.com>,
|
|
||||||
* incorporating modifications by:
|
|
||||||
* - Roni Saha <roni.cse@gmail.com>
|
|
||||||
* - Gergely Radics <gerifield@ustream.tv>
|
|
||||||
* - Warren Doyle <w.doyle@fuelled.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
|
||||||
* Print connector that writes to nowhere, but allows the user to retrieve the
|
|
||||||
* buffered data. Used for testing.
|
|
||||||
*/
|
|
||||||
final class DummyPrintConnector implements PrintConnector {
|
|
||||||
/**
|
|
||||||
* @var array Buffer of accumilated data.
|
|
||||||
*/
|
|
||||||
private $buffer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string data which the printer will provide on next read
|
|
||||||
*/
|
|
||||||
private $readData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new print connector
|
|
||||||
*/
|
|
||||||
public function __construct() {
|
|
||||||
$this -> buffer = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __destruct() {
|
|
||||||
if($this -> buffer !== null) {
|
|
||||||
trigger_error("Print connector was not finalized. Did you forget to close the printer?", E_USER_NOTICE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function finalize() {
|
|
||||||
$this -> buffer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string Get the accumulated data that has been sent to this buffer.
|
|
||||||
*/
|
|
||||||
public function getData() {
|
|
||||||
return implode($this -> buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-PHPdoc)
|
|
||||||
* @see PrintConnector::read()
|
|
||||||
*/
|
|
||||||
public function read($len) {
|
|
||||||
return $len >= strlen($this -> readData) ? $this -> readData : substr($this -> readData, 0, $len);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function write($data) {
|
|
||||||
$this -> buffer[] = $data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
<?php
|
|
||||||
class EposTepCapabilityProfile extends DefaultCapabilityProfile {
|
|
||||||
// TODO override list of code pages
|
|
||||||
}
|
|
||||||
@@ -1,405 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* escpos-php, a Thermal receipt printer library, for use with
|
|
||||||
* ESC/POS compatible printers.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014-2015 Michael Billington <michael.billington@gmail.com>,
|
|
||||||
* incorporating modifications by:
|
|
||||||
* - Roni Saha <roni.cse@gmail.com>
|
|
||||||
* - Gergely Radics <gerifield@ustream.tv>
|
|
||||||
* - Warren Doyle <w.doyle@fuelled.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
|
||||||
* This class deals with images in raster formats, and converts them into formats
|
|
||||||
* which are suitable for use on thermal receipt printers. Currently, only PNG
|
|
||||||
* images (in) and ESC/POS raster format (out) are implemeted.
|
|
||||||
*
|
|
||||||
* Input formats:
|
|
||||||
* - Currently, only PNG is supported.
|
|
||||||
* - Other easily read raster formats (jpg, gif) will be added at a later date, as this is not complex.
|
|
||||||
* - The BMP format can be directly read by some commands, but this has not yet been implemented.
|
|
||||||
*
|
|
||||||
* Output formats:
|
|
||||||
* - Currently, only ESC/POS raster format is supported
|
|
||||||
* - ESC/POS 'column format' support is partially implemented, but is not yet used by Escpos.php library.
|
|
||||||
* - Output as multiple rows of column format image is not yet in the works.
|
|
||||||
*
|
|
||||||
* Libraries:
|
|
||||||
* - Currently, php-gd is used to read the input. Support for imagemagick where gd is not installed is
|
|
||||||
* also not complex to add, and is a likely future feature.
|
|
||||||
* - Support for native use of the BMP format is a goal, for maximum compatibility with target environments.
|
|
||||||
*/
|
|
||||||
class EscposImage {
|
|
||||||
/**
|
|
||||||
* @var string The image's bitmap data (if it is a Windows BMP).
|
|
||||||
*/
|
|
||||||
protected $imgBmpData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string image data in rows: 1 for black, 0 for white.
|
|
||||||
*/
|
|
||||||
protected $imgData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string cached raster format data to avoid re-computation
|
|
||||||
*/
|
|
||||||
protected $imgRasterData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int height of the image
|
|
||||||
*/
|
|
||||||
protected $imgHeight;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int width of the image
|
|
||||||
*/
|
|
||||||
protected $imgWidth;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load up an image from a filename
|
|
||||||
*
|
|
||||||
* @param string $imgPath The path to the image to load, or null to skip
|
|
||||||
* loading the image (some other functions are available for
|
|
||||||
* populating the data). Supported graphics types depend on your PHP configuration.
|
|
||||||
*/
|
|
||||||
public function __construct($imgPath = null) {
|
|
||||||
/* Can't use bitmaps yet */
|
|
||||||
$this -> imgBmpData = null;
|
|
||||||
$this -> imgRasterData = null;
|
|
||||||
if($imgPath === null) {
|
|
||||||
// Blank image
|
|
||||||
$this -> imgHeight = 0;
|
|
||||||
$this -> imgWidth = 0;
|
|
||||||
$this -> imgData = "";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load up using GD */
|
|
||||||
if(!file_exists($imgPath)) {
|
|
||||||
throw new Exception("File '$imgPath' does not exist.");
|
|
||||||
}
|
|
||||||
$ext = pathinfo($imgPath, PATHINFO_EXTENSION);
|
|
||||||
if($ext == "bmp") {
|
|
||||||
// The plan is to implement BMP handling directly in
|
|
||||||
// PHP, as some printers understand this format themselves.
|
|
||||||
// TODO implement PHP bitmap handling
|
|
||||||
throw new Exception("Native bitmaps not yet supported. Please convert the file to a supported raster format.");
|
|
||||||
}
|
|
||||||
if($this -> isGdSupported()) {
|
|
||||||
// Prefer to use gd. It is installed by default, so
|
|
||||||
// most systems will have it, giving a consistent UX.
|
|
||||||
switch($ext) {
|
|
||||||
case "png":
|
|
||||||
$im = @imagecreatefrompng($imgPath);
|
|
||||||
$this -> readImageFromGdResource($im);
|
|
||||||
return;
|
|
||||||
case "jpg":
|
|
||||||
$im = @imagecreatefromjpeg($imgPath);
|
|
||||||
$this -> readImageFromGdResource($im);
|
|
||||||
return;
|
|
||||||
case "gif":
|
|
||||||
$im = @imagecreatefromgif($imgPath);
|
|
||||||
$this -> readImageFromGdResource($im);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if($this -> isImagickSupported()) {
|
|
||||||
$im = new Imagick();
|
|
||||||
try {
|
|
||||||
// Throws an ImagickException if the format is not supported or file is not found
|
|
||||||
$im -> readImage($imgPath);
|
|
||||||
} catch(ImagickException $e) {
|
|
||||||
// Wrap in normal exception, so that classes which call this do not themselves require imagick as a dependency.
|
|
||||||
throw new Exception($e);
|
|
||||||
}
|
|
||||||
/* Flatten by doing a composite over white, in case of transparency */
|
|
||||||
$flat = new Imagick();
|
|
||||||
$flat -> newImage($im -> getimagewidth(), $im -> getimageheight(), "white");
|
|
||||||
$flat -> compositeimage($im, Imagick::COMPOSITE_OVER, 0, 0);
|
|
||||||
$this -> readImageFromImagick($flat);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw new Exception("Images are not supported on your PHP. Please install either the gd or imagick extension.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int height of the image in pixels
|
|
||||||
*/
|
|
||||||
public function getHeight() {
|
|
||||||
return $this -> imgHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int Number of bytes to represent a row of this image
|
|
||||||
*/
|
|
||||||
public function getHeightBytes() {
|
|
||||||
return (int)(($this -> imgHeight + 7) / 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int Width of the image
|
|
||||||
*/
|
|
||||||
public function getWidth() {
|
|
||||||
return $this -> imgWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int Number of bytes to represent a row of this image
|
|
||||||
*/
|
|
||||||
public function getWidthBytes() {
|
|
||||||
return (int)(($this -> imgWidth + 7) / 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string binary data of the original file, for function which accept bitmaps.
|
|
||||||
*/
|
|
||||||
public function getWindowsBMPData() {
|
|
||||||
return $this -> imgBmpData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return boolean True if the image was a windows bitmap, false otherwise
|
|
||||||
*/
|
|
||||||
public function isWindowsBMP() {
|
|
||||||
return $this -> imgBmpData != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load actual image pixels from GD resource.
|
|
||||||
*
|
|
||||||
* @param resouce $im GD resource to use
|
|
||||||
* @throws Exception Where the image can't be read.
|
|
||||||
*/
|
|
||||||
public function readImageFromGdResource($im) {
|
|
||||||
if(!is_resource($im)) {
|
|
||||||
throw new Exception("Failed to load image.");
|
|
||||||
} else if(!$this -> isGdSupported()) {
|
|
||||||
throw new Exception(__FUNCTION__ . " requires 'gd' extension.");
|
|
||||||
}
|
|
||||||
/* Make a string of 1's and 0's */
|
|
||||||
$this -> imgHeight = imagesy($im);
|
|
||||||
$this -> imgWidth = imagesx($im);
|
|
||||||
$this -> imgData = str_repeat("\0", $this -> imgHeight * $this -> imgWidth);
|
|
||||||
for($y = 0; $y < $this -> imgHeight; $y++) {
|
|
||||||
for($x = 0; $x < $this -> imgWidth; $x++) {
|
|
||||||
/* Faster to average channels, blend alpha and negate the image here than via filters (tested!) */
|
|
||||||
$cols = imagecolorsforindex($im, imagecolorat($im, $x, $y));
|
|
||||||
$greyness = (int)(($cols['red'] + $cols['green'] + $cols['blue']) / 3) >> 7; // 1 for white, 0 for black
|
|
||||||
$black = (1 - $greyness) >> ($cols['alpha'] >> 6); // 1 for black, 0 for white, taking into account transparency
|
|
||||||
$this -> imgData[$y * $this -> imgWidth + $x] = $black;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load actual image pixels from Imagick object
|
|
||||||
*
|
|
||||||
* @param Imagick $im Image to load from
|
|
||||||
*/
|
|
||||||
public function readImageFromImagick(Imagick $im) {
|
|
||||||
/* Threshold */
|
|
||||||
$im -> setImageType(Imagick::IMGTYPE_TRUECOLOR); // Remove transparency (good for PDF's)
|
|
||||||
$max = $im->getQuantumRange();
|
|
||||||
$max = $max["quantumRangeLong"];
|
|
||||||
$im -> thresholdImage(0.5 * $max);
|
|
||||||
/* Make a string of 1's and 0's */
|
|
||||||
$geometry = $im -> getimagegeometry();
|
|
||||||
$this -> imgHeight = $im -> getimageheight();
|
|
||||||
$this -> imgWidth = $im -> getimagewidth();
|
|
||||||
$this -> imgData = str_repeat("\0", $this -> imgHeight * $this -> imgWidth);
|
|
||||||
|
|
||||||
for($y = 0; $y < $this -> imgHeight; $y++) {
|
|
||||||
for($x = 0; $x < $this -> imgWidth; $x++) {
|
|
||||||
/* Faster to average channels, blend alpha and negate the image here than via filters (tested!) */
|
|
||||||
$cols = $im -> getImagePixelColor($x, $y);
|
|
||||||
$cols = $cols -> getcolor();
|
|
||||||
$greyness = (int)(($cols['r'] + $cols['g'] + $cols['b']) / 3) >> 7; // 1 for white, 0 for black
|
|
||||||
$this -> imgData[$y * $this -> imgWidth + $x] = (1 - $greyness); // 1 for black, 0 for white
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Output the image in raster (row) format. This can result in padding on the right of the image, if its width is not divisible by 8.
|
|
||||||
*
|
|
||||||
* @throws Exception Where the generated data is unsuitable for the printer (indicates a bug or oversized image).
|
|
||||||
* @return string The image in raster format.
|
|
||||||
*/
|
|
||||||
public function toRasterFormat() {
|
|
||||||
if($this -> imgRasterData != null) {
|
|
||||||
/* Use previous calculation */
|
|
||||||
return $this -> imgRasterData;
|
|
||||||
}
|
|
||||||
/* Loop through and convert format */
|
|
||||||
$widthPixels = $this -> getWidth();
|
|
||||||
$heightPixels = $this -> getHeight();
|
|
||||||
$widthBytes = $this -> getWidthBytes();
|
|
||||||
$heightBytes = $this -> getHeightBytes();
|
|
||||||
$x = $y = $bit = $byte = $byteVal = 0;
|
|
||||||
$data = str_repeat("\0", $widthBytes * $heightPixels);
|
|
||||||
if(strlen($data) == 0) {
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
$byteVal |= (int)$this -> imgData[$y * $widthPixels + $x] << (7 - $bit);
|
|
||||||
$x++;
|
|
||||||
$bit++;
|
|
||||||
if($x >= $widthPixels) {
|
|
||||||
$x = 0;
|
|
||||||
$y++;
|
|
||||||
$bit = 8;
|
|
||||||
if($y >= $heightPixels) {
|
|
||||||
$data[$byte] = chr($byteVal);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if($bit >= 8) {
|
|
||||||
$data[$byte] = chr($byteVal);
|
|
||||||
$byteVal = 0;
|
|
||||||
$bit = 0;
|
|
||||||
$byte++;
|
|
||||||
}
|
|
||||||
} while(true);
|
|
||||||
if(strlen($data) != ($this -> getWidthBytes() * $this -> getHeight())) {
|
|
||||||
throw new Exception("Bug in " . __FUNCTION__ . ", wrong number of bytes.");
|
|
||||||
}
|
|
||||||
$this -> imgRasterData = $data;
|
|
||||||
return $this -> imgRasterData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Output image in column format. This format results in padding at the base and right of the image, if its height and width are not divisible by 8.
|
|
||||||
*/
|
|
||||||
private function toColumnFormat() {
|
|
||||||
/* Note: This function is marked private, as it is not yet used/tested and may be buggy. */
|
|
||||||
$widthPixels = $this -> getWidth();
|
|
||||||
$heightPixels = $this -> getHeight();
|
|
||||||
$widthBytes = $this -> getWidthBytes();
|
|
||||||
$heightBytes = $this -> getHeightBytes();
|
|
||||||
$x = $y = $bit = $byte = $byteVal = 0;
|
|
||||||
$data = str_repeat("\0", $widthBytes * $heightBytes * 8);
|
|
||||||
do {
|
|
||||||
$byteVal |= (int)$this -> imgData[$y * $widthPixels + $x] << (8 - $bit);
|
|
||||||
$y++;
|
|
||||||
$bit++;
|
|
||||||
if($y >= $heightPixels) {
|
|
||||||
$y = 0;
|
|
||||||
$x++;
|
|
||||||
$bit = 8;
|
|
||||||
if($x >= $widthPixels) {
|
|
||||||
$data[$byte] = chr($byteVal);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if($bit >= 8) {
|
|
||||||
$data[$byte] = chr($byteVal);
|
|
||||||
$byteVal = 0;
|
|
||||||
$bit = 0;
|
|
||||||
$byte++;
|
|
||||||
}
|
|
||||||
} while(true);
|
|
||||||
if(strlen($data) != ($widthBytes * $heightBytes * 8)) {
|
|
||||||
throw new Exception("Bug in " . __FUNCTION__ . ", wrong number of bytes. Should be " . ($widthBytes * $heightBytes * 8) . " but was " . strlen($data));
|
|
||||||
}
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return boolean True if GD is supported, false otherwise (a wrapper for the static version, for mocking in tests)
|
|
||||||
*/
|
|
||||||
protected function isGdSupported() {
|
|
||||||
return self::isGdLoaded();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return boolean True if Imagick is supported, false otherwise (a wrapper for the static version, for mocking in tests)
|
|
||||||
*/
|
|
||||||
protected function isImagickSupported() {
|
|
||||||
return self::isImagickLoaded();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return boolean True if GD is loaded, false otherwise
|
|
||||||
*/
|
|
||||||
public static function isGdLoaded() {
|
|
||||||
return extension_loaded('gd');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return boolean True if Imagick is loaded, false otherwise
|
|
||||||
*/
|
|
||||||
public static function isImagickLoaded() {
|
|
||||||
return extension_loaded('imagick');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load a PDF for use on the printer
|
|
||||||
*
|
|
||||||
* @param string $pdfFile The file to load
|
|
||||||
* @param string $pageWidth The width, in pixels, of the printer's output. The first page of the PDF will be scaled to approximately fit in this area.
|
|
||||||
* @param array $range array indicating the first and last page (starting from 0) to load. If not set, the entire document is loaded.
|
|
||||||
* @throws Exception Where Imagick is not loaded, or where a missing file or invalid page number is requested.
|
|
||||||
* @return multitype:EscposImage Array of images, retrieved from the PDF file.
|
|
||||||
*/
|
|
||||||
public static function loadPdf($pdfFile, $pageWidth = 550, array $range = null) {
|
|
||||||
if(!extension_loaded('imagick')) {
|
|
||||||
throw new Exception(__FUNCTION__ . " requires imagick extension.");
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Load first page at very low density (resolution), to figure out what
|
|
||||||
* density to use to achieve $pageWidth
|
|
||||||
*/
|
|
||||||
try {
|
|
||||||
$image = new Imagick();
|
|
||||||
$testRes = 2; // Test resolution
|
|
||||||
$image -> setresolution($testRes, $testRes);
|
|
||||||
$image -> readimage($pdfFile."[0]");
|
|
||||||
$geo = $image -> getimagegeometry();
|
|
||||||
$image -> destroy();
|
|
||||||
$width = $geo['width'];
|
|
||||||
$newRes = $pageWidth / $width * $testRes;
|
|
||||||
/* Load actual document (can be very slow!) */
|
|
||||||
$rangeStr = ""; // Set to [0] [0-1] page range if $range is set
|
|
||||||
if($range != null) {
|
|
||||||
if(count($range) != 2 || !isset($range[0]) || !is_integer($range[0]) || !isset($range[1]) || !is_integer($range[1]) || $range[0] > $range[1]) {
|
|
||||||
throw new Exception("Invalid range. Must be two numbers in the array: The start and finish page indexes, starting from 0.");
|
|
||||||
}
|
|
||||||
$rangeStr = "[" . ($range[0] == $range[1] ? $range[0] : implode($range, "-")) . "]";
|
|
||||||
}
|
|
||||||
$image -> setresolution($newRes, $newRes);
|
|
||||||
$image -> readImage($pdfFile."$rangeStr");
|
|
||||||
$pages = $image -> getNumberImages();
|
|
||||||
/* Convert images to Escpos objects */
|
|
||||||
$ret = array();
|
|
||||||
for($i = 0;$i < $pages; $i++) {
|
|
||||||
$image -> setIteratorIndex($i);
|
|
||||||
$ep = new EscposImage();
|
|
||||||
$ep -> readImageFromImagick($image);
|
|
||||||
$ret[] = $ep;
|
|
||||||
}
|
|
||||||
return $ret;
|
|
||||||
} catch(ImagickException $e) {
|
|
||||||
// Wrap in normal exception, so that classes which call this do not themselves require imagick as a dependency.
|
|
||||||
throw new Exception($e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,304 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* escpos-php, a Thermal receipt printer library, for use with
|
|
||||||
* ESC/POS compatible printers.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014-2015 Michael Billington <michael.billington@gmail.com>,
|
|
||||||
* incorporating modifications by:
|
|
||||||
* - Roni Saha <roni.cse@gmail.com>
|
|
||||||
* - Gergely Radics <gerifield@ustream.tv>
|
|
||||||
* - Warren Doyle <w.doyle@fuelled.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
|
||||||
* This class manages newlines and character encoding for the target printer, and
|
|
||||||
* can be interchanged for an image-bassed buffer (ImagePrintBuffer) if you can't
|
|
||||||
* get it operating properly on your machine.
|
|
||||||
*/
|
|
||||||
class EscposPrintBuffer implements PrintBuffer {
|
|
||||||
/**
|
|
||||||
* @var boolean True to cache output as .gz, false to leave un-compressed (useful for debugging)
|
|
||||||
*/
|
|
||||||
const COMPRESS_CACHE = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string The input encoding of the buffer.
|
|
||||||
*/
|
|
||||||
const INPUT_ENCODING = "UTF-8";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string Un-recorgnised characters will be replaced with this.
|
|
||||||
*/
|
|
||||||
const REPLACEMENT_CHAR = "?";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This array Maps ESC/POS character tables to names iconv encodings
|
|
||||||
*/
|
|
||||||
private $available = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array Maps of UTF-8 to code-pages
|
|
||||||
*/
|
|
||||||
private $encode = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var Escpos Printer for output
|
|
||||||
*/
|
|
||||||
private $printer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Empty print buffer.
|
|
||||||
*/
|
|
||||||
function __construct() {
|
|
||||||
$this -> printer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function flush() {
|
|
||||||
if($this -> printer == null) {
|
|
||||||
throw new LogicException("Not attached to a printer.");
|
|
||||||
}
|
|
||||||
// TODO Not yet implemented for this buffer: This indicates that the printer needs the current line to be ended.
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPrinter() {
|
|
||||||
return $this -> printer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setPrinter(Escpos $printer = null) {
|
|
||||||
$this -> printer = $printer;
|
|
||||||
if($printer != null) {
|
|
||||||
$this -> loadAvailableCharacters();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function writeText($text) {
|
|
||||||
if($this -> printer == null) {
|
|
||||||
throw new LogicException("Not attached to a printer.");
|
|
||||||
}
|
|
||||||
if($text == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(!mb_detect_encoding($text, self::INPUT_ENCODING, true)) {
|
|
||||||
// Assume that the user has already put non-UTF8 into the target encoding.
|
|
||||||
return $this -> writeTextRaw($text);
|
|
||||||
}
|
|
||||||
$i = 0;
|
|
||||||
$j = 0;
|
|
||||||
$len = mb_strlen($text, self::INPUT_ENCODING);
|
|
||||||
while($i < $len) {
|
|
||||||
$matching = true;
|
|
||||||
if(($encoding = $this -> identifyText(mb_substr($text, $i, 1, self::INPUT_ENCODING))) === false) {
|
|
||||||
// Un-encodeable text
|
|
||||||
$encoding = $this -> getPrinter() -> getCharacterTable();
|
|
||||||
}
|
|
||||||
$i++;
|
|
||||||
$j = 1;
|
|
||||||
do {
|
|
||||||
$char = mb_substr($text, $i, 1, self::INPUT_ENCODING);
|
|
||||||
$matching = !isset($this -> available[$char]) || isset($this -> available[$char][$encoding]);
|
|
||||||
if($matching) {
|
|
||||||
$i++;
|
|
||||||
$j++;
|
|
||||||
}
|
|
||||||
} while($matching && $i < $len);
|
|
||||||
$this -> writeTextUsingEncoding(mb_substr($text, $i - $j, $j, self::INPUT_ENCODING), $encoding);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function writeTextRaw($text) {
|
|
||||||
if($this -> printer == null) {
|
|
||||||
throw new LogicException("Not attached to a printer.");
|
|
||||||
}
|
|
||||||
if(strlen($text) == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Pass only printable characters
|
|
||||||
for($i = 0; $i < strlen($text); $i++) {
|
|
||||||
$c = substr($text, $i, 1);
|
|
||||||
if(!self::asciiCheck($c, true)) {
|
|
||||||
$text[$i] = self::REPLACEMENT_CHAR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this -> write($text);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an encoding which we can start to use for outputting this text. Later parts of the text need not be included in the returned code page.
|
|
||||||
*
|
|
||||||
* @param string $text Input text to check.
|
|
||||||
* @return boolean|integer Code page number, or FALSE if the text is not printable on any supported encoding.
|
|
||||||
*/
|
|
||||||
private function identifyText($text) {
|
|
||||||
// TODO Replace this with an algorithm to choose the encoding which will encode the farthest into the string, to minimise code page changes.
|
|
||||||
$char = mb_substr($text, 0, 1, self::INPUT_ENCODING);
|
|
||||||
if(!isset($this -> available[$char])) {
|
|
||||||
/* Character not available anywhere */
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
foreach($this -> available[$char] as $encodingNo => $true) {
|
|
||||||
/* Return first code-page where it is available */
|
|
||||||
return $encodingNo;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Based on the printer's connector, compute (or load a cached copy of) maps of UTF character to unicode characters for later use.
|
|
||||||
*/
|
|
||||||
private function loadAvailableCharacters() {
|
|
||||||
$supportedCodePages = $this -> printer -> getPrinterCapabilityProfile() -> getSupportedCodePages();
|
|
||||||
$capabilityClassName = get_class($this -> printer -> getPrinterCapabilityProfile());
|
|
||||||
$cacheFile = dirname(__FILE__) . "/cache/Characters-" . $capabilityClassName . ".ser" . (self::COMPRESS_CACHE ? ".gz" : "");
|
|
||||||
$cacheKey = md5(serialize($supportedCodePages));
|
|
||||||
/* Check for pre-generated file */
|
|
||||||
if(file_exists($cacheFile)) {
|
|
||||||
$cacheData = file_get_contents($cacheFile);
|
|
||||||
if(self::COMPRESS_CACHE) {
|
|
||||||
$cacheData = gzdecode($cacheData);
|
|
||||||
}
|
|
||||||
if($cacheData) {
|
|
||||||
$dataArray = unserialize($cacheData);
|
|
||||||
if(isset($dataArray["key"]) && isset($dataArray["available"]) && isset($dataArray["encode"]) && $dataArray["key"] == $cacheKey) {
|
|
||||||
$this -> available = $dataArray["available"];
|
|
||||||
$this -> encode = $dataArray["encode"];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Generate conversion tables */
|
|
||||||
$encode = array();
|
|
||||||
$available = array();
|
|
||||||
$custom = $this -> printer -> getPrinterCapabilityProfile() -> getCustomCodePages();
|
|
||||||
|
|
||||||
foreach($supportedCodePages as $num => $characterMap) {
|
|
||||||
$encode[$num] = array();
|
|
||||||
if($characterMap === false) {
|
|
||||||
continue;
|
|
||||||
} else if(strpos($characterMap, ":") !== false) {
|
|
||||||
/* Load a pre-defined custom map (vendor-specific code pages) */
|
|
||||||
$i = strpos($characterMap, ":");
|
|
||||||
if(substr($characterMap, 0, $i) !== "custom") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$i++;
|
|
||||||
$mapName = substr($characterMap, $i, strlen($characterMap) - $i);
|
|
||||||
if(!isset($custom[$mapName]) || mb_strlen($custom[$mapName], self::INPUT_ENCODING) != 128) {
|
|
||||||
throw new Exception("Capability profile referenced invalid custom map '$mapName'.");
|
|
||||||
}
|
|
||||||
$map = $custom[$mapName];
|
|
||||||
for($char = 128; $char <= 255; $char++) {
|
|
||||||
$utf8 = mb_substr($map, $char - 128, 1, self::INPUT_ENCODING);
|
|
||||||
if($utf8 == " ") { // Skip placeholders
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(!isset($available[$utf8])) {
|
|
||||||
$available[$utf8] = array();
|
|
||||||
}
|
|
||||||
$available[$utf8][$num] = true;
|
|
||||||
$encode[$num][$utf8] = chr($char);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Generate map using iconv */
|
|
||||||
for($char = 128; $char <= 255; $char++) {
|
|
||||||
$utf8 = @iconv($characterMap, self::INPUT_ENCODING, chr($char));
|
|
||||||
if($utf8 == '') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(iconv(self::INPUT_ENCODING, $characterMap, $utf8) != chr($char)) {
|
|
||||||
// Avoid non-canonical conversions
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(!isset($available[$utf8])) {
|
|
||||||
$available[$utf8] = array();
|
|
||||||
}
|
|
||||||
$available[$utf8][$num] = true;
|
|
||||||
$encode[$num][$utf8] = chr($char);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Use generated data */
|
|
||||||
$dataArray = array("available" => $available, "encode" => $encode, "key" => $cacheKey);
|
|
||||||
$this -> available = $dataArray["available"];
|
|
||||||
$this -> encode = $dataArray["encode"];
|
|
||||||
$cacheData = serialize($dataArray);
|
|
||||||
if(self::COMPRESS_CACHE) {
|
|
||||||
$cacheData = gzencode($cacheData);
|
|
||||||
}
|
|
||||||
/* Attempt to cache, but don't worry if we can't */
|
|
||||||
@file_put_contents($cacheFile, $cacheData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode a block of text using the specified map, and write it to the printer.
|
|
||||||
*
|
|
||||||
* @param string $text Text to print, UTF-8 format.
|
|
||||||
* @param integer $encodingNo Encoding number to use- assumed to exist.
|
|
||||||
*/
|
|
||||||
private function writeTextUsingEncoding($text, $encodingNo) {
|
|
||||||
$encodeMap = $this -> encode[$encodingNo];
|
|
||||||
$len = mb_strlen($text, self::INPUT_ENCODING);
|
|
||||||
$rawText = str_repeat(self::REPLACEMENT_CHAR, $len);
|
|
||||||
for($i = 0; $i < $len; $i++) {
|
|
||||||
$char = mb_substr($text, $i, 1, self::INPUT_ENCODING);
|
|
||||||
if(isset($encodeMap[$char])) {
|
|
||||||
$rawText[$i] = $encodeMap[$char];
|
|
||||||
} else if(self::asciiCheck($char)) {
|
|
||||||
$rawText[$i] = $char;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if($this -> printer -> getCharacterTable() != $encodingNo) {
|
|
||||||
$this -> printer -> selectCharacterTable($encodingNo);
|
|
||||||
}
|
|
||||||
$this -> writeTextRaw($rawText);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write data to the underlying printer.
|
|
||||||
*
|
|
||||||
* @param string $data
|
|
||||||
*/
|
|
||||||
private function write($data) {
|
|
||||||
$this -> printer -> getPrintConnector() -> write($data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if a character is an ASCII printable character.
|
|
||||||
*
|
|
||||||
* @param string $char Character to check
|
|
||||||
* @param boolean $extended True to allow 128-256 values also (excluded by default)
|
|
||||||
* @return boolean True if the character is printable, false if it is not.
|
|
||||||
*/
|
|
||||||
private static function asciiCheck($char, $extended = false) {
|
|
||||||
if(strlen($char) != 1) {
|
|
||||||
// Multi-byte string
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$num = ord($char);
|
|
||||||
if($num > 31 && $num < 127) { // Printable
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if($num == 10) { // New-line (printer will take these)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if($extended && $num > 127) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* escpos-php, a Thermal receipt printer library, for use with
|
|
||||||
* ESC/POS compatible printers.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014-2015 Michael Billington <michael.billington@gmail.com>,
|
|
||||||
* incorporating modifications by:
|
|
||||||
* - Roni Saha <roni.cse@gmail.com>
|
|
||||||
* - Gergely Radics <gerifield@ustream.tv>
|
|
||||||
* - Warren Doyle <w.doyle@fuelled.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
|
||||||
* PrintConnector for passing print data to a file.
|
|
||||||
*/
|
|
||||||
class FilePrintConnector implements PrintConnector {
|
|
||||||
/**
|
|
||||||
* @var resource The file pointer to send data to.
|
|
||||||
*/
|
|
||||||
protected $fp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct new connector, given a filename
|
|
||||||
*
|
|
||||||
* @param string $filename
|
|
||||||
*/
|
|
||||||
public function __construct($filename) {
|
|
||||||
$this -> fp = fopen($filename, "wb+");
|
|
||||||
if($this -> fp === false) {
|
|
||||||
throw new Exception("Cannot initialise FilePrintConnector.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __destruct() {
|
|
||||||
if($this -> fp !== false) {
|
|
||||||
trigger_error("Print connector was not finalized. Did you forget to close the printer?", E_USER_NOTICE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close file pointer
|
|
||||||
*/
|
|
||||||
public function finalize() {
|
|
||||||
fclose($this -> fp);
|
|
||||||
$this -> fp = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-PHPdoc)
|
|
||||||
* @see PrintConnector::read()
|
|
||||||
*/
|
|
||||||
public function read($len) {
|
|
||||||
rewind($this -> fp);
|
|
||||||
return fgets($this -> fp, $len + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write data to the file
|
|
||||||
*
|
|
||||||
* @param string $data
|
|
||||||
*/
|
|
||||||
public function write($data) {
|
|
||||||
fwrite($this -> fp, $data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* escpos-php, a Thermal receipt printer library, for use with
|
|
||||||
* ESC/POS compatible printers.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014-2015 Michael Billington <michael.billington@gmail.com>,
|
|
||||||
* incorporating modifications by:
|
|
||||||
* - Roni Saha <roni.cse@gmail.com>
|
|
||||||
* - Gergely Radics <gerifield@ustream.tv>
|
|
||||||
* - Warren Doyle <w.doyle@fuelled.co>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
|
||||||
* This class renders text to small images on-the-fly. It attempts to mimic the
|
|
||||||
* behaviour of text output, whilst supporting any fonts & character encodings
|
|
||||||
* which your system can handle. This class currently requires Imagick.
|
|
||||||
*/
|
|
||||||
class ImagePrintBuffer implements PrintBuffer {
|
|
||||||
private $printer;
|
|
||||||
|
|
||||||
function __construct() {
|
|
||||||
if(!EscposImage::isImagickLoaded()) {
|
|
||||||
throw new Exception("ImagePrintBuffer requires the imagick extension");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function flush() {
|
|
||||||
if($this -> printer == null) {
|
|
||||||
throw new LogicException("Not attached to a printer.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPrinter() {
|
|
||||||
return $this -> printer;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setPrinter(Escpos $printer = null) {
|
|
||||||
$this -> printer = $printer;
|
|
||||||
}
|
|
||||||
|
|
||||||
function writeText($text) {
|
|
||||||
if($this -> printer == null) {
|
|
||||||
throw new LogicException("Not attached to a printer.");
|
|
||||||
}
|
|
||||||
if($text == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$text = trim($text, "\n");
|
|
||||||
/* Create Imagick objects */
|
|
||||||
$image = new Imagick();
|
|
||||||
$draw = new ImagickDraw();
|
|
||||||
$color = new ImagickPixel('#000000');
|
|
||||||
$background = new ImagickPixel('white');
|
|
||||||
|
|
||||||
/* Create annotation */
|
|
||||||
//$draw -> setFont('Arial');// (not necessary?)
|
|
||||||
$draw -> setFontSize(24); // Size 21 looks good for FONT B
|
|
||||||
$draw -> setFillColor($color);
|
|
||||||
$draw -> setStrokeAntialias(true);
|
|
||||||
$draw -> setTextAntialias(true);
|
|
||||||
$metrics = $image -> queryFontMetrics($draw, $text);
|
|
||||||
$draw -> annotation(0, $metrics['ascender'], $text);
|
|
||||||
|
|
||||||
/* Create image & draw annotation on it */
|
|
||||||
$image -> newImage($metrics['textWidth'], $metrics['textHeight'], $background);
|
|
||||||
$image -> setImageFormat('png');
|
|
||||||
$image -> drawImage($draw);
|
|
||||||
//$image -> writeImage("test.png");
|
|
||||||
|
|
||||||
/* Save image */
|
|
||||||
$escposImage = new EscposImage();
|
|
||||||
$escposImage -> readImageFromImagick($image);
|
|
||||||
$size = Escpos::IMG_DEFAULT;
|
|
||||||
$this -> printer -> bitImage($escposImage, $size);
|
|
||||||
}
|
|
||||||
|
|
||||||
function writeTextRaw($text) {
|
|
||||||
if($this -> printer == null) {
|
|
||||||
throw new LogicException("Not attached to a printer.");
|
|
||||||
}
|
|
||||||
$this -> printer -> getPrintConnector() -> write($data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,348 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-18 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mike42\Escpos;
|
||||||
|
|
||||||
|
use \InvalidArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store compatibility information about one printer.
|
||||||
|
*/
|
||||||
|
class CapabilityProfile
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var string $codePageCacheKey
|
||||||
|
* Hash of the code page data structure, to identify it for caching.
|
||||||
|
*/
|
||||||
|
protected $codePageCacheKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var array $codePages
|
||||||
|
* Associtive array of CodePage objects, indicating which encodings the printer supports.
|
||||||
|
*/
|
||||||
|
protected $codePages;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var array $colors
|
||||||
|
* Not used.
|
||||||
|
*/
|
||||||
|
protected $colors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var array $features
|
||||||
|
* Feature values.
|
||||||
|
*/
|
||||||
|
protected $features;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var array $fonts
|
||||||
|
* Not used
|
||||||
|
*/
|
||||||
|
protected $fonts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var array $media
|
||||||
|
* Not used
|
||||||
|
*/
|
||||||
|
protected $media;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var string $name
|
||||||
|
* Name of the profile, including model number.
|
||||||
|
*/
|
||||||
|
protected $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var string $notes
|
||||||
|
* Notes on the profile, null if not set.
|
||||||
|
*/
|
||||||
|
protected $notes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var string $profileId
|
||||||
|
* ID of the profile.
|
||||||
|
*/
|
||||||
|
protected $profileId;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string $vendor
|
||||||
|
* Name of manufacturer.
|
||||||
|
*/
|
||||||
|
protected $vendor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var array $encodings
|
||||||
|
* Data structure containing encodings loaded from disk, null if not loaded yet.
|
||||||
|
*/
|
||||||
|
protected static $encodings = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var array $profiles
|
||||||
|
* Data structure containing profiles loaded from disk, null if not loaded yet.
|
||||||
|
*/
|
||||||
|
protected static $profiles = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct new CapabilityProfile.
|
||||||
|
* The encoding data must be loaded from disk before calling.
|
||||||
|
*
|
||||||
|
* @param string $profileId
|
||||||
|
* ID of the profile
|
||||||
|
* @param array $profileData
|
||||||
|
* Profile data from disk.
|
||||||
|
*/
|
||||||
|
protected function __construct($profileId, array $profileData)
|
||||||
|
{
|
||||||
|
// Basic primitive fields
|
||||||
|
$this->profileId = $profileId;
|
||||||
|
$this->name = $profileData['name'];
|
||||||
|
$this->notes = $profileData['notes'];
|
||||||
|
$this->vendor = $profileData['vendor'];
|
||||||
|
// More complex fields that are not currently loaded into custom objects
|
||||||
|
$this->features = $profileData['features'];
|
||||||
|
$this->colors = $profileData['colors'];
|
||||||
|
$this->fonts = $profileData['fonts'];
|
||||||
|
$this->media = $profileData['media'];
|
||||||
|
// More complex fields that are loaded into custom objects
|
||||||
|
$this->codePages = [];
|
||||||
|
$this->codePageCacheKey = md5(json_encode($profileData['codePages']));
|
||||||
|
foreach ($profileData['codePages'] as $k => $v) {
|
||||||
|
$this->codePages[$k] = new CodePage($v, self::$encodings[$v]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return string Hash of the code page data structure, to identify it for caching.
|
||||||
|
*/
|
||||||
|
public function getCodePageCacheKey()
|
||||||
|
{
|
||||||
|
return $this->codePageCacheKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return array Associtive array of CodePage objects, indicating which encodings the printer supports.
|
||||||
|
*/
|
||||||
|
public function getCodePages()
|
||||||
|
{
|
||||||
|
return $this->codePages;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param string $featureName
|
||||||
|
* Name of the feature to retrieve.
|
||||||
|
* @throws \InvalidArgumentException Where the feature does not exist.
|
||||||
|
* The exception will contain suggestions for the closest-named features.
|
||||||
|
* @return mixed feature value.
|
||||||
|
*/
|
||||||
|
public function getFeature($featureName)
|
||||||
|
{
|
||||||
|
if (isset($this->features[$featureName])) {
|
||||||
|
return $this->features[$featureName];
|
||||||
|
}
|
||||||
|
$suggestionsArr = $this->suggestFeatureName($featureName);
|
||||||
|
$suggestionsStr = implode(", ", $suggestionsArr);
|
||||||
|
$str = "The feature '$featureName' does not exist. Try one that does exist, such as $suggestionsStr";
|
||||||
|
throw new \InvalidArgumentException($str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return string ID of the profile.
|
||||||
|
*/
|
||||||
|
public function getId()
|
||||||
|
{
|
||||||
|
return $this->profileId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return string Name of the printer.
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return boolean True if Barcode B command is supported, false otherwise
|
||||||
|
*/
|
||||||
|
public function getSupportsBarcodeB()
|
||||||
|
{
|
||||||
|
return $this->getFeature('barcodeB') === true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return boolean True if Bit Image Raster command is supported, false otherwise
|
||||||
|
*/
|
||||||
|
public function getSupportsBitImageRaster()
|
||||||
|
{
|
||||||
|
return $this->getFeature('bitImageRaster') === true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return boolean True if Graphics command is supported, false otherwise
|
||||||
|
*/
|
||||||
|
public function getSupportsGraphics()
|
||||||
|
{
|
||||||
|
return $this->getFeature('graphics') === true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return boolean True if PDF417 code command is supported, false otherwise
|
||||||
|
*/
|
||||||
|
public function getSupportsPdf417Code()
|
||||||
|
{
|
||||||
|
// TODO submit 'pdf417Code' as a new feature to be tracked in upstream profiles
|
||||||
|
return $this->getFeature('qrCode') === true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return boolean True if QR code command is supported, false otherwise
|
||||||
|
*/
|
||||||
|
public function getSupportsQrCode()
|
||||||
|
{
|
||||||
|
return $this->getFeature('qrCode') === true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return boolean True if Star mode commands are supported, false otherwise
|
||||||
|
*/
|
||||||
|
public function getSupportsStarCommands()
|
||||||
|
{
|
||||||
|
return $this->getFeature('starCommands') === true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return string Vendor of this printer.
|
||||||
|
*/
|
||||||
|
public function getVendor()
|
||||||
|
{
|
||||||
|
return $this->vendor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param string $featureName
|
||||||
|
* Feature that does not exist
|
||||||
|
* @return array Three most similar feature names that do exist.
|
||||||
|
*/
|
||||||
|
protected function suggestFeatureName($featureName)
|
||||||
|
{
|
||||||
|
return self::suggestNearest($featureName, array_keys($this->features), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return array Names of all profiles that exist.
|
||||||
|
*/
|
||||||
|
public static function getProfileNames()
|
||||||
|
{
|
||||||
|
self::loadCapabilitiesDataFile();
|
||||||
|
return array_keys(self::$profiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the CapabilityProfile with the given ID.
|
||||||
|
*
|
||||||
|
* @param string $profileName
|
||||||
|
* The ID of the profile to load.
|
||||||
|
* @throws InvalidArgumentException Where the ID does not exist. Some similarly-named profiles will be suggested in the Exception text.
|
||||||
|
* @return CapabilityProfile The CapabilityProfile that was requested.
|
||||||
|
*/
|
||||||
|
public static function load($profileName)
|
||||||
|
{
|
||||||
|
self::loadCapabilitiesDataFile();
|
||||||
|
if (! isset(self::$profiles[$profileName])) {
|
||||||
|
$suggestionsArray = self::suggestProfileName($profileName);
|
||||||
|
$suggestionsStr = implode(", ", $suggestionsArray);
|
||||||
|
throw new InvalidArgumentException("The CapabilityProfile '$profileName' does not exist. Try one that does exist, such as $suggestionsStr.");
|
||||||
|
}
|
||||||
|
return new CapabilityProfile($profileName, self::$profiles[$profileName]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure that the capabilities.json data file has been loaded.
|
||||||
|
*/
|
||||||
|
protected static function loadCapabilitiesDataFile()
|
||||||
|
{
|
||||||
|
if (self::$profiles === null) {
|
||||||
|
$filename = dirname(__FILE__) . "/resources/capabilities.json";
|
||||||
|
$capabilitiesData = json_decode(file_get_contents($filename), true);
|
||||||
|
self::$profiles = $capabilitiesData['profiles'];
|
||||||
|
self::$encodings = $capabilitiesData['encodings'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return choices with smallest edit distance to an invalid input.
|
||||||
|
*
|
||||||
|
* @param string $input
|
||||||
|
* Input that is not a valid choice
|
||||||
|
* @param array $choices
|
||||||
|
* Array of valid choices.
|
||||||
|
* @param int $num
|
||||||
|
* Number of suggestions to return
|
||||||
|
*/
|
||||||
|
public static function suggestNearest($input, array $choices, $num)
|
||||||
|
{
|
||||||
|
$distances = array_fill_keys($choices, PHP_INT_MAX);
|
||||||
|
foreach ($distances as $word => $_) {
|
||||||
|
$distances[$word] = levenshtein($input, $word);
|
||||||
|
}
|
||||||
|
asort($distances);
|
||||||
|
return array_slice(array_keys($distances), 0, min($num, count($choices)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param string $profileName
|
||||||
|
* profile name that does not exist
|
||||||
|
* @return array Three similar profile names that do exist, plus 'simple' and 'default' for good measure.
|
||||||
|
*/
|
||||||
|
protected static function suggestProfileName($profileName)
|
||||||
|
{
|
||||||
|
$suggestions = self::suggestNearest($profileName, array_keys(self::$profiles), 3);
|
||||||
|
$alwaysSuggest = [
|
||||||
|
'simple',
|
||||||
|
'default'
|
||||||
|
];
|
||||||
|
foreach ($alwaysSuggest as $item) {
|
||||||
|
if (array_search($item, $suggestions) === false) {
|
||||||
|
array_push($suggestions, $item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $suggestions;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-16 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
namespace Mike42\Escpos\CapabilityProfiles;
|
||||||
|
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
|
||||||
|
class DefaultCapabilityProfile
|
||||||
|
{
|
||||||
|
public static function getInstance()
|
||||||
|
{
|
||||||
|
return CapabilityProfile::load('default');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-16 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
namespace Mike42\Escpos\CapabilityProfiles;
|
||||||
|
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
|
||||||
|
class EposTepCapabilityProfile
|
||||||
|
{
|
||||||
|
public static function getInstance()
|
||||||
|
{
|
||||||
|
return CapabilityProfile::load('TEP-200M');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-16 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
namespace Mike42\Escpos\CapabilityProfiles;
|
||||||
|
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
|
||||||
|
class P822DCapabilityProfile
|
||||||
|
{
|
||||||
|
public static function getInstance()
|
||||||
|
{
|
||||||
|
return CapabilityProfile::load('P822D');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-16 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
namespace Mike42\Escpos\CapabilityProfiles;
|
||||||
|
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
|
||||||
|
class SimpleCapabilityProfile
|
||||||
|
{
|
||||||
|
public static function getInstance()
|
||||||
|
{
|
||||||
|
return CapabilityProfile::load('simple');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-16 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
namespace Mike42\Escpos\CapabilityProfiles;
|
||||||
|
|
||||||
|
use Mike42\Escpos\CapabilityProfile;
|
||||||
|
|
||||||
|
class StarCapabilityProfile
|
||||||
|
{
|
||||||
|
public static function getInstance()
|
||||||
|
{
|
||||||
|
return CapabilityProfile::load('SP2000');
|
||||||
|
}
|
||||||
|
}
|
||||||
181
htdocs/includes/mike42/escpos-php/src/Mike42/Escpos/CodePage.php
Normal file
181
htdocs/includes/mike42/escpos-php/src/Mike42/Escpos/CodePage.php
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-18 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mike42\Escpos;
|
||||||
|
|
||||||
|
use \InvalidArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to handle data about a particular CodePage, as loaded from the receipt print
|
||||||
|
* database.
|
||||||
|
*
|
||||||
|
* Also computes map between UTF-8 and this encoding if necessary, using the iconv library.
|
||||||
|
*/
|
||||||
|
class CodePage
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The input encoding for generating character maps with iconv.
|
||||||
|
*/
|
||||||
|
const INPUT_ENCODING = "UTF-8";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string $data
|
||||||
|
* Data string, null if not known (can be computed with iconv)
|
||||||
|
*/
|
||||||
|
protected $data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string $iconv
|
||||||
|
* Iconv encoding name, null if not known
|
||||||
|
*/
|
||||||
|
protected $iconv;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string $id
|
||||||
|
* Internal ID of the CodePage
|
||||||
|
*/
|
||||||
|
protected $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string $name
|
||||||
|
* Name of the code page. Substituted with the ID if not set.
|
||||||
|
*/
|
||||||
|
protected $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string $notes
|
||||||
|
* Notes on this code page, or null if not set.
|
||||||
|
*/
|
||||||
|
protected $notes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param string $id
|
||||||
|
* Unique internal identifier for the CodePage.
|
||||||
|
* @param array $codePageData
|
||||||
|
* Associative array of CodePage data, as
|
||||||
|
* specified by the upstream receipt-print-hq/escpos-printer-db database.
|
||||||
|
* May contain 'name', 'data', 'iconv', and 'notes' fields.
|
||||||
|
*/
|
||||||
|
public function __construct($id, array $codePageData)
|
||||||
|
{
|
||||||
|
$this->id = $id;
|
||||||
|
$this->name = isset($codePageData['name']) ? $codePageData['name'] : $id;
|
||||||
|
$this->data = isset($codePageData['data']) ? implode("", $codePageData['data']) : null;
|
||||||
|
$this->iconv = isset($codePageData['iconv']) ? $codePageData['iconv'] : null;
|
||||||
|
$this->notes = isset($codePageData['notes']) ? $codePageData['notes'] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a 128-character data string representing this encoding.
|
||||||
|
* It will be
|
||||||
|
* calculated and cached if it was not previously known.
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException Where the data is now known or computable.
|
||||||
|
* @return string Data for this encoding.
|
||||||
|
*/
|
||||||
|
public function getData()
|
||||||
|
{
|
||||||
|
if ($this->data !== null) {
|
||||||
|
// Return data if known
|
||||||
|
return $this->data;
|
||||||
|
}
|
||||||
|
if ($this->iconv !== null) {
|
||||||
|
// Calculate with iconv if we know the encoding name
|
||||||
|
$this->data = self::generateEncodingMap($this->iconv);
|
||||||
|
return $this->data;
|
||||||
|
}
|
||||||
|
// Can't encode..
|
||||||
|
throw new InvalidArgumentException("Cannot encode this code page");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return string Iconv encoding name, or blank if not set.
|
||||||
|
*/
|
||||||
|
public function getIconv()
|
||||||
|
{
|
||||||
|
return $this->iconv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return string Unique identifier of the code page.
|
||||||
|
*/
|
||||||
|
public function getId()
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the code page.
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The notes may explain quirks about a code-page, such as a source if it's non-standard or un-encodeable.
|
||||||
|
*
|
||||||
|
* @return string Notes on the code page, or null if not set.
|
||||||
|
*/
|
||||||
|
public function getNotes()
|
||||||
|
{
|
||||||
|
return $this->notes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return boolean True if we can encode with this code page (ie, we know what data it holds).
|
||||||
|
*
|
||||||
|
* Many printers contain vendor-specific code pages, which are named but have not been identified or
|
||||||
|
* typed out. For our purposes, this is an "un-encodeable" code page.
|
||||||
|
*/
|
||||||
|
public function isEncodable()
|
||||||
|
{
|
||||||
|
return $this->iconv !== null || $this->data !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an iconv encoding name, generate a 128-character UTF-8 string, containing code points 128-255.
|
||||||
|
*
|
||||||
|
* This string is used to map UTF-8 characters to their location in this code page.
|
||||||
|
*
|
||||||
|
* @param string $iconvName
|
||||||
|
* Name of the encoding
|
||||||
|
* @return string 128-character string in UTF-8.
|
||||||
|
*/
|
||||||
|
protected static function generateEncodingMap($iconvName)
|
||||||
|
{
|
||||||
|
// Start with array of blanks (" " indicates unknown character).
|
||||||
|
$charMap = array_fill(0, 128, " ");
|
||||||
|
// Loop through 128 code points
|
||||||
|
for ($char = 128; $char <= 255; $char ++) {
|
||||||
|
// Try to identify the UTF-8 character that would go here
|
||||||
|
$utf8 = @iconv($iconvName, self::INPUT_ENCODING, chr($char));
|
||||||
|
if ($utf8 == '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (iconv(self::INPUT_ENCODING, $iconvName, $utf8) != chr($char)) {
|
||||||
|
// Avoid non-canonical conversions (no known examples)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Replace the ' ' with the correct character if we found it
|
||||||
|
$charMap[$char - 128] = $utf8;
|
||||||
|
}
|
||||||
|
// Join into a 128-character string and return.
|
||||||
|
$charMapStr = implode("", $charMap);
|
||||||
|
assert(mb_strlen($charMapStr, self::INPUT_ENCODING) == 128);
|
||||||
|
return $charMapStr;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-18 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mike42\Escpos\Devices;
|
||||||
|
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class for sending ESC/POS-like code to an Aures customer display.
|
||||||
|
* The display has some features that printers do not, such as an ability to "clear" the screen.
|
||||||
|
*/
|
||||||
|
class AuresCustomerDisplay extends Printer
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that the text should wrap and type over
|
||||||
|
* existing text on the screen, rather than scroll.
|
||||||
|
*/
|
||||||
|
const TEXT_OVERWRITE = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that overflowing text should cause the
|
||||||
|
* display to scroll vertically, like a computer terminal.
|
||||||
|
*/
|
||||||
|
const TEXT_VERTICAL_SCROLL = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that overflowing text should cause the
|
||||||
|
* display to scroll horizontally, like a news ticker.
|
||||||
|
*/
|
||||||
|
const TEXT_HORIZONTAL_SCROLL = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @see \Mike42\Escpos\Printer::initialize()
|
||||||
|
*/
|
||||||
|
public function initialize()
|
||||||
|
{
|
||||||
|
// Select ESC/POS mode first
|
||||||
|
$this->selectEscposMode();
|
||||||
|
parent::initialize();
|
||||||
|
// ESC @ does not reset character table on this printer
|
||||||
|
$this->selectCharacterTable(0);
|
||||||
|
// Default to horizontal scroll mode. Behaves most like a printer.
|
||||||
|
$this->selectTextScrollMode(AuresCustomerDisplay::TEXT_VERTICAL_SCROLL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects ESC/POS mode.
|
||||||
|
*
|
||||||
|
* This device supports other modes, which are not used.
|
||||||
|
*/
|
||||||
|
protected function selectEscposMode()
|
||||||
|
{
|
||||||
|
$this->connector->write("\x02\x05\x43\x31\x03");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param int $mode
|
||||||
|
* The text scroll mode to use. One of
|
||||||
|
* AuresCustomerDisplay::TEXT_OVERWRITE,
|
||||||
|
* AuresCustomerDisplay::TEXT_VERTICAL_SCROLL or
|
||||||
|
* AuresCustomerDisplay::TEXT_HORIZONTAL_SCROLL
|
||||||
|
*/
|
||||||
|
public function selectTextScrollMode($mode = AuresCustomerDisplay::TEXT_VERTICAL_SCROLL)
|
||||||
|
{
|
||||||
|
self::validateInteger($mode, 1, 3, __FUNCTION__);
|
||||||
|
$this->connector->write("\x1F" . chr($mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the display.
|
||||||
|
*/
|
||||||
|
public function clear()
|
||||||
|
{
|
||||||
|
$this->connector->write("\x0c");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instruct the display to show the firmware version.
|
||||||
|
*/
|
||||||
|
public function showFirmwareVersion()
|
||||||
|
{
|
||||||
|
$this->connector->write("\x02\x05\x56\x01\x03");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instruct the display to begin a self-test/demo sequence.
|
||||||
|
*/
|
||||||
|
public function selfTest()
|
||||||
|
{
|
||||||
|
$this->connector->write("\x02\x05\x44\x08\x03");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instruct the display to show a pre-loaded logo.
|
||||||
|
*
|
||||||
|
* Note that this driver is not capable of uploading a
|
||||||
|
* logo, but that the vendor supplies software
|
||||||
|
* which has this function.
|
||||||
|
*/
|
||||||
|
public function showLogo()
|
||||||
|
{
|
||||||
|
$this->connector->write("\x02\xFC\x55\xAA\x55\xAA");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @see \Mike42\Escpos\Printer::text()
|
||||||
|
*/
|
||||||
|
public function text($str = "")
|
||||||
|
{
|
||||||
|
self::validateString($str, __FUNCTION__);
|
||||||
|
// Need to intercept line-feeds, since "\n" is insufficient on this device.
|
||||||
|
foreach (explode("\n", $str) as $id => $line) {
|
||||||
|
if ($id > 0) {
|
||||||
|
$this->feed();
|
||||||
|
}
|
||||||
|
parent::text($line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @see \Mike42\Escpos\Printer::feed()
|
||||||
|
*/
|
||||||
|
public function feed($lines = 1)
|
||||||
|
{
|
||||||
|
self::validateInteger($lines, 1, 255, __FUNCTION__);
|
||||||
|
for ($i = 0; $i < $lines; $i ++) {
|
||||||
|
$this->connector->write("\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,460 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-18 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mike42\Escpos;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class deals with images in raster formats, and converts them into formats
|
||||||
|
* which are suitable for use on thermal receipt printers. Currently, only PNG
|
||||||
|
* images (in) and ESC/POS raster format (out) are implemeted.
|
||||||
|
*
|
||||||
|
* Input formats:
|
||||||
|
* - Currently, only PNG is supported.
|
||||||
|
* - Other easily read raster formats (jpg, gif) will be added at a later date, as this is not complex.
|
||||||
|
* - The BMP format can be directly read by some commands, but this has not yet been implemented.
|
||||||
|
*
|
||||||
|
* Output formats:
|
||||||
|
* - Currently, only ESC/POS raster format is supported
|
||||||
|
* - ESC/POS 'column format' support is partially implemented, but is not yet used by Escpos.php library.
|
||||||
|
* - Output as multiple rows of column format image is not yet in the works.
|
||||||
|
*
|
||||||
|
* Libraries:
|
||||||
|
* - Currently, php-gd is used to read the input. Support for imagemagick where gd is not installed is
|
||||||
|
* also not complex to add, and is a likely future feature.
|
||||||
|
* - Support for native use of the BMP format is a goal, for maximum compatibility with target environments.
|
||||||
|
*/
|
||||||
|
abstract class EscposImage
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int $imgHeight
|
||||||
|
* height of the image.
|
||||||
|
*/
|
||||||
|
protected $imgHeight = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int $imgWidth
|
||||||
|
* width of the image
|
||||||
|
*/
|
||||||
|
protected $imgWidth = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string $imgData
|
||||||
|
* Image data in rows: 1 for black, 0 for white.
|
||||||
|
*/
|
||||||
|
private $imgData = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array:string $imgColumnData
|
||||||
|
* Cached column-format data to avoid re-computation
|
||||||
|
*/
|
||||||
|
private $imgColumnData = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string $imgRasterData
|
||||||
|
* Cached raster format data to avoid re-computation
|
||||||
|
*/
|
||||||
|
private $imgRasterData = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string $filename
|
||||||
|
* Filename of image on disk - null if not loaded from disk.
|
||||||
|
*/
|
||||||
|
private $filename = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var boolean $allowOptimisations
|
||||||
|
* True to allow faster library-specific rendering shortcuts, false to always just use
|
||||||
|
* image libraries to read pixels (more reproducible between systems).
|
||||||
|
*/
|
||||||
|
private $allowOptimisations = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new EscposImage.
|
||||||
|
*
|
||||||
|
* @param string $filename Path to image filename, or null to create an empty image.
|
||||||
|
* @param boolean $allowOptimisations True (default) to use any library-specific tricks
|
||||||
|
* to speed up rendering, false to force the image to be read in pixel-by-pixel,
|
||||||
|
* which is easier to unit test and more reproducible between systems, but slower.
|
||||||
|
*/
|
||||||
|
public function __construct($filename = null, $allowOptimisations = true)
|
||||||
|
{
|
||||||
|
$this -> filename = $filename;
|
||||||
|
$this -> allowOptimisations = $allowOptimisations;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int height of the image in pixels
|
||||||
|
*/
|
||||||
|
public function getHeight()
|
||||||
|
{
|
||||||
|
return $this -> imgHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int Number of bytes to represent a row of this image
|
||||||
|
*/
|
||||||
|
public function getHeightBytes()
|
||||||
|
{
|
||||||
|
return (int)(($this -> imgHeight + 7) / 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int Width of the image
|
||||||
|
*/
|
||||||
|
public function getWidth()
|
||||||
|
{
|
||||||
|
return $this -> imgWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int Number of bytes to represent a row of this image
|
||||||
|
*/
|
||||||
|
public function getWidthBytes()
|
||||||
|
{
|
||||||
|
return (int)(($this -> imgWidth + 7) / 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output the image in raster (row) format. This can result in padding on the
|
||||||
|
* right of the image, if its width is not divisible by 8.
|
||||||
|
*
|
||||||
|
* @throws Exception Where the generated data is unsuitable for the printer
|
||||||
|
* (indicates a bug or oversized image).
|
||||||
|
* @return string The image in raster format.
|
||||||
|
*/
|
||||||
|
public function toRasterFormat()
|
||||||
|
{
|
||||||
|
// Just wraps implementations for caching & lazy loading
|
||||||
|
if ($this -> imgRasterData !== null) {
|
||||||
|
/* Return cached value */
|
||||||
|
return $this -> imgRasterData;
|
||||||
|
}
|
||||||
|
if ($this -> allowOptimisations) {
|
||||||
|
/* Use optimised code if allowed */
|
||||||
|
$this -> imgRasterData = $this -> getRasterFormatFromFile($this -> filename);
|
||||||
|
}
|
||||||
|
if ($this -> imgRasterData === null) {
|
||||||
|
/* Load in full image and render the slow way if no faster implementation
|
||||||
|
is available, or if we've been asked not to use it */
|
||||||
|
if ($this -> imgData === null) {
|
||||||
|
$this -> loadImageData($this -> filename);
|
||||||
|
}
|
||||||
|
$this -> imgRasterData = $this -> getRasterFormat();
|
||||||
|
}
|
||||||
|
return $this -> imgRasterData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output the image in column format.
|
||||||
|
*
|
||||||
|
* @param boolean $doubleDensity True for double density (24px) lines, false for single-density (8px) lines.
|
||||||
|
* @return string[] an array, one item per line of output. All lines will be of equal size.
|
||||||
|
*/
|
||||||
|
public function toColumnFormat($doubleDensity = false)
|
||||||
|
{
|
||||||
|
$densityIdx = $doubleDensity ? 1 : 0;
|
||||||
|
// Just wraps implementations for caching and lazy loading
|
||||||
|
if (isset($this -> imgColumnData[$densityIdx])) {
|
||||||
|
/* Return cached value */
|
||||||
|
return $this -> imgColumnData[$densityIdx];
|
||||||
|
}
|
||||||
|
$this -> imgColumnData[$densityIdx] = null;
|
||||||
|
if ($this -> allowOptimisations) {
|
||||||
|
/* Use optimised code if allowed */
|
||||||
|
$data = $this -> getColumnFormatFromFile($this -> filename, $doubleDensity);
|
||||||
|
$this -> imgColumnData[$densityIdx] = $data;
|
||||||
|
}
|
||||||
|
if ($this -> imgColumnData[$densityIdx] === null) {
|
||||||
|
/* Load in full image and render the slow way if no faster implementation
|
||||||
|
is available, or if we've been asked not to use it */
|
||||||
|
if ($this -> imgData === null) {
|
||||||
|
$this -> loadImageData($this -> filename);
|
||||||
|
}
|
||||||
|
$this -> imgColumnData[$densityIdx] = $this -> getColumnFormat($doubleDensity);
|
||||||
|
}
|
||||||
|
return $this -> imgColumnData[$densityIdx];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load an image from disk. This default implementation always gives a zero-sized image.
|
||||||
|
*
|
||||||
|
* @param string|null $filename Filename to load from.
|
||||||
|
*/
|
||||||
|
protected function loadImageData($filename = null)
|
||||||
|
{
|
||||||
|
// Load image in to string of 1's and 0's, also set width & height
|
||||||
|
$this -> setImgWidth(0);
|
||||||
|
$this -> setImgHeight(0);
|
||||||
|
$this -> setImgData("");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set image data.
|
||||||
|
*
|
||||||
|
* @param string $data Image data to use, string of 1's (black) and 0's (white) in row-major order.
|
||||||
|
*/
|
||||||
|
protected function setImgData($data)
|
||||||
|
{
|
||||||
|
$this -> imgData = $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set image width.
|
||||||
|
*
|
||||||
|
* @param int $width width of the image
|
||||||
|
*/
|
||||||
|
protected function setImgWidth($width)
|
||||||
|
{
|
||||||
|
$this -> imgWidth = $width;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set image height.
|
||||||
|
*
|
||||||
|
* @param int $height height of the image.
|
||||||
|
*/
|
||||||
|
protected function setImgHeight($height)
|
||||||
|
{
|
||||||
|
$this -> imgHeight = $height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $filename
|
||||||
|
* Filename to load from
|
||||||
|
* @return string|NULL
|
||||||
|
* Raster format data, or NULL if no optimised renderer is available in
|
||||||
|
* this implementation.
|
||||||
|
*/
|
||||||
|
protected function getRasterFormatFromFile($filename = null)
|
||||||
|
{
|
||||||
|
// No optimised implementation to provide
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $filename
|
||||||
|
* Filename to load from
|
||||||
|
* @param boolean $highDensityVertical
|
||||||
|
* True for high density output (24px lines), false for regular density (8px)
|
||||||
|
* @return string[]|NULL
|
||||||
|
* Column format data as array, or NULL if optimised renderer isn't
|
||||||
|
* available in this implementation.
|
||||||
|
*/
|
||||||
|
protected function getColumnFormatFromFile($filename = null, $highDensityVertical = true)
|
||||||
|
{
|
||||||
|
// No optimised implementation to provide
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get column fromat from loaded image pixels, line by line.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
* Where wrong number of bytes has been generated.
|
||||||
|
* @return string
|
||||||
|
* Raster format data
|
||||||
|
*/
|
||||||
|
private function getRasterFormat()
|
||||||
|
{
|
||||||
|
/* Loop through and convert format */
|
||||||
|
$widthPixels = $this -> getWidth();
|
||||||
|
$heightPixels = $this -> getHeight();
|
||||||
|
$widthBytes = $this -> getWidthBytes();
|
||||||
|
$heightBytes = $this -> getHeightBytes();
|
||||||
|
$x = $y = $bit = $byte = $byteVal = 0;
|
||||||
|
$data = str_repeat("\0", $widthBytes * $heightPixels);
|
||||||
|
if (strlen($data) == 0) {
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
$byteVal |= (int)$this -> imgData[$y * $widthPixels + $x] << (7 - $bit);
|
||||||
|
$x++;
|
||||||
|
$bit++;
|
||||||
|
if ($x >= $widthPixels) {
|
||||||
|
$x = 0;
|
||||||
|
$y++;
|
||||||
|
$bit = 8;
|
||||||
|
if ($y >= $heightPixels) {
|
||||||
|
$data[$byte] = chr($byteVal);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($bit >= 8) {
|
||||||
|
$data[$byte] = chr($byteVal);
|
||||||
|
$byteVal = 0;
|
||||||
|
$bit = 0;
|
||||||
|
$byte++;
|
||||||
|
}
|
||||||
|
} while (true);
|
||||||
|
if (strlen($data) != ($this -> getWidthBytes() * $this -> getHeight())) {
|
||||||
|
throw new Exception("Bug in " . __FUNCTION__ . ", wrong number of bytes.");
|
||||||
|
}
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get column fromat from loaded image pixels, line by line.
|
||||||
|
*
|
||||||
|
* @param boolean $highDensity
|
||||||
|
* True for high density output (24px lines), false for regular density (8px)
|
||||||
|
* @return string[]
|
||||||
|
* Array of column format data, one item per row.
|
||||||
|
*/
|
||||||
|
private function getColumnFormat($highDensity)
|
||||||
|
{
|
||||||
|
$out = [];
|
||||||
|
$i = 0;
|
||||||
|
while (($line = $this -> getColumnFormatLine($i, $highDensity)) !== null) {
|
||||||
|
$out[] = $line;
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output image in column format. Must be called once for each line of output.
|
||||||
|
*
|
||||||
|
* @param int $lineNo
|
||||||
|
* Line number to retrieve
|
||||||
|
* @param bool $highDensity
|
||||||
|
* True for high density output (24px lines), false for regular density (8px)
|
||||||
|
* @throws Exception
|
||||||
|
* Where wrong number of bytes has been generated.
|
||||||
|
* @return NULL|string
|
||||||
|
* Column format data, or null if there is no more data (when iterating)
|
||||||
|
*/
|
||||||
|
private function getColumnFormatLine($lineNo, $highDensity)
|
||||||
|
{
|
||||||
|
// Currently double density in both directions, very experimental
|
||||||
|
$widthPixels = $this -> getWidth();
|
||||||
|
$heightPixels = $this -> getHeight();
|
||||||
|
$widthBytes = $this -> getWidthBytes();
|
||||||
|
$heightBytes = $this -> getHeightBytes();
|
||||||
|
$lineHeight = $highDensity ? 3 : 1; // Vertical density. 1 or 3 (for 8 and 24 pixel lines)
|
||||||
|
// Initialise to zero
|
||||||
|
$x = $y = $bit = $byte = $byteVal = 0;
|
||||||
|
$data = str_repeat("\x00", $widthPixels * $lineHeight);
|
||||||
|
$yStart = $lineHeight * 8 * $lineNo;
|
||||||
|
if ($yStart >= $heightPixels) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (strlen($data) == 0) {
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
$yReal = $y + $yStart;
|
||||||
|
if ($yReal < $heightPixels) {
|
||||||
|
$byteVal |= (int)$this -> imgData[$yReal * $widthPixels + $x] << (7 - $bit);
|
||||||
|
}
|
||||||
|
$y++;
|
||||||
|
$bit++;
|
||||||
|
if ($y >= $lineHeight * 8) {
|
||||||
|
$y = 0;
|
||||||
|
$x++;
|
||||||
|
$bit = 8;
|
||||||
|
if ($x >= $widthPixels) {
|
||||||
|
$data[$byte] = chr($byteVal);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($bit >= 8) {
|
||||||
|
$data[$byte] = chr($byteVal);
|
||||||
|
$byteVal = 0;
|
||||||
|
$bit = 0;
|
||||||
|
$byte++;
|
||||||
|
}
|
||||||
|
} while (true);
|
||||||
|
if (strlen($data) != $widthPixels * $lineHeight) {
|
||||||
|
throw new Exception("Bug in " . __FUNCTION__ . ", wrong number of bytes.");
|
||||||
|
}
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return boolean True if GD is loaded, false otherwise
|
||||||
|
*/
|
||||||
|
public static function isGdLoaded()
|
||||||
|
{
|
||||||
|
return extension_loaded('gd');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return boolean True if Imagick is loaded, false otherwise
|
||||||
|
*/
|
||||||
|
public static function isImagickLoaded()
|
||||||
|
{
|
||||||
|
return extension_loaded('imagick');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a convinience method to load an image from file, auto-selecting
|
||||||
|
* an EscposImage implementation which uses an available library.
|
||||||
|
*
|
||||||
|
* The sub-classes can be constructed directly if you know that you will
|
||||||
|
* have Imagick or GD on the print server.
|
||||||
|
*
|
||||||
|
* @param string $filename
|
||||||
|
* File to load from
|
||||||
|
* @param bool $allowOptimisations
|
||||||
|
* True to allow the fastest rendering shortcuts, false to force the library
|
||||||
|
* to read the image into an internal raster format and use PHP to render
|
||||||
|
* the image (slower but less fragile).
|
||||||
|
* @param array $preferred
|
||||||
|
* Order to try to load libraries in- escpos-php supports pluggable image
|
||||||
|
* libraries. Items can be 'imagick', 'gd', 'native'.
|
||||||
|
* @throws Exception
|
||||||
|
* Where no suitable library could be found for the type of file being loaded.
|
||||||
|
* @return EscposImage
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static function load(
|
||||||
|
$filename,
|
||||||
|
$allowOptimisations = true,
|
||||||
|
array $preferred = ['imagick', 'gd', 'native']
|
||||||
|
) {
|
||||||
|
/* Fail early if file is not readble */
|
||||||
|
if (!file_exists($filename) || !is_readable($filename)) {
|
||||||
|
throw new Exception("File '$filename' does not exist, or is not readable.");
|
||||||
|
}
|
||||||
|
$ext = pathinfo($filename, PATHINFO_EXTENSION);
|
||||||
|
/* Choose the first implementation which can handle this format */
|
||||||
|
foreach ($preferred as $implemetnation) {
|
||||||
|
if ($implemetnation === 'imagick') {
|
||||||
|
if (!self::isImagickLoaded()) {
|
||||||
|
// Skip option if Imagick is not loaded
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return new \Mike42\Escpos\ImagickEscposImage($filename, $allowOptimisations);
|
||||||
|
} elseif ($implemetnation === 'gd') {
|
||||||
|
if (!self::isGdLoaded()) {
|
||||||
|
// Skip option if GD not loaded
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return new \Mike42\Escpos\GdEscposImage($filename, $allowOptimisations);
|
||||||
|
} elseif ($implemetnation === 'native') {
|
||||||
|
if (!in_array($ext, ['wbmp', 'pbm', 'bmp'])) {
|
||||||
|
// Pure PHP is fastest way to generate raster output from wbmp and pbm formats.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return new \Mike42\Escpos\NativeEscposImage($filename, $allowOptimisations);
|
||||||
|
} else {
|
||||||
|
// Something else on the 'preferred' list.
|
||||||
|
throw new InvalidArgumentException("'$implemetnation' is not a known EscposImage implementation");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new InvalidArgumentException("No suitable EscposImage implementation found for '$filename'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-16 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mike42\Escpos;
|
||||||
|
|
||||||
|
use Mike42\Escpos\EscposImage;
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of EscposImage using the GD PHP plugin.
|
||||||
|
*/
|
||||||
|
class GdEscposImage extends EscposImage
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Load an image from disk, into memory, using GD.
|
||||||
|
*
|
||||||
|
* @param string|null $filename The filename to load from
|
||||||
|
* @throws Exception if the image format is not supported,
|
||||||
|
* or the file cannot be opened.
|
||||||
|
*/
|
||||||
|
protected function loadImageData($filename = null)
|
||||||
|
{
|
||||||
|
if ($filename === null) {
|
||||||
|
/* Set to blank image */
|
||||||
|
return parent::loadImageData($filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ext = pathinfo($filename, PATHINFO_EXTENSION);
|
||||||
|
switch ($ext) {
|
||||||
|
case "png":
|
||||||
|
$im = @imagecreatefrompng($filename);
|
||||||
|
break;
|
||||||
|
case "jpg":
|
||||||
|
$im = @imagecreatefromjpeg($filename);
|
||||||
|
break;
|
||||||
|
case "gif":
|
||||||
|
$im = @imagecreatefromgif($filename);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception("Image format not supported in GD");
|
||||||
|
}
|
||||||
|
$this -> readImageFromGdResource($im);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load actual image pixels from GD resource.
|
||||||
|
*
|
||||||
|
* @param resource $im GD resource to use
|
||||||
|
* @throws Exception Where the image can't be read.
|
||||||
|
*/
|
||||||
|
public function readImageFromGdResource($im)
|
||||||
|
{
|
||||||
|
if (!is_resource($im)) {
|
||||||
|
throw new Exception("Failed to load image.");
|
||||||
|
} elseif (!EscposImage::isGdLoaded()) {
|
||||||
|
throw new Exception(__FUNCTION__ . " requires 'gd' extension.");
|
||||||
|
}
|
||||||
|
/* Make a string of 1's and 0's */
|
||||||
|
$imgHeight = imagesy($im);
|
||||||
|
$imgWidth = imagesx($im);
|
||||||
|
$imgData = str_repeat("\0", $imgHeight * $imgWidth);
|
||||||
|
for ($y = 0; $y < $imgHeight; $y++) {
|
||||||
|
for ($x = 0; $x < $imgWidth; $x++) {
|
||||||
|
/* Faster to average channels, blend alpha and negate the image here than via filters (tested!) */
|
||||||
|
$cols = imagecolorsforindex($im, imagecolorat($im, $x, $y));
|
||||||
|
// 1 for white, 0 for black, ignoring transparency
|
||||||
|
$greyness = (int)(($cols['red'] + $cols['green'] + $cols['blue']) / 3) >> 7;
|
||||||
|
// 1 for black, 0 for white, taking into account transparency
|
||||||
|
$black = (1 - $greyness) >> ($cols['alpha'] >> 6);
|
||||||
|
$imgData[$y * $imgWidth + $x] = $black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this -> setImgWidth($imgWidth);
|
||||||
|
$this -> setImgHeight($imgHeight);
|
||||||
|
$this -> setImgData($imgData);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,273 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-18 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mike42\Escpos;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Imagick;
|
||||||
|
use Mike42\Escpos\EscposImage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of EscposImage using the Imagick PHP plugin.
|
||||||
|
*/
|
||||||
|
class ImagickEscposImage extends EscposImage
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Load actual image pixels from Imagick object
|
||||||
|
*
|
||||||
|
* @param Imagick $im Image to load from
|
||||||
|
*/
|
||||||
|
public function readImageFromImagick(\Imagick $im)
|
||||||
|
{
|
||||||
|
/* Strip transparency */
|
||||||
|
$im = self::alphaRemove($im);
|
||||||
|
/* Threshold */
|
||||||
|
$im -> setImageType(\Imagick::IMGTYPE_TRUECOLOR); // Remove transparency (good for PDF's)
|
||||||
|
$max = $im->getQuantumRange();
|
||||||
|
$max = $max["quantumRangeLong"];
|
||||||
|
$im -> thresholdImage(0.5 * $max);
|
||||||
|
/* Make a string of 1's and 0's */
|
||||||
|
$imgHeight = $im -> getimageheight();
|
||||||
|
$imgWidth = $im -> getimagewidth();
|
||||||
|
$imgData = str_repeat("\0", $imgHeight * $imgWidth);
|
||||||
|
for ($y = 0; $y < $imgHeight; $y++) {
|
||||||
|
for ($x = 0; $x < $imgWidth; $x++) {
|
||||||
|
/* Faster to average channels, blend alpha and negate the image here than via filters (tested!) */
|
||||||
|
$cols = $im -> getImagePixelColor($x, $y);
|
||||||
|
$cols = $cols -> getcolor();
|
||||||
|
$greyness = (int)(($cols['r'] + $cols['g'] + $cols['b']) / 3) >> 7; // 1 for white, 0 for black
|
||||||
|
$imgData[$y * $imgWidth + $x] = (1 - $greyness); // 1 for black, 0 for white
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this -> setImgWidth($imgWidth);
|
||||||
|
$this -> setImgHeight($imgHeight);
|
||||||
|
$this -> setImgData($imgData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $filename
|
||||||
|
* Filename to load from
|
||||||
|
* @param boolean $highDensityVertical
|
||||||
|
* True for high density output (24px lines), false for regular density (8px)
|
||||||
|
* @return string[]|NULL
|
||||||
|
* Column format data as array, or NULL if optimised renderer isn't
|
||||||
|
* available in this implementation.
|
||||||
|
*/
|
||||||
|
protected function getColumnFormatFromFile($filename = null, $highDensityVertical = true)
|
||||||
|
{
|
||||||
|
if ($filename === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$im = $this -> getImageFromFile($filename);
|
||||||
|
$this -> setImgWidth($im -> getimagewidth());
|
||||||
|
$this -> setImgHeight($im -> getimageheight());
|
||||||
|
|
||||||
|
/* Strip transparency */
|
||||||
|
$im = self::alphaRemove($im);
|
||||||
|
$im -> setformat('pbm');
|
||||||
|
$im -> getimageblob(); // Forces 1-bit rendering now, so that subsequent operations are faster
|
||||||
|
$im -> rotateImage('#fff', 90.0);
|
||||||
|
$im -> flopImage();
|
||||||
|
$lineHeight = $highDensityVertical ? 3 : 1;
|
||||||
|
$blobs = $this -> getColumnFormatFromImage($im, $lineHeight * 8);
|
||||||
|
return $blobs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load an image from disk, into memory, using Imagick.
|
||||||
|
*
|
||||||
|
* @param string|null $filename The filename to load from
|
||||||
|
* @throws Exception if the image format is not supported,
|
||||||
|
* or the file cannot be opened.
|
||||||
|
*/
|
||||||
|
protected function loadImageData($filename = null)
|
||||||
|
{
|
||||||
|
if ($filename === null) {
|
||||||
|
/* Set to blank image */
|
||||||
|
return parent::loadImageData($filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
$im = $this -> getImageFromFile($filename);
|
||||||
|
$this -> readImageFromImagick($im);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return data in column format as array of slices.
|
||||||
|
* Operates recursively to save cloning larger image many times.
|
||||||
|
*
|
||||||
|
* @param Imagick $im
|
||||||
|
* @param int $lineHeight
|
||||||
|
* Height of printed line in dots. 8 or 24.
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
private function getColumnFormatFromImage(Imagick $im, $lineHeight)
|
||||||
|
{
|
||||||
|
$imgWidth = $im->getimagewidth();
|
||||||
|
if ($imgWidth == $lineHeight) {
|
||||||
|
// Return glob of this panel
|
||||||
|
return [$this -> getRasterBlobFromImage($im)];
|
||||||
|
} elseif ($imgWidth > $lineHeight) {
|
||||||
|
// Calculations
|
||||||
|
$slicesLeft = ceil($imgWidth / $lineHeight / 2);
|
||||||
|
$widthLeft = $slicesLeft * $lineHeight;
|
||||||
|
$widthRight = $imgWidth - $widthLeft;
|
||||||
|
// Slice up (left)
|
||||||
|
$left = clone $im;
|
||||||
|
$left -> extentimage($widthLeft, $left -> getimageheight(), 0, 0);
|
||||||
|
// Slice up (right - ensure width is divisible by lineHeight also)
|
||||||
|
$right = clone $im;
|
||||||
|
$widthRightRounded = $widthRight < $lineHeight ? $lineHeight : $widthRight;
|
||||||
|
$right -> extentimage($widthRightRounded, $right -> getimageheight(), $widthLeft, 0);
|
||||||
|
// Recurse
|
||||||
|
$leftBlobs = $this -> getColumnFormatFromImage($left, $lineHeight);
|
||||||
|
$rightBlobs = $this -> getColumnFormatFromImage($right, $lineHeight);
|
||||||
|
return array_merge($leftBlobs, $rightBlobs);
|
||||||
|
} else {
|
||||||
|
/* Image is smaller than full width */
|
||||||
|
$im -> extentimage($lineHeight, $im -> getimageheight(), 0, 0);
|
||||||
|
return [$this -> getRasterBlobFromImage($im)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load Imagick file from image
|
||||||
|
*
|
||||||
|
* @param string $filename Filename to load
|
||||||
|
* @throws Exception Wrapped Imagick error if image can't be loaded
|
||||||
|
* @return Imagick Loaded image
|
||||||
|
*/
|
||||||
|
private function getImageFromFile($filename)
|
||||||
|
{
|
||||||
|
$im = new Imagick();
|
||||||
|
try {
|
||||||
|
$im->setResourceLimit(6, 1); // Prevent libgomp1 segfaults, grumble grumble.
|
||||||
|
$im -> readimage($filename);
|
||||||
|
} catch (\ImagickException $e) {
|
||||||
|
/* Re-throw as normal exception */
|
||||||
|
throw new Exception($e);
|
||||||
|
}
|
||||||
|
return $im;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pull blob (from PBM-formatted image only!), and spit out a blob or raster data.
|
||||||
|
* Will crash out on anything which is not a valid 'P4' file.
|
||||||
|
*
|
||||||
|
* @param Imagick $im Image which has format PBM.
|
||||||
|
* @return string raster data from the image
|
||||||
|
*/
|
||||||
|
private function getRasterBlobFromImage(Imagick $im)
|
||||||
|
{
|
||||||
|
$blob = $im -> getimageblob();
|
||||||
|
/* Find where header ends */
|
||||||
|
$i = strpos($blob, "P4\n") + 2;
|
||||||
|
while ($blob[$i + 1] == '#') {
|
||||||
|
$i = strpos($blob, "\n", $i + 1);
|
||||||
|
}
|
||||||
|
$i = strpos($blob, "\n", $i + 1);
|
||||||
|
/* Return raster data only */
|
||||||
|
$subBlob = substr($blob, $i + 1);
|
||||||
|
return $subBlob;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $filename
|
||||||
|
* Filename to load from
|
||||||
|
* @return string|NULL
|
||||||
|
* Raster format data, or NULL if no optimised renderer is available in
|
||||||
|
* this implementation.
|
||||||
|
*/
|
||||||
|
protected function getRasterFormatFromFile($filename = null)
|
||||||
|
{
|
||||||
|
if ($filename === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$im = $this -> getImageFromFile($filename);
|
||||||
|
$this -> setImgWidth($im -> getimagewidth());
|
||||||
|
$this -> setImgHeight($im -> getimageheight());
|
||||||
|
/* Convert to PBM and extract raster portion */
|
||||||
|
$im = self::alphaRemove($im);
|
||||||
|
$im -> setFormat('pbm');
|
||||||
|
return $this -> getRasterBlobFromImage($im);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a PDF for use on the printer
|
||||||
|
*
|
||||||
|
* @param string $pdfFile
|
||||||
|
* The file to load
|
||||||
|
* @param int $pageWidth
|
||||||
|
* The width, in pixels, of the printer's output. The first page of the
|
||||||
|
* PDF will be scaled to approximately fit in this area.
|
||||||
|
* @throws Exception Where Imagick is not loaded, or where a missing file
|
||||||
|
* or invalid page number is requested.
|
||||||
|
* @return array Array of images, retrieved from the PDF file.
|
||||||
|
*/
|
||||||
|
public static function loadPdf($pdfFile, $pageWidth = 550)
|
||||||
|
{
|
||||||
|
if (!EscposImage::isImagickLoaded()) {
|
||||||
|
throw new Exception(__FUNCTION__ . " requires imagick extension.");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Load first page at very low density (resolution), to figure out what
|
||||||
|
* density to use to achieve $pageWidth
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
$image = new \Imagick();
|
||||||
|
$testRes = 2; // Test resolution
|
||||||
|
$image -> setresolution($testRes, $testRes);
|
||||||
|
/* Load document just to measure geometry */
|
||||||
|
$image -> readimage($pdfFile);
|
||||||
|
$geo = $image -> getimagegeometry();
|
||||||
|
$image -> destroy();
|
||||||
|
$width = $geo['width'];
|
||||||
|
$newRes = $pageWidth / $width * $testRes;
|
||||||
|
/* Load entire document in */
|
||||||
|
$image -> setresolution($newRes, $newRes);
|
||||||
|
$image -> readImage($pdfFile);
|
||||||
|
$pages = $image -> getNumberImages();
|
||||||
|
/* Convert images to Escpos objects */
|
||||||
|
$ret = [];
|
||||||
|
for ($i = 0; $i < $pages; $i++) {
|
||||||
|
$image -> setIteratorIndex($i);
|
||||||
|
$ep = new ImagickEscposImage();
|
||||||
|
$ep -> readImageFromImagick($image);
|
||||||
|
$ret[] = $ep;
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
} catch (\ImagickException $e) {
|
||||||
|
/* Wrap in normal exception, so that classes which call this do not
|
||||||
|
* themselves require imagick as a dependency. */
|
||||||
|
throw new Exception($e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paste image over white canvas to stip transparency reliably on different
|
||||||
|
* versions of ImageMagick.
|
||||||
|
*
|
||||||
|
* There are other methods for this:
|
||||||
|
* - flattenImages() is deprecated
|
||||||
|
* - setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE) is not available on
|
||||||
|
* ImageMagick < 6.8.
|
||||||
|
*
|
||||||
|
* @param Imagick $im Image to flatten
|
||||||
|
* @return Imagick Flattened image
|
||||||
|
*/
|
||||||
|
private static function alphaRemove(Imagick $im)
|
||||||
|
{
|
||||||
|
$flat = new \Imagick();
|
||||||
|
$flat -> newImage($im -> getimagewidth(), $im -> getimageheight(), "white", $im -> getimageformat());
|
||||||
|
$flat -> compositeimage($im, \Imagick::COMPOSITE_OVER, 0, 0);
|
||||||
|
return $flat;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-18 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mike42\Escpos;
|
||||||
|
|
||||||
|
use Mike42\Escpos\EscposImage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of EscposImage using only native PHP.
|
||||||
|
* TODO: wbmp, pbm, bmp files.
|
||||||
|
*/
|
||||||
|
class NativeEscposImage extends EscposImage
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,300 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-16 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mike42\Escpos\PrintBuffers;
|
||||||
|
|
||||||
|
use LogicException;
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class manages newlines and character encoding for the target printer, and
|
||||||
|
* can be interchanged for an image-bassed buffer (ImagePrintBuffer) if you can't
|
||||||
|
* get it operating properly on your machine.
|
||||||
|
*/
|
||||||
|
class EscposPrintBuffer implements PrintBuffer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* True to cache output as .z, false to leave un-compressed (useful for debugging)
|
||||||
|
*/
|
||||||
|
const COMPRESS_CACHE = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The input encoding of the buffer.
|
||||||
|
*/
|
||||||
|
const INPUT_ENCODING = "UTF-8";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Un-recognised characters will be replaced with this.
|
||||||
|
*/
|
||||||
|
const REPLACEMENT_CHAR = "?";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array $available
|
||||||
|
* This array Maps ESC/POS character tables to names iconv encodings
|
||||||
|
*/
|
||||||
|
private $available = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array $encode
|
||||||
|
* Maps of UTF-8 to code-pages
|
||||||
|
*/
|
||||||
|
private $encode = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Printer|null $printer
|
||||||
|
* Printer for output
|
||||||
|
*/
|
||||||
|
private $printer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty print buffer.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this -> printer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function flush()
|
||||||
|
{
|
||||||
|
if ($this -> printer == null) {
|
||||||
|
throw new LogicException("Not attached to a printer.");
|
||||||
|
}
|
||||||
|
// TODO Not yet implemented for this buffer: This indicates that the printer needs the current line to be ended.
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPrinter()
|
||||||
|
{
|
||||||
|
return $this -> printer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPrinter(Printer $printer = null)
|
||||||
|
{
|
||||||
|
$this -> printer = $printer;
|
||||||
|
if ($printer != null) {
|
||||||
|
$this -> loadAvailableCharacters();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function writeText($text)
|
||||||
|
{
|
||||||
|
if ($this -> printer == null) {
|
||||||
|
throw new LogicException("Not attached to a printer.");
|
||||||
|
}
|
||||||
|
if ($text == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!mb_detect_encoding($text, self::INPUT_ENCODING, true)) {
|
||||||
|
// Assume that the user has already put non-UTF8 into the target encoding.
|
||||||
|
return $this -> writeTextRaw($text);
|
||||||
|
}
|
||||||
|
$i = 0;
|
||||||
|
$j = 0;
|
||||||
|
$len = mb_strlen($text, self::INPUT_ENCODING);
|
||||||
|
while ($i < $len) {
|
||||||
|
$matching = true;
|
||||||
|
if (($encoding = $this -> identifyText(mb_substr($text, $i, 1, self::INPUT_ENCODING))) === false) {
|
||||||
|
// Un-encodeable text
|
||||||
|
$encoding = $this -> getPrinter() -> getCharacterTable();
|
||||||
|
}
|
||||||
|
$i++;
|
||||||
|
$j = 1;
|
||||||
|
do {
|
||||||
|
$char = mb_substr($text, $i, 1, self::INPUT_ENCODING);
|
||||||
|
$matching = !isset($this -> available[$char]) || isset($this -> available[$char][$encoding]);
|
||||||
|
if ($matching) {
|
||||||
|
$i++;
|
||||||
|
$j++;
|
||||||
|
}
|
||||||
|
} while ($matching && $i < $len);
|
||||||
|
$this -> writeTextUsingEncoding(mb_substr($text, $i - $j, $j, self::INPUT_ENCODING), $encoding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function writeTextRaw($text)
|
||||||
|
{
|
||||||
|
if ($this -> printer == null) {
|
||||||
|
throw new LogicException("Not attached to a printer.");
|
||||||
|
}
|
||||||
|
if (strlen($text) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Pass only printable characters
|
||||||
|
$j = 0;
|
||||||
|
$l = strlen($text);
|
||||||
|
$outp = str_repeat(self::REPLACEMENT_CHAR, $l);
|
||||||
|
for ($i = 0; $i < $l; $i++) {
|
||||||
|
$c = substr($text, $i, 1);
|
||||||
|
if ($c == "\r") {
|
||||||
|
/* Skip past Windows line endings (raw usage). */
|
||||||
|
continue;
|
||||||
|
} else if (self::asciiCheck($c, true)) {
|
||||||
|
$outp[$j] = $c;
|
||||||
|
}
|
||||||
|
$j++;
|
||||||
|
}
|
||||||
|
$this -> write(substr($outp, 0, $j));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an encoding which we can start to use for outputting this text.
|
||||||
|
* Later parts of the text need not be included in the returned code page.
|
||||||
|
*
|
||||||
|
* @param string $text Input text to check.
|
||||||
|
* @return boolean|integer Code page number, or FALSE if the text is not
|
||||||
|
* printable on any supported encoding.
|
||||||
|
*/
|
||||||
|
private function identifyText($text)
|
||||||
|
{
|
||||||
|
// TODO Replace this with an algorithm to choose the encoding which will
|
||||||
|
// encode the farthest into the string, to minimise code page changes.
|
||||||
|
$char = mb_substr($text, 0, 1, self::INPUT_ENCODING);
|
||||||
|
if (!isset($this -> available[$char])) {
|
||||||
|
/* Character not available anywhere */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
foreach ($this -> available[$char] as $encodingNo => $true) {
|
||||||
|
/* Return first code-page where it is available */
|
||||||
|
return $encodingNo;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Based on the printer's connector, compute (or load a cached copy of) maps
|
||||||
|
* of UTF character to unicode characters for later use.
|
||||||
|
*/
|
||||||
|
private function loadAvailableCharacters()
|
||||||
|
{
|
||||||
|
$profile = $this -> printer -> getPrinterCapabilityProfile();
|
||||||
|
$supportedCodePages = $profile -> getCodePages();
|
||||||
|
$profileName = $profile -> getId();
|
||||||
|
$cacheFile = dirname(__FILE__) . "/cache/Characters-" . $profileName . ".ser" .
|
||||||
|
(self::COMPRESS_CACHE ? ".z" : "");
|
||||||
|
$cacheKey = $profile -> getCodePageCacheKey();
|
||||||
|
/* Check for pre-generated file */
|
||||||
|
if (file_exists($cacheFile)) {
|
||||||
|
$cacheData = file_get_contents($cacheFile);
|
||||||
|
if (self::COMPRESS_CACHE) {
|
||||||
|
$cacheData = gzuncompress($cacheData);
|
||||||
|
}
|
||||||
|
if ($cacheData) {
|
||||||
|
$dataArray = unserialize($cacheData);
|
||||||
|
if (isset($dataArray["key"]) && isset($dataArray["available"]) &&
|
||||||
|
isset($dataArray["encode"]) && $dataArray["key"] == $cacheKey) {
|
||||||
|
$this -> available = $dataArray["available"];
|
||||||
|
$this -> encode = $dataArray["encode"];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate conversion tables */
|
||||||
|
$encode = [];
|
||||||
|
$available = [];
|
||||||
|
|
||||||
|
foreach ($supportedCodePages as $num => $codePage) {
|
||||||
|
$encode[$num] = [];
|
||||||
|
if (!$codePage -> isEncodable()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$map = $codePage -> getData();
|
||||||
|
for ($char = 128; $char <= 255; $char++) {
|
||||||
|
$utf8 = mb_substr($map, $char - 128, 1, self::INPUT_ENCODING);
|
||||||
|
if ($utf8 == " ") { // Skip placeholders
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!isset($available[$utf8])) {
|
||||||
|
$available[$utf8] = [];
|
||||||
|
}
|
||||||
|
$available[$utf8][$num] = true;
|
||||||
|
$encode[$num][$utf8] = chr($char);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use generated data */
|
||||||
|
$dataArray = ["available" => $available, "encode" => $encode, "key" => $cacheKey];
|
||||||
|
$this -> available = $dataArray["available"];
|
||||||
|
$this -> encode = $dataArray["encode"];
|
||||||
|
$cacheData = serialize($dataArray);
|
||||||
|
if (self::COMPRESS_CACHE) {
|
||||||
|
$cacheData = gzcompress($cacheData);
|
||||||
|
}
|
||||||
|
/* Attempt to cache, but don't worry if we can't */
|
||||||
|
@file_put_contents($cacheFile, $cacheData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a block of text using the specified map, and write it to the printer.
|
||||||
|
*
|
||||||
|
* @param string $text Text to print, UTF-8 format.
|
||||||
|
* @param integer $encodingNo Encoding number to use- assumed to exist.
|
||||||
|
*/
|
||||||
|
private function writeTextUsingEncoding($text, $encodingNo)
|
||||||
|
{
|
||||||
|
$encodeMap = $this -> encode[$encodingNo];
|
||||||
|
$len = mb_strlen($text, self::INPUT_ENCODING);
|
||||||
|
$rawText = str_repeat(self::REPLACEMENT_CHAR, $len);
|
||||||
|
$j = 0;
|
||||||
|
for ($i = 0; $i < $len; $i++) {
|
||||||
|
$char = mb_substr($text, $i, 1, self::INPUT_ENCODING);
|
||||||
|
if (isset($encodeMap[$char])) {
|
||||||
|
$rawText[$j] = $encodeMap[$char];
|
||||||
|
} elseif (self::asciiCheck($char)) {
|
||||||
|
$rawText[$j] = $char;
|
||||||
|
} elseif ($char === "\r") {
|
||||||
|
/* Skip past Windows line endings (UTF-8 usage) */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$j++;
|
||||||
|
}
|
||||||
|
if ($this -> printer -> getCharacterTable() != $encodingNo) {
|
||||||
|
$this -> printer -> selectCharacterTable($encodingNo);
|
||||||
|
}
|
||||||
|
$this -> writeTextRaw(substr($rawText, 0, $j));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write data to the underlying printer.
|
||||||
|
*
|
||||||
|
* @param string $data
|
||||||
|
*/
|
||||||
|
private function write($data)
|
||||||
|
{
|
||||||
|
$this -> printer -> getPrintConnector() -> write($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if a character is an ASCII printable character.
|
||||||
|
*
|
||||||
|
* @param string $char Character to check
|
||||||
|
* @param boolean $extended True to allow 128-256 values also (excluded by default)
|
||||||
|
* @return boolean True if the character is printable, false if it is not.
|
||||||
|
*/
|
||||||
|
private static function asciiCheck($char, $extended = false)
|
||||||
|
{
|
||||||
|
if (strlen($char) != 1) {
|
||||||
|
// Multi-byte string
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$num = ord($char);
|
||||||
|
if ($num > 31 && $num < 127) { // Printable
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ($num == 10) { // New-line (printer will take these)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ($extended && $num > 127) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-16 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mike42\Escpos\PrintBuffers;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use LogicException;
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
use Mike42\Escpos\EscposImage;
|
||||||
|
use Mike42\Escpos\ImagickEscposImage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class renders text to small images on-the-fly. It attempts to mimic the
|
||||||
|
* behaviour of text output, whilst supporting any fonts & character encodings
|
||||||
|
* which your system can handle. This class currently requires Imagick.
|
||||||
|
*/
|
||||||
|
class ImagePrintBuffer implements PrintBuffer
|
||||||
|
{
|
||||||
|
private $printer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string|null font to use
|
||||||
|
*/
|
||||||
|
private $font;
|
||||||
|
|
||||||
|
private $fontSize;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
if (!EscposImage::isImagickLoaded()) {
|
||||||
|
throw new Exception("ImagePrintBuffer requires the imagick extension");
|
||||||
|
}
|
||||||
|
$this -> font = null;
|
||||||
|
$this -> fontSize = 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function flush()
|
||||||
|
{
|
||||||
|
if ($this -> printer == null) {
|
||||||
|
throw new LogicException("Not attached to a printer.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPrinter()
|
||||||
|
{
|
||||||
|
return $this -> printer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPrinter(Printer $printer = null)
|
||||||
|
{
|
||||||
|
$this -> printer = $printer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function writeText($text)
|
||||||
|
{
|
||||||
|
if ($this -> printer == null) {
|
||||||
|
throw new LogicException("Not attached to a printer.");
|
||||||
|
}
|
||||||
|
if ($text == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$text = trim($text, "\n");
|
||||||
|
/* Create Imagick objects */
|
||||||
|
$image = new \Imagick();
|
||||||
|
$draw = new \ImagickDraw();
|
||||||
|
$color = new \ImagickPixel('#000000');
|
||||||
|
$background = new \ImagickPixel('white');
|
||||||
|
|
||||||
|
/* Create annotation */
|
||||||
|
if ($this->font !== null) {
|
||||||
|
// Allow fallback on defaults as necessary
|
||||||
|
$draw->setFont($this->font);
|
||||||
|
}
|
||||||
|
/* In Arial, size 21 looks good as a substitute for FONT_B, 24 for FONT_A */
|
||||||
|
$draw -> setFontSize($this -> fontSize);
|
||||||
|
$draw -> setFillColor($color);
|
||||||
|
$draw -> setStrokeAntialias(true);
|
||||||
|
$draw -> setTextAntialias(true);
|
||||||
|
$metrics = $image -> queryFontMetrics($draw, $text);
|
||||||
|
$draw -> annotation(0, $metrics['ascender'], $text);
|
||||||
|
|
||||||
|
/* Create image & draw annotation on it */
|
||||||
|
$image -> newImage($metrics['textWidth'], $metrics['textHeight'], $background);
|
||||||
|
$image -> setImageFormat('png');
|
||||||
|
$image -> drawImage($draw);
|
||||||
|
// debugging if you want to view the images yourself
|
||||||
|
//$image -> writeImage("test.png");
|
||||||
|
|
||||||
|
/* Save image */
|
||||||
|
$escposImage = new ImagickEscposImage();
|
||||||
|
$escposImage -> readImageFromImagick($image);
|
||||||
|
$size = Printer::IMG_DEFAULT;
|
||||||
|
$this -> printer -> bitImage($escposImage, $size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function writeTextRaw($text)
|
||||||
|
{
|
||||||
|
if ($this -> printer == null) {
|
||||||
|
throw new LogicException("Not attached to a printer.");
|
||||||
|
}
|
||||||
|
$this -> printer -> getPrintConnector() -> write($text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set path on disk to TTF font that will be used to render text to image,
|
||||||
|
* or 'null' to use a default.
|
||||||
|
*
|
||||||
|
* ImageMagick will also accept a font name, but this will not port as well
|
||||||
|
* between systems.
|
||||||
|
*
|
||||||
|
* @param string $font
|
||||||
|
* Font name or a filename
|
||||||
|
*/
|
||||||
|
public function setFont($font)
|
||||||
|
{
|
||||||
|
$this->font = $font;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Numeric font size for rendering text to image
|
||||||
|
*/
|
||||||
|
public function setFontSize($fontSize)
|
||||||
|
{
|
||||||
|
$this->fontSize = $fontSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-16 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mike42\Escpos\PrintBuffers;
|
||||||
|
|
||||||
|
use Mike42\Escpos\Printer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print buffers manage newlines and character encoding for the target printer.
|
||||||
|
* They are used as a swappable component: text or image-based output.
|
||||||
|
*
|
||||||
|
* - Text output (EscposPrintBuffer) is the fast default, and is recommended for
|
||||||
|
* most people, as the text output can be more directly manipulated by ESC/POS
|
||||||
|
* commands.
|
||||||
|
* - Image output (ImagePrintBuffer) is designed to accept more encodings than the
|
||||||
|
* physical printer supports, by rendering the text to small images on-the-fly.
|
||||||
|
* This takes a lot more CPU than sending text, but is necessary for some users.
|
||||||
|
* - If your use case fits outside these, then a further speed/flexibility trade-off
|
||||||
|
* can be made by printing directly from generated HTML or PDF.
|
||||||
|
*/
|
||||||
|
interface PrintBuffer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Cause the buffer to send any partial input and wait on a newline.
|
||||||
|
* If the printer is already on a new line, this does nothing.
|
||||||
|
*/
|
||||||
|
public function flush();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by Escpos to check if a printer is set.
|
||||||
|
*/
|
||||||
|
public function getPrinter();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by Escpos to hook up one-to-one link between buffers and printers.
|
||||||
|
*
|
||||||
|
* @param Printer|null $printer New printer
|
||||||
|
*/
|
||||||
|
public function setPrinter(Printer $printer = null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accept UTF-8 text for printing.
|
||||||
|
*
|
||||||
|
* @param string $text Text to print
|
||||||
|
*/
|
||||||
|
public function writeText($text);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accept 8-bit text in the current encoding and add it to the buffer.
|
||||||
|
*
|
||||||
|
* @param string $text Text to print, already the target encoding.
|
||||||
|
*/
|
||||||
|
public function writeTextRaw($text);
|
||||||
|
}
|
||||||
BIN
htdocs/includes/mike42/escpos-php/src/Mike42/Escpos/PrintBuffers/cache/Characters-OCD-300.ser.z
vendored
Normal file
BIN
htdocs/includes/mike42/escpos-php/src/Mike42/Escpos/PrintBuffers/cache/Characters-OCD-300.ser.z
vendored
Normal file
Binary file not shown.
BIN
htdocs/includes/mike42/escpos-php/src/Mike42/Escpos/PrintBuffers/cache/Characters-P822D.ser.z
vendored
Normal file
BIN
htdocs/includes/mike42/escpos-php/src/Mike42/Escpos/PrintBuffers/cache/Characters-P822D.ser.z
vendored
Normal file
Binary file not shown.
BIN
htdocs/includes/mike42/escpos-php/src/Mike42/Escpos/PrintBuffers/cache/Characters-POS-5890.ser.z
vendored
Normal file
BIN
htdocs/includes/mike42/escpos-php/src/Mike42/Escpos/PrintBuffers/cache/Characters-POS-5890.ser.z
vendored
Normal file
Binary file not shown.
BIN
htdocs/includes/mike42/escpos-php/src/Mike42/Escpos/PrintBuffers/cache/Characters-SP2000.ser.z
vendored
Normal file
BIN
htdocs/includes/mike42/escpos-php/src/Mike42/Escpos/PrintBuffers/cache/Characters-SP2000.ser.z
vendored
Normal file
Binary file not shown.
BIN
htdocs/includes/mike42/escpos-php/src/Mike42/Escpos/PrintBuffers/cache/Characters-TEP-200M.ser.z
vendored
Normal file
BIN
htdocs/includes/mike42/escpos-php/src/Mike42/Escpos/PrintBuffers/cache/Characters-TEP-200M.ser.z
vendored
Normal file
Binary file not shown.
BIN
htdocs/includes/mike42/escpos-php/src/Mike42/Escpos/PrintBuffers/cache/Characters-default.ser.z
vendored
Normal file
BIN
htdocs/includes/mike42/escpos-php/src/Mike42/Escpos/PrintBuffers/cache/Characters-default.ser.z
vendored
Normal file
Binary file not shown.
BIN
htdocs/includes/mike42/escpos-php/src/Mike42/Escpos/PrintBuffers/cache/Characters-simple.ser.z
vendored
Normal file
BIN
htdocs/includes/mike42/escpos-php/src/Mike42/Escpos/PrintBuffers/cache/Characters-simple.ser.z
vendored
Normal file
Binary file not shown.
@@ -0,0 +1,102 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Mike42\Escpos\PrintConnectors;
|
||||||
|
|
||||||
|
use Guzzle\Http\Client;
|
||||||
|
use Guzzle\Http\Message\Request;
|
||||||
|
use Guzzle\Http\Message\Response;
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class ApiPrintConnector implements PrintConnector
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $stream;
|
||||||
|
/**
|
||||||
|
* @var Client
|
||||||
|
*/
|
||||||
|
protected $httpClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $printerId;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $apiToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct new connector
|
||||||
|
*
|
||||||
|
* @param string $host
|
||||||
|
* @param string $printerId
|
||||||
|
* @param string $apiToken
|
||||||
|
*/
|
||||||
|
public function __construct($host, $printerId, $apiToken)
|
||||||
|
{
|
||||||
|
$this->httpClient = new Client(['base_uri' => $host]);
|
||||||
|
$this->printerId = $printerId;
|
||||||
|
$this->apiToken = $apiToken;
|
||||||
|
|
||||||
|
$this->stream = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print connectors should cause a NOTICE if they are deconstructed
|
||||||
|
* when they have not been finalized.
|
||||||
|
*/
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
if (! empty($this->stream)) {
|
||||||
|
trigger_error("Print connector was not finalized. Did you forget to close the printer?", E_USER_NOTICE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finish using this print connector (close file, socket, send
|
||||||
|
* accumulated output, etc).
|
||||||
|
*/
|
||||||
|
public function finalize()
|
||||||
|
{
|
||||||
|
/** @var Request $request */
|
||||||
|
$request = $this->httpClient->post(
|
||||||
|
'printers/'.$this->printerId.'/print?api_token='.$this->apiToken,
|
||||||
|
null,
|
||||||
|
$this->stream
|
||||||
|
);
|
||||||
|
|
||||||
|
/** @var Response $response */
|
||||||
|
$response = $request->send();
|
||||||
|
|
||||||
|
if (! $response->isSuccessful()) {
|
||||||
|
throw new Exception(
|
||||||
|
sprintf('Failed to print. API returned "%s: %s"', $response->getStatusCode(), $response->getReasonPhrase())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->stream = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read data from the printer.
|
||||||
|
*
|
||||||
|
* @param string $len Length of data to read.
|
||||||
|
* @return string Data read from the printer.
|
||||||
|
*/
|
||||||
|
public function read($len)
|
||||||
|
{
|
||||||
|
return $this->stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write data to the print connector.
|
||||||
|
*
|
||||||
|
* @param string $data The data to write
|
||||||
|
*/
|
||||||
|
public function write($data)
|
||||||
|
{
|
||||||
|
$this->stream .= $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,182 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-18 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mike42\Escpos\PrintConnectors;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use BadMethodCallException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print connector that passes print data to CUPS print commands.
|
||||||
|
* Your printer mut be installed on the local CUPS instance to use this connector.
|
||||||
|
*/
|
||||||
|
class CupsPrintConnector implements PrintConnector
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array $buffer
|
||||||
|
* Buffer of accumilated data.
|
||||||
|
*/
|
||||||
|
private $buffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var string $printerName
|
||||||
|
* The name of the target printer.
|
||||||
|
*/
|
||||||
|
private $printerName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct new CUPS print connector.
|
||||||
|
*
|
||||||
|
* @param string $dest
|
||||||
|
* The CUPS printer name to print to. This must be loaded using a raw driver.
|
||||||
|
* @throws BadMethodCallException
|
||||||
|
*/
|
||||||
|
public function __construct($dest)
|
||||||
|
{
|
||||||
|
$valid = $this->getLocalPrinters();
|
||||||
|
if (count($valid) == 0) {
|
||||||
|
throw new BadMethodCallException("You do not have any printers installed on " .
|
||||||
|
"this system via CUPS. Check 'lpr -a'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_search($dest, $valid, true) === false) {
|
||||||
|
throw new BadMethodCallException("'$dest' is not a printer on this system. " .
|
||||||
|
"Printers are: [" . implode(", ", $valid) . "]");
|
||||||
|
}
|
||||||
|
$this->buffer = array ();
|
||||||
|
$this->printerName = $dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cause a NOTICE if deconstructed before the job was printed.
|
||||||
|
*/
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
if ($this->buffer !== null) {
|
||||||
|
trigger_error("Print connector was not finalized. Did you forget to close the printer?", E_USER_NOTICE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send job to printer.
|
||||||
|
*/
|
||||||
|
public function finalize()
|
||||||
|
{
|
||||||
|
$data = implode($this->buffer);
|
||||||
|
$this->buffer = null;
|
||||||
|
|
||||||
|
// Build command to work on data
|
||||||
|
$tmpfname = tempnam(sys_get_temp_dir(), 'print-');
|
||||||
|
file_put_contents($tmpfname, $data);
|
||||||
|
$cmd = sprintf(
|
||||||
|
"lp -d %s %s",
|
||||||
|
escapeshellarg($this->printerName),
|
||||||
|
escapeshellarg($tmpfname)
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
$this->getCmdOutput($cmd);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
unlink($tmpfname);
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
unlink($tmpfname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a command and throw an exception if it fails, or return the output if it works.
|
||||||
|
* (Basically exec() with good error handling)
|
||||||
|
*
|
||||||
|
* @param string $cmd
|
||||||
|
* Command to run
|
||||||
|
*/
|
||||||
|
protected function getCmdOutput($cmd)
|
||||||
|
{
|
||||||
|
$descriptors = array (
|
||||||
|
1 => array (
|
||||||
|
"pipe",
|
||||||
|
"w"
|
||||||
|
),
|
||||||
|
2 => array (
|
||||||
|
"pipe",
|
||||||
|
"w"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$process = proc_open($cmd, $descriptors, $fd);
|
||||||
|
if (! is_resource($process)) {
|
||||||
|
throw new Exception("Command '$cmd' failed to start.");
|
||||||
|
}
|
||||||
|
/* Read stdout */
|
||||||
|
$outputStr = stream_get_contents($fd [1]);
|
||||||
|
fclose($fd [1]);
|
||||||
|
/* Read stderr */
|
||||||
|
$errorStr = stream_get_contents($fd [2]);
|
||||||
|
fclose($fd [2]);
|
||||||
|
/* Finish up */
|
||||||
|
$retval = proc_close($process);
|
||||||
|
if ($retval != 0) {
|
||||||
|
throw new Exception("Command $cmd failed: $errorStr");
|
||||||
|
}
|
||||||
|
return $outputStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read data from the printer.
|
||||||
|
*
|
||||||
|
* @param string $len Length of data to read.
|
||||||
|
* @return Data read from the printer, or false where reading is not possible.
|
||||||
|
*/
|
||||||
|
public function read($len)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $data
|
||||||
|
*/
|
||||||
|
public function write($data)
|
||||||
|
{
|
||||||
|
$this->buffer [] = $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a list of CUPS printers.
|
||||||
|
*
|
||||||
|
* @return array A list of printer names installed on this system. Any item
|
||||||
|
* on this list is valid for constructing a printer.
|
||||||
|
*/
|
||||||
|
protected function getLocalPrinters()
|
||||||
|
{
|
||||||
|
$outpStr = $this->getCmdOutput("lpstat -a");
|
||||||
|
$outpLines = explode("\n", trim($outpStr));
|
||||||
|
foreach ($outpLines as $line) {
|
||||||
|
$ret [] = $this->chopLpstatLine($line);
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the item before the first space in a string
|
||||||
|
*
|
||||||
|
* @param string $line
|
||||||
|
* @return string the string, up to the first space, or the whole string if it contains no spaces.
|
||||||
|
*/
|
||||||
|
private function chopLpstatLine($line)
|
||||||
|
{
|
||||||
|
if (($pos = strpos($line, " ")) === false) {
|
||||||
|
return $line;
|
||||||
|
} else {
|
||||||
|
return substr($line, 0, $pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-18 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mike42\Escpos\PrintConnectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print connector that writes to nowhere, but allows the user to retrieve the
|
||||||
|
* buffered data. Used for testing.
|
||||||
|
*/
|
||||||
|
final class DummyPrintConnector implements PrintConnector
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array $buffer
|
||||||
|
* Buffer of accumilated data.
|
||||||
|
*/
|
||||||
|
private $buffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string data which the printer will provide on next read
|
||||||
|
*/
|
||||||
|
private $readData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new print connector
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this -> buffer = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function clear()
|
||||||
|
{
|
||||||
|
$this -> buffer = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
if ($this -> buffer !== null) {
|
||||||
|
trigger_error("Print connector was not finalized. Did you forget to close the printer?", E_USER_NOTICE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function finalize()
|
||||||
|
{
|
||||||
|
$this -> buffer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string Get the accumulated data that has been sent to this buffer.
|
||||||
|
*/
|
||||||
|
public function getData()
|
||||||
|
{
|
||||||
|
return implode($this -> buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* @see PrintConnector::read()
|
||||||
|
*/
|
||||||
|
public function read($len)
|
||||||
|
{
|
||||||
|
return $len >= strlen($this -> readData) ? $this -> readData : substr($this -> readData, 0, $len);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write($data)
|
||||||
|
{
|
||||||
|
$this -> buffer[] = $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-18 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mike42\Escpos\PrintConnectors;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PrintConnector for passing print data to a file.
|
||||||
|
*/
|
||||||
|
class FilePrintConnector implements PrintConnector
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var resource $fp
|
||||||
|
* The file pointer to send data to.
|
||||||
|
*/
|
||||||
|
protected $fp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct new connector, given a filename
|
||||||
|
*
|
||||||
|
* @param string $filename
|
||||||
|
*/
|
||||||
|
public function __construct($filename)
|
||||||
|
{
|
||||||
|
$this -> fp = fopen($filename, "wb+");
|
||||||
|
if ($this -> fp === false) {
|
||||||
|
throw new Exception("Cannot initialise FilePrintConnector.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
if ($this -> fp !== false) {
|
||||||
|
trigger_error("Print connector was not finalized. Did you forget to close the printer?", E_USER_NOTICE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close file pointer
|
||||||
|
*/
|
||||||
|
public function finalize()
|
||||||
|
{
|
||||||
|
if ($this -> fp !== false) {
|
||||||
|
fclose($this -> fp);
|
||||||
|
$this -> fp = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-PHPdoc)
|
||||||
|
* @see PrintConnector::read()
|
||||||
|
*/
|
||||||
|
public function read($len)
|
||||||
|
{
|
||||||
|
if ($this -> fp === false) {
|
||||||
|
throw new Exception("PrintConnector has been closed, cannot read input.");
|
||||||
|
}
|
||||||
|
return fread($this -> fp, $len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write data to the file
|
||||||
|
*
|
||||||
|
* @param string $data
|
||||||
|
*/
|
||||||
|
public function write($data)
|
||||||
|
{
|
||||||
|
if ($this -> fp === false) {
|
||||||
|
throw new Exception("PrintConnector has been closed, cannot send output.");
|
||||||
|
}
|
||||||
|
fwrite($this -> fp, $data);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-18 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mike42\Escpos\PrintConnectors;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PrintConnector for directly opening a network socket to a printer to send it commands.
|
||||||
|
*/
|
||||||
|
class NetworkPrintConnector extends FilePrintConnector
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Construct a new NetworkPrintConnector
|
||||||
|
*
|
||||||
|
* @param string $ip IP address or hostname to use.
|
||||||
|
* @param string $port The port number to connect on.
|
||||||
|
* @param string $timeout The connection timeout, in seconds.
|
||||||
|
* @throws Exception Where the socket cannot be opened.
|
||||||
|
*/
|
||||||
|
public function __construct($ip, $port = "9100", $timeout = false)
|
||||||
|
{
|
||||||
|
// Default to 60 if default_socket_timeout isn't defined in the ini
|
||||||
|
$defaultSocketTimeout = ini_get("default_socket_timeout") ?: 60;
|
||||||
|
$timeout = $timeout ?: $defaultSocketTimeout;
|
||||||
|
|
||||||
|
$this -> fp = @fsockopen($ip, $port, $errno, $errstr, $timeout);
|
||||||
|
if ($this -> fp === false) {
|
||||||
|
throw new Exception("Cannot initialise NetworkPrintConnector: " . $errstr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-18 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mike42\Escpos\PrintConnectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface passed to Escpos class for receiving print data. Print connectors
|
||||||
|
* are responsible for transporting this to the actual printer.
|
||||||
|
*/
|
||||||
|
interface PrintConnector
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Print connectors should cause a NOTICE if they are deconstructed
|
||||||
|
* when they have not been finalized.
|
||||||
|
*/
|
||||||
|
public function __destruct();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finish using this print connector (close file, socket, send
|
||||||
|
* accumulated output, etc).
|
||||||
|
*/
|
||||||
|
public function finalize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read data from the printer.
|
||||||
|
*
|
||||||
|
* @param string $len Length of data to read.
|
||||||
|
* @return Data read from the printer, or false where reading is not possible.
|
||||||
|
*/
|
||||||
|
public function read($len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write data to the print connector.
|
||||||
|
*
|
||||||
|
* @param string $data The data to write
|
||||||
|
*/
|
||||||
|
public function write($data);
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of escpos-php: PHP receipt printer library for use with
|
||||||
|
* ESC/POS-compatible thermal and impact printers.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-18 Michael Billington < michael.billington@gmail.com >,
|
||||||
|
* incorporating modifications by others. See CONTRIBUTORS.md for a full list.
|
||||||
|
*
|
||||||
|
* This software is distributed under the terms of the MIT license. See LICENSE.md
|
||||||
|
* for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mike42\Escpos\PrintConnectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print connector for android RawBT application
|
||||||
|
* https://play.google.com/store/apps/details?id=ru.a402d.rawbtprinter
|
||||||
|
*/
|
||||||
|
final class RawbtPrintConnector implements PrintConnector
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array $buffer
|
||||||
|
* Buffer of accumilated data.
|
||||||
|
*/
|
||||||
|
private $buffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string data which the printer will provide on next read
|
||||||
|
*/
|
||||||
|
private $readData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new print connector
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
ob_start();
|
||||||
|
$this->buffer = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function clear()
|
||||||
|
{
|
||||||
|
$this->buffer = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
if ($this->buffer !== null) {
|
||||||
|
trigger_error("Print connector was not finalized. Did you forget to close the printer?", E_USER_NOTICE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function finalize()
|
||||||
|
{
|
||||||
|
ob_end_clean();
|
||||||
|
echo "intent:base64," . base64_encode($this->getData()) . "#Intent;scheme=rawbt;package=ru.a402d.rawbtprinter;end;";
|
||||||
|
$this->buffer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string Get the accumulated data that has been sent to this buffer.
|
||||||
|
*/
|
||||||
|
public function getData()
|
||||||
|
{
|
||||||
|
return implode($this->buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* @see PrintConnector::read()
|
||||||
|
*/
|
||||||
|
public function read($len)
|
||||||
|
{
|
||||||
|
return $len >= strlen($this->readData) ? $this->readData : substr($this->readData, 0, $len);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write($data)
|
||||||
|
{
|
||||||
|
$this->buffer[] = $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user