From c5d3ec331ecbbee9f5a40668b8ef7d9d02bcbf3b Mon Sep 17 00:00:00 2001 From: Jack Zhao Date: Wed, 14 Sep 2022 16:12:09 -0700 Subject: [PATCH 1/5] Fixed new line not being printed on some printers --- lib/src/generator.dart | 4 ++-- lib/src/pos_column.dart | 3 +-- pubspec.lock | 21 ++++++++++++++------- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/lib/src/generator.dart b/lib/src/generator.dart index 6b464a6..d8b6f69 100644 --- a/lib/src/generator.dart +++ b/lib/src/generator.dart @@ -498,7 +498,7 @@ class Generator { } else { // Insert an empty col nextRow.add(PosColumn( - text: '', width: cols[i].width, styles: cols[i].styles)); + text: ' ', width: cols[i].width, styles: cols[i].styles)); } // end rows splitting bytes += _text( @@ -533,7 +533,7 @@ class Generator { } else { // Insert an empty col nextRow.add(PosColumn( - text: '', width: cols[i].width, styles: cols[i].styles)); + text: ' ', width: cols[i].width, styles: cols[i].styles)); } // Print current row diff --git a/lib/src/pos_column.dart b/lib/src/pos_column.dart index 9a1ba50..e2ecc9d 100644 --- a/lib/src/pos_column.dart +++ b/lib/src/pos_column.dart @@ -23,8 +23,7 @@ class PosColumn { if (width < 1 || width > 12) { throw Exception('Column width must be between 1..12'); } - if (text != null && - text.length > 0 && + if (text.length > 0 && textEncoded != null && textEncoded!.length > 0) { throw Exception( diff --git a/pubspec.lock b/pubspec.lock index 3447480..9a85c45 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -49,7 +49,7 @@ packages: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0" + version: "1.16.0" crypto: dependency: transitive description: @@ -70,7 +70,7 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.0" flutter: dependency: "direct main" description: flutter @@ -116,6 +116,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.12.11" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4" meta: dependency: transitive description: @@ -129,7 +136,7 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.1" petitparser: dependency: transitive description: @@ -148,7 +155,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.2" stack_trace: dependency: transitive description: @@ -183,7 +190,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.3" + version: "0.4.9" typed_data: dependency: transitive description: @@ -197,7 +204,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.2" xml: dependency: transitive description: @@ -206,4 +213,4 @@ packages: source: hosted version: "5.3.0" sdks: - dart: ">=2.14.0 <3.0.0" + dart: ">=2.17.0-0 <3.0.0" From 62e48dc8708932b3ad2e01e3f791b70c931f10e4 Mon Sep 17 00:00:00 2001 From: Jack Zhao Date: Wed, 14 Sep 2022 16:20:13 -0700 Subject: [PATCH 2/5] Fixed change row --- lib/src/generator.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/generator.dart b/lib/src/generator.dart index d8b6f69..57793c9 100644 --- a/lib/src/generator.dart +++ b/lib/src/generator.dart @@ -559,7 +559,7 @@ class Generator { bytes += emptyLines(1); if (isNextRow) { - row(nextRow); + bytes += row(nextRow); } return bytes; } From bb18f37633c8be51216009546198b7b1ea7a0668 Mon Sep 17 00:00:00 2001 From: Jack Zhao Date: Wed, 14 Sep 2022 16:21:23 -0700 Subject: [PATCH 3/5] Fixed CJK String overlapping issue --- lib/src/generator.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/src/generator.dart b/lib/src/generator.dart index 57793c9..5633f4e 100644 --- a/lib/src/generator.dart +++ b/lib/src/generator.dart @@ -542,16 +542,18 @@ class Generator { final List isLexemeChinese = list[1]; // Print each lexeme using codetable OR kanji + int? colIndex = colInd; for (var j = 0; j < lexemes.length; ++j) { bytes += _text( _encode(lexemes[j], isKanji: isLexemeChinese[j]), styles: cols[i].styles, - colInd: colInd, + colInd: colIndex, colWidth: cols[i].width, isKanji: isLexemeChinese[j], ); // Define the absolute position only once (we print one line only) // colInd = null; + colIndex = null; } } } From 8e3e950a947fd9b2dcc97a5a7f4710c8210bcf23 Mon Sep 17 00:00:00 2001 From: Jack Zhao Date: Wed, 14 Sep 2022 17:57:14 -0700 Subject: [PATCH 4/5] Align right fix attempt --- lib/src/generator.dart | 192 +++++++++++++++++++----------------- lib/src/text_with_type.dart | 44 +++++++++ 2 files changed, 148 insertions(+), 88 deletions(-) create mode 100644 lib/src/text_with_type.dart diff --git a/lib/src/generator.dart b/lib/src/generator.dart index 5633f4e..54bf1f2 100644 --- a/lib/src/generator.dart +++ b/lib/src/generator.dart @@ -7,10 +7,12 @@ */ import 'dart:convert'; +import 'dart:ffi'; import 'dart:typed_data' show Uint8List; import 'package:hex/hex.dart'; import 'package:image/image.dart'; -import 'package:gbk_codec/gbk_codec.dart'; +// import 'package:gbk_codec/gbk_codec.dart'; +import 'package:esc_pos_utils/src/text_with_type.dart'; import 'package:esc_pos_utils/esc_pos_utils.dart'; import 'enums.dart'; import 'commands.dart'; @@ -65,24 +67,26 @@ class Generator { return charsPerLine; } - Uint8List _encode(String text, {bool isKanji = false}) { - // replace some non-ascii characters - text = text - .replaceAll("’", "'") - .replaceAll("´", "'") - .replaceAll("»", '"') - .replaceAll(" ", ' ') - .replaceAll("•", '.'); - if (!isKanji) { - return latin1.encode(text); - } else { - return Uint8List.fromList(gbk_bytes.encode(text)); - } - } - - List _getLexemes(String text) { - final List lexemes = []; - final List isLexemeChinese = []; + // Uint8List _encode(String text, {bool isKanji = false}) { + // // replace some non-ascii characters + // text = text + // .replaceAll("’", "'") + // .replaceAll("´", "'") + // .replaceAll("»", '"') + // .replaceAll(" ", ' ') + // .replaceAll("•", '.'); + // if (!isKanji) { + // return latin1.encode(text); + // } else { + // return Uint8List.fromList(gbk_bytes.encode(text)); + // } + // } + + // List _getLexemes(String text) { + // final List lexemes = []; + // final List isLexemeChinese = []; + List _splitByTextType(String text) { + final List textWithType = []; int start = 0; int end = 0; bool curLexemeChinese = _isChinese(text[0]); @@ -90,17 +94,26 @@ class Generator { if (curLexemeChinese == _isChinese(text[i])) { end += 1; } else { - lexemes.add(text.substring(start, end + 1)); - isLexemeChinese.add(curLexemeChinese); + // lexemes.add(text.substring(start, end + 1)); + // isLexemeChinese.add(curLexemeChinese); + textWithType.add(TextWithType.fromText( + text: text.substring(start, end + 1), + isCjk: curLexemeChinese, + )); start = i; end = i; curLexemeChinese = !curLexemeChinese; } } - lexemes.add(text.substring(start, end + 1)); - isLexemeChinese.add(curLexemeChinese); + // lexemes.add(text.substring(start, end + 1)); + // isLexemeChinese.add(curLexemeChinese); + textWithType.add(TextWithType.fromText( + text: text.substring(start, end + 1), + isCjk: curLexemeChinese, + )); + return textWithType; - return [lexemes, isLexemeChinese]; + // return [lexemes, isLexemeChinese]; } /// Break text into chinese/non-chinese lexemes @@ -351,15 +364,23 @@ class Generator { List bytes = []; if (!containsChinese) { bytes += _text( - _encode(text, isKanji: containsChinese), + // _encode(text, isKanji: containsChinese), + [TextWithType.fromText(text: text, isCjk: containsChinese)], styles: styles, - isKanji: containsChinese, + // isKanji: containsChinese, maxCharsPerLine: maxCharsPerLine, ); // Ensure at least one line break after the text bytes += emptyLines(linesAfter + 1); } else { - bytes += _mixedKanji(text, styles: styles, linesAfter: linesAfter); + // bytes += _mixedKanji(text, styles: styles, linesAfter: linesAfter); + bytes += _text( + _splitByTextType(text), + styles: styles, + maxCharsPerLine: maxCharsPerLine, + ); + // Ensure at least one line break after the text + bytes += emptyLines(linesAfter + 1); } return bytes; } @@ -479,17 +500,25 @@ class Generator { if (!cols[i].containsChinese) { // CASE 1: containsChinese = false - Uint8List encodedToPrint = cols[i].textEncoded != null - ? cols[i].textEncoded! - : _encode(cols[i].text); + // Uint8List encodedToPrint = cols[i].textEncoded != null + // ? cols[i].textEncoded! + // : _encode(cols[i].text); + var textWithType = cols[i].textEncoded != null + ? TextWithType.fromEncoded(encodedBytes: cols[i].textEncoded!) + : TextWithType.fromText(text: cols[i].text); // If the col's content is too long, split it to the next row - int realCharactersNb = encodedToPrint.length; + // int realCharactersNb = encodedToPrint.length; + int realCharactersNb = textWithType.encodedBytes.length; if (realCharactersNb > maxCharactersNb) { // Print max possible and split to the next row Uint8List encodedToPrintNextRow = - encodedToPrint.sublist(maxCharactersNb); - encodedToPrint = encodedToPrint.sublist(0, maxCharactersNb); + // encodedToPrint.sublist(maxCharactersNb); + // encodedToPrint = encodedToPrint.sublist(0, maxCharactersNb); + textWithType.encodedBytes.sublist(maxCharactersNb); + textWithType = TextWithType.fromEncoded( + encodedBytes: + textWithType.encodedBytes.sublist(0, maxCharactersNb)); isNextRow = true; nextRow.add(PosColumn( textEncoded: encodedToPrintNextRow, @@ -502,7 +531,8 @@ class Generator { } // end rows splitting bytes += _text( - encodedToPrint, + // encodedToPrint, + [textWithType], styles: cols[i].styles, colInd: colInd, colWidth: cols[i].width, @@ -537,24 +567,30 @@ class Generator { } // Print current row - final list = _getLexemes(toPrint); - final List lexemes = list[0]; - final List isLexemeChinese = list[1]; - - // Print each lexeme using codetable OR kanji - int? colIndex = colInd; - for (var j = 0; j < lexemes.length; ++j) { - bytes += _text( - _encode(lexemes[j], isKanji: isLexemeChinese[j]), - styles: cols[i].styles, - colInd: colIndex, - colWidth: cols[i].width, - isKanji: isLexemeChinese[j], - ); - // Define the absolute position only once (we print one line only) - // colInd = null; - colIndex = null; - } + // final list = _getLexemes(toPrint); + // final List lexemes = list[0]; + // final List isLexemeChinese = list[1]; + + // // Print each lexeme using codetable OR kanji + // int? colIndex = colInd; + // for (var j = 0; j < lexemes.length; ++j) { + // bytes += _text( + // _encode(lexemes[j], isKanji: isLexemeChinese[j]), + // styles: cols[i].styles, + // colInd: colIndex, + // colWidth: cols[i].width, + // isKanji: isLexemeChinese[j], + // ); + // // Define the absolute position only once (we print one line only) + // // colInd = null; + // colIndex = null; + // } + bytes += _text( + _splitByTextType(toPrint), + styles: cols[i].styles, + colInd: colInd, + colWidth: cols[i].width, + ); } } @@ -751,7 +787,8 @@ class Generator { int? maxCharsPerLine, }) { List bytes = []; - bytes += _text(textBytes, styles: styles, maxCharsPerLine: maxCharsPerLine); + bytes += _text([TextWithType.fromEncoded(encodedBytes: textBytes)], + styles: styles, maxCharsPerLine: maxCharsPerLine); // Ensure at least one line break after the text bytes += emptyLines(linesAfter + 1); return bytes; @@ -763,10 +800,11 @@ class Generator { /// /// [colInd] range: 0..11. If null: do not define the position List _text( - Uint8List textBytes, { + // Uint8List textBytes, { + List textWithTypes, { PosStyles styles = const PosStyles(), int? colInd = 0, - bool isKanji = false, + // bool isKanji = false, int colWidth = 12, int? maxCharsPerLine, }) { @@ -781,7 +819,12 @@ class Generator { // Update fromPos final double toPos = _colIndToPosition(colInd + colWidth) - spaceBetweenRows; - final double textLen = textBytes.length * charWidth; + // final double textLen = textBytes.length * charWidth; + final int textByteLength = textWithTypes.fold( + 0, + (int previousValue, textWithType) => + previousValue + textWithType.encodedBytes.length); + final double textLen = textByteLength * charWidth; if (styles.align == PosAlign.right) { fromPos = toPos - textLen; @@ -802,39 +845,12 @@ class Generator { ); } - bytes += setStyles(styles, isKanji: isKanji); + // bytes += setStyles(styles, isKanji: isKanji); + textWithTypes.forEach((textWithType) { + bytes += setStyles(styles, isKanji: textWithType.isCjk); - bytes += textBytes; - return bytes; - } - - /// Prints one line of styled mixed (chinese and latin symbols) text - List _mixedKanji( - String text, { - PosStyles styles = const PosStyles(), - int linesAfter = 0, - int? maxCharsPerLine, - }) { - List bytes = []; - final list = _getLexemes(text); - final List lexemes = list[0]; - final List isLexemeChinese = list[1]; - - // Print each lexeme using codetable OR kanji - int? colInd = 0; - for (var i = 0; i < lexemes.length; ++i) { - bytes += _text( - _encode(lexemes[i], isKanji: isLexemeChinese[i]), - styles: styles, - colInd: colInd, - isKanji: isLexemeChinese[i], - maxCharsPerLine: maxCharsPerLine, - ); - // Define the absolute position only once (we print one line only) - colInd = null; - } - - bytes += emptyLines(linesAfter + 1); + bytes += textWithType.encodedBytes; + }); return bytes; } // ************************ (end) Internal command generators ************************ diff --git a/lib/src/text_with_type.dart b/lib/src/text_with_type.dart new file mode 100644 index 0000000..4d552ed --- /dev/null +++ b/lib/src/text_with_type.dart @@ -0,0 +1,44 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:gbk_codec/gbk_codec.dart'; + +class TextWithType { + TextWithType.fromText({ + required this.text, + this.isCjk = false, + }) { + if (text!.length == 0) { + throw Exception('text should be passed'); + } + encodedBytes = _encodeText(text!, isCjk: isCjk); + } + + TextWithType.fromEncoded({ + required this.encodedBytes, + this.isCjk = false, + }) { + if (encodedBytes.length == 0) { + throw Exception('encodedBytes should be passed'); + } + } + + String? text; + bool isCjk; + late Uint8List encodedBytes; + + Uint8List _encodeText(String text, {bool isCjk = false}) { + // replace some non-ascii characters + text = text + .replaceAll("’", "'") + .replaceAll("´", "'") + .replaceAll("»", '"') + .replaceAll(" ", ' ') + .replaceAll("•", '.'); + if (!isCjk) { + return latin1.encode(text); + } else { + return Uint8List.fromList(gbk_bytes.encode(text)); + } + } +} From b4a79494e4d72b964fd872d3468b1254faae1beb Mon Sep 17 00:00:00 2001 From: Jack Zhao Date: Thu, 15 Sep 2022 00:44:31 -0700 Subject: [PATCH 5/5] Fix out of range text --- lib/src/generator.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/src/generator.dart b/lib/src/generator.dart index 54bf1f2..e0797e8 100644 --- a/lib/src/generator.dart +++ b/lib/src/generator.dart @@ -86,6 +86,9 @@ class Generator { // final List lexemes = []; // final List isLexemeChinese = []; List _splitByTextType(String text) { + if (text.isEmpty) { + return []; + } final List textWithType = []; int start = 0; int end = 0;