-
Notifications
You must be signed in to change notification settings - Fork 861
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for right-to-left text output #6
Comments
Sure, good suggestion. This would take the form of a function to switch between the (default) CP437 and the Arabic character sets Windows-1256, CP720 and CP864, as well as a new textRaw() function which behaves the same as the current text() function. In the long run, text() is likely to be modified to accept UTF-8 and auto-switch code pages when needed. This is will be a simple change, but it will be quite annoying to work with, as you'll have to encode each character in hex according to the new code page. |
Hi Sam, Can you try sending the output of example/character-set.php to your printer and get me a description of what it prints? I have the three code pages displaying on my TM-T20, but I'd be interested to know how it goes. I'll leave this enhancement open, as there is still more to do in the character encoding space. |
Thanks, this post contains a lot of very useful information. I had assumed (incorrectly) that the character code tables were the same between Epson and non-Epson models, but the test print confirms that they are different, and explains why your printer was spitting out Hebrew with my code. I'll see if I can put together another test. Two quick queries-
|
Please try this string for the test. You are right Arabic is RTL, but in the example receipt it is not written RTL. But I have sen some receipts where Arabic is written in RTL orientation. |
First attempt- I'm using iconv to convert the string from UTF8 to CP864 and CP1256 (It looks like both will be needed) Some of the characters are visibly different.
I haven't yet sorted out text direction, but if we have the characters, and your output is similar, then this will be a good starting point to code Arabic support into the driver properly. <?php
require_once(dirname(__FILE__) . "/Escpos.php");
$printer = new Escpos();
$str = "ص.ب. ١١٠٦ ر.ب. ٣١١ صحار، سلطنة عمان";
// Epson character tables
//$try = array(
// 37 => 'CP864',
// 50 => 'CP1256');
// E-pos TEP 200M character tables
$try = array(
28 => 'CP864',
34 => 'CP1256');
foreach($try as $targetNumber => $targetEncoding) {
$map = makeMap($targetEncoding);
$outp = convert($str, $map);
$printer -> selectCharacterTable($targetNumber);
$printer -> textRaw(strrev($outp) . "\n");
}
$printer -> cut();
function convert($str, $map) {
// Convert UTF8 to the target encoding
$len = mb_strlen($str);
$outp = str_repeat("?", $len);
for($i = 0; $i < $len; $i++) {
$utf8 = mb_substr($str, $i, 1);
if(isset($map[$utf8])) {
$outp[$i] = $map[$utf8];
}
}
return $outp;
}
function makeMap($targetEncoding) {
// Make map of target encoding v UTF-8
$map = array();
for($i = 0; $i < 255; $i++) {
$native = chr($i);
$utf8 = @iconv($targetEncoding, 'UTF-8', $native);
if($utf8 == '') {
continue;
}
$map[$utf8] = $native;
}
return $map;
} |
Ok, not to worry. Our computers are generating different output. This means that either your text editor has different encoding to mine (UTF-8), our our versions of Re the number-direction, I can see that one, and I'll need to script up a Unicode layout engine to render this correctly. I have three more things I'd like you to run to get to the bottom of this. (1) I need to rule out the character encoding of your text editor as a factor. I was expecting UTF-8 <?php
$str = "ص.ب. ١١٠٦ ر.ب. ٣١١ صحار، سلطنة عمان";
echo base64_encode($str) . "\n";
// I get 2LUu2KguINmh2aHZoNmmINixLtioLiDZo9mh2aEg2LXYrdin2LHYjCDYs9mE2LfZhtipINi52YXYp9mG (2) I've switched of error-supression on <?php
/* Changing these for my setup */
require_once(dirname(__FILE__) . "/../Escpos.php");
$fp = fopen ("LPT2", "w");
$printer = new Escpos($fp);
// Using base64-encoded UTF-8 in case the above text is not UTF-8
$str = base64_decode("2LUu2KguINmh2aHZoNmmINixLtioLiDZo9mh2aEg2LXYrdin2LHYjCDYs9mE2LfZhtipINi52YXYp9mG");
// Epson character tables
//$try = array(
// 37 => 'CP864',
// 50 => 'CP1256');
// E-pos TEP 200M character tables
$try = array(
28 => 'CP864',
29 => 'CPW1001',
33 => 'CP720',
34 => 'CP1256' ,
63 => 'CP864',
34 => 'CP1256',
82 => 'CP1001'
);
foreach($try as $targetNumber => $targetEncoding) {
$map = makeMap($targetEncoding);
$outp = convert($str, $map);
/* Print test output */
$printer -> selectCharacterTable($targetNumber);
$printer -> text($targetNumber." : ".$targetEncoding. "\n");
if(count($map) == 0) {
$printer -> text("Can't make $targetEncoding output with iconv.\n");
} else {
$printer -> textRaw(strrev($outp) . "\n");
}
compactCharTable($printer, 8);
}
$printer -> feed(2);
$printer -> cut();
function convert($str, $map) {
// Convert UTF8 to the target encoding
$len = mb_strlen($str);
$outp = str_repeat("?", $len);
for($i = 0; $i < $len; $i++) {
$utf8 = mb_substr($str, $i, 1);
if(isset($map[$utf8])) {
$outp[$i] = $map[$utf8];
}
}
return $outp;
}
function makeMap($targetEncoding) {
// Make map of target encoding v UTF-8
$map = array();
for($i = 0; $i < 255; $i++) {
$native = chr($i);
$utf8 = iconv($targetEncoding, 'UTF-8', $native);
if($utf8 == '') {
continue;
}
$map[$utf8] = $native;
}
return $map;
}
function compactCharTable($printer, $start = 2) {
// Output a table of characters for a code
$chars = str_repeat(' ', 256);
for($i = 0; $i < 255; $i++) {
$chars[$i] = ($i > 32 && $i != 127) ? chr($i) : ' ';
}
$printer -> setEmphasis(true);
$printer -> textRaw(" 0123456789ABCDEF\n");
$printer -> setEmphasis(false);
for($y = $start; $y < 16; $y++) {
$printer -> setEmphasis(true);
$printer -> textRaw(strtoupper(dechex($y)) . " ");
$printer -> setEmphasis(false);
$printer -> textRaw(substr($chars,$y * 16, 16) . "\n");
}
} (3) I've run the above script on my computer and saved the output, so this version should look similar to the above, but I'm hoping it contains the strings that I sent yesterday, under CP1256 and CP864 (I have no automated way to generate output in the other code pages). I'm most interested in the strings here: <?php
$fp = fopen ("LPT2", "w");
$str = "G0AbdBwyOCA6IENQODY0Cj8/Pz8gPz8/Pz8grD8/Pz8gsbGzIC4/Lj8gtrCxsSAuPy4/ChtFASAg".
"MDEyMzQ1Njc4OUFCQ0RFRgobRQAbRQE4IBtFAICBgoOEhYaHiImKi4yNjo8KG0UBOSAbRQCQkZKT".
"lJWWl5iZmpucnZ6fChtFAUEgG0UAoKGio6SlpqeoqaqrrK2urwobRQFCIBtFALCxsrO0tba3uLm6".
"u7y9vr8KG0UBQyAbRQDAwcLDxMXGx8jJysvMzc7PChtFAUQgG0UA0NHS09TV1tfY2drb3N3e3wob".
"RQFFIBtFAODh4uPk5ebn6Onq6+zt7u8KG0UBRiAbRQDw8fLz9PX29/j5+vv8/f4gCht0HTI5IDog".
"Q1BXMTAwMQpDYW4ndCBtYWtlIENQVzEwMDEgb3V0cHV0IHdpdGggaWNvbnYuChtFASAgMDEyMzQ1".
"Njc4OUFCQ0RFRgobRQAbRQE4IBtFAICBgoOEhYaHiImKi4yNjo8KG0UBOSAbRQCQkZKTlJWWl5iZ".
"mpucnZ6fChtFAUEgG0UAoKGio6SlpqeoqaqrrK2urwobRQFCIBtFALCxsrO0tba3uLm6u7y9vr8K".
"G0UBQyAbRQDAwcLDxMXGx8jJysvMzc7PChtFAUQgG0UA0NHS09TV1tfY2drb3N3e3wobRQFFIBtF".
"AODh4uPk5ebn6Onq6+zt7u8KG0UBRiAbRQDw8fLz9PX29/j5+vv8/f4gCht0ITMzIDogQ1A3MjAK".
"Q2FuJ3QgbWFrZSBDUDcyMCBvdXRwdXQgd2l0aCBpY29udi4KG0UBICAwMTIzNDU2Nzg5QUJDREVG".
"ChtFABtFATggG0UAgIGCg4SFhoeIiYqLjI2OjwobRQE5IBtFAJCRkpOUlZaXmJmam5ydnp8KG0UB".
"QSAbRQCgoaKjpKWmp6ipqqusra6vChtFAUIgG0UAsLGys7S1tre4ubq7vL2+vwobRQFDIBtFAMDB".
"wsPExcbHyMnKy8zNzs8KG0UBRCAbRQDQ0dLT1NXW19jZ2tvc3d7fChtFAUUgG0UA4OHi4+Tl5ufo".
"6err7O3u7wobRQFGIBtFAPDx8vP09fb3+Pn6+/z9/iAKG3QiMzQgOiBDUDEyNTYK5Mfj2iDJ5Njh".
"0yCh0cfN1SA/Pz8gLsgu0SA/Pz8/IC7ILtUKG0UBICAwMTIzNDU2Nzg5QUJDREVGChtFABtFATgg".
"G0UAgIGCg4SFhoeIiYqLjI2OjwobRQE5IBtFAJCRkpOUlZaXmJmam5ydnp8KG0UBQSAbRQCgoaKj".
"pKWmp6ipqqusra6vChtFAUIgG0UAsLGys7S1tre4ubq7vL2+vwobRQFDIBtFAMDBwsPExcbHyMnK".
"y8zNzs8KG0UBRCAbRQDQ0dLT1NXW19jZ2tvc3d7fChtFAUUgG0UA4OHi4+Tl5ufo6err7O3u7wob".
"RQFGIBtFAPDx8vP09fb3+Pn6+/z9/iAKG3Q/NjMgOiBDUDg2NAo/Pz8/ID8/Pz8/IKw/Pz8/ILGx".
"syAuPy4/ILawsbEgLj8uPwobRQEgIDAxMjM0NTY3ODlBQkNERUYKG0UAG0UBOCAbRQCAgYKDhIWG".
"h4iJiouMjY6PChtFATkgG0UAkJGSk5SVlpeYmZqbnJ2enwobRQFBIBtFAKChoqOkpaanqKmqq6yt".
"rq8KG0UBQiAbRQCwsbKztLW2t7i5uru8vb6/ChtFAUMgG0UAwMHCw8TFxsfIycrLzM3OzwobRQFE".
"IBtFANDR0tPU1dbX2Nna29zd3t8KG0UBRSAbRQDg4eLj5OXm5+jp6uvs7e7vChtFAUYgG0UA8PHy".
"8/T19vf4+fr7/P3+IAobdFI4MiA6IENQMTAwMQpDYW4ndCBtYWtlIENQMTAwMSBvdXRwdXQgd2l0".
"aCBpY29udi4KG0UBICAwMTIzNDU2Nzg5QUJDREVGChtFABtFATggG0UAgIGCg4SFhoeIiYqLjI2O".
"jwobRQE5IBtFAJCRkpOUlZaXmJmam5ydnp8KG0UBQSAbRQCgoaKjpKWmp6ipqqusra6vChtFAUIg".
"G0UAsLGys7S1tre4ubq7vL2+vwobRQFDIBtFAMDBwsPExcbHyMnKy8zNzs8KG0UBRCAbRQDQ0dLT".
"1NXW19jZ2tvc3d7fChtFAUUgG0UA4OHi4+Tl5ufo6err7O3u7wobRQFGIBtFAPDx8vP09fb3+Pn6".
"+/z9/iAKG2QCHVZBAw==";
fwrite($fp, base64_decode($str)); Thanks for sticking with this. I know it's a lot of questions, but we should have a better library in the end! |
Thanks. This output is enough for me to start coding with. Looks like your <?php
// Check internal encoding, the previous scripts assumed UTF-8
echo mb_internal_encoding() . "\n\n";
// Lengths seem to be different on your computer
$str = "ص.ب. ١١٠٦ ر.ب. ٣١١ صحار، سلطنة عمان";
echo mb_strlen($str) . "\n";
echo mb_strlen($str, 'UTF-8') . "\n";
?> Output for me (should be different for you if I've debugged this right):
This is quite an extensive thing to implement properly, so it will take me a few weeks to get it working in a cross-platform, cross-printer way. In the meantime, if I know that this is the only remaining issue, I'll be able to put together a minimal example to send your test string to your specific printer, which should hopefully solve your immediate issue. |
Hi Mike, the output is in the same line even there is "\n" for line break, but still the output is on the same line |
Hi Mike, you have any updates for me related to this enhancement? |
Hi, Nothing quite yet. I'm working on a snippet which will let you pass mixed RTL/LTR unicode text to the printer as a series of text chunks labelled with code-page and direction, but it's not yet complete. |
Hello, Added a new <?php
require_once(dirname(__FILE__) . "/../Escpos.php");
require_once(dirname(__FILE__) . "/../src/RTLBuffer.php");
/*
* Example of how to use the current work-around for bi-directional text.
*/
// Instantiate printer as normal
$printer = new Escpos();
// Different character tables for each printer
// $epsonEncodings = array( // Epson character tables used for testing
// 'CP437' => 0,
// 'CP1256' => 50,
// 'CP864' => 37);
$eposEncodings = array( // E-pos TEP 200M character tables
'CP437' => 0,
'CP1256' => 34,
'CP864' => 63);
$buf = new RTLBuffer($printer, $eposEncodings, array('CP1256'));
// Call one output() statement per line.
$buf -> output("ص.ب. ١١٠٦ ر.ب. ٣١١ صحار، سلطنة عمان");
$printer -> feed(2);
$printer -> cut();
$printer -> close(); Which will hopefully get this output: This is not a very smart algorithm, so try not to send anything too complex :). It works like this:
I'm simply not cut out to attempt to produce combined characters correctly, but hopefully this un-sohisticated text layout engine is sufficient for your use case. Let me know how it goes! |
Hi Mike, I cannot find the mentioned files, have you updated the code in the repo? example/rtl-example.php |
Hi Sam, It's in the
|
Sorry Mike, My mistake, i overlooked that line... i already tested this script, the output on my printer is exactly same as your output. But this doesn't suffice my requirement. But this is indeed a good way to printout numerals and individual letters. Mike, i checked with few vendors who provide arabic text printing on the thermal printers. They are using another approach, they convert the arabic text to png image on the fly and then print it. Also there is one library named PHP-Ar, that might help you in this enhancement. |
Hi Sam, Very different approach. There are some improvements in the pipeline around image support (#16 #13), so I may be able to add in some text helper functions somewhere. I'm sure a text-as-graphics option would also be useful for others (it lets you use non-monospace fonts, additional characters, and so on). Some quick tests with PHP-Ar seem to show:
|
It looks like due to the complexity of the script and the characteristics of mixed LTR/RTL text, it is not feasible to implement a native esc/pos text rendering of Arabic text in this driver at the moment. I've uploaded the example script which I've been working with, which uses the It shows a number of limitations, but also illustrates the fact that it should be possible to make a system which prints Arabic:
Because most of these limitations are covered by other missing functionality (alignment, fonts), deficiencies in features available in external libraries (ImageMagick, PHP-Ar), no more action is likely in this bug report as far as I can. If there's no new information or feedback on the image-based print example for a few weeks, I'll go ahead and close this thread. |
Hi Guys, I was able to print Arabic letters with above code when using below code page:
|
I'm going to close this issue off, as the discussion has run its course, and the remaining scope does not appear to be technically feasible to implement. Specifically, I don't know of a high-quality way to transform bi-directional Arabic text from UTF-8 to native ESC/POS (using the legacy code pages that are built into the printer). The original use case (Arabic printing on receipts) can now be achieved via images, using the I'm open to suggestions that would allow this to be implemented with native ESC/POS output, which would be faster and more readable. Please follow up if you can demonstrate a snippet that will transform UTF-8 bi-directional Arabic text to these legacy code pages, and I'll work on it as a new feature request. |
Well i found a work around on this issue what I converted my print file to html first with wkhtmltopdf along with all the data then converted it to a Low Resolution png image using this command Here is the code for printing the image to escpos. `<?php $connector = null; try {
} catch (Exception $e) { |
hi mike i just have a question why is it that the justify_center sometimes work and sometimes it doesn`t in my POS-58 thermal printer? |
hi mike42
|
Hi Mike,
I am here with yet another change. I want to add Arabic Printing support for thermal printers also. can you please write a function to change the code page.
Thanks,
Sam
The text was updated successfully, but these errors were encountered: