1<?php 2/** 3 * This file is part of escpos-php: PHP receipt printer library for use with 4 * ESC/POS-compatible thermal and impact printers. 5 * 6 * Copyright (c) 2014-18 Michael Billington < michael.billington@gmail.com >, 7 * incorporating modifications by others. See CONTRIBUTORS.md for a full list. 8 * 9 * This software is distributed under the terms of the MIT license. See LICENSE.md 10 * for details. 11 */ 12 13namespace Mike42\Escpos; 14 15use Exception; 16use InvalidArgumentException; 17use Mike42\Escpos\PrintBuffers\PrintBuffer; 18use Mike42\Escpos\PrintBuffers\EscposPrintBuffer; 19use Mike42\Escpos\PrintConnectors\PrintConnector; 20use Mike42\Escpos\CapabilityProfile; 21 22/** 23 * Main class for ESC/POS code generation 24 */ 25class Printer 26{ 27 /** 28 * ASCII null control character 29 */ 30 const NUL = "\x00"; 31 32 /** 33 * ASCII linefeed control character 34 */ 35 const LF = "\x0a"; 36 37 /** 38 * ASCII escape control character 39 */ 40 const ESC = "\x1b"; 41 42 /** 43 * ASCII form separator control character 44 */ 45 const FS = "\x1c"; 46 47 /** 48 * ASCII form feed control character 49 */ 50 const FF = "\x0c"; 51 52 /** 53 * ASCII group separator control character 54 */ 55 const GS = "\x1d"; 56 57 /** 58 * ASCII data link escape control character 59 */ 60 const DLE = "\x10"; 61 62 /** 63 * ASCII end of transmission control character 64 */ 65 const EOT = "\x04"; 66 67 /** 68 * Indicates UPC-A barcode when used with Printer::barcode 69 */ 70 const BARCODE_UPCA = 65; 71 72 /** 73 * Indicates UPC-E barcode when used with Printer::barcode 74 */ 75 const BARCODE_UPCE = 66; 76 77 /** 78 * Indicates JAN13 barcode when used with Printer::barcode 79 */ 80 const BARCODE_JAN13 = 67; 81 82 /** 83 * Indicates JAN8 barcode when used with Printer::barcode 84 */ 85 const BARCODE_JAN8 = 68; 86 87 /** 88 * Indicates CODE39 barcode when used with Printer::barcode 89 */ 90 const BARCODE_CODE39 = 69; 91 92 /** 93 * Indicates ITF barcode when used with Printer::barcode 94 */ 95 const BARCODE_ITF = 70; 96 97 /** 98 * Indicates CODABAR barcode when used with Printer::barcode 99 */ 100 const BARCODE_CODABAR = 71; 101 102 /** 103 * Indicates CODE93 barcode when used with Printer::barcode 104 */ 105 const BARCODE_CODE93 = 72; 106 107 /** 108 * Indicates CODE128 barcode when used with Printer::barcode 109 */ 110 const BARCODE_CODE128 = 73; 111 112 /** 113 * Indicates that HRI (human-readable interpretation) text should not be 114 * printed, when used with Printer::setBarcodeTextPosition 115 */ 116 const BARCODE_TEXT_NONE = 0; 117 118 /** 119 * Indicates that HRI (human-readable interpretation) text should be printed 120 * above a barcode, when used with Printer::setBarcodeTextPosition 121 */ 122 const BARCODE_TEXT_ABOVE = 1; 123 124 /** 125 * Indicates that HRI (human-readable interpretation) text should be printed 126 * below a barcode, when used with Printer::setBarcodeTextPosition 127 */ 128 const BARCODE_TEXT_BELOW = 2; 129 130 /** 131 * Use the first color (usually black), when used with Printer::setColor 132 */ 133 const COLOR_1 = 0; 134 135 /** 136 * Use the second color (usually red or blue), when used with Printer::setColor 137 */ 138 const COLOR_2 = 1; 139 140 /** 141 * Make a full cut, when used with Printer::cut 142 */ 143 const CUT_FULL = 65; 144 145 /** 146 * Make a partial cut, when used with Printer::cut 147 */ 148 const CUT_PARTIAL = 66; 149 150 /** 151 * Use Font A, when used with Printer::setFont 152 */ 153 const FONT_A = 0; 154 155 /** 156 * Use Font B, when used with Printer::setFont 157 */ 158 const FONT_B = 1; 159 160 /** 161 * Use Font C, when used with Printer::setFont 162 */ 163 const FONT_C = 2; 164 165 /** 166 * Use default (high density) image size, when used with Printer::graphics, 167 * Printer::bitImage or Printer::bitImageColumnFormat 168 */ 169 const IMG_DEFAULT = 0; 170 171 /** 172 * Use lower horizontal density for image printing, when used with Printer::graphics, 173 * Printer::bitImage or Printer::bitImageColumnFormat 174 */ 175 const IMG_DOUBLE_WIDTH = 1; 176 177 /** 178 * Use lower vertical density for image printing, when used with Printer::graphics, 179 * Printer::bitImage or Printer::bitImageColumnFormat 180 */ 181 const IMG_DOUBLE_HEIGHT = 2; 182 183 /** 184 * Align text to the left, when used with Printer::setJustification 185 */ 186 const JUSTIFY_LEFT = 0; 187 188 /** 189 * Center text, when used with Printer::setJustification 190 */ 191 const JUSTIFY_CENTER = 1; 192 193 /** 194 * Align text to the right, when used with Printer::setJustification 195 */ 196 const JUSTIFY_RIGHT = 2; 197 198 /** 199 * Use Font A, when used with Printer::selectPrintMode 200 */ 201 const MODE_FONT_A = 0; 202 203 /** 204 * Use Font B, when used with Printer::selectPrintMode 205 */ 206 const MODE_FONT_B = 1; 207 208 /** 209 * Use text emphasis, when used with Printer::selectPrintMode 210 */ 211 const MODE_EMPHASIZED = 8; 212 213 /** 214 * Use double height text, when used with Printer::selectPrintMode 215 */ 216 const MODE_DOUBLE_HEIGHT = 16; 217 218 /** 219 * Use double width text, when used with Printer::selectPrintMode 220 */ 221 const MODE_DOUBLE_WIDTH = 32; 222 223 /** 224 * Underline text, when used with Printer::selectPrintMode 225 */ 226 const MODE_UNDERLINE = 128; 227 228 /** 229 * Indicates standard PDF417 code 230 */ 231 const PDF417_STANDARD = 0; 232 233 /** 234 * Indicates truncated PDF417 code 235 */ 236 const PDF417_TRUNCATED = 1; 237 238 /** 239 * Indicates error correction level L when used with Printer::qrCode 240 */ 241 const QR_ECLEVEL_L = 0; 242 243 /** 244 * Indicates error correction level M when used with Printer::qrCode 245 */ 246 const QR_ECLEVEL_M = 1; 247 248 /** 249 * Indicates error correction level Q when used with Printer::qrCode 250 */ 251 const QR_ECLEVEL_Q = 2; 252 253 /** 254 * Indicates error correction level H when used with Printer::qrCode 255 */ 256 const QR_ECLEVEL_H = 3; 257 258 /** 259 * Indicates QR model 1 when used with Printer::qrCode 260 */ 261 const QR_MODEL_1 = 1; 262 263 /** 264 * Indicates QR model 2 when used with Printer::qrCode 265 */ 266 const QR_MODEL_2 = 2; 267 268 /** 269 * Indicates micro QR code when used with Printer::qrCode 270 */ 271 const QR_MICRO = 3; 272 273 /** 274 * Indicates a request for printer status when used with 275 * Printer::getPrinterStatus (experimental) 276 */ 277 const STATUS_PRINTER = 1; 278 279 /** 280 * Indicates a request for printer offline cause when used with 281 * Printer::getPrinterStatus (experimental) 282 */ 283 const STATUS_OFFLINE_CAUSE = 2; 284 285 /** 286 * Indicates a request for error cause when used with Printer::getPrinterStatus 287 * (experimental) 288 */ 289 const STATUS_ERROR_CAUSE = 3; 290 291 /** 292 * Indicates a request for error cause when used with Printer::getPrinterStatus 293 * (experimental) 294 */ 295 const STATUS_PAPER_ROLL = 4; 296 297 /** 298 * Indicates a request for ink A status when used with Printer::getPrinterStatus 299 * (experimental) 300 */ 301 const STATUS_INK_A = 7; 302 303 /** 304 * Indicates a request for ink B status when used with Printer::getPrinterStatus 305 * (experimental) 306 */ 307 const STATUS_INK_B = 6; 308 309 /** 310 * Indicates a request for peeler status when used with Printer::getPrinterStatus 311 * (experimental) 312 */ 313 const STATUS_PEELER = 8; 314 315 /** 316 * Indicates no underline when used with Printer::setUnderline 317 */ 318 const UNDERLINE_NONE = 0; 319 320 /** 321 * Indicates single underline when used with Printer::setUnderline 322 */ 323 const UNDERLINE_SINGLE = 1; 324 325 /** 326 * Indicates double underline when used with Printer::setUnderline 327 */ 328 const UNDERLINE_DOUBLE = 2; 329 330 /** 331 * @var PrintBuffer|null $buffer 332 * The printer's output buffer. 333 */ 334 protected $buffer; 335 336 /** 337 * @var PrintConnector $connector 338 * Connector showing how to print to this printer 339 */ 340 protected $connector; 341 342 /** 343 * @var CapabilityProfile $profile 344 * Profile showing supported features for this printer 345 */ 346 protected $profile; 347 348 /** 349 * @var int $characterTable 350 * Current character code table 351 */ 352 protected $characterTable; 353 354 /** 355 * Construct a new print object 356 * 357 * @param PrintConnector $connector The PrintConnector to send data to. If not set, output is sent to standard output. 358 * @param CapabilityProfile|null $profile Supported features of this printer. If not set, the "default" CapabilityProfile will be used, which is suitable for Epson printers. 359 * @throws InvalidArgumentException 360 */ 361 public function __construct(PrintConnector $connector, CapabilityProfile $profile = null) 362 { 363 /* Set connector */ 364 $this -> connector = $connector; 365 366 /* Set capability profile */ 367 if ($profile === null) { 368 $profile = CapabilityProfile::load('default'); 369 } 370 $this -> profile = $profile; 371 /* Set buffer */ 372 $buffer = new EscposPrintBuffer(); 373 $this -> buffer = null; 374 $this -> setPrintBuffer($buffer); 375 $this -> initialize(); 376 } 377 378 /** 379 * Print a barcode. 380 * 381 * @param string $content The information to encode. 382 * @param int $type The barcode standard to output. Supported values are 383 * `Printer::BARCODE_UPCA`, `Printer::BARCODE_UPCE`, `Printer::BARCODE_JAN13`, 384 * `Printer::BARCODE_JAN8`, `Printer::BARCODE_CODE39`, `Printer::BARCODE_ITF`, 385 * `Printer::BARCODE_CODABAR`, `Printer::BARCODE_CODE93`, and `Printer::BARCODE_CODE128`. 386 * If not specified, `Printer::BARCODE_CODE39` will be used. Note that some 387 * barcode formats only support specific lengths or sets of characters, and that 388 * available barcode types vary between printers. 389 * @throws InvalidArgumentException Where the length or characters used in $content is invalid for the requested barcode format. 390 */ 391 public function barcode($content, $type = Printer::BARCODE_CODE39) 392 { 393 /* Validate input */ 394 self::validateInteger($type, 65, 73, __FUNCTION__, "Barcode type"); 395 $len = strlen($content); 396 switch ($type) { 397 case self::BARCODE_UPCA: 398 self::validateInteger($len, 11, 12, __FUNCTION__, "UPCA barcode content length"); 399 self::validateStringRegex($content, __FUNCTION__, "/^[0-9]{11,12}$/", "UPCA barcode content"); 400 break; 401 case self::BARCODE_UPCE: 402 self::validateIntegerMulti($len, [[6, 8], [11, 12]], __FUNCTION__, "UPCE barcode content length"); 403 self::validateStringRegex($content, __FUNCTION__, "/^([0-9]{6,8}|[0-9]{11,12})$/", "UPCE barcode content"); 404 break; 405 case self::BARCODE_JAN13: 406 self::validateInteger($len, 12, 13, __FUNCTION__, "JAN13 barcode content length"); 407 self::validateStringRegex($content, __FUNCTION__, "/^[0-9]{12,13}$/", "JAN13 barcode content"); 408 break; 409 case self::BARCODE_JAN8: 410 self::validateInteger($len, 7, 8, __FUNCTION__, "JAN8 barcode content length"); 411 self::validateStringRegex($content, __FUNCTION__, "/^[0-9]{7,8}$/", "JAN8 barcode content"); 412 break; 413 case self::BARCODE_CODE39: 414 self::validateInteger($len, 1, 255, __FUNCTION__, "CODE39 barcode content length"); // 255 is a limitation of the "function b" command, not the barcode format. 415 self::validateStringRegex($content, __FUNCTION__, "/^([0-9A-Z \$\%\+\-\.\/]+|\*[0-9A-Z \$\%\+\-\.\/]+\*)$/", "CODE39 barcode content"); 416 break; 417 case self::BARCODE_ITF: 418 self::validateInteger($len, 2, 255, __FUNCTION__, "ITF barcode content length"); // 255 is a limitation of the "function b" command, not the barcode format. 419 self::validateStringRegex($content, __FUNCTION__, "/^([0-9]{2})+$/", "ITF barcode content"); 420 break; 421 case self::BARCODE_CODABAR: 422 self::validateInteger($len, 1, 255, __FUNCTION__, "Codabar barcode content length"); // 255 is a limitation of the "function b" command, not the barcode format. 423 self::validateStringRegex($content, __FUNCTION__, "/^[A-Da-d][0-9\$\+\-\.\/\:]+[A-Da-d]$/", "Codabar barcode content"); 424 break; 425 case self::BARCODE_CODE93: 426 self::validateInteger($len, 1, 255, __FUNCTION__, "Code93 barcode content length"); // 255 is a limitation of the "function b" command, not the barcode format. 427 self::validateStringRegex($content, __FUNCTION__, "/^[\\x00-\\x7F]+$/", "Code93 barcode content"); 428 break; 429 case self::BARCODE_CODE128: 430 self::validateInteger($len, 1, 255, __FUNCTION__, "Code128 barcode content length"); // 255 is a limitation of the "function b" command, not the barcode format. 431 // The CODE128 encoder is quite complex, so only a very basic header-check is applied here. 432 self::validateStringRegex($content, __FUNCTION__, "/^\{[A-C][\\x00-\\x7F]+$/", "Code128 barcode content"); 433 break; 434 } 435 if (!$this -> profile -> getSupportsBarcodeB()) { 436 // A simpler barcode command which supports fewer codes 437 self::validateInteger($type, 65, 71, __FUNCTION__); 438 $this -> connector -> write(self::GS . "k" . chr($type - 65) . $content . self::NUL); 439 return; 440 } 441 // More advanced function B, used in preference 442 $this -> connector -> write(self::GS . "k" . chr($type) . chr(strlen($content)) . $content); 443 } 444 445 /** 446 * Print an image, using the older "bit image" command. This creates padding on the right of the image, 447 * if its width is not divisible by 8. 448 * 449 * Should only be used if your printer does not support the graphics() command. 450 * See also bitImageColumnFormat(). 451 * 452 * @param EscposImage $img The image to print 453 * @param int $size Size modifier for the image. Must be either `Printer::IMG_DEFAULT` 454 * (default), or any combination of the `Printer::IMG_DOUBLE_HEIGHT` and 455 * `Printer::IMG_DOUBLE_WIDTH` flags. 456 */ 457 public function bitImage(EscposImage $img, $size = Printer::IMG_DEFAULT) 458 { 459 self::validateInteger($size, 0, 3, __FUNCTION__); 460 $rasterData = $img -> toRasterFormat(); 461 $header = Printer::dataHeader([$img -> getWidthBytes(), $img -> getHeight()], true); 462 $this -> connector -> write(self::GS . "v0" . chr($size) . $header); 463 $this -> connector -> write($rasterData); 464 } 465 466 /** 467 * Print an image, using the older "bit image" command in column format. 468 * 469 * Should only be used if your printer does not support the graphics() or 470 * bitImage() commands. 471 * 472 * @param EscposImage $img The image to print 473 * @param int $size Size modifier for the image. Must be either `Printer::IMG_DEFAULT` 474 * (default), or any combination of the `Printer::IMG_DOUBLE_HEIGHT` and 475 * `Printer::IMG_DOUBLE_WIDTH` flags. 476 */ 477 public function bitImageColumnFormat(EscposImage $img, $size = Printer::IMG_DEFAULT) 478 { 479 $highDensityVertical = ! (($size & self::IMG_DOUBLE_HEIGHT) == Printer::IMG_DOUBLE_HEIGHT); 480 $highDensityHorizontal = ! (($size & self::IMG_DOUBLE_WIDTH) == Printer::IMG_DOUBLE_WIDTH); 481 // Experimental column format printing 482 // This feature is not yet complete and may produce unpredictable results. 483 $this -> setLineSpacing(16); // 16-dot line spacing. This is the correct value on both TM-T20 and TM-U220 484 // Header and density code (0, 1, 32, 33) re-used for every line 485 $densityCode = ($highDensityHorizontal ? 1 : 0) + ($highDensityVertical ? 32 : 0); 486 $colFormatData = $img -> toColumnFormat($highDensityVertical); 487 $header = Printer::dataHeader([$img -> getWidth()], true); 488 foreach ($colFormatData as $line) { 489 // Print each line, double density etc for printing are set here also 490 $this -> connector -> write(self::ESC . "*" . chr($densityCode) . $header . $line); 491 $this -> feed(); 492 // sleep(0.1); // Reduces the amount of trouble that a TM-U220 has keeping up with large images 493 } 494 $this -> setLineSpacing(); // Revert to default line spacing 495 } 496 497 /** 498 * Close the underlying buffer. With some connectors, the 499 * job will not actually be sent to the printer until this is called. 500 */ 501 public function close() 502 { 503 $this -> connector -> finalize(); 504 } 505 506 /** 507 * Cut the paper. 508 * 509 * @param int $mode Cut mode, either Printer::CUT_FULL or Printer::CUT_PARTIAL. If not specified, `Printer::CUT_FULL` will be used. 510 * @param int $lines Number of lines to feed 511 */ 512 public function cut($mode = Printer::CUT_FULL, $lines = 3) 513 { 514 // TODO validation on cut() inputs 515 $this -> connector -> write(self::GS . "V" . chr($mode) . chr($lines)); 516 } 517 518 /** 519 * Print and feed line / Print and feed n lines. 520 * 521 * @param int $lines Number of lines to feed 522 */ 523 public function feed($lines = 1) 524 { 525 self::validateInteger($lines, 1, 255, __FUNCTION__); 526 if ($lines <= 1) { 527 $this -> connector -> write(self::LF); 528 } else { 529 $this -> connector -> write(self::ESC . "d" . chr($lines)); 530 } 531 } 532 533 /** 534 * Some printers require a form feed to release the paper. On most printers, this 535 * command is only useful in page mode, which is not implemented in this driver. 536 */ 537 public function feedForm() 538 { 539 $this -> connector -> write(self::FF); 540 } 541 542 /** 543 * Some slip printers require `ESC q` sequence to release the paper. 544 */ 545 public function release() 546 { 547 $this -> connector -> write(self::ESC . chr(113)); 548 } 549 550 /** 551 * Print and reverse feed n lines. 552 * 553 * @param int $lines number of lines to feed. If not specified, 1 line will be fed. 554 */ 555 public function feedReverse($lines = 1) 556 { 557 self::validateInteger($lines, 1, 255, __FUNCTION__); 558 $this -> connector -> write(self::ESC . "e" . chr($lines)); 559 } 560 561 /** 562 * @return number 563 */ 564 public function getCharacterTable() 565 { 566 return $this -> characterTable; 567 } 568 569 /** 570 * @return PrintBuffer 571 */ 572 public function getPrintBuffer() 573 { 574 return $this -> buffer; 575 } 576 577 /** 578 * @return PrintConnector 579 */ 580 public function getPrintConnector() 581 { 582 return $this -> connector; 583 } 584 585 /** 586 * @return CapabilityProfile 587 */ 588 public function getPrinterCapabilityProfile() 589 { 590 return $this -> profile; 591 } 592 593 /** 594 * Print an image to the printer. 595 * 596 * Size modifiers are: 597 * - Printer::IMG_DEFAULT (leave image at original size) 598 * - Printer::IMG_DOUBLE_WIDTH 599 * - Printer::IMG_DOUBLE_HEIGHT 600 * 601 * See the example/ folder for detailed examples. 602 * 603 * The functions bitImage() and bitImageColumnFormat() take the same 604 * parameters, and can be used if your printer doesn't support the newer 605 * graphics commands. 606 * 607 * @param EscposImage $img The image to print. 608 * @param int $size Size modifier for the image. Must be either `Printer::IMG_DEFAULT` 609 * (default), or any combination of the `Printer::IMG_DOUBLE_HEIGHT` and 610 * `Printer::IMG_DOUBLE_WIDTH` flags. 611 */ 612 public function graphics(EscposImage $img, $size = Printer::IMG_DEFAULT) 613 { 614 self::validateInteger($size, 0, 3, __FUNCTION__); 615 $rasterData = $img -> toRasterFormat(); 616 $imgHeader = Printer::dataHeader([$img -> getWidth(), $img -> getHeight()], true); 617 $tone = '0'; 618 $colors = '1'; 619 $xm = (($size & self::IMG_DOUBLE_WIDTH) == Printer::IMG_DOUBLE_WIDTH) ? chr(2) : chr(1); 620 $ym = (($size & self::IMG_DOUBLE_HEIGHT) == Printer::IMG_DOUBLE_HEIGHT) ? chr(2) : chr(1); 621 $header = $tone . $xm . $ym . $colors . $imgHeader; 622 $this -> wrapperSendGraphicsData('0', 'p', $header . $rasterData); 623 $this -> wrapperSendGraphicsData('0', '2'); 624 } 625 626 /** 627 * Initialize printer. This resets formatting back to the defaults. 628 */ 629 public function initialize() 630 { 631 $this -> connector -> write(self::ESC . "@"); 632 $this -> characterTable = 0; 633 } 634 635 /** 636 * Print a two-dimensional data code using the PDF417 standard. 637 * 638 * @param string $content Text or numbers to store in the code 639 * @param int $width Width of a module (pixel) in the printed code. 640 * Default is 3 dots. 641 * @param int $heightMultiplier Multiplier for height of a module. 642 * Default is 3 times the width. 643 * @param int $dataColumnCount Number of data columns to use. 0 (default) 644 * is to auto-calculate. Smaller numbers will result in a narrower code, 645 * making larger pixel sizes possible. Larger numbers require smaller pixel sizes. 646 * @param float $ec Error correction ratio, from 0.01 to 4.00. Default is 0.10 (10%). 647 * @param int $options Standard code Printer::PDF417_STANDARD with 648 * start/end bars, or truncated code Printer::PDF417_TRUNCATED with start bars only. 649 * @throws Exception If this profile indicates that PDF417 code is not supported 650 */ 651 public function pdf417Code($content, $width = 3, $heightMultiplier = 3, $dataColumnCount = 0, $ec = 0.10, $options = Printer::PDF417_STANDARD) 652 { 653 self::validateString($content, __FUNCTION__, 'content'); 654 self::validateInteger($width, 2, 8, __FUNCTION__, 'width'); 655 self::validateInteger($heightMultiplier, 2, 8, __FUNCTION__, 'heightMultiplier'); 656 self::validateInteger($dataColumnCount, 0, 30, __FUNCTION__, 'dataColumnCount'); 657 self::validateFloat($ec, 0.01, 4.00, __FUNCTION__, 'ec'); 658 self::validateInteger($options, 0, 1, __FUNCTION__, 'options'); 659 if ($content == "") { 660 return; 661 } 662 if (!$this -> profile -> getSupportsPdf417Code()) { 663 // TODO use software rendering via a library instead 664 throw new Exception("PDF417 codes are not supported on your printer."); 665 } 666 $cn = '0'; // Code type for pdf417 code 667 // Select model: standard or truncated 668 $this -> wrapperSend2dCodeData(chr(70), $cn, chr($options)); 669 // Column count 670 $this -> wrapperSend2dCodeData(chr(65), $cn, chr($dataColumnCount)); 671 // Set dot sizes 672 $this -> wrapperSend2dCodeData(chr(67), $cn, chr($width)); 673 $this -> wrapperSend2dCodeData(chr(68), $cn, chr($heightMultiplier)); 674 // Set error correction ratio: 1% to 400% 675 $ec_int = (int)ceil(floatval($ec) * 10); 676 $this -> wrapperSend2dCodeData(chr(69), $cn, chr($ec_int), '1'); 677 // Send content & print 678 $this -> wrapperSend2dCodeData(chr(80), $cn, $content, '0'); 679 $this -> wrapperSend2dCodeData(chr(81), $cn, '', '0'); 680 } 681 682 /** 683 * Generate a pulse, for opening a cash drawer if one is connected. 684 * The default settings should open an Epson drawer. 685 * 686 * @param int $pin 0 or 1, for pin 2 or pin 5 kick-out connector respectively. 687 * @param int $on_ms pulse ON time, in milliseconds. 688 * @param int $off_ms pulse OFF time, in milliseconds. 689 */ 690 public function pulse($pin = 0, $on_ms = 120, $off_ms = 240) 691 { 692 self::validateInteger($pin, 0, 1, __FUNCTION__); 693 self::validateInteger($on_ms, 1, 511, __FUNCTION__); 694 self::validateInteger($off_ms, 1, 511, __FUNCTION__); 695 $this -> connector -> write(self::ESC . "p" . chr($pin + 48) . chr($on_ms / 2) . chr($off_ms / 2)); 696 } 697 698 /** 699 * Print the given data as a QR code on the printer. 700 * 701 * @param string $content The content of the code. Numeric data will be more efficiently compacted. 702 * @param 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. 703 * @param int $size Pixel size to use. Must be 1-16 (default 3) 704 * @param 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). 705 */ 706 public function qrCode($content, $ec = Printer::QR_ECLEVEL_L, $size = 3, $model = Printer::QR_MODEL_2) 707 { 708 self::validateString($content, __FUNCTION__); 709 self::validateInteger($ec, 0, 3, __FUNCTION__); 710 self::validateInteger($size, 1, 16, __FUNCTION__); 711 self::validateInteger($model, 1, 3, __FUNCTION__); 712 if ($content == "") { 713 return; 714 } 715 if (!$this -> profile -> getSupportsQrCode()) { 716 // TODO use software rendering via phpqrcode instead 717 throw new Exception("QR codes are not supported on your printer."); 718 } 719 $cn = '1'; // Code type for QR code 720 // Select model: 1, 2 or micro. 721 $this -> wrapperSend2dCodeData(chr(65), $cn, chr(48 + $model) . chr(0)); 722 // Set dot size. 723 $this -> wrapperSend2dCodeData(chr(67), $cn, chr($size)); 724 // Set error correction level: L, M, Q, or H 725 $this -> wrapperSend2dCodeData(chr(69), $cn, chr(48 + $ec)); 726 // Send content & print 727 $this -> wrapperSend2dCodeData(chr(80), $cn, $content, '0'); 728 $this -> wrapperSend2dCodeData(chr(81), $cn, '', '0'); 729 } 730 731 /** 732 * Switch character table (code page) manually. Used in conjunction with textRaw() to 733 * print special characters which can't be encoded automatically. 734 * 735 * @param int $table The table to select. Available code tables are model-specific. 736 */ 737 public function selectCharacterTable($table = 0) 738 { 739 self::validateInteger($table, 0, 255, __FUNCTION__); 740 $supported = $this -> profile -> getCodePages(); 741 if (!isset($supported[$table])) { 742 throw new InvalidArgumentException("There is no code table $table allowed by this printer's capability profile."); 743 } 744 $this -> characterTable = $table; 745 if ($this -> profile -> getSupportsStarCommands()) { 746 /* Not an ESC/POS command: STAR printers stash all the extra code pages under a different command. */ 747 $this -> connector -> write(self::ESC . self::GS . "t" . chr($table)); 748 return; 749 } 750 $this -> connector -> write(self::ESC . "t" . chr($table)); 751 } 752 753 /** 754 * Select print mode(s). 755 * 756 * Several MODE_* constants can be OR'd together passed to this function's `$mode` argument. The valid modes are: 757 * - Printer::MODE_FONT_A 758 * - Printer::MODE_FONT_B 759 * - Printer::MODE_EMPHASIZED 760 * - Printer::MODE_DOUBLE_HEIGHT 761 * - Printer::MODE_DOUBLE_WIDTH 762 * - Printer::MODE_UNDERLINE 763 * 764 * @param int $mode The mode to use. Default is Printer::MODE_FONT_A, with no special formatting. This has a similar effect to running initialize(). 765 */ 766 public function selectPrintMode($mode = Printer::MODE_FONT_A) 767 { 768 $allModes = Printer::MODE_FONT_B | self::MODE_EMPHASIZED | self::MODE_DOUBLE_HEIGHT | self::MODE_DOUBLE_WIDTH | self::MODE_UNDERLINE; 769 if (!is_integer($mode) || $mode < 0 || ($mode & $allModes) != $mode) { 770 throw new InvalidArgumentException("Invalid mode"); 771 } 772 773 $this -> connector -> write(self::ESC . "!" . chr($mode)); 774 } 775 776 /** 777 * Set barcode height. 778 * 779 * @param int $height Height in dots. If not specified, 8 will be used. 780 */ 781 public function setBarcodeHeight($height = 8) 782 { 783 self::validateInteger($height, 1, 255, __FUNCTION__); 784 $this -> connector -> write(self::GS . "h" . chr($height)); 785 } 786 787 /** 788 * Set barcode bar width. 789 * 790 * @param int $width Bar width in dots. If not specified, 3 will be used. 791 * Values above 6 appear to have no effect. 792 */ 793 public function setBarcodeWidth($width = 3) 794 { 795 self::validateInteger($width, 1, 255, __FUNCTION__); 796 $this -> connector -> write(self::GS . "w" . chr($width)); 797 } 798 799 /** 800 * Set the position for the Human Readable Interpretation (HRI) of barcode characters. 801 * 802 * @param int $position. Use Printer::BARCODE_TEXT_NONE to hide the text (default), 803 * or any combination of Printer::BARCODE_TEXT_ABOVE and Printer::BARCODE_TEXT_BELOW 804 * flags to display the text. 805 */ 806 public function setBarcodeTextPosition($position = Printer::BARCODE_TEXT_NONE) 807 { 808 self::validateInteger($position, 0, 3, __FUNCTION__, "Barcode text position"); 809 $this -> connector -> write(self::GS . "H" . chr($position)); 810 } 811 812 /** 813 * Turn double-strike mode on/off. 814 * 815 * @param boolean $on true for double strike, false for no double strike 816 */ 817 public function setDoubleStrike($on = true) 818 { 819 self::validateBoolean($on, __FUNCTION__); 820 $this -> connector -> write(self::ESC . "G". ($on ? chr(1) : chr(0))); 821 } 822 823 /** 824 * Select print color on printers that support multiple colors. 825 * 826 * @param int $color Color to use. Must be either Printer::COLOR_1 (default), or Printer::COLOR_2. 827 */ 828 public function setColor($color = Printer::COLOR_1) 829 { 830 self::validateInteger($color, 0, 1, __FUNCTION__, "Color"); 831 $this -> connector -> write(self::ESC . "r" . chr($color)); 832 } 833 834 /** 835 * Turn emphasized mode on/off. 836 * 837 * @param boolean $on true for emphasis, false for no emphasis 838 */ 839 public function setEmphasis($on = true) 840 { 841 self::validateBoolean($on, __FUNCTION__); 842 $this -> connector -> write(self::ESC . "E". ($on ? chr(1) : chr(0))); 843 } 844 845 /** 846 * Select font. Most printers have two fonts (Fonts A and B), and some have a third (Font C). 847 * 848 * @param int $font The font to use. Must be either Printer::FONT_A, Printer::FONT_B, or Printer::FONT_C. 849 */ 850 public function setFont($font = Printer::FONT_A) 851 { 852 self::validateInteger($font, 0, 2, __FUNCTION__); 853 $this -> connector -> write(self::ESC . "M" . chr($font)); 854 } 855 856 /** 857 * Select justification. 858 * 859 * @param int $justification One of Printer::JUSTIFY_LEFT, Printer::JUSTIFY_CENTER, or Printer::JUSTIFY_RIGHT. 860 */ 861 public function setJustification($justification = Printer::JUSTIFY_LEFT) 862 { 863 self::validateInteger($justification, 0, 2, __FUNCTION__); 864 $this -> connector -> write(self::ESC . "a" . chr($justification)); 865 } 866 867 /** 868 * Set the height of the line. 869 * 870 * Some printers will allow you to overlap lines with a smaller line feed. 871 * 872 * @param int|null $height The height of each line, in dots. If not set, the printer 873 * will reset to its default line spacing. 874 */ 875 public function setLineSpacing($height = null) 876 { 877 if ($height === null) { 878 // Reset to default 879 $this -> connector -> write(self::ESC . "2"); // Revert to default line spacing 880 return; 881 } 882 self::validateInteger($height, 1, 255, __FUNCTION__); 883 $this -> connector -> write(self::ESC . "3" . chr($height)); 884 } 885 886 /** 887 * Set print area left margin. Reset to default with Printer::initialize() 888 * 889 * @param int $margin The left margin to set on to the print area, in dots. 890 */ 891 public function setPrintLeftMargin($margin = 0) 892 { 893 self::validateInteger($margin, 0, 65535, __FUNCTION__); 894 $this -> connector -> write(Printer::GS . 'L' . self::intLowHigh($margin, 2)); 895 } 896 897 /** 898 * Set print area width. This can be used to add a right margin to the print area. 899 * Reset to default with Printer::initialize() 900 * 901 * @param int $width The width of the page print area, in dots. 902 */ 903 public function setPrintWidth($width = 512) 904 { 905 self::validateInteger($width, 1, 65535, __FUNCTION__); 906 $this -> connector -> write(Printer::GS . 'W' . self::intLowHigh($width, 2)); 907 } 908 909 /** 910 * Attach a different print buffer to the printer. Buffers are responsible for handling text output to the printer. 911 * 912 * @param PrintBuffer $buffer The buffer to use. 913 * @throws InvalidArgumentException Where the buffer is already attached to a different printer. 914 */ 915 public function setPrintBuffer(PrintBuffer $buffer) 916 { 917 if ($buffer === $this -> buffer) { 918 return; 919 } 920 if ($buffer -> getPrinter() != null) { 921 throw new InvalidArgumentException("This buffer is already attached to a printer."); 922 } 923 if ($this -> buffer !== null) { 924 $this -> buffer -> setPrinter(null); 925 } 926 $this -> buffer = $buffer; 927 $this -> buffer -> setPrinter($this); 928 } 929 930 /** 931 * Set black/white reverse mode on or off. In this mode, text is printed white on a black background. 932 * 933 * @param boolean $on True to enable, false to disable. 934 */ 935 public function setReverseColors($on = true) 936 { 937 self::validateBoolean($on, __FUNCTION__); 938 $this -> connector -> write(self::GS . "B" . ($on ? chr(1) : chr(0))); 939 } 940 941 /** 942 * Set the size of text, as a multiple of the normal size. 943 * 944 * @param int $widthMultiplier Multiple of the regular height to use (range 1 - 8) 945 * @param int $heightMultiplier Multiple of the regular height to use (range 1 - 8) 946 */ 947 public function setTextSize($widthMultiplier, $heightMultiplier) 948 { 949 self::validateInteger($widthMultiplier, 1, 8, __FUNCTION__); 950 self::validateInteger($heightMultiplier, 1, 8, __FUNCTION__); 951 $c = pow(2, 4) * ($widthMultiplier - 1) + ($heightMultiplier - 1); 952 $this -> connector -> write(self::GS . "!" . chr($c)); 953 } 954 955 /** 956 * Set underline for printed text. 957 * 958 * Argument can be true/false, or one of UNDERLINE_NONE, 959 * UNDERLINE_SINGLE or UNDERLINE_DOUBLE. 960 * 961 * @param int $underline Either true/false, or one of Printer::UNDERLINE_NONE, Printer::UNDERLINE_SINGLE or Printer::UNDERLINE_DOUBLE. Defaults to Printer::UNDERLINE_SINGLE. 962 */ 963 public function setUnderline($underline = Printer::UNDERLINE_SINGLE) 964 { 965 /* Map true/false to underline constants */ 966 if ($underline === true) { 967 $underline = Printer::UNDERLINE_SINGLE; 968 } elseif ($underline === false) { 969 $underline = Printer::UNDERLINE_NONE; 970 } 971 /* Set the underline */ 972 self::validateInteger($underline, 0, 2, __FUNCTION__); 973 $this -> connector -> write(self::ESC . "-" . chr($underline)); 974 } 975 976 /** 977 * Print each line upside-down (180 degrees rotated). 978 * 979 * @param boolean $on True to enable, false to disable. 980 */ 981 public function setUpsideDown($on = true) 982 { 983 self::validateBoolean($on, __FUNCTION__); 984 $this -> connector -> write(self::ESC . "{" . ($on ? chr(1) : chr(0))); 985 } 986 987 /** 988 * Add text to the buffer. 989 * 990 * Text should either be followed by a line-break, or feed() should be called 991 * after this to clear the print buffer. 992 * 993 * @param string $str Text to print 994 */ 995 public function text($str = "") 996 { 997 self::validateString($str, __FUNCTION__); 998 $this -> buffer -> writeText((string)$str); 999 } 1000 1001 /** 1002 * Add Chinese text to the buffer. This is a specific workaround for the common Zijang printer- The printer will be switched to a two-byte mode and sent GBK-encoded text. 1003 * 1004 * Support for this will be merged into a print buffer. 1005 * 1006 * @param string $str Text to print, as UTF-8 1007 */ 1008 public function textChinese($str = "") 1009 { 1010 self::validateString($str, __FUNCTION__); 1011 $this -> connector -> write(self::FS . "&"); 1012 $str = iconv("UTF-8", "GBK//IGNORE", $str); 1013 $this -> buffer -> writeTextRaw((string)$str); 1014 $this -> connector -> write(self::FS . "."); 1015 } 1016 1017 /** 1018 * Add text to the buffer without attempting to interpret chararacter codes. 1019 * 1020 * Text should either be followed by a line-break, or feed() should be called 1021 * after this to clear the print buffer. 1022 * 1023 * @param string $str Text to print 1024 */ 1025 public function textRaw($str = "") 1026 { 1027 self::validateString($str, __FUNCTION__); 1028 $this -> buffer -> writeTextRaw((string)$str); 1029 } 1030 1031 /** 1032 * Wrapper for GS ( k, to calculate and send correct data length. 1033 * 1034 * @param string $fn Function to use 1035 * @param string $cn Output code type. Affects available data 1036 * @param string $data Data to send. 1037 * @param string $m Modifier/variant for function. Often '0' where used. 1038 * @throws InvalidArgumentException Where the input lengths are bad. 1039 */ 1040 protected function wrapperSend2dCodeData($fn, $cn, $data = '', $m = '') 1041 { 1042 if (strlen($m) > 1 || strlen($cn) != 1 || strlen($fn) != 1) { 1043 throw new InvalidArgumentException("wrapperSend2dCodeData: cn and fn must be one character each."); 1044 } 1045 $header = $this -> intLowHigh(strlen($data) + strlen($m) + 2, 2); 1046 $this -> connector -> write(self::GS . "(k" . $header . $cn . $fn . $m . $data); 1047 } 1048 1049 /** 1050 * Wrapper for GS ( L, to calculate and send correct data length. 1051 * 1052 * @param string $m Modifier/variant for function. Usually '0'. 1053 * @param string $fn Function number to use, as character. 1054 * @param string $data Data to send. 1055 * @throws InvalidArgumentException Where the input lengths are bad. 1056 */ 1057 protected function wrapperSendGraphicsData($m, $fn, $data = '') 1058 { 1059 if (strlen($m) != 1 || strlen($fn) != 1) { 1060 throw new InvalidArgumentException("wrapperSendGraphicsData: m and fn must be one character each."); 1061 } 1062 $header = $this -> intLowHigh(strlen($data) + 2, 2); 1063 $this -> connector -> write(self::GS . "(L" . $header . $m . $fn . $data); 1064 } 1065 1066 /** 1067 * Convert widths and heights to characters. Used before sending graphics to set the size. 1068 * 1069 * @param array $inputs 1070 * @param boolean $long True to use 4 bytes, false to use 2 1071 * @return string 1072 */ 1073 protected static function dataHeader(array $inputs, $long = true) 1074 { 1075 $outp = []; 1076 foreach ($inputs as $input) { 1077 if ($long) { 1078 $outp[] = Printer::intLowHigh($input, 2); 1079 } else { 1080 self::validateInteger($input, 0, 255, __FUNCTION__); 1081 $outp[] = chr($input); 1082 } 1083 } 1084 return implode("", $outp); 1085 } 1086 1087 /** 1088 * Generate two characters for a number: In lower and higher parts, or more parts as needed. 1089 * 1090 * @param int $input Input number 1091 * @param int $length The number of bytes to output (1 - 4). 1092 */ 1093 protected static function intLowHigh($input, $length) 1094 { 1095 $maxInput = (256 << ($length * 8) - 1); 1096 self::validateInteger($length, 1, 4, __FUNCTION__); 1097 self::validateInteger($input, 0, $maxInput, __FUNCTION__); 1098 $outp = ""; 1099 for ($i = 0; $i < $length; $i++) { 1100 $outp .= chr($input % 256); 1101 $input = (int)($input / 256); 1102 } 1103 return $outp; 1104 } 1105 1106 /** 1107 * Throw an exception if the argument given is not a boolean 1108 * 1109 * @param boolean $test the input to test 1110 * @param string $source the name of the function calling this 1111 */ 1112 protected static function validateBoolean($test, $source) 1113 { 1114 if (!($test === true || $test === false)) { 1115 throw new InvalidArgumentException("Argument to $source must be a boolean"); 1116 } 1117 } 1118 1119 /** 1120 * Throw an exception if the argument given is not a float within the specified range 1121 * 1122 * @param float $test the input to test 1123 * @param float $min the minimum allowable value (inclusive) 1124 * @param float $max the maximum allowable value (inclusive) 1125 * @param string $source the name of the function calling this 1126 * @param string $argument the name of the invalid parameter 1127 */ 1128 protected static function validateFloat($test, $min, $max, $source, $argument = "Argument") 1129 { 1130 if (!is_numeric($test)) { 1131 throw new InvalidArgumentException("$argument given to $source must be a float, but '$test' was given."); 1132 } 1133 if ($test < $min || $test > $max) { 1134 throw new InvalidArgumentException("$argument given to $source must be in range $min to $max, but $test was given."); 1135 } 1136 } 1137 1138 /** 1139 * Throw an exception if the argument given is not an integer within the specified range 1140 * 1141 * @param int $test the input to test 1142 * @param int $min the minimum allowable value (inclusive) 1143 * @param int $max the maximum allowable value (inclusive) 1144 * @param string $source the name of the function calling this 1145 * @param string $argument the name of the invalid parameter 1146 */ 1147 protected static function validateInteger($test, $min, $max, $source, $argument = "Argument") 1148 { 1149 self::validateIntegerMulti($test, [[$min, $max]], $source, $argument); 1150 } 1151 1152 /** 1153 * Throw an exception if the argument given is not an integer within one of the specified ranges 1154 * 1155 * @param int $test the input to test 1156 * @param array $ranges array of two-item min/max ranges. 1157 * @param string $source the name of the function calling this 1158 * @param string $source the name of the function calling this 1159 * @param string $argument the name of the invalid parameter 1160 */ 1161 protected static function validateIntegerMulti($test, array $ranges, $source, $argument = "Argument") 1162 { 1163 if (!is_integer($test)) { 1164 throw new InvalidArgumentException("$argument given to $source must be a number, but '$test' was given."); 1165 } 1166 $match = false; 1167 foreach ($ranges as $range) { 1168 $match |= $test >= $range[0] && $test <= $range[1]; 1169 } 1170 if (!$match) { 1171 // Put together a good error "range 1-2 or 4-6" 1172 $rangeStr = "range "; 1173 for ($i = 0; $i < count($ranges); $i++) { 1174 $rangeStr .= $ranges[$i][0] . "-" . $ranges[$i][1]; 1175 if ($i == count($ranges) - 1) { 1176 continue; 1177 } elseif ($i == count($ranges) - 2) { 1178 $rangeStr .= " or "; 1179 } else { 1180 $rangeStr .= ", "; 1181 } 1182 } 1183 throw new InvalidArgumentException("$argument given to $source must be in $rangeStr, but $test was given."); 1184 } 1185 } 1186 1187 /** 1188 * Throw an exception if the argument given can't be cast to a string 1189 * 1190 * @param string $test the input to test 1191 * @param string $source the name of the function calling this 1192 * @param string $argument the name of the parameter being validated 1193 * @throws InvalidArgumentException Where the argument is not valid 1194 */ 1195 protected static function validateString($test, $source, $argument = "Argument") 1196 { 1197 if (is_object($test) && !method_exists($test, '__toString')) { 1198 throw new InvalidArgumentException("$argument to $source must be a string"); 1199 } 1200 } 1201 1202 /** 1203 * Throw an exception if the argument doesn't match the given regex. 1204 * 1205 * @param string $test the input to test 1206 * @param string $source the name of the function calling this 1207 * @param string $regex valid values for this attribute, as a regex 1208 * @param string $argument the name of the parameter being validated 1209 * @throws InvalidArgumentException Where the argument is not valid 1210 */ 1211 protected static function validateStringRegex($test, $source, $regex, $argument = "Argument") 1212 { 1213 if (preg_match($regex, $test) === 0) { 1214 throw new InvalidArgumentException("$argument given to $source is invalid. It should match regex '$regex', but '$test' was given."); 1215 } 1216 } 1217} 1218