From 6b722ca7fdde04bfbc6dc3739a02b7c6601c7b0f Mon Sep 17 00:00:00 2001 From: Khoren Markosyan Date: Sat, 7 Jan 2023 17:23:04 +0400 Subject: [PATCH] added more validations in encoding codes --- lib/src/logic/zxing.dart | 2 +- lib/src/models/format.dart | 75 +++++++++++++++++++++++++++++++---- lib/src/ui/writer_widget.dart | 49 ++++++++++++++++------- 3 files changed, 103 insertions(+), 23 deletions(-) diff --git a/lib/src/logic/zxing.dart b/lib/src/logic/zxing.dart index e4c22e4..9e96ffb 100644 --- a/lib/src/logic/zxing.dart +++ b/lib/src/logic/zxing.dart @@ -29,7 +29,7 @@ void setZxingLogEnabled(bool enabled) => bindings.setLogEnabled(enabled ? 1 : 0); /// Returns a readable barcode format name -String zxingBarcodeFormatName(int format) => formatNames[format] ?? 'Unknown'; +String zxingBarcodeFormatName(int format) => barcodeNames[format] ?? 'Unknown'; extension Uint8ListBlobConversion on Uint8List { /// Allocates a pointer filled with the Uint8List data. diff --git a/lib/src/models/format.dart b/lib/src/models/format.dart index 6d3fda9..ee948ab 100644 --- a/lib/src/models/format.dart +++ b/lib/src/models/format.dart @@ -35,22 +35,24 @@ abstract class Format { static const int any = oneDCodes | twoDCodes; } -extension EccSupportedExtension on int { +extension CodeFormat on int { + String get name => barcodeNames[this] ?? 'Unknown'; + + // The width divided by the height of the barcode + double get ratio => barcodeRatios[this] ?? 1.0; + String get demoText => barcodeDemoText[this] ?? ''; + int get maxTextLength => barcodeMaxTextLengths[this] ?? 0; bool get isSupportedEccLevel => eccSupported.contains(this); static final List eccSupported = [ Format.qrCode, ]; -} - -extension CodeFormat on Format { - String get name => formatNames[this] ?? 'Unknown'; - static final List writerFormats = [ + static final List supportedEncodeFormats = [ Format.qrCode, Format.dataMatrix, Format.aztec, - Format.pdf417, + // Format.pdf417, Format.codabar, Format.code39, Format.code93, @@ -66,7 +68,7 @@ extension CodeFormat on Format { ]; } -final Map formatNames = { +final Map barcodeNames = { Format.none: 'None', Format.aztec: 'Aztec', Format.codabar: 'CodaBar', @@ -88,3 +90,60 @@ final Map formatNames = { Format.twoDCodes: 'TwoD', Format.any: 'Any', }; + +final Map barcodeRatios = { + Format.aztec: 3.0 / 3.0, // recommended ratio: 3:3 (square) + Format.codabar: 3.0 / 1.0, // recommended ratio: 3:1 + Format.code39: 3.0 / 1.0, // recommended ratio: 3:1 + Format.code93: 3.0 / 1.0, // recommended ratio: 3:1 + Format.code128: 2.0 / 1.0, // recommended ratio: 2:1 + Format.dataBar: 3.0 / 1.0, // recommended ratio: 3:1 + Format.dataBarExpanded: 1.0 / 1.0, // recommended ratio: 1:1 (square) + Format.dataMatrix: 3.0 / 3.0, // recommended ratio: 3:3 (square) + Format.ean8: 3.0 / 1.0, // recommended ratio: 3:1 + Format.ean13: 3.0 / 1.0, // recommended ratio: 3:1 + Format.itf: 3.0 / 1.0, // recommended ratio: 3:1 + Format.maxiCode: 3.0 / 3.0, // recommended ratio: 3:3 (square) + Format.pdf417: 3.0 / 1.0, // recommended ratio: 3:1 + Format.qrCode: 3.0 / 3.0, // recommended ratio: 3:3 (square) + Format.upca: 3.0 / 1.0, // recommended ratio: 3:1 + Format.upce: 1.0 / 1.0, // recommended ratio: 1:1 (square) +}; + +final Map barcodeDemoText = { + Format.aztec: 'This is an Aztec Code', + Format.codabar: 'A123456789B', + Format.code39: 'ABC-1234', + Format.code93: 'ABC-1234-/+', + Format.code128: 'ABC-abc-1234', + Format.dataBar: '0123456789012', + Format.dataBarExpanded: '011234567890123-ABCabc', + Format.dataMatrix: 'This is a Data Matrix', + Format.ean8: '9031101', + Format.ean13: '978020137962', + Format.itf: '00012345600012', + Format.maxiCode: 'This is a MaxiCode', + Format.pdf417: 'This is a PDF417', + Format.qrCode: 'This is a QR Code', + Format.upca: '72527273070', + Format.upce: '0123456', +}; + +final Map barcodeMaxTextLengths = { + Format.aztec: 3832, + Format.codabar: 20, + Format.code39: 43, + Format.code93: 47, + Format.code128: 2046, + Format.dataBar: 74, + Format.dataBarExpanded: 4107, + Format.dataMatrix: 2335, + Format.ean8: 8, + Format.ean13: 13, + Format.itf: 20, + Format.maxiCode: 30, + Format.pdf417: 2953, + Format.qrCode: 4296, + Format.upca: 12, + Format.upce: 8, +}; diff --git a/lib/src/ui/writer_widget.dart b/lib/src/ui/writer_widget.dart index e57dcff..11e3903 100644 --- a/lib/src/ui/writer_widget.dart +++ b/lib/src/ui/writer_widget.dart @@ -9,10 +9,9 @@ import '../../flutter_zxing.dart'; class WriterWidget extends StatefulWidget { const WriterWidget({ super.key, - this.text = '', + this.text, this.format = Format.qrCode, - this.width = 120, - this.height = 120, + this.height = 120, // Width is calculated from height and format ratio this.margin = 0, this.eccLevel = EccLevel.low, this.messages = const Messages(), @@ -20,9 +19,8 @@ class WriterWidget extends StatefulWidget { this.onError, }); - final String text; + final String? text; final int format; - final int width; final int height; final int margin; final EccLevel eccLevel; @@ -44,8 +42,7 @@ class _WriterWidgetState extends State bool isAndroid() => Theme.of(context).platform == TargetPlatform.android; - final int _maxTextLength = 2000; - final List _supportedFormats = CodeFormat.writerFormats; + final List _supportedFormats = CodeFormat.supportedEncodeFormats; int _codeFormat = Format.qrCode; EccLevel _eccLevel = EccLevel.low; @@ -60,12 +57,13 @@ class _WriterWidgetState extends State @override void initState() { - _textController.text = widget.text; - _widthController.text = widget.width.toString(); + _codeFormat = widget.format; + _eccLevel = widget.eccLevel; + _textController.text = widget.text ?? _codeFormat.demoText; + _widthController.text = + (widget.height * _codeFormat.ratio).round().toString(); _heightController.text = widget.height.toString(); _marginController.text = widget.margin.toString(); - _eccLevel = widget.eccLevel; - _codeFormat = widget.format; super.initState(); } @@ -95,7 +93,7 @@ class _WriterWidgetState extends State controller: _textController, keyboardType: TextInputType.multiline, maxLines: null, - maxLength: _maxTextLength, + maxLength: _codeFormat.maxTextLength, onChanged: (String value) { setState(() {}); }, @@ -104,7 +102,7 @@ class _WriterWidgetState extends State filled: true, labelText: messages.textLabel, counterText: - '${_textController.value.text.length} / $_maxTextLength', + '${_textController.value.text.length} / ${_codeFormat.maxTextLength}', ), validator: (String? value) { if (value?.isEmpty ?? false) { @@ -134,6 +132,12 @@ class _WriterWidgetState extends State onChanged: (int? format) { setState(() { _codeFormat = format ?? Format.qrCode; + _textController.text = _codeFormat.demoText; + _heightController.text = widget.height.toString(); + _widthController.text = + (widget.height * _codeFormat.ratio) + .round() + .toString(); }); }, ), @@ -182,6 +186,15 @@ class _WriterWidgetState extends State } return null; }, + onChanged: (String value) { + // use format ratio to calculate height + final int? width = int.tryParse(value); + if (width != null) { + final int height = + (width / _codeFormat.ratio).round(); + _heightController.text = height.toString(); + } + }, ), ), // const SizedBox(width: 8), @@ -199,6 +212,15 @@ class _WriterWidgetState extends State } return null; }, + onChanged: (String value) { + // use format ratio to calculate width + final int? height = int.tryParse(value); + if (height != null) { + final int width = + (height * _codeFormat.ratio).round(); + _widthController.text = width.toString(); + } + }, ), ), Flexible( @@ -219,7 +241,6 @@ class _WriterWidgetState extends State ), ], ), - const SizedBox(height: 20), // Write button ElevatedButton(