From 2905ee4c8de47cfdeea4787e465eb827f9b99e8b Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Thu, 5 Dec 2019 03:00:50 +0000 Subject: CTAN sync 201912050300 --- macros/luatex/generic/barracuda/INSTALL.txt | 29 +- macros/luatex/generic/barracuda/README.md | 42 +- macros/luatex/generic/barracuda/TODO.txt | 92 +++ macros/luatex/generic/barracuda/barracuda.pdf | Bin 54826 -> 0 bytes .../generic/barracuda/doc/barracuda-ga-asm.pdf | Bin 0 -> 38718 bytes .../generic/barracuda/doc/barracuda-ga-asm.tex | 148 ++++ .../barracuda/doc/barracuda-manual-tool.tex | 7 + macros/luatex/generic/barracuda/doc/barracuda.pdf | Bin 0 -> 57452 bytes macros/luatex/generic/barracuda/doc/barracuda.tex | 331 +++++++++ .../generic/barracuda/doc/image/8006194056290.pdf | Bin 0 -> 5682 bytes .../generic/barracuda/example/001-13-ean-test.pdf | Bin 23619 -> 0 bytes .../generic/barracuda/example/001-13-ean-test.tex | 220 ------ .../generic/barracuda/example/001-code128-test.lua | 32 - .../generic/barracuda/example/001-i2of5-test.pdf | Bin 19127 -> 0 bytes .../generic/barracuda/example/001-i2of5-test.tex | 187 ----- .../generic/barracuda/example/003-code39-test.pdf | Bin 19827 -> 0 bytes .../generic/barracuda/example/003-code39-test.tex | 53 -- .../generic/barracuda/example/003-ean-test.pdf | Bin 3988 -> 0 bytes .../generic/barracuda/example/003-ean-test.tex | 16 - .../generic/barracuda/example/004-ean-test.lua | 9 - .../generic/barracuda/example/006-code39-test.lua | 45 -- .../luatex/generic/barracuda/example/006-six.svg | 653 ----------------- .../generic/barracuda/example/01-latex-code39.pdf | Bin 3621 -> 0 bytes .../generic/barracuda/example/01-latex-code39.tex | 14 - .../generic/barracuda/example/8006194056290.svg | 89 --- .../luatex/generic/barracuda/example/c128-123.svg | 42 -- macros/luatex/generic/barracuda/lib/barracuda.lua | 116 --- .../generic/barracuda/lib/lib-barcode/barcode.lua | 544 -------------- .../generic/barracuda/lib/lib-barcode/code128.lua | 341 --------- .../generic/barracuda/lib/lib-barcode/code39.lua | 381 ---------- .../generic/barracuda/lib/lib-barcode/ean.lua | 790 --------------------- .../generic/barracuda/lib/lib-barcode/i2of5.lua | 378 ---------- .../generic/barracuda/lib/lib-driver/driver.lua | 400 ----------- .../barracuda/lib/lib-driver/drv-pdfliteral.lua | 284 -------- .../generic/barracuda/lib/lib-driver/drv-svg.lua | 260 ------- .../generic/barracuda/lib/lib-geo/gacanvas.lua | 340 --------- .../generic/barracuda/lib/lib-geo/libgeo.lua | 289 -------- macros/luatex/generic/barracuda/src/barracuda.lua | 116 +++ .../barracuda/src/lib-barcode/brcd-barcode.lua | 544 ++++++++++++++ .../barracuda/src/lib-barcode/brcd-code128.lua | 341 +++++++++ .../barracuda/src/lib-barcode/brcd-code39.lua | 381 ++++++++++ .../generic/barracuda/src/lib-barcode/brcd-ean.lua | 790 +++++++++++++++++++++ .../barracuda/src/lib-barcode/brcd-i2of5.lua | 378 ++++++++++ .../barracuda/src/lib-driver/brcd-driver.lua | 399 +++++++++++ .../src/lib-driver/brcd-drv-pdfliteral.lua | 284 ++++++++ .../barracuda/src/lib-driver/brcd-drv-svg.lua | 260 +++++++ .../barracuda/src/lib-geo/brcd-gacanvas.lua | 340 +++++++++ .../generic/barracuda/src/lib-geo/brcd-libgeo.lua | 289 ++++++++ .../01-barracuda-latex-test.pdf | Bin 0 -> 3621 bytes .../01-barracuda-latex-test.tex | 13 + .../test/test-code128/001-code128-test.lua | 32 + .../test/test-code128/002-code128-test.pdf | Bin 0 -> 22044 bytes .../test/test-code128/002-code128-test.tex | 125 ++++ .../test/test-code128/02-05-pdfliteral.txt | 43 ++ .../barracuda/test/test-code128/c128-123.svg | 42 ++ .../barracuda/test/test-code39/001-code39-test.lua | 41 ++ .../barracuda/test/test-code39/002-code39-test.pdf | Bin 0 -> 22618 bytes .../barracuda/test/test-code39/002-code39-test.tex | 120 ++++ .../barracuda/test/test-code39/003-code39-test.pdf | Bin 0 -> 19827 bytes .../barracuda/test/test-code39/003-code39-test.tex | 53 ++ .../barracuda/test/test-code39/004-code39-test.pdf | Bin 0 -> 15243 bytes .../barracuda/test/test-code39/004-code39-test.tex | 46 ++ .../barracuda/test/test-code39/005-code39-test.lua | 8 + .../barracuda/test/test-code39/006-code39-test.lua | 45 ++ .../generic/barracuda/test/test-code39/006-six.svg | 653 +++++++++++++++++ .../barracuda/test/test-code39/my_barcode.svg | 76 ++ .../barracuda/test/test-ean/001-13-ean-test.pdf | Bin 0 -> 23619 bytes .../barracuda/test/test-ean/001-13-ean-test.tex | 220 ++++++ .../barracuda/test/test-ean/002-ean-test.pdf | Bin 0 -> 10601 bytes .../barracuda/test/test-ean/002-ean-test.tex | 12 + .../barracuda/test/test-ean/003-ean-test.pdf | Bin 0 -> 3901 bytes .../barracuda/test/test-ean/003-ean-test.tex | 16 + .../barracuda/test/test-ean/004-ean-test.lua | 9 + .../barracuda/test/test-ean/8006194056290.svg | 89 +++ .../test-ga-pdfliteral/001-ga-pdfliteral-test.pdf | Bin 0 -> 30290 bytes .../test-ga-pdfliteral/001-ga-pdfliteral-test.tex | 740 +++++++++++++++++++ .../barracuda/test/test-ga-svg/001-ga-svg-test.lua | 28 + .../barracuda/test/test-ga-svg/002-ga-svg-test.lua | 18 + .../generic/barracuda/test/test-ga-svg/test-01.svg | 26 + .../generic/barracuda/test/test-ga-svg/test-02.svg | 17 + .../barracuda/test/test-ga-svg/test-code39.svg | 76 ++ .../barracuda/test/test-i2of5/001-i2of5-test.pdf | Bin 0 -> 19127 bytes .../barracuda/test/test-i2of5/001-i2of5-test.tex | 187 +++++ 83 files changed, 7483 insertions(+), 5506 deletions(-) create mode 100644 macros/luatex/generic/barracuda/TODO.txt delete mode 100644 macros/luatex/generic/barracuda/barracuda.pdf create mode 100644 macros/luatex/generic/barracuda/doc/barracuda-ga-asm.pdf create mode 100644 macros/luatex/generic/barracuda/doc/barracuda-ga-asm.tex create mode 100644 macros/luatex/generic/barracuda/doc/barracuda-manual-tool.tex create mode 100644 macros/luatex/generic/barracuda/doc/barracuda.pdf create mode 100644 macros/luatex/generic/barracuda/doc/barracuda.tex create mode 100644 macros/luatex/generic/barracuda/doc/image/8006194056290.pdf delete mode 100644 macros/luatex/generic/barracuda/example/001-13-ean-test.pdf delete mode 100644 macros/luatex/generic/barracuda/example/001-13-ean-test.tex delete mode 100644 macros/luatex/generic/barracuda/example/001-code128-test.lua delete mode 100644 macros/luatex/generic/barracuda/example/001-i2of5-test.pdf delete mode 100644 macros/luatex/generic/barracuda/example/001-i2of5-test.tex delete mode 100644 macros/luatex/generic/barracuda/example/003-code39-test.pdf delete mode 100644 macros/luatex/generic/barracuda/example/003-code39-test.tex delete mode 100644 macros/luatex/generic/barracuda/example/003-ean-test.pdf delete mode 100644 macros/luatex/generic/barracuda/example/003-ean-test.tex delete mode 100644 macros/luatex/generic/barracuda/example/004-ean-test.lua delete mode 100644 macros/luatex/generic/barracuda/example/006-code39-test.lua delete mode 100644 macros/luatex/generic/barracuda/example/006-six.svg delete mode 100644 macros/luatex/generic/barracuda/example/01-latex-code39.pdf delete mode 100644 macros/luatex/generic/barracuda/example/01-latex-code39.tex delete mode 100644 macros/luatex/generic/barracuda/example/8006194056290.svg delete mode 100644 macros/luatex/generic/barracuda/example/c128-123.svg delete mode 100644 macros/luatex/generic/barracuda/lib/barracuda.lua delete mode 100644 macros/luatex/generic/barracuda/lib/lib-barcode/barcode.lua delete mode 100644 macros/luatex/generic/barracuda/lib/lib-barcode/code128.lua delete mode 100644 macros/luatex/generic/barracuda/lib/lib-barcode/code39.lua delete mode 100644 macros/luatex/generic/barracuda/lib/lib-barcode/ean.lua delete mode 100644 macros/luatex/generic/barracuda/lib/lib-barcode/i2of5.lua delete mode 100644 macros/luatex/generic/barracuda/lib/lib-driver/driver.lua delete mode 100644 macros/luatex/generic/barracuda/lib/lib-driver/drv-pdfliteral.lua delete mode 100644 macros/luatex/generic/barracuda/lib/lib-driver/drv-svg.lua delete mode 100644 macros/luatex/generic/barracuda/lib/lib-geo/gacanvas.lua delete mode 100644 macros/luatex/generic/barracuda/lib/lib-geo/libgeo.lua create mode 100644 macros/luatex/generic/barracuda/src/barracuda.lua create mode 100644 macros/luatex/generic/barracuda/src/lib-barcode/brcd-barcode.lua create mode 100644 macros/luatex/generic/barracuda/src/lib-barcode/brcd-code128.lua create mode 100644 macros/luatex/generic/barracuda/src/lib-barcode/brcd-code39.lua create mode 100644 macros/luatex/generic/barracuda/src/lib-barcode/brcd-ean.lua create mode 100644 macros/luatex/generic/barracuda/src/lib-barcode/brcd-i2of5.lua create mode 100644 macros/luatex/generic/barracuda/src/lib-driver/brcd-driver.lua create mode 100644 macros/luatex/generic/barracuda/src/lib-driver/brcd-drv-pdfliteral.lua create mode 100644 macros/luatex/generic/barracuda/src/lib-driver/brcd-drv-svg.lua create mode 100644 macros/luatex/generic/barracuda/src/lib-geo/brcd-gacanvas.lua create mode 100644 macros/luatex/generic/barracuda/src/lib-geo/brcd-libgeo.lua create mode 100644 macros/luatex/generic/barracuda/test/test-barracuda-package/01-barracuda-latex-test.pdf create mode 100644 macros/luatex/generic/barracuda/test/test-barracuda-package/01-barracuda-latex-test.tex create mode 100644 macros/luatex/generic/barracuda/test/test-code128/001-code128-test.lua create mode 100644 macros/luatex/generic/barracuda/test/test-code128/002-code128-test.pdf create mode 100644 macros/luatex/generic/barracuda/test/test-code128/002-code128-test.tex create mode 100644 macros/luatex/generic/barracuda/test/test-code128/02-05-pdfliteral.txt create mode 100644 macros/luatex/generic/barracuda/test/test-code128/c128-123.svg create mode 100644 macros/luatex/generic/barracuda/test/test-code39/001-code39-test.lua create mode 100644 macros/luatex/generic/barracuda/test/test-code39/002-code39-test.pdf create mode 100644 macros/luatex/generic/barracuda/test/test-code39/002-code39-test.tex create mode 100644 macros/luatex/generic/barracuda/test/test-code39/003-code39-test.pdf create mode 100644 macros/luatex/generic/barracuda/test/test-code39/003-code39-test.tex create mode 100644 macros/luatex/generic/barracuda/test/test-code39/004-code39-test.pdf create mode 100644 macros/luatex/generic/barracuda/test/test-code39/004-code39-test.tex create mode 100644 macros/luatex/generic/barracuda/test/test-code39/005-code39-test.lua create mode 100644 macros/luatex/generic/barracuda/test/test-code39/006-code39-test.lua create mode 100644 macros/luatex/generic/barracuda/test/test-code39/006-six.svg create mode 100644 macros/luatex/generic/barracuda/test/test-code39/my_barcode.svg create mode 100644 macros/luatex/generic/barracuda/test/test-ean/001-13-ean-test.pdf create mode 100644 macros/luatex/generic/barracuda/test/test-ean/001-13-ean-test.tex create mode 100644 macros/luatex/generic/barracuda/test/test-ean/002-ean-test.pdf create mode 100644 macros/luatex/generic/barracuda/test/test-ean/002-ean-test.tex create mode 100644 macros/luatex/generic/barracuda/test/test-ean/003-ean-test.pdf create mode 100644 macros/luatex/generic/barracuda/test/test-ean/003-ean-test.tex create mode 100644 macros/luatex/generic/barracuda/test/test-ean/004-ean-test.lua create mode 100644 macros/luatex/generic/barracuda/test/test-ean/8006194056290.svg create mode 100644 macros/luatex/generic/barracuda/test/test-ga-pdfliteral/001-ga-pdfliteral-test.pdf create mode 100644 macros/luatex/generic/barracuda/test/test-ga-pdfliteral/001-ga-pdfliteral-test.tex create mode 100644 macros/luatex/generic/barracuda/test/test-ga-svg/001-ga-svg-test.lua create mode 100644 macros/luatex/generic/barracuda/test/test-ga-svg/002-ga-svg-test.lua create mode 100644 macros/luatex/generic/barracuda/test/test-ga-svg/test-01.svg create mode 100644 macros/luatex/generic/barracuda/test/test-ga-svg/test-02.svg create mode 100644 macros/luatex/generic/barracuda/test/test-ga-svg/test-code39.svg create mode 100644 macros/luatex/generic/barracuda/test/test-i2of5/001-i2of5-test.pdf create mode 100644 macros/luatex/generic/barracuda/test/test-i2of5/001-i2of5-test.tex (limited to 'macros/luatex') diff --git a/macros/luatex/generic/barracuda/INSTALL.txt b/macros/luatex/generic/barracuda/INSTALL.txt index 55ce68da5c..0c06f98488 100644 --- a/macros/luatex/generic/barracuda/INSTALL.txt +++ b/macros/luatex/generic/barracuda/INSTALL.txt @@ -1,30 +1,37 @@ Installation ------------- +============ Installing `barracuda` for TeX Live +----------------------------------- -If you have TeX Live installed from CTAN or from DVD TeX Collection, check -before any modification to your system if the package is already installed +If you have TeX Live installed from CTAN or from DVD TeX Collection, before +any modification to your system check if the package is already installed looking for `installed` key in the output of the command: -$ tlmgr show barracuda + $ tlmgr show barracuda If `barracuda` is not present, run the command: -$ tlmgr install barracuda + $ tlmgr install barracuda If you have installed TeX Live via Linux OS repository try your distribution's package management system. It's also possible a manual installation: -a. Grab the sources from CTAN or https://github.com/robitex/barracuda . -b. Unzip it at the root of one or your TDS trees. -c. You may need to update some filename database after this, see your TeX - distribution's manual for details. + a. Grab the sources from CTAN or https://github.com/robitex/barracuda . + b. Unzip it at the root of one or your TDS trees. + c. You may need to update some filename database after this running `texhash`, + see your TeX distribution's manual for details. + +Any TeX Live documentation files can be easily opened on screen with the +`texdoc` command line utility (this way is very handy). + + $ texdoc pkgname Installing for Lua +------------------ -Manually copy `src` folder content to a suitable directory of your system that -is reachable to Lua interpreter. +Manually copy the `src` folder content to a suitable directory of your system +that is reachable to a Lua interpreter. diff --git a/macros/luatex/generic/barracuda/README.md b/macros/luatex/generic/barracuda/README.md index e4ca271287..6dc3ccb2db 100644 --- a/macros/luatex/generic/barracuda/README.md +++ b/macros/luatex/generic/barracuda/README.md @@ -3,8 +3,8 @@ This Lua library is for drawing barcode symbols. The project delivers modules to typeset barcode from within a LuaTeX document. Therefore is also possible to use `barracuda` with a Lua standalone interpreter to draw barcodes with -different graphic format such as `SVG`. -The package does not have dependences. +different graphic format such as `SVG` (see an example below). +This package does not have dependences. ![a SVG formatted Code39 symbol](/test/test-ga-svg/test-code39.svg) @@ -14,7 +14,12 @@ complete user control over barcode symbol parameters :thumbsup: . Although development is in beta stage, `barracuda` has a good level of stability. -## Barcode symbologies +## Current version information + +Version: v0.0.9.1 +Date: 2019-12-04 + +## Barcode symbologies list So far, are supported @@ -23,15 +28,15 @@ So far, are supported - Interleaved 2 of 5 - EAN family (EAN8, EAN13, and the add-ons EAN5 and EAN2) -Other 1D encoding format will be added to the project, then it will be the -turn for 2D barcode type. +Other 1D encoding symbology will be added to the project, then it will be the +turn of 2D barcode types like Datamatrix, QRCode or PDF417. ## A very simple LaTeX example The LaTeX package `barracuda.sty` under the cover uses Lua code so you need to compile your source files with LuaTeX or LuajitTeX with the LaTeX format. -For instance here there is a minimal example for LuaLaTeX: +For instance, here there is a minimal example for LuaLaTeX: ```latex % !TeX program = LuaLaTeX @@ -47,7 +52,7 @@ For instance here there is a minimal example for LuaLaTeX: Details and package reference can be found in the manual delivered in the `doc` project directory, even if it is very minimal at the moment. -The directory `test` contains files that can be seen as code examples. +Directory `test` contains files useful also for code examples. ## Installation @@ -58,20 +63,33 @@ your system. Otherwise, you can install the package via `tlmgr` for your TeX Live distribution. If you have installed TeX Live with the `full` schema, `barracuda` is just -available and no further action is required because the last package tagged -version is periodically sent to CTAN. +available and no further action is required. Please, take into account that +only the tagged version (in the `git` sense) of the package will be sent to +CTAN. This means that intermediate development version between consecutive +releases can be found only at https://github.com/robitex/barracuda . TeX Live distribution or Lua interpreter executable are available for a very large number of Operating Systems so it is also for `barracuda`. -More detailed istruction will come soon. +Step by step istruction can be found in the INSTALL.txt file. ## Contribute -Contributes are welcome in any form and for any topics. +Contributes are welcome in any form and for any topics. You can contact me +directly via email at giaconet.mailbox@gmail.com or via a pull request on the +repository https://github.com/robitex/barracuda or writing a public message +via the web page https://github.com/robitex/barracuda/issues for todos, bugs, +feature requests, and more (press the bottom `New issue`). + +Anyway, as a starting point take a look of TODO.txt file for the next +scheduled development tasks. ## License -Please, for more legal details refer to LICENSE.txt file. +`barracuda` project is released under the +[GNU GPL v2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.html). +Please, for more legal details refer to LICENSE.txt file or visit the web page +https://www.gnu.org/licenses/old-licenses/gpl-2.0.html Copyright (C) 2019 Roberto Giacomelli + diff --git a/macros/luatex/generic/barracuda/TODO.txt b/macros/luatex/generic/barracuda/TODO.txt new file mode 100644 index 0000000000..5b1970810c --- /dev/null +++ b/macros/luatex/generic/barracuda/TODO.txt @@ -0,0 +1,92 @@ +Development Program Task Table + +Hypothetical developing tasks list: + +__.__: 20__-__-__: [dev] TiKz driver +__.__: 20__-__-__: [dev] debug driver, ga code pretty printing +__.__: 20__-__-__: [dev] make thing happen: font property for text +__.__: 20__-__-__: [dev] develop LaTeX user package +__.__: 20__-__-__: [dev] coherent error management +__.__: 20__-__-__: [dev] proportional options +__.__: 20__-__-__: [dev] a number parameter can be a string? unit measure... +__.__: 20__-__-__: [prj] a command line program to print barcodes +__.__: 20__-__-__: [man] put ga-asm-spec together with the manual +__.__: 2019-__-__: [dev] guard text in EAN simbology +__.__: 2019-__-__: [dev] ISBN support +__.__: 2019-__-__: [dev] UPC support +__.__: 2019-__-__: [dev] make optional file name in all the Driver methods +__.__: 2019-__-__: [prj] use l3build for testing and CTAN files packaging + +Scheduled tasks (What we are working on): +[ ] 2019-__-__: Data Matrix 2D symbology + +__.__: 2019-__-__: [dmx] data matrix first run +__.__: 2019-__-__: [dmx] ecc200 error correction code +__.__: 2019-__-__: [svg] opcode for grids +__.__: 2019-__-__: [pdf] opcode for grids +__.__: 2019-__-__: [gas] ga-asm grid opcode +__.__: 2019-__-__: [geo] grid vector object +_1.__: 2019-__-__: [dev] init source file encoder for Data Matrix + +[🎉] 2019-12-04: prelude to version v0.1 +09.15: 2019-11-29: [prj] upload to CTAN version v0.0.9.1 (CTAN conditions) +09.14: 2019-11-29: [prj] upload to CTAN version v0.0.9 +09.13: 2019-11-26: [man] say something about barracuda.sty +09.12: 2019-11-26: [man] edit the section 'A more deep look' for clearness +09.11: 2019-11-26: [prj] reformat todo file: no more date at line end +09.10: 2019-11-26: [svg] take dimensions as scaled point and then mm +09.09: 2019-11-26: [prj] every dev task ends with a repository commit +09.08: 2019-11-25: [prj] .gitignore .out file +09.07: 2019-11-25: [svg] support for text +09.06: 2019-11-25: [man] time to get an usable manual even if minimal +09.05: 2019-11-23: [chk] some new test files +09.04: 2019-11-23: [dev] new barracuda methods save() and hbox() +09.03: 2019-11-20: [svg] driver first run +09.02: 2019-11-10: [dev] implement ga opcode for line-join style and line-cap style +09.01: 2019-11-10: [prj] make lib-parseopt a separated project + +Completed tasks: + + move costructors to the barcode abstract class 🎉 2019-11-09 +Task 8.5: adopted new Barcode costructors in the EAN encoder 2019-11-09 +Task 8.4: adopted new Barcode costructors in the ITF encoder 2019-11-09 +Task 8.3: adopted new Barcode costructors in the Code128 encoder 2019-11-09 +Task 8.2: adopted new Barcode costructors in the Code39 encoder 2019-11-04 +Task 8.1: new costructor method in the barcode superclass 2019-11-04 + + code refactoring for ga-canvas 🎉 2019-11-02 +Task 7.5: recompile all the test files 2019-11-02 +Task 7.4: new functions canvas:encode_() 2019-11-02 +Task 7.3: text position options for Code39 became two indipendent 2019-11-02 +Task 7.2: added a new code39 test file (and bugs fixed) 2019-11-02 +Task 7.1: added subdirectories in the test tree 2019-11-02 + + implement Interleaved 2 of 5 encoder 🎉 2019-07-02 +Task 6.4: test files 2019-07-02 +Task 6.3: add bearer bars for itf encoder 2019-07-02 +Task 6.2: check digit capability for itf 2 of 5 encoder 2019-07-02 +Task 6.1: implement basic Interleaved 2 of 5 encoder 2019-06-29 + + implement Code128 and EAN family encoders 🎉 2019-01-27 +Task 5.5: test file 2019-01-27 +Task 5.4: implement EAN2 variant 2019-01-26 +Task 5.3: implement EAN5 variant 2019-01-26 +Task 5.2: new family encoder concept 2019-01-25 +Task 5.1: implement EAN13 encoder 2019-01-12 +Task 4.4: refactoring param iterator 2018-12-30 +Task 4.3: test the local system of option set up for Code128 2018-12-30 +Task 4.2: test the local system of option set up for Code39 2018-12-30 +Task 4.1: test for ga-canvas 2018-12-29 +Task 3.3: opt in Code 39 and Code 128 symbol constructors 2018-12-24 +Task 3.2: focus on a new constructor in Barcode Class for + better encoder implementation 2018-12-21 +Task 3.1: import and refactoring previous Code128 encoder code 2018-12-16 + + 🎉 2018-12-11 +Task 2.5: option text_gap for code39 2018-12-11 +Task 2.4: resolved the horizontal correction in spaced text 2018-12-11 +Task 2.3: further text option for the Code39 encoder 2018-12-06 +Task 2.2: include minimal text ability to the system +Task 2.1: design and implement a basic framework + + open 0.0.1 alpha dev master branch 🎉 2018-11-30 diff --git a/macros/luatex/generic/barracuda/barracuda.pdf b/macros/luatex/generic/barracuda/barracuda.pdf deleted file mode 100644 index 3554d40a4a..0000000000 Binary files a/macros/luatex/generic/barracuda/barracuda.pdf and /dev/null differ diff --git a/macros/luatex/generic/barracuda/doc/barracuda-ga-asm.pdf b/macros/luatex/generic/barracuda/doc/barracuda-ga-asm.pdf new file mode 100644 index 0000000000..18ba18b9c2 Binary files /dev/null and b/macros/luatex/generic/barracuda/doc/barracuda-ga-asm.pdf differ diff --git a/macros/luatex/generic/barracuda/doc/barracuda-ga-asm.tex b/macros/luatex/generic/barracuda/doc/barracuda-ga-asm.tex new file mode 100644 index 0000000000..1c403455f8 --- /dev/null +++ b/macros/luatex/generic/barracuda/doc/barracuda-ga-asm.tex @@ -0,0 +1,148 @@ +% !TeX program = LuaLaTeX +% Copyright (C) 2019 Roberto Giacomelli + +\documentclass{article} + +\usepackage{fontspec} +\setmainfont{Libertinus Serif} + +\usepackage[margin=18mm]{geometry} +\usepackage{array} +\usepackage{booktabs} + +\newcolumntype{C}{>{\ttfamily}c} +\newcolumntype{L}{>{\ttfamily}l} + +\begin{document} +Goal: describe geometrical object like lines and rectangles +mainly for a barcode drawing library. + + + +\section{\texttt{ga} instruction set} + +A graphic data specification format called '\texttt{ga}' \emph{graphic alchemy}, +or if you want \emph{generic graphic assembler}. + +\begin{verbatim} +ga := generic graphic assembler + := numeric type parameter for dimension, for example f64 or i32 + := numeric type parameter for quantity, an unsigned integer, i.e. u8 + +ga := +Elem + +Elem := Code + Args + +Code := State | Object | Fn + State := 1 -> 31 -- graphic properties + Object := 32 -> 239 -- graphic objects + Fn := 240 -> 255 -- functions + +Args : | | | + := a dimension value of type DIM + := an enumeration value of type u8 (unsigned byte) + := an unsigned integer for multiplicity + := chars sequence ended with 0 +\end{verbatim} + + + +\section{Properties} + +Colors, linecap style etc\dots + +\noindent\begin{tabular}{CLlL} +\toprule +OpCode & Mnemonic key & Graphic property & Operands\\ +\midrule + 1 & pen\_thick & Line thick & \\ + 2 & line\_cap\_style & Line cap style & \\ + 3 & line\_join\_style & Line join style & \\ + 8 & color & ... \\ +\midrule +30 & start\_bbox\_group & Stop to check the bounding box & -\\ +31 & end\_bbox\_group & Set a bounding box and restart to check & \\ +\bottomrule +\end{tabular} + + + +\section{Objects} + +\subsection{Lines} + +A segment that starts from point P1 (x1, y1) and ends to P2 (x2, y2). + +\noindent\begin{tabular}{CLlL} +\toprule +OpCode & Mnemonic key & Graphic object & Operands\\ +\midrule +32 & line & Line & \\ +33 & hline & Horizontal line & \\ +34 & vline & Vertical line & \\ +\midrule +36 & vbar & Vertical bars & ...\\ +37 & hbar & Horizontal bars & ...\\ +\midrule +38 & polyline & Open polyline & ...\\ +39 & c\_polyline & Closed polyline & ...\\ +\bottomrule +\end{tabular} + + +\subsection{Rectangles} + +\noindent\begin{tabular}{CLlL} +\toprule +OpCode & Mnemonic key & Graphic object & Operands\\ +\midrule + 48 & rect & Rectangle & \\ + 49 & f\_rect & Filled rectangle & \\ + 50 & rect\_size & Rectangle & \\ + 51 & f\_rect\_size & Filled rectangle & \\ + +\bottomrule +\end{tabular} + + +\subsection{Text} + +\noindent\begin{tabular}{CLl} +\toprule +OpCode & Mnemonic key & Graphic object/Operands\\ +\midrule + 130 & text & A text with several glyphs\\ + & & \ttfamily \\ +\midrule + 131 & text\_xspaced & A text with glyphs equally spaced on its vertical axis\\ + & & \ttfamily \\ +\midrule + 132 & text\_xwidth & Glyphs equally spaced on vertical axis between two x coordinates\\ + & & \ttfamily \\ +\midrule + & under design assessment\\ + 140 & \_text\_group & Texts on the same baseline \\ + & & \ttfamily < > \\ +\bottomrule +\end{tabular} + + +\subsection{Function} + + +\noindent\begin{tabular}{CLlL} +\toprule +OpCode & Mnemonic key & Function & Operands\\ +\midrule + 240 & move & Translate objects & \\ + 241 & copy & Copy object & ...\\ + 242 & and\_copy & Place and copy objects & ...\\ + 243 & grid & Copy next \(n\) objects on a grid & \\ + 244 & sl\_grid\\ + 250 & mirror\\ + 255 & comment & A string comment & \\ +\bottomrule +\end{tabular} + + +\end{document} diff --git a/macros/luatex/generic/barracuda/doc/barracuda-manual-tool.tex b/macros/luatex/generic/barracuda/doc/barracuda-manual-tool.tex new file mode 100644 index 0000000000..9e5f5f8a47 --- /dev/null +++ b/macros/luatex/generic/barracuda/doc/barracuda-manual-tool.tex @@ -0,0 +1,7 @@ + + + + + + + diff --git a/macros/luatex/generic/barracuda/doc/barracuda.pdf b/macros/luatex/generic/barracuda/doc/barracuda.pdf new file mode 100644 index 0000000000..6472da10ee Binary files /dev/null and b/macros/luatex/generic/barracuda/doc/barracuda.pdf differ diff --git a/macros/luatex/generic/barracuda/doc/barracuda.tex b/macros/luatex/generic/barracuda/doc/barracuda.tex new file mode 100644 index 0000000000..e5d6b6acdb --- /dev/null +++ b/macros/luatex/generic/barracuda/doc/barracuda.tex @@ -0,0 +1,331 @@ +% !TeX program = LuaLaTeX +% Copyright (C) 2019 Roberto Giacomelli +% Barracuda manual main source file + +\documentclass[11pt]{article} +\usepackage{fontspec} +\usepackage{geometry} +\usepackage{fancyvrb} +\usepackage{graphicx} +\usepackage{hyperref} + +% special macro for manual typesetting +\input{barracuda-manual-tool} + +\hypersetup{ +pdfinfo={ + Title={Barracuda manual}, + Subject={Barcode printing package}, + Author={Roberto Giacomelli}, + Keywords={Barcode EAN Code128 Lua} +}} + +\setmainfont{Libertinus Serif} +\setmonofont{IBM Plex Sans Condensed} +\fvset{ + fontsize=\small, + frame=single, + labelposition=topline, + framesep=6pt +} +\geometry{ + left=32mm, + right=40mm, + top=28mm, + bottom=28mm +} +\newcommand{\code}[1]{\texttt{#1}} +\newcommand{\brcd}{\code{barracuda}} + +\author{Roberto Giacomelli\\\small email: \url{giaconet.mailbox@gmail.com}} +\title{\code{barracuda} manual\\[1ex] +\small \url{https://github.com/robitex/barracuda}} +\date{\small 2019-12-04\\Version v0.0.9.1} + +\begin{document} +\maketitle + +\abstract{% +Welcome to the \brcd{} software project devoted to barcodes printing. + +This manual shows you how to print barcodes in your \TeX{} documents and how to +export such graphic content to an external file, using \brcd{}. + +\brcd{} is written in Lua programming language and is free software released +under the GPL 2 License.% +} + + +\section{Introduction} + +Barcode symbols are usually a sequence of vertical lines representing encoded +data that can be retrived with special laser scanner or more simpler with a +smartphone running dedicated apps. Almost every store item has a label with a +printed barcode for automatic identification purpose. + +So far, \brcd{} supported symbologies are as the following: +\begin{itemize} + \item Code 39, + \item Code 128, + \item EAN family (EAN 8, EAN 13, and the add-ons EAN 2 and EAN 5), + \item ITF 2of5, interleaved Two of Five. +\end{itemize} + +The package provides drivers for different graphic format, at the moment are: +\begin{itemize} + \item PDF Portable Document Format (require a modern \TeX{} engine), + \item SVG Scalable Vector Graphic. +\end{itemize} + +The name \brcd{} is an assonance with the name Barcode. I started the project +back in 2016 for getting barcode in my \TeX{} generated PDF documents, studying +the Lua\TeX{} technology. + + +\subsection{Manual Content} + +The manual is divided into three parts. At section~\ref{secEnter} the first look +gives to the user a proof of concept to how to use and how works the package +while the next parts present details like how to change the \emph{module} width +of a EAN-13 barcode or how to implement a barcode symbology not already included +in the package. + +The plan of the manual is (but some sections are not completed yet): +\begin{description} +\item[Part 1:] Get started +\begin{itemize} + \item print your first barcode \( \to \) \ref{secEnter} + \item installing \brcd{} on your system \( \to \) \ref{secInstall} + \item \brcd{} \LaTeX{} package \( \to \) \ref{secLaTeXPkg} +\end{itemize} +\item[Part 2:] Advanced Work with \brcd{} +\begin{itemize} + \item Lua framework description \( \to \) \ref{secFramework} + \item working example and use cases \( \to \) \ref{secExample} +\end{itemize} +\item[Part 3:] Reference and parameters +\begin{itemize} + \item barcode symbology reference \( \to \) \ref{secBcRef} + \item \code{ga} specification + \item API reference \( \to \) \ref{secAPI} +\end{itemize} +\end{description} + +\subsection{Required knowledge and useful resources} + +The \brcd{} is a Lua package that can be executed by any Lua interpreter. To use +it, it's necessary some knowledge of Lua programming language and a certain +ability with the terminal of your computer system in order to accomplish command +tasks or software installations. + +It's also possible to run \brcd{} directly from within a \TeX{} source file, +compiled with a suitable typesetting engine like Lua\TeX{}. To do so a minimal +\TeX{} system knowledge is required. As an example of this workflow you simply +can look to this manual because itself is typesetted with LuaLa\TeX{}, running +\brcd{} to include barcodes as a vector graphic object. + +Here is a collection of useful learning resources\dots + +% +% +% +% + + +\section{Get Started with Barracuda} +\label{secEnter} + +The starting point to work with \brcd{} is always a plain text file with some +code, late processed by a command line program with a Lua interpreter. + +As a practical example producing an EAN-13 barcode, in a text editor of your +choice on a empty file called \code{first-run.lua}, type the following two lines +of code: +\medskip +\begin{Verbatim}[label=\footnotesize\code{first-run.lua}] +local barracuda = require "barracuda" +barracuda:save("ean-13", "8006194056290", "my_barcode", "svg") +\end{Verbatim} + +What you have done is to write a \emph{script}. If you have installed a Lua +interpreter and \brcd{}, open a terminal and run the command: +\begin{Verbatim} +$ lua first-run.lua +\end{Verbatim} + +You will see in the same directory of your script, appearing the new file +\code{my\_barcode.svg} with the drawing: +\begin{center} +\includegraphics{image/8006194056290} +\end{center} + +Coming back to the script \code{first-run.lua}, first of all, it's necessary to +load the library with the standard statement \code{require()}. What that Lua +function returns is an object---more precisely a table reference---where are +stored every package features. + +We can now produce the EAN-13 barcode using the method \code{save()} of the +\brcd{} object. The \code{save()} method takes in order the barcode symbology +identifier, the data to be encoded as a string or also a whole number, the +output file name and the optional output format. + + +\subsection{Running Lua\TeX} + +Barracuda can also running inside Lua\TeX{} and the others Lua powered \TeX{} +engine. The text source file is a bit difference respect to a Lua script: Lua +code have to bring place as the argument of directlua primitive... we must use +a box register of type horizontal... + +\begin{Verbatim} +% !TeX program = LuaTeX +\nopagenumbers +\newbox\mybox +\directlua{ + local require "barracuda" + barracuda:hbox("ean-13", "8006194056290", "mybox") +}\box\mybox +\bye +\end{Verbatim} + +The method \code{hbox()} works only with Lua\TeX{}. + + +\subsection{A more deep look} + +Barracuda is designed to be modular and flexible. For example it is possible +to draw different barcodes on the same canvas or tune barcode parameters. + +The main workflow to draw a barcode object reveals more details on internal +structure. In fact, to draw an EAN-13 barcode we must do at least the following +steps: +\begin{enumerate} +\item load the library, +\item get a reference to the \code{Barcode} class, +\item build an EAN encoder, +\item build an EAN symbol passing data to a costructor, +\item get a reference to a new canvas object, +\item draw barcode on canvas, +\item get a reference of driver object, +\item address canvas toward a driver. +\end{enumerate} + +Follow that step by step procedure the corresponding code is in the next +listing: +\begin{Verbatim} +local barracuda = require "barracuda" +local barcode = barracuda:get_barcode_class() + +local ean13, err_enc = barcode:new_encoder("ean-13") +assert(ean13, err_enc) + +local symb, err_symb = ean13:from_string("8006194056290") +assert(symb, err_symb) + +local canvas = barracuda:new_canvas() +symb:append_ga(canvas) + +local driver = barracuda:get_driver() +local ok, err_out = driver:save("svg", canvas, "my_barcode", "svg") +assert(ok, err_out) +\end{Verbatim} + + +\section{Installing} +\label{secInstall} + +\subsection{Installing `barracuda` for TeX Live} + +If you have TeX Live installed from CTAN or from DVD TeX Collection, check +before any modification to your system if the package is already installed +looking for \emph{installed} key in the output of the command: +\begin{Verbatim} +$ tlmgr show barracuda +\end{Verbatim} + +If `barracuda` is not present, run the command: +\begin{Verbatim} +$ tlmgr install barracuda +\end{Verbatim} + +If you have installed TeX Live via Linux OS repository try your distribution's +package management system. + +It's also possible a manual installation: +\begin{enumerate} +\item Grab the sources from CTAN or \url{https://github.com/robitex/barracuda}. +\item Unzip it at the root of one or your TDS trees. +\item You may need to update some filename database after this, see your \TeX{} +distribution's manual for details. +\end{enumerate} + +\subsection{Installing for Lua} + +Manually copy \code{src} folder content to a suitable directory of your system +that is reachable to Lua interpreter. + + +\section{Barracuda \LaTeX{} Package} +\label{secLaTeXPkg} + +The \LaTeX{} package delivered with \brcd{} is still under an early stage of +development. The only macro available is \verb=\barracuda{encoder}{data}=. +A simple example is the following source file for Lua\LaTeX{}: +\begin{Verbatim} +% !TeX program = LuaLaTeX +\documentclass{article} +\usepackage{barracuda} +\begin{document} +\leavevmode +\barracuda{code39}{123ABC}\\ +\barracuda{code128}{123ABC} +\end{document} +\end{Verbatim} + +Every macro \verb=\barracuda= typesets a barcode symbol represented with the +encoder defined in the first argument, the information defined by the second. + + +\section{The Barracuda Framework} +\label{secFramework} + +The \brcd{} package framework consists in indipendet modules: a barcode class +hierarchy encoding a text into a barcode symbology; a geometrical library called +\code{libgeo} representing several graphic object; an encoding library for the +\code{ga} format (graphic assembler) several driver to "print" a ga stream +into a file or a \TeX{} hbox register. + +To implement a barcode encoder you need to write a component called +\emph{encoder} defining every parameters and producing the encoder class, while +a driver must understand ga opcode stream and print the corresponding graphic +object. + +Every barcode encoder come with a set of parameters, some of them can be +reserved and can be setting up by the user only through the encoder. + +So, you can create many instances of the same encoder for a single barcode +type, with its own parameter set. + +The basic idea is getting faster encoder, for which the user may set up +paramenters at any level: barcode abstract class, encoder, down to a single +symbol. + +Barcode class is completely indipendent from the ouput driver and viceversa. + + +\section{Example and use cases} +\label{secExample} + +TODO + +\section{Barcode Reference} +\label{secBcRef} + +TODO + +\section{API reference} +\label{secAPI} + +TODO + +\end{document} diff --git a/macros/luatex/generic/barracuda/doc/image/8006194056290.pdf b/macros/luatex/generic/barracuda/doc/image/8006194056290.pdf new file mode 100644 index 0000000000..8effe87846 Binary files /dev/null and b/macros/luatex/generic/barracuda/doc/image/8006194056290.pdf differ diff --git a/macros/luatex/generic/barracuda/example/001-13-ean-test.pdf b/macros/luatex/generic/barracuda/example/001-13-ean-test.pdf deleted file mode 100644 index 925a8ad8f0..0000000000 Binary files a/macros/luatex/generic/barracuda/example/001-13-ean-test.pdf and /dev/null differ diff --git a/macros/luatex/generic/barracuda/example/001-13-ean-test.tex b/macros/luatex/generic/barracuda/example/001-13-ean-test.tex deleted file mode 100644 index c0a4db3894..0000000000 --- a/macros/luatex/generic/barracuda/example/001-13-ean-test.tex +++ /dev/null @@ -1,220 +0,0 @@ -% !TeX program = LuaTeX -% Copyright (C) 2019 Roberto Giacomelli - -\newbox\mybox -\nopagenumbers - -EAN encoder test. - -Test 1: one simple barcode EAN13 with default parameter: - -\directlua{ -local barracuda = require "barracuda" -local barcode = barracuda:get_barcode_class() - -local ean13, err = barcode:new_encoder("ean-13") -assert(not err, err) - -local symbo, err = ean13:from_string("8006194056290") -assert(not err, err) - -local canvas = barracuda:new_canvas() -symbo:append_ga(canvas) - -local drv = barracuda:get_driver() -drv:ga_to_hbox(canvas, "mybox") -} -\vrule A\vrule\box\mybox \vrule A\vrule - -\medskip -Test 2: one simple EAN8 barcode with default parameter: - -\directlua{ -local barracuda = require "barracuda" -local barcode = barracuda:get_barcode_class() - -local ean8, err = barcode:new_encoder("ean-8") -assert(not err, err) - -local symbo, err = ean8:from_string("96385074") -assert(not err, err) - -local canvas = barracuda:new_canvas() -symbo:append_ga(canvas) - -local drv = barracuda:get_driver() -drv:ga_to_hbox(canvas, "mybox") -} -\vrule A\vrule\box\mybox \vrule A\vrule - -\medskip -Test 3: one simple EAN5 barcode with default parameter: - -\directlua{ -local barracuda = require "barracuda" -local barcode = barracuda:get_barcode_class() -local ean5, err = barcode:new_encoder("ean-5") -assert(not err, err) -local symbo, err = ean5:from_string("54495") -assert(not err, err) -local canvas = barracuda:new_canvas() -symbo:append_ga(canvas) -local drv = barracuda:get_driver() -drv:ga_to_hbox(canvas, "mybox") -} -\vrule A\vrule\box\mybox \vrule A\vrule - -\medskip -Test 4: one simple EAN2 barcode with default parameter: - -\directlua{ -local barracuda = require "barracuda" -local barcode = barracuda:get_barcode_class() -local ean2, err = barcode:new_encoder("ean-2") -assert(not err, err) -local symbo, err = ean2:from_string("53") -assert(not err, err) -local canvas = barracuda:new_canvas() -symbo:append_ga(canvas) -local drv = barracuda:get_driver() -drv:ga_to_hbox(canvas, "mybox") -} -\vrule A\vrule\box\mybox \vrule A\vrule - -\medskip -Test 5: EAN13 + EAN5 barcode with default parameter: - -\directlua{ -local barracuda = require "barracuda" -local barcode = barracuda:get_barcode_class() -local ean, err = barcode:new_encoder("ean-13+5"); assert(not err, err) -local n = 123456789012 -local c = ean:checksum(n) -local s = n .. c -local symbo, err = ean:from_string(s.."12345") -assert(not err, err) -local canvas = barracuda:new_canvas() -symbo:append_ga(canvas) -local drv = barracuda:get_driver() -drv:ga_to_hbox(canvas, "mybox") -} -\vrule Test 5\vrule\box\mybox \vrule Test 5\vrule - -\medskip -Test 6: EAN13 + EAN2 barcode with default parameter: - -\directlua{ -local barracuda = require "barracuda" -local barcode = barracuda:get_barcode_class() -local ean, err = barcode:new_encoder("ean-13+2"); assert(not err, err) -local n = 123456789012 -local c = ean:checksum(n) -local s = n .. c -local symbo, err = ean:from_string(s.."12") -assert(not err, err) -local canvas = barracuda:new_canvas() -symbo:append_ga(canvas) -local drv = barracuda:get_driver() -drv:ga_to_hbox(canvas, "mybox") -} -\vrule Test 6\vrule\box\mybox \vrule Test 6\vrule - -\medskip -Test 7: EAN8 + EAN5 barcode with default parameter: - -\directlua{ -local barracuda = require "barracuda" -local barcode = barracuda:get_barcode_class() -local ean, err = barcode:new_encoder("ean-8+5"); assert(not err, err) -local n = 1234567 -local c = ean:checksum(n) -local s = n .. c -local symbo, err = ean:from_string(s.."12345") -assert(not err, err) -local canvas = barracuda:new_canvas() -symbo:append_ga(canvas) -local drv = barracuda:get_driver() -drv:ga_to_hbox(canvas, "mybox") -} -\vrule Test 7\vrule\box\mybox \vrule Test 7\vrule - -\medskip -Test 8: EAN8 + EAN2 barcode with default parameter: - -\directlua{ -local barracuda = require "barracuda" -local barcode = barracuda:get_barcode_class() -local ean, err = barcode:new_encoder("ean-8+2"); assert(not err, err) -local n = 7865431 -local c = ean:checksum(n) -local s = n .. c -local symbo, err = ean:from_string(s.."88") -assert(not err, err) -local canvas = barracuda:new_canvas() -symbo:append_ga(canvas) -local drv = barracuda:get_driver() -drv:ga_to_hbox(canvas, "mybox") -} -\vrule Test 8\vrule\box\mybox \vrule Test 8\vrule - -\medskip -Test 9: draw an EAN13 symbol with a user defined height. - -\smallskip -We will test also the function barcode:enc\_by\_name(bc\_type, name), -reusing encoders generated previuosly. The height parameter remain local -to the object symbol. -\smallskip - -\directlua{ -local barracuda = require "barracuda" -local barcode = barracuda:get_barcode_class() -local ean, err = barcode:enc_by_name("ean-13"); assert(not err, err) -local n = 818571884348 -local c = ean:checksum(n) -local s = n .. c -local symbo, err = ean:from_string(s); assert(not err, err) -local ok, err = symbo:set_param("height", tex.sp "5mm"); assert(ok, err) -local canvas = barracuda:new_canvas() -symbo:append_ga(canvas) - -local s2, err = ean:from_uint(8001120972163); assert(not err, err) -s2:append_ga(canvas, tex.sp "45mm", 0) - -local drv = barracuda:get_driver() -drv:ga_to_hbox(canvas, "mybox") -} -\vrule Test 9\vrule\box\mybox \vrule Test 9\vrule - -\medskip -Test 10: draw EAN13 symbols with a user defined height. - -\smallskip -The parameter height is setting up in the encoder so it will be global. -\smallskip - -\directlua{ -local barracuda = require "barracuda" -local barcode = barracuda:get_barcode_class() -local ean, err = barcode:enc_by_name("ean-13"); assert(not err, err) -local ok, err = ean:set_param("height", tex.sp "5mm"); assert(ok, err) -local n = 758458535897; local c = ean:checksum(n); local s = n .. c -local s1, err = ean:from_string(s); assert(not err, err) -local canvas = barracuda:new_canvas() -s1:append_ga(canvas) -local s2, err = ean:from_uint(8001120972163); assert(not err, err) -s2:append_ga(canvas, tex.sp "40mm", 0) -local s3, err = ean:from_uint(8000570000310); assert(not err, err) -local ok, e = s3:set_param{height = tex.sp "10mm"}; assert(ok, e) -s3:append_ga(canvas, tex.sp "90mm", 0) -local drv = barracuda:get_driver() -drv:ga_to_hbox(canvas, "mybox") -} -\vrule Test 10\vrule\box\mybox \vrule Test 10\vrule - -\medskip -That's all folk! - -\bye - - diff --git a/macros/luatex/generic/barracuda/example/001-code128-test.lua b/macros/luatex/generic/barracuda/example/001-code128-test.lua deleted file mode 100644 index 78645612dc..0000000000 --- a/macros/luatex/generic/barracuda/example/001-code128-test.lua +++ /dev/null @@ -1,32 +0,0 @@ --- Copyright (C) 2018 Roberto Giacomelli - -local barracuda = require "barracuda" -local barcode = barracuda:get_barcode_class() -local c128, err = barcode:new_encoder("code128") -assert(not err, err) - -print(c128._NAME) -print(c128._VERSION) - -local info = c128:info() -print("encoder name = ", info.name) -print("description = ", info.description) -for k, tp in ipairs(info.param) do - print(k, tp.name, tp.value) -end - -local symb = c128:from_string("123") -print("Symbol char list:") -for _, c in ipairs(symb._code_data) do - print(c) -end - -local canvas = barracuda:new_canvas() - -symb:append_ga(canvas) - --- driver library -local drv = barracuda:get_driver() -drv:save("svg", canvas, "c128-123") - - diff --git a/macros/luatex/generic/barracuda/example/001-i2of5-test.pdf b/macros/luatex/generic/barracuda/example/001-i2of5-test.pdf deleted file mode 100644 index c46bb12d50..0000000000 Binary files a/macros/luatex/generic/barracuda/example/001-i2of5-test.pdf and /dev/null differ diff --git a/macros/luatex/generic/barracuda/example/001-i2of5-test.tex b/macros/luatex/generic/barracuda/example/001-i2of5-test.tex deleted file mode 100644 index 43c652d66a..0000000000 --- a/macros/luatex/generic/barracuda/example/001-i2of5-test.tex +++ /dev/null @@ -1,187 +0,0 @@ -% !TeX program = LuaTeX -% Copyright (C) 2019 Roberto Giacomelli - -\newbox\mybox -\nopagenumbers - -\directlua{barracuda = require "barracuda"} - -Interleaved 2 of 5 encoder test. - -Test 1: one simple barcode with default parameters: - -\directlua{ -local barcode = barracuda:get_barcode_class() - -local enc, err = barcode:new_encoder("i2of5"); assert(not err, err) -local symbo, err = enc:from_uint(54654681); assert(not err, err) -local canvas = barracuda:new_canvas(); symbo:append_ga(canvas) -local drv = barracuda:get_driver() -drv:ga_to_hbox(canvas, "mybox") -} -\vrule A\vrule\box\mybox \vrule A\vrule - -\bigskip -Test 2: one simple barcode with default parameter: - -\directlua{ -local barcode = barracuda:get_barcode_class() -local enc, err = barcode:enc_by_name("i2of5"); assert(not err, err) -local symbo, err = enc:from_uint(1234567895); assert(not err, err) -local canvas = barracuda:new_canvas(); symbo:append_ga(canvas) -local drv = barracuda:get_driver() -drv:ga_to_hbox(canvas, "mybox") -} -\vrule A\vrule\box\mybox \vrule A\vrule - -% check digit tests - -\directlua{% verify check digits, the last one -local code = { - 7352621, - 9624764, - 7592881, - 5344147, - 742238, - 199766, - 4544739, - 2774794, - 8509895, - 8285157, - 5387564, - 5534371, - 2155678, - 4529545, - 4689164, - 1674910, - 5317837, - 4117698, -} -local barcode = barracuda:get_barcode_class() -local enc, err = barcode:enc_by_name("i2of5"); assert(not err, err) -for _, n in ipairs(code) do - local smbl, err = enc:from_uint(n, {check_digit_policy="verify"}) - assert(not err, err) -end -} - -\directlua{% check digits evaluation -local code = { - ["735262"] = 1, - ["962476"] = 4, - ["759288"] = 1, - ["534414"] = 7, - ["74223"] = 8, - ["19976"] = 6, - ["454473"] = 9, - ["277479"] = 4, - ["850989"] = 5, - ["828515"] = 7, - ["538756"] = 4, - ["553437"] = 1, - ["215567"] = 8, - ["452954"] = 5, - ["468916"] = 4, - ["167491"] = 0, - ["531783"] = 7, - ["411769"] = 8, -} -local barcode = barracuda:get_barcode_class() -local enc, err = barcode:enc_by_name("i2of5"); assert(not err, err) -for sc, ck in pairs(code) do - local n = tonumber(sc) - local c, err = enc:get_checkdigit(n) - assert(not err, err) - assert(c == ck, "Wrong check digit "..c.." vs "..ck .." for "..sc) -end -} - -\bigskip -Test 3: one simple barcode with check digit automatically added: - -\directlua{ -local barcode = barracuda:get_barcode_class() -local enc, err = barcode:enc_by_name("i2of5"); assert(not err, err) -local symbo, err = enc:from_uint(454473, {check_digit_policy="add"}) -assert(not err, err) -local canvas = barracuda:new_canvas(); symbo:append_ga(canvas) -local drv = barracuda:get_driver() -drv:ga_to_hbox(canvas, "mybox") -} -\vrule A\vrule\box\mybox \vrule A\vrule - -\bigskip -Test 4: a second simple barcode with check digit automatically added: - -\directlua{ -local barcode = barracuda:get_barcode_class() -local enc, err = barcode:enc_by_name("i2of5"); assert(not err, err) -local symbo, err = enc:from_uint(74223, {check_digit_policy="add"}) -assert(not err, err) -local canvas = barracuda:new_canvas(); symbo:append_ga(canvas) -local drv = barracuda:get_driver() -drv:ga_to_hbox(canvas, "mybox") -} -\vrule A\vrule\box\mybox \vrule A\vrule - -\bigskip -Test 5: a symbol with native check digits: - -\directlua{ -local barcode = barracuda:get_barcode_class() -local enc, err = barcode:enc_by_name("i2of5"); assert(not err, err) -local symbo, err = enc:from_uint(121891259, {check_digit_policy="verify"}) -assert(not err, err) -local canvas = barracuda:new_canvas(); symbo:append_ga(canvas) -local drv = barracuda:get_driver() -drv:ga_to_hbox(canvas, "mybox") -} -\vrule A\vrule\box\mybox \vrule A\vrule - -\bigskip -Test 6: bearer bars please: - -\directlua{ -local barcode = barracuda:get_barcode_class() -local enc, err = barcode:enc_by_name("i2of5"); assert(not err, err) -local symbo, err = enc:from_uint(747867239, {bearer_bars_enabled = true}) -assert(not err, err) -local canvas = barracuda:new_canvas(); symbo:append_ga(canvas) -local drv = barracuda:get_driver() -drv:ga_to_hbox(canvas, "mybox") -} -\vrule A\vrule\box\mybox \vrule A\vrule - -\bigskip -Test 7: bearer bars all around the symbol: - -\directlua{ -local barcode = barracuda:get_barcode_class() -local enc, err = barcode:enc_by_name("i2of5"); assert(not err, err) -local symbo, err = enc:from_uint(986790868, {bearer_bars_enabled = true, bearer_bars_layout="frame"}) -assert(not err, err) -local canvas = barracuda:new_canvas(); symbo:append_ga(canvas) -local drv = barracuda:get_driver() -drv:ga_to_hbox(canvas, "mybox") -} -\vrule A\vrule\box\mybox \vrule A\vrule - -\bigskip -Test 8: bearer bars all around the symbol (with string costructor): - -\directlua{ -local barcode = barracuda:get_barcode_class() -local enc, err = barcode:enc_by_name("i2of5"); assert(not err, err) -local symbo, err = enc:from_string("986790868", {bearer_bars_enabled = true, bearer_bars_layout="frame"}) -assert(not err, err) -local canvas = barracuda:new_canvas(); symbo:append_ga(canvas) -local drv = barracuda:get_driver() -drv:ga_to_hbox(canvas, "mybox") -} -\vrule A\vrule\box\mybox \vrule A\vrule - -That's all folks! - -\bye - - diff --git a/macros/luatex/generic/barracuda/example/003-code39-test.pdf b/macros/luatex/generic/barracuda/example/003-code39-test.pdf deleted file mode 100644 index 4625a40010..0000000000 Binary files a/macros/luatex/generic/barracuda/example/003-code39-test.pdf and /dev/null differ diff --git a/macros/luatex/generic/barracuda/example/003-code39-test.tex b/macros/luatex/generic/barracuda/example/003-code39-test.tex deleted file mode 100644 index a4ba3d6e81..0000000000 --- a/macros/luatex/generic/barracuda/example/003-code39-test.tex +++ /dev/null @@ -1,53 +0,0 @@ -% !TeX program = LuaTeX -% Copyright (C) 2019 Roberto Giacomelli - -\newbox\mybox -\nopagenumbers - -Test 3: the same Code 39 symbol drawing multiple time on the same canvas - -\directlua{ -local barracuda = require "barracuda" -local c39, err = barracuda:get_barcode_class() - :new_encoder("code39") -assert(not err, err) -local err -local symbol -symbol, err = c39:from_string("ABCDEF12QJ31+") -assert(not err, err) - -local ok, err = c39:set_param("text_vpos", "top") -assert(ok, err) - -local canvas = barracuda:new_canvas() -symbol:append_ga(canvas) - -local ok, err = symbol:set_param("text_hpos", "center") -assert(ok, err) -symbol:append_ga(canvas, tex.sp "4.5cm") - -local ok, err = symbol:set_param("text_hpos", "right") -assert(ok, err) -symbol:append_ga(canvas, tex.sp "9.0cm") - -local ok, err = c39:set_param("text_vpos", "bottom") -assert(ok, err) - -local ok, err = symbol:set_param("text_hpos", "left") -symbol:append_ga(canvas, 0, tex.sp "-2.0cm") - -local ok, err = symbol:set_param("text_hpos", "center") -assert(ok, err) -symbol:append_ga(canvas, tex.sp "4.5cm", tex.sp "-2.0cm") - -local ok, err = symbol:set_param("text_hpos", "right") -assert(ok, err) -symbol:append_ga(canvas, tex.sp "9.0cm", tex.sp "-2.0cm") - -local drv = barracuda:get_driver() -drv:ga_to_hbox(canvas, "mybox") -} -\box\mybox -\bye - - diff --git a/macros/luatex/generic/barracuda/example/003-ean-test.pdf b/macros/luatex/generic/barracuda/example/003-ean-test.pdf deleted file mode 100644 index e03c2d48d7..0000000000 Binary files a/macros/luatex/generic/barracuda/example/003-ean-test.pdf and /dev/null differ diff --git a/macros/luatex/generic/barracuda/example/003-ean-test.tex b/macros/luatex/generic/barracuda/example/003-ean-test.tex deleted file mode 100644 index 59b17c4c07..0000000000 --- a/macros/luatex/generic/barracuda/example/003-ean-test.tex +++ /dev/null @@ -1,16 +0,0 @@ -% !TeX program = LuaLaTeX -\documentclass{standalone} -\usepackage{fontspec} -\setmainfont{ocrb10.otf} -\newbox\mybox -\directlua{ - local barracuda = require "barracuda" - barracuda:hbox("ean-13", "8006194056290", "mybox") -} - -\begin{document} -\box\mybox -\end{document} - - - diff --git a/macros/luatex/generic/barracuda/example/004-ean-test.lua b/macros/luatex/generic/barracuda/example/004-ean-test.lua deleted file mode 100644 index 017e0725b8..0000000000 --- a/macros/luatex/generic/barracuda/example/004-ean-test.lua +++ /dev/null @@ -1,9 +0,0 @@ - -local barracuda = require "barracuda" -barracuda:save("ean-13", "8006194056290", "8006194056290") - - - - - - diff --git a/macros/luatex/generic/barracuda/example/006-code39-test.lua b/macros/luatex/generic/barracuda/example/006-code39-test.lua deleted file mode 100644 index d33ad4ffaf..0000000000 --- a/macros/luatex/generic/barracuda/example/006-code39-test.lua +++ /dev/null @@ -1,45 +0,0 @@ - -local cm = 1864679.8110236 -- sp - -local barracuda = require "barracuda" -local c39, err = barracuda:get_barcode_class() - :new_encoder("code39") -assert(not err, err) -local err -local symbol -symbol, err = c39:from_string("ABCDEF12QJ31+") -assert(not err, err) - -local ok, err = c39:set_param("text_vpos", "top") -assert(ok, err) - -local canvas = barracuda:new_canvas() -symbol:append_ga(canvas) - -local ok, err = symbol:set_param("text_hpos", "center") -assert(ok, err) -symbol:append_ga(canvas, 4.5*cm) - -local ok, err = symbol:set_param("text_hpos", "right") -assert(ok, err) -symbol:append_ga(canvas, 9.0*cm) - -local ok, err = c39:set_param("text_vpos", "bottom") -assert(ok, err) - -local ok, err = symbol:set_param("text_hpos", "left") -symbol:append_ga(canvas, 0, -2.0*cm) - -local ok, err = symbol:set_param("text_hpos", "center") -assert(ok, err) -symbol:append_ga(canvas, 4.5*cm, -2.0*cm) - -local ok, err = symbol:set_param("text_hpos", "right") -assert(ok, err) -symbol:append_ga(canvas, 9.0*cm, -2.0*cm) - -local drv = barracuda:get_driver() -drv:save("svg", canvas, "006-six") - - - diff --git a/macros/luatex/generic/barracuda/example/006-six.svg b/macros/luatex/generic/barracuda/example/006-six.svg deleted file mode 100644 index 25ce8bb34c..0000000000 --- a/macros/luatex/generic/barracuda/example/006-six.svg +++ /dev/null @@ -1,653 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ABCDEF12QJ31+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ABCDEF12QJ31+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ABCDEF12QJ31+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ABCDEF12QJ31+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ABCDEF12QJ31+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ABCDEF12QJ31+ - - diff --git a/macros/luatex/generic/barracuda/example/01-latex-code39.pdf b/macros/luatex/generic/barracuda/example/01-latex-code39.pdf deleted file mode 100644 index d40c55f46c..0000000000 Binary files a/macros/luatex/generic/barracuda/example/01-latex-code39.pdf and /dev/null differ diff --git a/macros/luatex/generic/barracuda/example/01-latex-code39.tex b/macros/luatex/generic/barracuda/example/01-latex-code39.tex deleted file mode 100644 index c74935ed8d..0000000000 --- a/macros/luatex/generic/barracuda/example/01-latex-code39.tex +++ /dev/null @@ -1,14 +0,0 @@ -% !TeX program = LuaLaTeX -% Copyright (C) 2019 Roberto Giacomelli - -\documentclass{article} - -\usepackage{barracuda} - -\begin{document} - -A\barracuda{code39}{123QWE}A - -\end{document} - - diff --git a/macros/luatex/generic/barracuda/example/8006194056290.svg b/macros/luatex/generic/barracuda/example/8006194056290.svg deleted file mode 100644 index f7965e94d4..0000000000 --- a/macros/luatex/generic/barracuda/example/8006194056290.svg +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 8 - - 0 - 0 - 6 - 1 - 9 - 4 - - - 0 - 5 - 6 - 2 - 9 - 0 - - - diff --git a/macros/luatex/generic/barracuda/example/c128-123.svg b/macros/luatex/generic/barracuda/example/c128-123.svg deleted file mode 100644 index 9f5b5847aa..0000000000 --- a/macros/luatex/generic/barracuda/example/c128-123.svg +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/macros/luatex/generic/barracuda/lib/barracuda.lua b/macros/luatex/generic/barracuda/lib/barracuda.lua deleted file mode 100644 index 33e81be24f..0000000000 --- a/macros/luatex/generic/barracuda/lib/barracuda.lua +++ /dev/null @@ -1,116 +0,0 @@ --- Welcome to the 'barracuda' barcode library --- --- Encode a message into a barcode symbol, in Lua or within a LuaTeX source file --- --- Copyright (C) 2019 Roberto Giacomelli --- --- 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 --- the Free Software Foundation; either version 2 of the License, or --- (at your option) any later version. --- --- This program is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with this program; if not, write to the Free Software --- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - --- Basic Conventions: --- fields that start with an undercore are private --- class name follows the snake case naming convention --- the 'barracuda' table is the only global object to access every package --- modules. - -local Barracuda = { - _VERSION = "barracuda v0.0.9", - _NAME = "barracuda", - _DESCRIPTION = "Lua library for barcode printing", - _URL = "https://github.com/robitex/barracuda", - _LICENSE = "GNU GENERAL PUBLIC LICENSE, Version 2, June 1991", -} - --- essential sub-module loading -Barracuda._libgeo = require "lib-geo.libgeo" -- basic vectorial objects -Barracuda._gacanvas = require "lib-geo.gacanvas" -- ga stream library -Barracuda._barcode = require "lib-barcode.barcode" -- barcode abstract class - -local Barcode = Barracuda._barcode -Barcode._libgeo = Barracuda._libgeo - --- encoder builder -function Barracuda:get_barcode_class() --> Barcode class object - return self._barcode -end - --- where we place output driver library -function Barracuda:get_driver() --> Driver object, err - if not self._lib_driver then - self._lib_driver = require "lib-driver.driver" - end - return self._lib_driver -end - -function Barracuda:new_canvas() --> driver - local gacanvas = self._gacanvas - return gacanvas:new() -end - --- high level barcode functions --- only default options --- panic on error - --- save barcode as a graphic external file -function Barracuda:save(bc_type, data, filename, id_drv) - local barcode = self:get_barcode_class() - local enc, err = barcode:new_encoder(bc_type) - assert(enc, err) - local arg_data = type(data) - local symb - if arg_data == "number" then - local err_data - symb, err_data = enc:from_uint(data) - asser(symb, err_data) - elseif arg_data == "string" then - local err_data - symb, err_data = enc:from_string(data) - assert(symb, err_data) - else - error("[argErr] unsupported 'data' type") - end - local canvas = self:new_canvas() - symb:append_ga(canvas) - local driver = self:get_driver() - id_drv = id_drv or "svg" - local ok, out_err = driver:save(id_drv, canvas, filename) - assert(ok, out_err) -end - --- this is a only LuaTeX method -function Barracuda:hbox(bc_type, data, box_name) - local barcode = self:get_barcode_class() - local enc, err = barcode:new_encoder(bc_type) - assert(enc, err) - local arg_data = type(data) - local symb - if arg_data == "number" then - local err_data - symb, err_data = enc:from_uint(data) - asser(symb, err_data) - elseif arg_data == "string" then - local err_data - symb, err_data = enc:from_string(data) - assert(symb, err_data) - else - error("[argErr] unsupported 'data' type") - end - local canvas = self:new_canvas() - symb:append_ga(canvas) - local driver = self:get_driver() - local ok, err_hbox = driver:ga_to_hbox(canvas, box_name) - assert(ok, err_hbox) -end - -return Barracuda diff --git a/macros/luatex/generic/barracuda/lib/lib-barcode/barcode.lua b/macros/luatex/generic/barracuda/lib/lib-barcode/barcode.lua deleted file mode 100644 index ed6204528a..0000000000 --- a/macros/luatex/generic/barracuda/lib/lib-barcode/barcode.lua +++ /dev/null @@ -1,544 +0,0 @@ - --- Barcode abstract class --- Copyright (C) 2019 Roberto Giacomelli --- Please see LICENSE.TXT for any legal information about present software - -local Barcode = { - _VERSION = "Barcode v0.0.5", - _NAME = "Barcode", - _DESCRIPTION = "Barcode abstract class", -} -Barcode.__index = Barcode - --- barcode_type/submodule name -Barcode._available_enc = {-- keys must be lowercase - code39 = "lib-barcode.code39", - code128 = "lib-barcode.code128", - ean = "lib-barcode.ean", - i2of5 = "lib-barcode.i2of5", -- Interleaved 2 of 5 -} -Barcode._builder_instances = {} -- encoder builder instances repository - --- common parameters to all the barcode objects -Barcode._super_par_def = {} -local pardef = Barcode._super_par_def - --- set an Anchor point (ax, ay) relatively to the barcode bounding box --- without considering any text object --- ax = 0, ay = 0 is the lower left corner of the symbol --- ax = 1, ay = 1 is the upper right corner of the symbol -Barcode.ax = 0.0 -pardef.ax = { - default = 0.0, - unit = "sp", -- scaled point - isReserved = false, - order = 1, - fncheck = function (self, ax, _) --> boolean, err - if ax >= 0.0 and ax <= 1.0 then return true, nil end - return false, "[OutOfRange] 'ax' out of [0, 1] interval" - end, -} -Barcode.ay = 0.0 -pardef.ay = { - default = 0.0, - unit = "sp", -- scaled point - isReserved = false, - order = 2, - fncheck = function (self, ay, _) --> boolean, err - if ay >= 0.0 and ay <= 1.0 then return true, nil end - return false, "[OutOfRange] 'ay' out of [0, 1] interval" - end, -} - --- Barcode.bbox_to_quietzone -- under assessment - --- Barcode methods - --- stateless iterator troughtout the ordered parameters collection -local function p_iter(state, i) - i = i + 1 - local t = state[i] - if t then - return i, t - end -end - --- main iterator on parameter definitions -function Barcode:param_ord_iter() - local state = {} - -- append family parameter - local p2_family = self._par_def -- base family parameters - local fam_len = 0 - if p2_family then - for pname, pdef in pairs(p2_family) do - state[pdef.order] = { - pname = pname, - pdef = pdef, - isSuper = false, - } - fam_len = fam_len + 1 - end - assert(fam_len == #state) - end - -- append the variant parameters - local var_len = 0 - local var = self._variant - if var then -- specific variant parameters - local p2_variant = assert(self._par_def_variant[var]) - for pname, pdef in pairs(p2_variant) do - if state[pname] then - error("[InternalErr] overriding paramenter '"..pname.."'") - end - state[pdef.order + fam_len] = { - pname = pname, - pdef = pdef, - isSuper = false, - } - var_len = var_len + 1 - end - assert(fam_len + var_len == #state) - end - -- append the super class parameter to the iterator state - local p1 = self._super_par_def - local super_len = 0 - for pname, pdef in pairs(p1) do - if state[pname] then - error("[InternalError] overriding paramenter name '"..pname.."'") - end - state[fam_len + var_len + pdef.order] = { - pname = pname, - pdef = pdef, - isSuper = true, - } - super_len = super_len + 1 - end - assert(super_len + fam_len + var_len == #state) - return p_iter, state, 0 -end - --- encoder costructor --- Symbology can be a family with many variants. This is represented by the --- first argument 'bc_type' formatted as -. --- in more details: --- if there are variants --- if not --- i.e. when 'bc_type' is the string "ean-13", "ean" is the barcode family and --- "13" is its variant name. --- For whose barcodes that do not have variants, 'bc_type' is simply the endoder id --- such as "code128". --- 'id_enc' is an optional identifier useful to retrive an encoder reference later --- 'opt' is an optional table with the user-defined parameters setting up encoders --- -function Barcode:new_encoder(bc_type, id_enc, opt) --> object, err - -- argument checking - if type(bc_type) ~= "string" then - return nil, "[ArgErr] 'bc_type' is not a string" - end - local pdash = string.find(bc_type, "-") - local family, variant - if pdash then - family = string.sub(bc_type, 1, pdash - 1) - variant = string.sub(bc_type, pdash + 1) - else - family = bc_type - end - local av_enc = self._available_enc - if not av_enc[family] then -- is the barcode type a real module? - return nil, "[Err] barcode type '"..family.."' not found" - end - if id_enc == nil then - id_enc = (variant or "") .. "_noname" - elseif type(id_enc) ~= "string" then - return nil, "[ArgErr] provided 'id_enc' is not a string" - end - if type(opt) == "table" or opt == nil then - opt = opt or {} - else - return nil, "[ArgErr] provided 'opt' is wrong" - end - local tenc = self._builder_instances - local builder; - if tenc[family] then -- is the encoder builder already loaded? - builder = tenc[family] - else -- loading the encoder builder - local mod_path = av_enc[family] - builder = require(mod_path) - tenc[family] = assert(builder, "[InternalErr] module not found!") - builder._enc_instances = {} - end - if builder._enc_instances[id_enc] then - return nil, "[Err] 'id_enc' already present" - end - local enc = {} -- the new encoder - enc.__index = enc - enc._variant = variant - setmetatable(enc, { - __index = function(_, k) - if builder[k] ~= nil then - return builder[k] - end - return self[k] - end - }) - builder._enc_instances[id_enc] = enc - -- param defition - for _, tpar in enc:param_ord_iter() do - local pname = tpar.pname - local pdef = tpar.pdef - local isSuper = tpar.isSuper - local val = opt[pname] -- param = val - if val ~= nil then - local ok, err = pdef:fncheck(val, enc) - if ok then - enc[pname] = val - else -- error! - return nil, err - end - else - -- load the default value of - local def_val; if pdef.fndefault then - def_val = pdef:fndefault(enc) - else - def_val = pdef.default - end - if not isSuper then - enc[pname] = def_val - end - end - end - if enc.config then -- this must be called after the parameter definition - enc:config(variant) - end - return enc, nil -end - --- retrive encoder object already created --- 'name' is optional in case you didn't assign one to the encoder -function Barcode:enc_by_name(bc_type, name) --> , - if type(bc_type) ~= "string" then - return nil, "[ArgErr] 'bc_type' must be a string" - end - local pdash = string.find(bc_type, "-") - local family, variant - if pdash then - family = string.sub(bc_type, 1, pdash - 1) - variant = string.sub(bc_type, pdash + 1) - else - family = bc_type - end - local av_enc = self._available_enc - if not av_enc[family] then -- is the barcode type a real module? - return nil, "[Err] barcode type '"..family.."' not found" - end - local builder = self._builder_instances[family] - if builder == nil then - return nil, "[Err] enc builder '"..family.."' not loaded, use 'new_encoder()' method" - end - if name == nil then - name = (variant or "") .. "_noname" - elseif type(name) ~= "string" then - return nil, "[ArgErr] 'name' must be a string" - end - local repo = builder._enc_instances - local enc = repo[name] - if enc == nil then - return nil, "[Err] encoder '"..name.."' not found" - else - return enc, nil - end -end - --- base constructors common to all the encoders --- for numeric only simbology -function Barcode:_check_char(c) --> elem, err - if type(c) ~= "string" or #c ~= 1 then - return nil, "[InternalErr] invalid char" - end - local n = string.byte(c) - 48 - if n < 0 or n > 9 then - return nil, "[ArgErr] found a not digit char" - end - return n, nil -end -function Barcode:_check_digit(n) --> elem, err - if type(n) ~= "number" then - return nil, "[InternalErr] not a number" - end - if n < 0 or n > 9 then - return nil, "[InternalErr] not a digit" - end - return n, nil -end - --- not empty string --> Barcode object -function Barcode:from_string(symb, opt) --> object, err - assert(self._check_char, "[InternalErr] undefined _check_char() method") - if type(symb) ~= "string" then - return nil, "[ArgErr] 'symb' is not a string" - end - if #symb == 0 then - return nil, "[ArgErr] 'symb' is an empty string" - end - local chars = {} - local len = 0 - for c in string.gmatch(symb, ".") do - local elem, err = self:_check_char(c) - if err then - return nil, err - else - chars[#chars+1] = elem - len = len + 1 - end - end - -- build the barcode object - local o = { - _code_data = chars, -- array of chars - _code_len = len, -- symbol lenght - } - setmetatable(o, self) - if opt ~= nil then - if type(opt) ~= "table" then - return nil, "[ArgErr] 'opt' is not a table" - else - local ok, err = o:set_param(opt) - if not ok then - return nil, err - end - end - end - if o._finalize then - local ok, e = o:_finalize() - if not ok then return nil, e end - end - return o, nil -end - --- positive integer --> Barcode object -function Barcode:from_uint(n, opt) --> object, err - assert(self._check_digit, "[InternalErr] undefined _check_digit() method") - if type(n) ~= "number" then return nil, "[ArgErr] 'n' is not a number" end - if n < 0 then return nil, "[ArgErr] 'n' must be a positive integer" end - if n - math.floor(n) ~= 0 then - return nil, "[ArgErr] 'n' is not an integer" - end - if opt ~= nil and type(opt) ~= "table" then - return nil, "[ArgErr] 'opt' is not a table" - end - local digits = {} - local i = 0 - if n == 0 then - local elem, err = self:_check_digit(0) - if err then - return nil, err - end - digits[1] = elem - i = 1 - else - while n > 0 do - local d = n % 10 - i = i + 1 - local elem, err = self:_check_digit(d) - if err then - return nil, err - end - digits[i] = elem - n = (n - d) / 10 - end - for k = 1, i/2 do -- reverse the array - local d = digits[k] - local h = i - k + 1 - digits[k] = digits[h] - digits[h] = d - end - end - -- build the barcode object - local o = { - _code_data = digits, -- array of digits - _code_len = i, -- symbol lenght - } - setmetatable(o, self) - if opt ~= nil then - if type(opt) ~= "table" then - return nil, "[ArgErr] 'opt' is not a table" - else - local ok, err = o:set_param(opt) - if not ok then - return nil, err - end - end - end - if o._finalize then - local ok, e = o:_finalize() - if not ok then return nil, e end - end - return o, nil -end - --- check a parameter set --- this method check also reserved parameter --- argments: {k=v, ...}, "default" | "current" --- if ref is "default" parameters are checked with default values --- if ref is "current" parameters are checked with current values -function Barcode:check_param(opt, ref) --> boolean, check report - if type(opt) ~= "table" then - return nil, "[ArgErr] opt is not a table" - end - if ref == nil then - ref = "current" - else - if type(ref) ~= "string" then - return nil, "[ArgErr] ref is not a string" - end - if (ref ~= "current") or (ref ~= "default") then - return nil, "[ArgErr] ref can only be 'default' or 'current'" - end - end - -- checking process - local cktab = {} - local isOk = true - local err_rpt -- nil if no error - for _, tpar in self:param_ord_iter() do - local pname = tpar.pname - local pdef = tpar.pdef - -- load the default value of - local def_val; if pdef.fndefault then - def_val = pdef:fndefault(cktab) - else - def_val = pdef.default - end - local val = opt[pname] - if val ~= nil then - local ok, err = pdef:fncheck(val, cktab) - if ok then - cktab[pname] = val - else -- error! - isOk = false - if err_rpt == nil then err_rpt = {} end - err_rpt[#err_rpt + 1] = { - param = pname, - checked_val = val, - default_val = def_val, - isOk = ok, - err = err, - } - end - end - local v - if ref == "current" then - v = self[pname] - else - v = def_val - end - cktab[pname] = v - end - return isOk, err_rpt -end - --- restore to the default values all the parameter --- (reserved parameters are unmodified so no need to restore it) --- this need further investigation about the conseguence of a restore --- that reset the parameter but "locally" --- so this method must be considered experimental -function Barcode:restore_param() --> self :FIXME: - for _, par in ipairs(self._par_id) do - local pdef = self[par.."_def"] - if not pdef.isReserved then - self[par] = pdef.default - end - end - return self -end - --- create a table with the information of the current barcode encoder -function Barcode:info() --> table - local info = { - name = self._NAME, - version = self._VERSION, - description = self._DESCRIPTION, - param = {}, - } - local tpar = info.param - for _, pardef in self:param_ord_iter() do - local id = pardef.pname - local pdef = pardef.pdef - tpar[#tpar + 1] = { - name = id, - descr = nil, -- TODO: - value = self[id], - isReserved = pdef.isReserved, - unit = pdef.unit, - } - end - return info -end - --- make accessible by name parameter values --- id: parameter identifier -function Barcode:get_param(id) --> value, err - if type(id) ~= "string" then - return nil, "[ArgErr] 'id' must be a string" - end - local pardef = self._par_def - if not pardef[id] then - return nil, "[Err] Parameter '"..id.."' doesn't exist" - end - local res = assert(self[id], "[InternalErr] parameter value unreachable") - return res, nil -end - --- set a barcode parameter only if it is not reserved --- arguments: --- :set_param{key = value, key = value, ...} --- :set_param(key, value) -function Barcode:set_param(arg1, arg2) --> boolean, err - -- processing arguments - local targ - local isPair = true - if type(arg1) == "table" then - if arg2 ~= nil then - return false, "[ArgErr] Further arguments not allowed" - end - targ = arg1 - isPair = false - elseif type(arg1) == "string" then -- key/value - if arg2 == nil then - return false, "[ArgErr] 'value' as the second argument expected" - end - targ = {} - targ[arg1] = arg2 - else - return false, "[ArgErr] param name must be a string" - end - -- preparing to the checking process - local cktab = {} - local ckparam = {} - -- checking process - for _, tpar in self:param_ord_iter() do - local pname = tpar.pname - local pdef = tpar.pdef - local val = targ[pname] -- par = val - if val ~= nil then - if pdef.isReserved then - return false, "[Err] parameter '" .. pname .. - "' is reserved, create another encoder" - end - local ok, err = pdef:fncheck(val, cktab) - if ok then - cktab[pname] = val - ckparam[pname] = val - else -- error! - return false, err - end - else -- no val in user option - cktab[pname] = self[pname] - end - end - for p, v in pairs(ckparam) do - self[p] = v - end - return true, nil -end - -return Barcode - --- diff --git a/macros/luatex/generic/barracuda/lib/lib-barcode/code128.lua b/macros/luatex/generic/barracuda/lib/lib-barcode/code128.lua deleted file mode 100644 index 317b3de8f8..0000000000 --- a/macros/luatex/generic/barracuda/lib/lib-barcode/code128.lua +++ /dev/null @@ -1,341 +0,0 @@ --- Code128 barcode generator module --- Copyright (C) 2019 Roberto Giacomelli --- --- All dimension must be in scaled point (sp) --- every fields that starts with an undercore sign are intended as private - -local Code128 = { - _VERSION = "code128 v0.0.5", - _NAME = "Code128", - _DESCRIPTION = "Code128 barcode encoder", -} - -Code128._int_def_bar = {-- code bar definitions - [0] = 212222, 222122, 222221, 121223, 121322, 131222, 122213, 122312, - 132212, 221213, 221312, 231212, 112232, 122132, 122231, 113222, 123122, - 123221, 223211, 221132, 221231, 213212, 223112, 312131, 311222, 321122, - 321221, 312212, 322112, 322211, 212123, 212321, 232121, 111323, 131123, - 131321, 112313, 132113, 132311, 211313, 231113, 231311, 112133, 112331, - 132131, 113123, 113321, 133121, 313121, 211331, 231131, 213113, 213311, - 213131, 311123, 311321, 331121, 312113, 312311, 332111, 314111, 221411, - 431111, 111224, 111422, 121124, 121421, 141122, 141221, 112214, 112412, - 122114, 122411, 142112, 142211, 241211, 221114, 413111, 241112, 134111, - 111242, 121142, 121241, 114212, 124112, 124211, 411212, 421112, 421211, - 212141, 214121, 412121, 111143, 111341, 131141, 114113, 114311, 411113, - 411311, 113141, 114131, 311141, 411131, 211412, 211214, 211232, - 2331112, -- this is the stop char at index 106 -} - -Code128._codeset = { - A = 103, -- Start char for Codeset A - B = 104, -- Start char for Codeset B - C = 105, -- Start char for Codeset C - stopChar = 106, -- Stop char - shift = 98, -- A to B or B to A -} - -Code128._switch = { -- codes for switching from a codeset to another one - [103] = {[104] = 100, [105] = 99}, -- from A to B or C - [104] = {[103] = 101, [105] = 99}, -- from B to A or C - [105] = {[103] = 101, [104] = 100}, -- from C to A or B -} - --- parameters definition -Code128._par_def = {} -local pardef = Code128._par_def - --- module main parameter -pardef.xdim = { - default = 0.21 * 186467, -- X dimension - unit = "sp", -- scaled point - isReserved = true, - order = 1, -- the one first to be modified - fncheck = function (self, x, _) --> boolean, err - if x >= self.default then - return true, nil - else - return false, "[OutOfRange] too small value for xdim" - end - end, -} - -pardef.ydim = { - default = 10 * 186467, -- Y dimension - unit = "sp", - isReserved = false, - order = 2, - fncheck = function (self, y, tpar) --> boolean, err - local xdim = tpar.xdim - if y >= 10*xdim then - return true, nil - else - return false, "[OutOfRange] too small value for ydim" - end - end, -} - -pardef.quietzone_factor = { - default = 10, - unit = "absolute-number", - isReserved = false, - order = 3, - fncheck = function (self, z, _) --> boolean, err - if z >= 10 then - return true, nil - else - return false, "[OutOfRange] too small value for quietzone_factor" - end - end, -} - --- create vbar objects -function Code128:config() --> ok, err - -- build Vbar object for the start/stop symbol - local mod = self.xdim - local sc = self._codeset.stopChar -- build the stop char - local n = self._int_def_bar[sc] - local Vbar = self._libgeo.Vbar -- Vbar class - self._vbar = {} - local b = self._vbar - b[sc] = Vbar:from_int(n, mod, true) - return true, nil -end - --- utility functions - --- the number of consecutive digits from the index 'i' in the code array -local function count_digits_from(arr, i) - local start = i - local dim = #arr - while i <= dim and (arr[i] > 47 and arr[i] < 58) do - i = i + 1 - end - return i - start -end - --- evaluate the check digit of the data representation -local function check_digit(code) - local sum = code[1] -- this is the start character - for i = 2, #code do - sum = sum + code[i]*(i-1) - end - return sum % 103 -end - --- return a pair of boolean the first one is true --- if a control char and a lower case char occurs in the data --- and the second one is true if the control char occurs before --- the lower case char -local function ctrl_or_lowercase(pos, data) --> boolean, boolean|nil - local len = #data - local ctrl_occur, lower_occur = false, false - for i = pos, len do - local c = data[i] - if (not ctrl_occur) and (c >= 0 and c < 32) then - -- [0,31] control chars - if lower_occur then - return true, false -- lowercase char < ctrl char - else - ctrl_occur = true - end - elseif (not lower_occur) and (c > 95 and c < 128) then - -- [96, 127] lower case chars - if ctrl_occur then - return true, true -- ctrl char < lowercase char - else - lower_occur = true - end - end - end - return false -- no such data -end - --- encode the provided char against a codeset --- in the future this function will consider FN data -local function encode_char(t, codesetAorB, char_code, codesetA) - local code - if codesetAorB == codesetA then -- codesetA - if char_code < 32 then - code = char_code + 64 - elseif char_code > 31 and char_code < 96 then - code = char_code - 32 - else - error("Not implemented or wrong code") - end - else -- codesetB - if char_code > 31 and char_code < 128 then - code = char_code - 32 - else - error("Not implemented or wrong code") - end - end - t[#t + 1] = code -end - --- encode the message in a sequence of Code128 symbol minimizing its lenght -local function encode128(arr, codeset, switch) --> data, err :TODO: - local res = {} -- the result array (the check character will be appended) - -- find the Start Character A, B, or C - local cur_codeset - local ndigit = count_digits_from(arr, 1) - local len = #arr - --local no_ctrl_lower_char - if (ndigit == 2 and len == 2) or ndigit > 3 then -- start char code C - cur_codeset = codeset.C - else - local ok, ctrl_first = ctrl_or_lowercase(1, arr) - if ok and ctrl_first then - cur_codeset = codeset.A - else - cur_codeset = codeset.B - end - end - res[#res + 1] = cur_codeset - local pos = 1 -- symbol's index to encode - while pos <= len do - if cur_codeset == codeset.C then - if arr[pos] < 48 or arr[pos] > 57 then -- not numeric char - local ok, ctrl_first = ctrl_or_lowercase(pos, arr) - if ok and ctrl_first then - cur_codeset = codeset.A - else - cur_codeset = codeset.B - end - res[#res + 1] = switch[codeset.C][cur_codeset] - else - local imax = pos + 2*math.floor(ndigit/2) - 1 - for idx = pos, imax, 2 do - res[#res + 1] = (arr[idx] - 48)*10 + arr[idx+1] - 48 - end - pos = pos + imax - ndigit = ndigit - imax - if ndigit == 1 then - -- cur_codeset setup - local ok, ctrl_first = ctrl_or_lowercase(pos + 1, arr) - if ok and ctrl_first then - cur_codeset = codeset.A - else - cur_codeset = codeset.B - end - res[#res + 1] = switch[codeset.C][cur_codeset] - end - end - else --- current codeset is A or B - if ndigit > 3 then - if ndigit % 2 > 1 then -- odd number of digits - encode_char(res, cur_codeset, arr[pos], codeset.A) - pos = pos + 1 - ndigit = ndigit - 1 - end - res[#res + 1] = switch[cur_codeset][codeset.C] - cur_codeset = codeset.C - elseif (cur_codeset == codeset.B) and - (arr[pos] >= 0 and arr[pos] < 32) then -- ops a control char - local ok, ctrl_first = ctrl_or_lowercase(pos + 1, arr) - if ok and (not ctrl_first) then -- shift to codeset A - res[#res + 1] = codeset.shift - encode_char(res, codeset.A, arr[pos], codeset.A) - pos = pos + 1 - ndigit = count_digits_from(pos, arr) - else -- switch to code set A - res[#res + 1] = switch[cur_codeset][codeset.A] - cur_codeset = codeset.A - end - elseif (cur_codeset == codeset.A) and - (arr[pos] > 95 and arr[pos] < 128) then -- ops a lower case char - local ok, ctrl_first = ctrl_or_lowercase(pos+1, arr) - if ok and ctrl_first then -- shift to codeset B - res[#res + 1] = codeset.shift - encode_char(res, codeset.B, arr[pos], codeset.A) - pos = pos + 1 - ndigit = count_digits_from(arr, pos) - else -- switch to code set B - res[#res + 1] = switch[cur_codeset][codeset.B] - cur_codeset = codeset.B - end - else - -- insert char - encode_char(res, cur_codeset, arr[pos], codeset.A) - pos = pos + 1 - ndigit = count_digits_from(arr, pos) - end - end - end - res[#res + 1] = check_digit(res) - res[#res + 1] = codeset.stopChar - return res -end - --- Code 128 internal functions used by Barcode costructors - -function Code128:_check_char(c) --> elem, err - if type(c) ~= "string" or #c ~= 1 then - return nil, "[InternalErr] invalid char" - end - local b = string.byte(c) - if b > 127 then - local fmt = "[unimplemented] the '%d' is an ASCII extented char" - return nil, string.format(fmt, c) - end - return b, nil -end - -function Code128:_check_digit(n) --> elem, err - if type(n) ~= "number" then - return nil, "[InternalErr] invalid digit" - end - return n + 48, nil -end - -function Code128:_finalize() --> ok, err - local chr = assert(self._code_data, "[InternalErr] '_code_data' field is nil") - local data, err = encode128(chr, self._codeset, self._switch) - if err then return false, err end - -- load dynamically required Vbar objects - local vbar = self._vbar - local oVbar = self._libgeo.Vbar - for _, c in ipairs(data) do - if not vbar[c] then - local n = self._int_def_bar[c] - local mod = self.xdim - vbar[c] = oVbar:from_int(n, mod, true) - end - end - self._enc_data = data - return true, nil -end - --- Drawing into the provided channel the geometrical barcode data --- tx, ty is the optional translator vector --- the function return the canvas reference to allow call chaining -function Code128:append_ga(canvas, tx, ty) --> canvas - local xdim, h = self.xdim, self.ydim - local sw = 11*xdim -- the width of a symbol - local data = self._enc_data - local w = #data * sw + 2 * xdim -- total symbol width - local ax, ay = self.ax, self.ay - local x0 = (tx or 0) - ax * w - local y0 = (ty or 0) - ay * h - local x1 = x0 + w - local y1 = y0 + h - local xpos = x0 - -- drawing the symbol - local err - err = canvas:start_bbox_group() - assert(not err, err) - for _, c in ipairs(data) do - local vb = self._vbar[c] - err = canvas:encode_Vbar(vb, xpos, y0, y1) - assert(not err, err) - xpos = xpos + sw - end - -- bounding box setting - local qz = self.quietzone_factor * xdim - -- { xmin, ymin, xmax, ymax } - err = canvas:stop_bbox_group(x0 - qz, y0, x1 + qz, y1) - assert(not err, err) - return canvas -end - -return Code128 --- \ No newline at end of file diff --git a/macros/luatex/generic/barracuda/lib/lib-barcode/code39.lua b/macros/luatex/generic/barracuda/lib/lib-barcode/code39.lua deleted file mode 100644 index a639619c63..0000000000 --- a/macros/luatex/generic/barracuda/lib/lib-barcode/code39.lua +++ /dev/null @@ -1,381 +0,0 @@ --- Code39 barcode encoder implementation --- Copyright (C) 2019 Roberto Giacomelli --- --- All dimensions must be in scaled point (sp) --- every fields that starts with an undercore sign are intended as private - -local Code39 = { - _VERSION = "code39 v0.0.5", - _NAME = "Code39", - _DESCRIPTION = "Code39 barcode encoder", -} - -Code39._symb_def = {-- symbol definition - ["0"] = 112122111, ["1"] = 211112112, ["2"] = 211112211, - ["3"] = 111112212, ["4"] = 211122111, ["5"] = 111122112, - ["6"] = 111122211, ["7"] = 212112111, ["8"] = 112112112, - ["9"] = 112112211, ["A"] = 211211112, ["B"] = 211211211, - ["C"] = 111211212, ["D"] = 211221111, ["E"] = 111221112, - ["F"] = 111221211, ["G"] = 212211111, ["H"] = 112211112, - ["I"] = 112211211, ["J"] = 112221111, ["K"] = 221111112, - ["L"] = 221111211, ["M"] = 121111212, ["N"] = 221121111, - ["O"] = 121121112, ["P"] = 121121211, ["Q"] = 222111111, - ["R"] = 122111112, ["S"] = 122111211, ["T"] = 122121111, - ["U"] = 211111122, ["V"] = 211111221, ["W"] = 111111222, - ["X"] = 211121121, ["Y"] = 111121122, ["Z"] = 111121221, - ["-"] = 212111121, ["."] = 112111122, [" "] = 112111221, - ["$"] = 111212121, ["/"] = 121112121, ["+"] = 121211121, - ["%"] = 121212111, -} -Code39._star_def = 112121121 -- '*' start/stop character - --- parameters definition -Code39._par_def = {} -local pardef = Code39._par_def - --- module main parameter -pardef.module = { - -- Narrow element X-dimension is the width of the smallest element in a - -- barcode symbol. - -- The X-dimension impacts scan-ability. Within the allowed range, it is - -- recommended to use the largest possible X-dimension that is consistent - -- with label or form design. - -- The module width (width of narrow element) should be at least 7.5 mils - -- or 0.1905mm (a mil is 1/1000 inch). - default = 7.5 * 0.0254 * 186467, -- 7.5 mils (sp) unit misure, - unit = "sp", -- scaled point - isReserved = true, - order = 1, -- the one first to be modified - fncheck = function (self, mod, _) --> boolean, err - if mod >= self.default then return true, nil end - return false, "[OutOfRange] too small value for module" - end, -} - -pardef.ratio = { - -- The "wide" element is a multiple of the "narrow" element and this - -- multiple must remain the same throughout the symbol. This multiple can - -- range between 2.0 and 3.0. Preferred value is 3.0. - -- The multiple for the wide element should be between 2.0 and 3.0 if the - -- narrow element is greater than 20 mils. If the narrow element is less - -- than 20 mils (0.508mm), the multiple can only range between 2.0 and 2.2. - default = 2.0, -- the minimum - unit = "absolute-number", - isReserved = true, - order = 2, - fncheck = function (self, ratio, tparcheck) --> boolean, err - local mils = 0.0254 * 186467 - local mod = tparcheck.module - local maxr; if mod < 20*mils then maxr = 2.2 else maxr = 3.0 end - if ratio < 2.0 then - return false, "[OutOfRange] too small ratio (min 2.0)" - end - if ratio > maxr then - return false, "[OutOfRange] too big ratio (max "..maxr..")" - end - return true, nil - end, -} - -pardef.quietzone = { - -- It is recommended to use the largest possible quiet zone, that is - -- consistent with label or form design. - -- Quiet zones must be at least 10 times the module width or 0.10 inches, - -- whichever is larger. Default value (100 mils) - default = 2.54 * 186467, -- 0.1 inches equal to 100*mils - unit = "sp", -- scaled point - isReserved = false, - order = 3, - fncheck = function (self, qz, tparcheck) --> boolean, err - local mils = 0.0254 * 186467 - local mod = tparcheck.module - local min = math.max(10*mod, 100*mils) - if qz >= min then - return true, nil - end - return false, "[OutOfRange] quietzone too small" - end, - fndefault = function(self, tck) --> default value respect to a set of param - local mod = tck.module - return math.max(10*mod, self.default) - end, -} - -pardef.interspace = { -- Intercharacter gap - -- The intercharacter gap width (igw) is 5.3 times the module width (mw) if - -- mw is less than 10 mils. If mw is 10 mils or greater, the value for igw - -- is 3mw or 53 mils, whichever is greater. However, for quality printers, - -- igw often equals mw. - default = 7.5 * 0.0254 * 186467, -- 1 module, for quality printer - unit = "sp", -- scaled point - isReserved = false, - order = 4, - fncheck = function (self, igw, tparcheck) --> boolean, err - local mod = tparcheck.module - if igw >= mod then return true, nil end - return false, "[OutOfRange] interspace too small" - end, - fndefault = function(self, tck) --> default value respect to a set of param - return tck.module - end, -} - -pardef.height = { - -- To enhance readability, it is recommended that the barcode be designed - -- to be as tall as possible, taking into consideration the aspects of label - -- and forms design. - -- The height should be at least 0.15 times the barcode's length or 0.25 inch. - default = 8 * 186467, -- 8 mm -- TODO: better assessment for symbol length - unit = "sp", -- scaled point - isReserved = false, - order = 5, - fncheck = function (self, h, _) --> boolean, err - local mils = 0.0254 * 186467 - if h >= 250*mils then return true, nil end - return false, "[OutOfRange] height too small" - end, -} - --- text yes or not -pardef.text_enabled = { -- boolean type - -- enable/disable a text label upon the barcode symbol - default = true, - isReserved = false, - order = 6, - fncheck = function (self, flag, _) --> boolean, err - if type(flag) == "boolean" then - return true, nil - else - return false, "[TypeErr] not a boolean value" - end - end, -} - --- define the text label vertical position -pardef.text_vpos = { -- enumeration - default = "bottom", - isReserved = false, - order = 7, - policy_enum = { - top = true, -- place text at the top of symbol - bottom = true, -- place text under the symbol - }, - fncheck = function (self, e, _) --> boolean, err - if type(e) ~= "string" then return false, "[TypeError] not a string" end - local keys = self.policy_enum - if keys[e] == true then - return true, nil - else - return false, "[Err] enumeration value '"..e.."' not found" - end - end, -} - --- define the text label horizontal position -pardef.text_hpos = { -- enumeration - default = "left", - isReserved = false, - order = 8, - policy_enum = { - left = true, - center = true, - right = true, - spaced = true, - }, - fncheck = function (self, e, _) --> boolean, err - if type(e) ~= "string" then return false, "[TypeError] not a string" end - local keys = self.policy_enum - if keys[e] == true then - return true, nil - else - return false, "[Err] enumeration value '"..e.."' not found" - end - end, -} - --- vertical dimension between symbol and text -pardef.text_gap = { - default = 2.2 * 65536, -- 2.2 pt - isReserved = false, - order = 9, - unit = "em", --> TODO: please put this under further analisys asap - fncheck = function(self, g, _) --> boolean, err - if type(g) == "number" then - if g > 0 then - return true, nil - else - return false, "[OptErr] negative number" - end - else - return false, "[TypeErr] not valid type for gap opt" - end - end, -} - --- star character appearing -pardef.text_star = { - default = false, - isReserved = false, - order = 10, - fncheck = function(self, flag, _) --> boolean, err - if type(flag) == "boolean" then - return true, nil - else - return false, "[TypeErr] not a boolean value" - end - end, -} - --- configuration function -function Code39:config() --> ok, err - -- build Vbar object for the start/stop symbol - local mod, ratio = self.module, self.ratio - local n_star = self._star_def - local Vbar = self._libgeo.Vbar -- Vbar class - self._vbar = {['*'] = Vbar:from_int_revpair(n_star, mod, mod*ratio)} - return true, nil -end - --- overriding Barcode method -function Code39:_check_char(c) --> elem, err - if type(c) ~= "string" or #c ~= 1 then - return nil, "[InternalErr] invalid char" - end - local symb_def = self._symb_def - local n = symb_def[c] - if not n then - local fmt = "[ArgErr] '%s' is not a valid Code 39 symbol" - return nil, string.format(fmt, c) - end - return c, nil -end - --- overriding Barcode method -function Code39:_check_digit(n) --> elem, err - if type(n) ~= "number" then - return nil, "[InteranlErr] not a number" - end - if n < 0 or n > 9 then - return nil, "[InternalErr] not a digit" - end - return tostring(n), nil -end - -function Code39:_finalize() --> ok, err - local v = assert(self._code_data, "[InternalErr] '_code_data' field is nil") - local vbar = self._vbar - local g_Vbar = self._libgeo.Vbar - local mod, ratio = self.module, self.ratio - local symb_def = self._symb_def - for _, c in ipairs(v) do - if not vbar[c] then - local n1 = symb_def[c] - vbar[c] = g_Vbar:from_int_revpair(n1, mod, mod*ratio) - end - end - return true, nil -end - --- tx, ty is an optional translator vector -function Code39:append_ga(canvas, tx, ty) --> canvas - local code = self._code_data - local ns = self._code_len -- number of chars inside the symbol - local mod = self.module - local ratio = self.ratio - local interspace = self.interspace - local h = self.height - local xs = mod*(6 + 3*ratio) - local xgap = xs + interspace - local w = xgap*(ns + 1) + xs -- (ns + 2)*xgap - interspace - local ax, ay = self.ax, self.ay - local x0 = (tx or 0) - ax * w - local y0 = (ty or 0) - ay * h - local x1 = x0 + w - local y1 = y0 + h - local xpos = x0 - local err - err = canvas:start_bbox_group() - assert(not err, err) - local vbar = self._vbar - -- start/stop symbol - local term_vbar = vbar['*'] - -- draw start symbol - err = canvas:encode_Vbar(term_vbar, xpos, y0, y1) - assert(not err, err) - for _, c in ipairs(code) do -- draw code symbols - xpos = xpos + xgap - local vb = vbar[c] - err = canvas:encode_Vbar(vb, xpos, y0, y1) - assert(not err, err) - end - -- draw stop symbol - err = canvas:encode_Vbar(term_vbar, xpos + xgap, y0, y1) - assert(not err, err) - -- bounding box setting - local qz = self.quietzone - err = canvas:stop_bbox_group(x0 - qz, y0, x1 + qz, y1) - assert(not err, err) - -- check height as the minimum of 15% of length - -- TODO: message could warn the user - -- if 0.15 * w > h then - -- message("The height of the barcode is to small") - -- end - if self.text_enabled then -- human readable text - local chars; if self.text_star then - chars = {"*"} - for _, c in ipairs(code) do - chars[#chars + 1] = c - end - chars[#chars + 1] = "*" - else - chars = {} - for _, c in ipairs(code) do - chars[#chars + 1] = c - end - end - local Text = self._libgeo.Text - local txt = Text:from_chars(chars) - -- setup text position - local txt_vpos = self.text_vpos - local txt_gap = self.text_gap - local ypos, tay; if txt_vpos == "top" then -- vertical setup - ypos = y1 + txt_gap - tay = 0.0 - elseif txt_vpos == "bottom" then - ypos = y0 - txt_gap - tay = 1.0 - else - error("[IntenalErr] text vertical placement option is wrong") - end - local txt_hpos = self.text_hpos - if txt_hpos == "spaced" then -- horizontal setup - local xaxis = x0 - if not self.text_star then - xaxis = xaxis + xgap - end - xaxis = xaxis + xs/2 - err = canvas:encode_Text_xspaced(txt, xaxis, xgap, ypos, tay) - assert(not err, err) - else - local xpos, tax - if txt_hpos == "left" then - xpos = x0 - tax = 0.0 - elseif txt_hpos == "center" then - xpos = (x1 + x0)/2 - tax = 0.5 - elseif txt_hpos == "right" then - xpos = x1 - tax = 1.0 - else - error("[InternalErr] wrong option for text_pos") - end - err = canvas:encode_Text(txt, xpos, ypos, tax, tay) - assert(not err, err) - end - end - return canvas -end - -return Code39 --- \ No newline at end of file diff --git a/macros/luatex/generic/barracuda/lib/lib-barcode/ean.lua b/macros/luatex/generic/barracuda/lib/lib-barcode/ean.lua deleted file mode 100644 index 6893550a5c..0000000000 --- a/macros/luatex/generic/barracuda/lib/lib-barcode/ean.lua +++ /dev/null @@ -1,790 +0,0 @@ --- EAN family barcode generator --- --- Copyright (C) 2019 Roberto Giacomelli --- see LICENSE.txt file --- --- variant identifiers of the EAN family barcodes: --- "13" EAN13 --- "8" EAN8 --- "5" EAN5 add-on --- "2" EAN2 add-on --- "13+5" EAN13 with EAN5 add-on --- "13+2" EAN13 with EAN2 add-on --- "8+5" EAN8 with EAN5 add-on --- "8+2" EAN8 with EAN2 add-on - -local EAN = { - _VERSION = "ean v0.0.5", - _NAME = "ean", - _DESCRIPTION = "EAN barcode encoder", -} - -EAN._codeset_seq = {-- 1 -> A, 2 -> B, 3 -> C -[0]={1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3}, - {1, 1, 2, 1, 2, 2, 3, 3, 3, 3, 3, 3}, - {1, 1, 2, 2, 1, 2, 3, 3, 3, 3, 3, 3}, - {1, 1, 2, 2, 2, 1, 3, 3, 3, 3, 3, 3}, - {1, 2, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3}, - {1, 2, 2, 1, 1, 2, 3, 3, 3, 3, 3, 3}, - {1, 2, 2, 2, 1, 1, 3, 3, 3, 3, 3, 3}, - {1, 2, 1, 2, 1, 2, 3, 3, 3, 3, 3, 3}, - {1, 2, 1, 2, 2, 1, 3, 3, 3, 3, 3, 3}, - {1, 2, 2, 1, 2, 1, 3, 3, 3, 3, 3, 3}, -} - -EAN._codeset14_8 = 1 -EAN._codeset58_8 = 3 - -EAN._codeset_5 = { -- check digit => structure -[0]={2, 2, 1, 1, 1}, -- 0 GGLLL - {2, 1, 2, 1, 1}, -- 1 GLGLL - {2, 1, 1, 2, 1}, -- 2 GLLGL - {2, 1, 1, 1, 2}, -- 3 GLLLG - {1, 2, 2, 1, 1}, -- 4 LGGLL - {1, 1, 2, 2, 1}, -- 5 LLGGL - {1, 1, 1, 2, 2}, -- 6 LLLGG - {1, 2, 1, 2, 1}, -- 7 LGLGL - {1, 2, 1, 1, 2}, -- 8 LGLLG - {1, 1, 2, 1, 2}, -- 9 LLGLG -} - -EAN._symbol = { -- codesets A, B, and C - [1] = {[0] = 3211, 2221, 2122, 1411, 1132, 1231, 1114, 1312, 1213, 3112,}, - [2] = {[0] = 1123, 1222, 2212, 1141, 2311, 1321, 4111, 2131, 3121, 2113,}, - [3] = {[0] = 3211, 2221, 2122, 1411, 1132, 1231, 1114, 1312, 1213, 3112,}, -} - -EAN._is_first_bar = {false, false, true} -EAN._start = {111, true} -EAN._stop = {11111, false} - --- family parameters - -EAN._par_def = {}; local pardef = EAN._par_def - --- standard module is 0.33 mm but it can vary from 0.264 to 0.66mm -pardef.mod = { - default = 0.33 * 186467, -- (mm to sp) X dimension (original value 0.33) - unit = "sp", -- scaled point - isReserved = true, - order = 1, -- the one first to be modified - fncheck = function (self, x, _) --> boolean, err - local mm = 186467 - local min, max = 0.264 * mm, 0.660 * mm - if x < min then - return false, "[OutOfRange] too small value for mod" - elseif x > max then - return false, "[OutOfRange] too big value for mod" - end - return true, nil - end, -} - -pardef.height = { - default = 22.85 * 186467, -- 22.85 mm - unit = "sp", - isReserved = false, - order = 2, - fncheck = function (self, h, _) --> boolean, err - if h > 0 then - return true, nil - else - return false, "[OutOfRange] non positive value for height" - end - end, -} - -pardef.quietzone_left_factor = { - default = 11, - unit = "absolute-number", - isReserved = false, - order = 3, - fncheck = function (self, qzf, _) --> boolean, err - if qzf > 0 then - return true, nil - else - return false, "[OutOfRange] non positive value for quietzone_left_factor" - end - end, -} - -pardef.quietzone_right_factor = { - default = 7, - unit = "absolute-number", - isReserved = false, - order = 4, - fncheck = function (self, qzf, _) --> boolean, err - if qzf > 0 then - return true, nil - else - return false, "[OutOfRange] non positive value for quietzone_right_factor" - end - end, -} - -pardef.bars_depth_factor = { - default = 5, - unit = "absolute-number", - isReserved = false, - order = 5, - fncheck = function (self, b, _) --> boolean, err - if b >= 0 then - return true, nil - else - return false, "[OutOfRange] non positive value for bars_depth_factor" - end - end, -} - --- enable/disable a text label upon the barcode symbol -pardef.text_enabled = { -- boolean type - default = true, - isReserved = false, - order = 6, - fncheck = function (self, flag, _) --> boolean, err - if type(flag) == "boolean" then - return true, nil - else - return false, "[TypeErr] not a boolean value for text_enabled" - end - end, -} - -pardef.text_ygap_factor = { - default = 1.0, - unit = "absolute-number", - isReserved = false, - order = 7, - fncheck = function (self, t, _) --> boolean, err - if t >= 0 then - return true, nil - else - return false, "[OutOfRange] non positive value for text_ygap_factor" - end - end, -} - -pardef.text_xgap_factor = { - default = 0.75, - unit = "absolute-number", - isReserved = false, - order = 8, - fncheck = function (self, t, _) --> boolean, err - if t >= 0 then - return true, nil - else - return false, "[OutOfRange] non positive value for text_xgap_factor" - end - end, -} - --- variant parameters - -EAN._par_def_variant = { - ["13"] = {}, -- EAN13 - ["8"] = {}, -- EAN8 - ["5"] = {}, -- add-on EAN5 - ["2"] = {}, -- add-on EAN2 - ["13+5"] = {}, -- EAN13 with EAN5 add-on - ["13+2"] = {}, -- EAN13 with EAN2 add-on - ["8+5"] = {}, -- EAN8 with EAN5 add-on - ["8+2"] = {}, -- EAN8 with EAN2 add-on -} - --- ean13_pardef.text_ISBN parameter -- TODO: - --- EAN 13/8 + add-on parameters -local addon_xgap_factor = {-- distance between symbol - default = 10, - unit = "absolute-number", - isReserved = false, - order = 1, - fncheck = function (self, t, _) --> boolean, err - if t >= 7 then - return true, nil - else - return false, "[OutOfRange] not positive value for xgap_factor" - end - end, -} -EAN._par_def_variant["13+5"].addon_xgap_factor = addon_xgap_factor -EAN._par_def_variant["13+2"].addon_xgap_factor = addon_xgap_factor -EAN._par_def_variant["8+5"].addon_xgap_factor = addon_xgap_factor -EAN._par_def_variant["8+2"].addon_xgap_factor = addon_xgap_factor - --- configuration functions - --- utility for generic configuration of full symbol, add-on included --- n1 length of main symbol, 8 or 13 --- n2 length of add-on symbol, 2 or 5 -local function config_full(ean, Vbar, mod, n1, n2) - local i1 = tostring(n1) - local fn_1 = assert(ean._config_variant[i1]) - fn_1(ean, Vbar, mod) - local i2 = tostring(n2) - local fn_2 = assert(ean._config_variant[i2]) - fn_2(ean, Vbar, mod) - ean._main_len = n1 - ean._addon_len = n2 - ean._is_last_checksum = true -end - -EAN._config_variant = { - ["13"] = function (ean13, Vbar, mod) - ean13._main_len = 13 - ean13._is_last_checksum = true - local start = ean13._start - local stop = ean13._stop - ean13._13_start_stop_vbar = Vbar:from_int(start[1], mod, start[2]) - ean13._13_ctrl_center_vbar = Vbar:from_int(stop[1], mod, stop[2]) - ean13._13_codeset_vbar = {} - local tvbar = ean13._13_codeset_vbar - for i_cs, codetab in ipairs(ean13._symbol) do - tvbar[i_cs] = {} - local tv = tvbar[i_cs] - local isbar = ean13._is_first_bar[i_cs] - for i = 0, 9 do - tv[i] = Vbar:from_int(codetab[i], mod, isbar) - end - end - end, - ["8"] = function (ean8, Vbar, mod) - ean8._main_len = 8 - ean8._is_last_checksum = true - local start = ean8._start - local stop = ean8._stop - ean8._8_start_stop_vbar = Vbar:from_int(start[1], mod, start[2]) - ean8._8_ctrl_center_vbar = Vbar:from_int(stop[1], mod, stop[2]) - ean8._8_codeset_vbar = {} - local tvbar = ean8._8_codeset_vbar - for k = 1, 3, 2 do -- only codeset A and C (k == 1, 3) - tvbar[k] = {} - local codetab = ean8._symbol[k] - local isbar = ean8._is_first_bar[k] - local tv = tvbar[k] - for i = 0, 9 do - tv[i] = Vbar:from_int(codetab[i], mod, isbar) - end - end - end, - ["5"] = function (ean5, Vbar, mod) -- add-on EAN5 - ean5._main_len = 5 - ean5._is_last_checksum = false - ean5._5_start_vbar = Vbar:from_int(112, mod, true) - ean5._5_sep_vbar = Vbar:from_int(11, mod, false) - ean5._5_codeset_vbar = {} - local tvbar = ean5._5_codeset_vbar - local symbols = ean5._symbol - for c = 1, 2 do - tvbar[c] = {} - local tcs = tvbar[c] - local isbar = false - local sb = symbols[c] - for i = 0, 9 do - tcs[i] = Vbar:from_int(sb[i], mod, false) - end - end - end, - ["2"] = function (ean2, Vbar, mod) -- add-on EAN2 - ean2._main_len = 2 - ean2._is_last_checksum = false - ean2._2_start_vbar = Vbar:from_int(112, mod, true) - ean2._2_sep_vbar = Vbar:from_int(11, mod, false) - ean2._2_codeset_vbar = {} - local tvbar = ean2._2_codeset_vbar - local symbols = ean2._symbol - for c = 1, 2 do - tvbar[c] = {} - local tcs = tvbar[c] - local isbar = false - local sb = symbols[c] - for i = 0, 9 do - tcs[i] = Vbar:from_int(sb[i], mod, false) - end - end - end, - ["13+5"] = function (ean, Vbar, mod) -- EAN13 with EAN5 add-on - config_full(ean, Vbar, mod, 13, 5) - end, - ["13+2"] = function(ean, Vbar, mod) -- EAN13 with EAN2 add-on - config_full(ean, Vbar, mod, 13, 2) - end, - ["8+5"] = function(ean, Vbar, mod) -- EAN8 with EAN5 add-on - config_full(ean, Vbar, mod, 8, 5) - end, - ["8+2"] = function(ean, Vbar, mod) -- EAN8 with EAN2 add-on - config_full(ean, Vbar, mod, 8, 2) - end, -} - --- config function --- create all the possible VBar object -function EAN:config(variant) --> ok, err - if not type(variant) == "string" then - return false, "[ArgErr] incorrect type for 'variant', string expected" - end - local fnconfig = self._config_variant[variant] - if not fnconfig then - return false, "[Err] EAN variant '".. variant .."' not found" - end - local Vbar = self._libgeo.Vbar -- Vbar class - local mod = self.mod - fnconfig(self, Vbar, mod) - return true, nil -end - --- utility function - --- the checksum of EAN8 or EAN13 code --- 'data' is an array of digits -local function checksum_8_13(data, stop_index) - local s1 = 0; for i = 2, stop_index, 2 do - s1 = s1 + data[i] - end - local s2 = 0; for i = 1, stop_index, 2 do - s2 = s2 + data[i] - end - local sum; if stop_index % 2 == 0 then - sum = 3 * s1 + s2 - else - sum = s1 + 3 * s2 - end - return (10 - (sum % 10)) % 10 -end - --- return the checksum digit of an EAN 5 or EAN 2 add-on --- this digits will not be part of the code --- 'data' is an array of digits --- i is the index where the code starts --- len is the length of the code -local function checksum_5_2(data, i, len) --> checksum digit or nil - if len == 5 then -- EAN 5 add-on - local c1 = data[i] + data[i + 2] + data[i + 4] - local c2 = data[i + 1] + data[i + 3] - local ck = 3 * c1 + 9 * c2 - return ck % 10 - elseif len == 2 then -- EAN 2 add-on - local ck = 10 * data[i] + data[i + 1] - return ck % 4 - end -end - --- public methods - --- return the checksum digit of the argument or an error --- respect to the encoder variant EAN8 or EAN13 --- 'n' can be an integer, a string of digits or an array of digits -function EAN:checksum(n) --> n, err - local arr; - if type(n) == "number" then - if n <= 0 then - return nil, "[ArgErr] number must be a positive integer" - end - if n - math.floor(n) > 0 then - return nil, "[ArgErr] 'n' is not an integer" - end - arr = {} - local i = 0 - while n > 0 do - i = i + 1 - arr[i] = n % 10 - n = (n - arr[i]) / 10 - end - -- array reversing - local len = #arr + 1 - for i = 1, #arr/2 do - local dt = arr[i] - arr[i] = arr[len - i] - arr[len - i] = dt - end - elseif type(n) == "table" then - if not #n > 0 then return nil, "[ArgErr] empty array" end - for _, d in ipairs(n) do - if type(d) ~= "number" then - return nil, "[ArgErr] array 'n' contains a not digit element" - end - if d < 0 or d > 9 then - return nil, "[ArgErr] array contains a not digit number" - end - end - arr = n - elseif type(n) == "string" then - arr = {} - for c in string.gmatch(n, ".") do - local d = tonumber(c) - if (not d) or d > 9 then - return nil, "[ArgErr] 's' contains a not digit char" - end - arr[#arr + 1] = d - end - else - return nil, "[ArgErr] not a number, a string or an array of digits" - end - local i = #arr - if i == 7 or i == 8 then - return checksum_8_13(arr, 7) - elseif i == 12 or i == 13 then - return checksum_8_13(arr, 12) - else - return nil, "[Err] unsuitable data length for EAN8 or EAN13 checksum" - end -end - -function EAN:get_code() --> string - local var = self._variant - local code = self.code13 -- TODO: - return table.concat(code) -end - --- internal methods for Barcode costructors - -function EAN:_finalize() --> ok, err - local l1 = self._main_len - local l2 = self._addon_len - local ok_len = l1 + (l2 or 0) - local symb_len = self._code_len - if symb_len ~= ok_len then - return false, "[ArgErr] not a "..ok_len.."-digits long array" - end - if self._is_last_checksum then -- is the last digit ok? - local data = self._code_data - local ck = checksum_8_13(data, l1 - 1) - if ck ~= data[l1] then - return false, "[Err] wrong checksum digit" - end - end - return true, nil -end - --- drawing functions - -EAN._append_ga_variant = {} -local fn_append_ga_variant = EAN._append_ga_variant - --- draw EAN13 symbol -fn_append_ga_variant["13"] = function (ean, canvas, tx, ty, ax, ay) - local code = ean._code_data - local mod = ean.mod - local bars_depth = mod * ean.bars_depth_factor - local w, h = 95*mod, ean.height + bars_depth - local x0 = (tx or 0) - ax * w - local y0 = (ty or 0) - ay * h - local x1 = x0 + w - local y1 = y0 + h - local xpos = x0 -- current insertion x-coord - local ys = y0 + bars_depth - local s_width = 7*mod - local code_seq = ean._codeset_seq[code[1]] - -- draw the start symbol - local err - err = canvas:start_bbox_group(); assert(not err, err) - local be = ean._13_start_stop_vbar - err = canvas:encode_Vbar(be, xpos, y0, y1); assert(not err, err) - xpos = xpos + 3*mod - -- draw the first 6 numbers - for i = 2, 7 do - local codeset = code_seq[i-1] - local n = code[i] - local vbar = ean._13_codeset_vbar[codeset][n] - err = canvas:encode_Vbar(vbar, xpos, ys, y1); assert(not err, err) - xpos = xpos + s_width - end - -- draw the control symbol - local ctrl = ean._13_ctrl_center_vbar - err = canvas:encode_Vbar(ctrl, xpos, y0, y1); assert(not err, err) - xpos = xpos + 5*mod - -- draw the last 6 numbers - for i = 8, 13 do - local codeset = code_seq[i-1] - local n = code[i] - local vbar = ean._13_codeset_vbar[codeset][n] - err = canvas:encode_Vbar(vbar, xpos, ys, y1); assert(not err, err) - xpos = xpos + s_width - end - -- draw the stop char - err = canvas:encode_Vbar(be, xpos, y0, y1); assert(not err, err) - -- bounding box set up - local qzl = ean.quietzone_left_factor * mod - local qzr = ean.quietzone_right_factor * mod - local err = canvas:stop_bbox_group(x0 - qzl, y0, x1 + qzr, y1) - assert(not err, err) - if ean.text_enabled then -- human readable text - local Text = ean._libgeo.Text - local txt_1 = Text:from_digit_array(code, 1, 1) - local txt_2 = Text:from_digit_array(code, 2, 7) - local txt_3 = Text:from_digit_array(code, 8, 13) - local y_bl = ys - ean.text_ygap_factor * mod - local mx = ean.text_xgap_factor - local err - err = canvas:encode_Text(txt_1, x0 - qzl, y_bl, 0, 1) - assert(not err, err) - local x2_1 = x0 + (3+mx)*mod - local x2_2 = x0 + (46-mx)*mod - err = canvas:encode_Text_xwidth(txt_2, x2_1, x2_2, y_bl, 1) - assert(not err, err) - local x3_1 = x0 + (49+mx)*mod - local x3_2 = x0 + (92-mx)*mod - err = canvas:encode_Text_xwidth(txt_3, x3_1, x3_2, y_bl, 1) - assert(not err, err) - end -end - --- draw EAN8 symbol -fn_append_ga_variant["8"] = function (ean, canvas, tx, ty, ax, ay) - local code = ean._code_data - local mod = ean.mod - local bars_depth = mod * ean.bars_depth_factor - local w, h = 67*mod, ean.height + bars_depth - local x0 = (tx or 0) - ax * w - local y0 = (ty or 0) - ay * h - local x1 = x0 + w - local y1 = y0 + h - local xpos = x0 -- current insertion x-coord - local ys = y0 + bars_depth - local s_width = 7*mod - -- draw the start symbol - local err - err = canvas:start_bbox_group(); assert(not err, err) - local be = ean._8_start_stop_vbar - err = canvas:encode_Vbar(be, xpos, y0, y1); assert(not err, err) - xpos = xpos + 3*mod - -- draw the first 4 numbers - local t_vbar = ean._8_codeset_vbar - local cs14 = ean._codeset14_8 - for i = 1, 4 do - local n = code[i] - local vbar = t_vbar[cs14][n] - err = canvas:encode_Vbar(vbar, xpos, ys, y1); assert(not err, err) - xpos = xpos + s_width - end - -- draw the control symbol - local ctrl = ean._8_ctrl_center_vbar - err = canvas:encode_Vbar(ctrl, xpos, y0, y1); assert(not err, err) - xpos = xpos + 5*mod - -- draw the product code - local cs58 = ean._codeset58_8 - for i = 5, 8 do - local n = code[i] - local vbar = t_vbar[cs58][n] - err = canvas:encode_Vbar(vbar, xpos, ys, y1); assert(not err, err) - xpos = xpos + s_width - end - -- draw the stop char - err = canvas:encode_Vbar(be, xpos, y0, y1); assert(not err, err) - -- bounding box set up - local qzl = ean.quietzone_left_factor * mod - local qzr = ean.quietzone_right_factor * mod - local err = canvas:stop_bbox_group(x0 - qzl, y0, x1 + qzr, y1) - assert(not err, err) - if ean.text_enabled then -- human readable text - local Text = ean._libgeo.Text - local t_1 = Text:from_digit_array(code, 1, 4) - local t_2 = Text:from_digit_array(code, 5, 8) - local y_bl = ys - ean.text_ygap_factor * mod - local mx = ean.text_xgap_factor - local x1_1 = x0 + ( 3 + mx)*mod - local x1_2 = x0 + (32 - mx)*mod - err = canvas:encode_Text_xwidth(t_1, x1_1, x1_2, y_bl, 1) - assert(not err, err) - local x2_1 = x0 + (35+mx)*mod - local x2_2 = x0 + (64-mx)*mod - err = canvas:encode_Text_xwidth(t_2, x2_1, x2_2, y_bl, 1) - assert(not err, err) - end -end - --- draw EAN5 add-on symbol -fn_append_ga_variant["5"] = function (ean, canvas, tx, ty, ax, ay, h) - local code = ean._code_data - local l1 = ean._main_len - local i1; if l1 == 5 then - i1 = 1 - else - i1 = l1 + 1 - end - local i2 = i1 + 4 - local mod = ean.mod - local w = 47*mod - h = h or ean.height - local x0 = (tx or 0) - ax * w - local y0 = (ty or 0) - ay * h - local x1 = x0 + w - local y1 = y0 + h - local xpos = x0 -- current insertion x-coord - local sym_w = 7*mod - local sep_w = 2*mod - -- draw the start symbol - local err - err = canvas:start_bbox_group(); assert(not err, err) - local start = ean._5_start_vbar - err = canvas:encode_Vbar(start, xpos, y0, y1); assert(not err, err) - xpos = xpos + 4*mod - local ck = checksum_5_2(code, i1, 5) - local codeset = ean._codeset_5[ck] - local sep = ean._5_sep_vbar - local t_vbar = ean._5_codeset_vbar - -- draw the five digits - local k = 0 - for i = i1, i2 do - k = k + 1 - local cs = codeset[k] -- 1 or 2 - local d = code[i] - local vbar = t_vbar[cs][d] - err = canvas:encode_Vbar(vbar, xpos, y0, y1); assert(not err, err) - xpos = xpos + sym_w - if k < 5 then - err = canvas:encode_Vbar(sep, xpos, y0, y1); assert(not err, err) - xpos = xpos + sep_w - end - end - -- bounding box set up - local qzl = ean.quietzone_left_factor * mod - local qzr = ean.quietzone_right_factor * mod - local err = canvas:stop_bbox_group(x0 - qzl, y0, x1 + qzr, y1) - assert(not err, err) - if ean.text_enabled then -- human readable text - local Text = ean._libgeo.Text - local txt = Text:from_digit_array(code, i1, i2) - local y_bl = y1 + ean.text_ygap_factor * mod - local x1_1 = x0 + 3*mod - local x1_2 = x1 - 3*mod - err = canvas:encode_Text_xwidth(txt, x1_1, x1_2, y_bl, 0) - assert(not err, err) - end -end - --- draw EAN2 symbol -fn_append_ga_variant["2"] = function (ean, canvas, tx, ty, ax, ay, h) - local code = ean._code_data - local l1 = ean._main_len - local i1; if l1 == 2 then - i1 = 1 - else - i1 = l1 + 1 - end - local mod = ean.mod - local w = 20*mod - h = h or ean.height - local x0 = (tx or 0.0) - ax * w - local y0 = (ty or 0.0) - ay * h - local x1 = x0 + w - local y1 = y0 + h - local xpos = x0 -- current insertion x-coord - local sym_w = 7*mod - local sep_w = 2*mod - -- draw the start symbol - local err - err = canvas:start_bbox_group(); assert(not err, err) - local start = ean._2_start_vbar - err = canvas:encode_Vbar(start, xpos, y0, y1); assert(not err, err) - xpos = xpos + 4*mod - local r = checksum_5_2(code, i1, 2) - local s1, s2 - if r == 0 then -- LL scheme - s1, s2 = 1, 1 - elseif r == 1 then -- LG scheme - s1, s2 = 1, 2 - elseif r == 2 then -- GL scheme - s1, s2 = 2, 1 - else -- r == 3 -- GG scheme - s1, s2 = 2, 2 - end - local t_vbar = ean._2_codeset_vbar - local d1 = code[i1] -- render the first digit - local vb1 = t_vbar[s1][d1] - err = canvas:encode_Vbar(vb1, xpos, y0, y1); assert(not err, err) - xpos = xpos + sym_w - local sep = ean._2_sep_vbar - err = canvas:encode_Vbar(sep, xpos, y0, y1); assert(not err, err) - xpos = xpos + sep_w - local d2 = code[i1 + 1] -- render the second digit - local vb2 = t_vbar[s2][d2] - err = canvas:encode_Vbar(vb2, xpos, y0, y1); assert(not err, err) - -- bounding box set up - local qzl = ean.quietzone_left_factor * mod - local qzr = ean.quietzone_right_factor * mod - local err = canvas:stop_bbox_group(x0 - qzl, y0, x1 + qzr, y1) - assert(not err, err) - if ean.text_enabled then -- human readable text - local Text = ean._libgeo.Text - local txt = Text:from_digit_array(code, i1, i1 + 1) - local y_bl = y1 + ean.text_ygap_factor * mod - local x1_1 = x0 + 3*mod - local x1_2 = x1 - 3*mod - err = canvas:encode_Text_xwidth(txt, x1_1, x1_2, y_bl, 0) - assert(not err, err) - end -end - -fn_append_ga_variant["13+5"] = function (ean, canvas, tx, ty, ax, ay) - local mod = ean.mod - local bars_depth = mod * ean.bars_depth_factor - local h = ean.height + bars_depth - local w = (142 + ean.addon_xgap_factor) * mod - local x0 = (tx or 0) - ax * w - local y0 = (ty or 0) - ay * h - local x1 = x0 + w - local fn_ga = ean._append_ga_variant - local fn_1 = fn_ga["13"] - local fn_2 = fn_ga["5"] - fn_1(ean, canvas, x0, y0, 0, 0) - fn_2(ean, canvas, x1, y0, 1, 0, 0.85 * h) -end - -fn_append_ga_variant["13+2"] = function (ean, canvas, tx, ty, ax, ay) - local mod = ean.mod - local bars_depth = mod * ean.bars_depth_factor - local h = ean.height + bars_depth - local w = (115 + ean.addon_xgap_factor) * mod - local x0 = (tx or 0) - ax * w - local y0 = (ty or 0) - ay * h - local x1 = x0 + w - local fn_ga = ean._append_ga_variant - local fn_1 = fn_ga["13"] - local fn_2 = fn_ga["2"] - fn_1(ean, canvas, x0, y0, 0, 0) - fn_2(ean, canvas, x1, y0, 1, 0, 0.85 * h) -end - -fn_append_ga_variant["8+5"] = function (ean, canvas, tx, ty, ax, ay) - local mod = ean.mod - local bars_depth = mod * ean.bars_depth_factor - local h = ean.height + bars_depth - local w = (114 + ean.addon_xgap_factor) * mod - local x0 = (tx or 0) - ax * w - local y0 = (ty or 0) - ay * h - local x1 = x0 + w - local fn_ga = ean._append_ga_variant - local fn_1 = fn_ga["8"] - local fn_2 = fn_ga["5"] - fn_1(ean, canvas, x0, y0, 0, 0) - fn_2(ean, canvas, x1, y0, 1, 0, 0.85 * h) -end - -fn_append_ga_variant["8+2"] = function (ean, canvas, tx, ty, ax, ay) - local mod = ean.mod - local bars_depth = mod * ean.bars_depth_factor - local h = ean.height + bars_depth - local w = (87 + ean.addon_xgap_factor) * mod - local x0 = (tx or 0) - ax * w - local y0 = (ty or 0) - ay * h - local x1 = x0 + w - local fn_ga = ean._append_ga_variant - local fn_1 = fn_ga["8"] - local fn_2 = fn_ga["2"] - fn_1(ean, canvas, x0, y0, 0, 0) - fn_2(ean, canvas, x1, y0, 1, 0, 0.85 * h) -end - --- Drawing into the provided channel geometrical data --- tx, ty is the optional translation vector --- the function return the canvas reference to allow call chaining -function EAN:append_ga(canvas, tx, ty) --> canvas - local var = self._variant - local fn_append_ga = assert(self._append_ga_variant[var]) - local ax, ay = self.ax, self.ay - fn_append_ga(self, canvas, tx, ty, ax, ay) - return canvas -end - -return EAN diff --git a/macros/luatex/generic/barracuda/lib/lib-barcode/i2of5.lua b/macros/luatex/generic/barracuda/lib/lib-barcode/i2of5.lua deleted file mode 100644 index 8097b855f7..0000000000 --- a/macros/luatex/generic/barracuda/lib/lib-barcode/i2of5.lua +++ /dev/null @@ -1,378 +0,0 @@ --- Interleaved 2 of 5 (ITF) barcode generator --- --- Copyright (C) 2019 Roberto Giacomelli --- see LICENSE.txt file - -local ITF = { -- main container - _VERSION = "ITF v0.0.1", - _NAME = "ITF", - _DESCRIPTION = "Interleaved 2 of 5 barcode encoder", -} - -ITF._start = 111 -- nnnn -ITF._stop = 112 -- Wnn (integer must be in reverse order) - -ITF._pattern = { -- true -> narrow, false -> Wide - [0] = {true, true, false, false, true}, - [1] = {false, true, true, true, false}, - [2] = {true, false, true, true, false}, - [3] = {false, false, true, true, true}, - [4] = {true, true, false, true, false}, - [5] = {false, true, false, true, true}, - [6] = {true, false, false, true, true}, - [7] = {true, true, true, false, false}, - [8] = {false, true, true, false, true}, - [9] = {true, false, true, false, true}, -} - --- define parameters -ITF._par_def = {} -local pardef = ITF._par_def - --- module main parameter -pardef.module = { - -- Narrow element X-dimension is the width of the smallest element. - -- The module width (width of narrow element) should be at least 7.5 mils - -- that is exactly 0.1905mm (1 mil is 1/1000 inch). - default = 7.5 * 0.0254 * 186467, -- 7.5 mils (sp) unit misure, - unit = "sp", -- scaled point - isReserved = true, - order = 1, -- the one first to be modified - fncheck = function (self, mod, _) --> boolean, err - if mod >= self.default then return true, nil end - return false, "[OutOfRange] too small lenght for X-dim" - end, -} - -pardef.ratio = { - -- The "wide" element is a multiple of the "narrow" element that can - -- range between 2.0 and 3.0. Preferred value is 3.0. - -- The multiple for the wide element should be between 2.0 and 3.0 if the - -- narrow element is greater than 20 mils. If the narrow element is less - -- than 20 mils (0.508mm), the ratio must exceed 2.2. - default = 3.0, - unit = "absolute-number", - isReserved = true, - order = 2, - fncheck = function (_, ratio, tpardef) --> boolean, err - local mils = 0.0254 * 186467 - local mod = tpardef.module - local minr; if mod < 20*mils then minr = 2.2 else minr = 2.0 end - if ratio < minr then - return false, "[OutOfRange] too small ratio (the min is "..minr..")" - end - if ratio > 3.0 then - return false, "[OutOfRange] too big ratio (the max is 3.0)" - end - return true, nil - end, -} - -pardef.height = { - -- The height should be at least 0.15 times the barcode's length or 0.25 inch. - default = 15 * 186467, -- 15mm -- TODO: better assessment for symbol length - unit = "sp", -- scaled point - isReserved = false, - order = 3, - fncheck = function (_self, h, _opt) --> boolean, err - local mils = 0.0254 * 186467 - if h >= 250*mils then - return true, nil - end - return false, "[OutOfRange] height too small" - end, -} - -pardef.quietzone = { - -- Quiet zones must be at least 10 times the module width or 0.25 inches, - -- whichever is larger - default = 250 * 0.0254 * 186467, -- 0.25 inch (250 mils) - unit = "sp", -- scaled point - isReserved = false, - order = 4, - fncheck = function (self, qz, _opt) --> boolean, err - local mils = 0.0254 * 186467 - local mod = self.module - local min = math.max(10*mod, 250*mils) - if qz >= min then - return true, nil - else - return false, "[OutOfRange] quietzone too small" - end - end, -} - -pardef.check_digit_policy = { -- enumeration - default = "none", - isReserved = false, - policy_enum = { - add = true, -- add a check digit to the symbol - verify = true, -- check the last digit of the symbol as check digit - none = true, -- do nothing - }, - order = 5, - fncheck = function (self, e, _) --> boolean, err - if type(e) ~= "string" then return false, "[TypeError] not a string" end - local keys = self.policy_enum - if keys[e] == true then - return true, nil - else - return false, "[Err] enum value not found" - end - end, -} - -pardef.check_digit_method = { -- enumeration - -- determine the algorithm for the check digit calculation - default = "mod_10", - isReserved = false, - order = 6, - method_enum = { - mod_10 = true, -- MOD 10 check digits method - }, - fncheck = function (self, e, _) --> boolean, err - if type(e) ~= "string" then return false, "[TypeError] not a string" end - local keys = self.method_enum - if keys[e] == true then - return true, nil - else - return false, "[Err] enum value not found" - end - end, -} - -pardef.bearer_bars_enabled = { -- boolean type - -- enable/disable Bearer bars around the barcode symbol - default = false, - isReserved = false, - order = 7, - fncheck = function (_, flag, _) --> boolean, err - if type(flag) == "boolean" then - return true, nil - else - return false, "[TypeErr] not a boolean value" - end - end, -} - -pardef.bearer_bars_thickness = { -- dimension - default = 37.5 * 0.0254 * 186467, -- 5 modules - unit = "sp", -- scaled point - isReserved = false, - order = 8, - fncheck = function (_self, thick, tpardef) --> boolean, err - local module = tpardef.module - if thick >= 2*module then - return true, nil - end - return false, "[OutOfRange] thickness too small" - end, -} - -pardef.bearer_bars_layout = { -- enumeration - -- determine the algorithm for the check digit calculation - default = "hbar", - isReserved = false, - order = 9, - method_enum = { - frame = true, -- a rectangle around the symbol - hbar = true, -- top and bottom horizontal bars - }, - fncheck = function (self, e, _) --> boolean, err - if type(e) ~= "string" then return false, "[TypeError] not a string" end - local keys = self.method_enum - if keys[e] == true then - return true, nil - else - return false, "[Err] enum value not found" - end - end, -} - --- auxiliary functions - --- separate a non negative integer in its digits {d_n-1, ..., d_1, d_0} -local function n_to_arr(n) --> len, digits - local digits = {} - local slen - if n == 0 then - digits[#digits + 1] = 0 - slen = 1 - else - slen = 0 - while n > 0 do - local d = n % 10 - digits[#digits + 1] = d - n = (n - d) / 10 - slen = slen + 1 - end - end - for k = 1, slen/2 do -- array reversing - local h = slen - k + 1 - local d = digits[k] - digits[k] = digits[h] - digits[h] = d - end - return slen, digits -end - -local function rshift(t) - local tlen = #t - for i = tlen, 1, -1 do - t[i + 1] = t[i] - end - t[1] = 0 -end - - -local function check_mod10(t, last) - local sum = 0 - local w = true - for i = last, 1, -1 do - if w then - sum = sum + 3*t[i] - else - sum = sum + t[i] - end - w = not w - end - local m = sum % 10 - if m == 0 then return 0 else return 10 - m end -end - -local function checkdigit(t, last, method) - if method == "mod_10" then - return check_mod10(t, last) - else - assert(false, "[InternalErr] unknow method") - end -end - - --- configuration function -function ITF:config() --> ok, err - -- init Vbar objects - local narrow = self.module - local wide = narrow * self.ratio - -- start symbol - local Vbar = self._libgeo.Vbar -- Vbar class - self._vbar_start = Vbar:from_int_revpair(self._start, narrow, wide) - self._vbar_stop = Vbar:from_int_revpair(self._stop, narrow, wide) - - -- build every possible pair of digits from 00 to 99 - self._vbar_data = {} - local vbar = self._vbar_data - local pattern = self._pattern - for dec = 0, 9 do - for unit = 0, 9 do - local t1 = pattern[dec] - local t2 = pattern[unit] - local n = dec*10 + unit - vbar[n] = Vbar:from_two_tab(t1, t2, narrow, wide) - end - end - return true, nil -end - --- public functions - -function ITF:get_checkdigit(n, method) - if type(n) ~= "number" then return nil, "[ArgErr] 'n' is not a number" end - if n < 0 then return nil, "[ArgErr] found a negative number" end - if n - math.floor(n) ~= 0 then return nil, "[ArgErr] found a float number" end - method = method or self.check_digit_method - local last, t = n_to_arr(n) - return checkdigit(t, last, method) -end - --- internal methods for constructors - -function ITF:_finalize() --> ok, err - -- check digit action - local policy = self.check_digit_policy - local slen = self._code_len - local is_even = (slen % 2 == 0) - local digits = self._code_data - if policy == "none" then - if not is_even then - rshift(digits) -- add a heading zero for padding - slen = slen + 1 - end - elseif policy == "add" then - if is_even then - rshift(digits) -- add a heading zero for padding - slen = slen + 1 - end - local c = checkdigit(digits, slen, self.check_digit_method) - digits[#digits + 1] = c - elseif policy == "verify" then - if not is_even then - rshift(digits) - slen = slen + 1 - end - local c = checkdigit(digits, slen - 1, self.check_digit_method) - if c ~= digits[slen] then - return false, "[DataErr] wrong check digit" - end - else - return false, "[InternalError] wrong enum value" - end - self._code_len = slen - return true, nil -end - --- drawing function --- tx, ty is an optional translator vector -function ITF:append_ga(canvas, tx, ty) --> canvas - local err = canvas:start_bbox_group(); assert(not err, err) - -- draw the start symbol - local xdim = self.module - local ratio = self.ratio - local symb_len = 2 * xdim * (3 + 2*ratio) - local x0 = tx or 0 - local xpos = x0 - local y0 = ty or 0 - local y1 = y0 + self.height - local start = self._vbar_start - local err - err = canvas:encode_Vbar(start, xpos, y0, y1); assert(not err, err) - xpos = xpos + 4 * xdim - -- draw the code symbol - local digits = self._code_data - local vbars = self._vbar_data - for i = 1, #digits, 2 do - local index = 10 * digits[i] + digits[i+1] - local b = vbars[index] - err = canvas:encode_Vbar(b, xpos, y0, y1); assert(not err, err) - xpos = xpos + symb_len - end - -- draw the stop symbol - local stop = self._vbar_stop - err = canvas:encode_Vbar(stop, xpos, y0, y1); assert(not err, err) - -- bounding box setting - local x1 = xpos + (2 + ratio)*xdim - local qz = self.quietzone - local b1x, b1y = x0 - qz, y0 - local b2x, b2y = x1 + qz, y1 - if self.bearer_bars_enabled then - local w = self.bearer_bars_thickness - err = canvas:encode_linethick(w); assert(not err, err) - b1y, b2y = b1y - w, b2y + w - local layout = self.bearer_bars_layout - if layout == "hbar" then - err = canvas:encode_hline(b1x, b2x, y0 - w/2); assert(not err, err) - err = canvas:encode_hline(b1x, b2x, y1 + w/2); assert(not err, err) - elseif layout == "frame" then - err = canvas:encode_rectangle(b1x - w/2, y0 - w/2, b2x + w/2, y1 + w/2) - assert(not err, err) - b1x, b2x = b1x - w, b2x + w - else - error("[IntenalErr] bearer bars layout option is wrong") - end - end - local err = canvas:stop_bbox_group(b1x, b1y, b2x, b2y) - assert(not err, err) - return canvas -end - -return ITF diff --git a/macros/luatex/generic/barracuda/lib/lib-driver/driver.lua b/macros/luatex/generic/barracuda/lib/lib-driver/driver.lua deleted file mode 100644 index 956c1f1e9d..0000000000 --- a/macros/luatex/generic/barracuda/lib/lib-driver/driver.lua +++ /dev/null @@ -1,400 +0,0 @@ --- --- ga Intermediate Graphic Language for barcode drawing --- Copyright (C) 2019 Roberto Giacomelli --- --- Basic driver interface --- drawing elementary vector shape --- All dimensions are in scaled point (sp) - -local Driver = { - _VERSION = "Driver v0.0.1", - _NAME = "Driver", - _DESCRIPTION = "Driver for ga graphic assembler stream", -} - -Driver.__index = Driver -Driver._drv_instance = {} -- driver instances repository - --- driver_type/submodule name -Driver._drv_available_drv = { -- lowercase keys please - native = "lib-driver.drv-pdfliteral", -- only LuaTeX driver - svg = "lib-driver.drv-svg", - -- tikz = "lib-driver.drv-tikz", -} - -function Driver:_get_driver(id_drv) --> object, err - if type(id_drv) ~= "string" then - return nil, "[ArgErr] 'id_drv' is not a string" - end - if not self._drv_available_drv[id_drv] then - return nil, "[ArgErr] driver '"..id_drv.."' not found" - end - local t_drv = self._drv_instance - if t_drv[id_drv] then -- is the repo already loaded? - return t_drv[id_drv], nil - else -- loading driver - local module = self._drv_available_drv[id_drv] - local channel = require(module) - t_drv[id_drv] = channel - return channel, nil - end -end - -function Driver:_new_state() --> a new state - return { - line_width = 65781.76, -- line width 1bp (in scaled point sp) - line_cap = 0, -- line cap style - line_join = 0, -- line join style - gtext = false, -- text group off - bb_on = true, -- bounding box checking activation - bb_x1 = nil, -- bounding box coordinates in sp (nil means no data) - bb_y1 = nil, - bb_x2 = nil, - bb_y2 = nil, - mm = 186467.98110236, -- conversion factor sp -> mm (millimeter) - bp = 65781.76, -- conversion factor sp -> bp (big point) - } -end - -function Driver:_ga_process(drv, ga, st, bf, xt) - local op_fn = self._opcode_v001 - local pc = 1 -- program counter - local data = ga._data - while data[pc] do -- stream processing - local opcode = data[pc] - local fn = assert(op_fn[opcode], "[InternalErr] unimpl opcode ".. opcode) - pc = fn(drv, st, pc + 1, data, bf, xt) - end -end - --- save graphic data in an external file with the 'id_drv' format --- id_drv: specific driver output --- ga: ga object --- filename: file name --- ext: file extension (optional) -function Driver:save(id_drv, ga, filename, ext) --> ok, err - -- retrive the output library - local drv, err = self:_get_driver(id_drv) - if err then return false, err end - -- init - local state = self:_new_state() - local buf, txt_buf = drv.init_buffer(state) -- a new buffer and text_buffer - -- processing - self:_ga_process(drv, ga, state, buf, txt_buf) - -- buffer finalizing - drv.close_buffer(state, buf, txt_buf) -- finalize the istruction - -- file saving - local sep = drv.buf_sep - ext = ext or drv.ext - local fn = io.open(filename.."."..ext, "w") -- output the file - fn:write(table.concat(buf, sep)) -- concat the buffer - fn:close() - return true, nil -end - --- insert a ga drawing in a TeX box --- PDFnative only function -function Driver:ga_to_hbox(ga, boxname) --> ok, err - -- retrive the output library - local id_drv = "native" - local drv, err = self:_get_driver(id_drv) - if err then return false, err end - -- init process - local state = self:_new_state() - local buf, txt_buf = drv.init_buffer(state) -- a new buffer and text_buffer - -- processing - self:_ga_process(drv, ga, state, buf, txt_buf) - -- finalizing - drv.close_buffer(state, buf, txt_buf) -- finalize the istruction sequence - -- build hbox - local ok, err = drv.hboxcreate(boxname, state, buf, txt_buf) - return ok, err -end - - --- operational functions --- _op_v001 corresponds to the version 1 of ga graphic assembler specification. --- The table indexes every opcode to a function that takes these arguments and --- return the updated program counter pointed to the next operation: --- fn: format specific driver library --- st: state --- pc: program counter --- ga: read only ga stream --- bf: the output buffer --- xt: the output text object buffer -Driver._opcode_v001 = { - [1] = function (drv, st, pc, ga, bf, xt) -- 1 ; set line width - local w = ga[pc] - st.line_width = w - if not drv.append_001 then - error("[InternalErr] unimplemented opcode 1 for "..drv._NAME) - end - drv.append_001(st, bf, xt, w) - return pc + 1 - end, - [2] = function (drv, st, pc, ga, bf, xt) -- 2 ; set line cap style - local style = ga[pc] - st.line_cap = style - if not drv.append_002 then - error("[InternalErr] unimplemented opcode 2 for "..drv._NAME) - end - drv.append_002(st, bf, xt, style) - return pc + 1 - end, - [3] = function (drv, st, pc, ga, bf, xt) -- 3 ; set line join style - local join = ga[pc] - if not drv.append_003 then - error("[InternalErr] unimplemented opcode 3 for "..drv._NAME) - end - drv.append_003(st, bf, xt, join) - return pc + 1 - end, - [30] = function (drv, st, pc, ga, bf, xt) -- start_bbox_group - assert(st.bb_on) - st.bb_on = false - return pc - end, - [31] = function (drv, st, pc, ga, bf, xt) -- end_bbox_group - assert(st.bb_on == false) - st.bb_on = true - local x1 = ga[pc]; pc = pc + 1 - local y1 = ga[pc]; pc = pc + 1 - local x2 = ga[pc]; pc = pc + 1 - local y2 = ga[pc]; pc = pc + 1 - if st.bb_x1 == nil then - st.bb_x1 = x1 - st.bb_y1 = y1 - st.bb_x2 = x2 - st.bb_y2 = y2 - else - if x1 < st.bb_x1 then st.bb_x1 = x1 end - if x2 > st.bb_x2 then st.bb_x2 = x2 end - if y1 < st.bb_y1 then st.bb_y1 = y1 end - if y2 > st.bb_y2 then st.bb_y2 = y2 end - end - return pc - end, - -- draw an horizontal line - -- 33 - [33] = function (drv, st, pc, ga, bf, xt) - local x1 = ga[pc]; pc = pc + 1 - local x2 = ga[pc]; pc = pc + 1 - local y = ga[pc]; pc = pc + 1 - if st.bb_on then -- eventually update bbox - local hw = st.line_width/2 - local by1 = y - hw - local by2 = y + hw - if st.bb_x1 == nil then - st.bb_x1 = x1 - st.bb_x2 = x2 - st.bb_y1 = by1 - st.bb_y2 = by2 - else - if x1 < st.bb_x1 then st.bb_x1 = x1 end - if x2 > st.bb_x2 then st.bb_x2 = x2 end - if by1 < st.bb_y1 then st.bb_y1 = by1 end - if by2 > st.bb_y2 then st.bb_y2 = by2 end - end - end - if not drv.append_033 then - error("[InternalErr] unimplemented opcode 33 for "..drv._NAME) - end - drv.append_033(st, bf, xt, x1, x2, y) - return pc - end, - -- draw a vertical line - [34] = function (drv, st, pc, ga, bf, xt) -- 34 - local y1 = ga[pc]; pc = pc + 1 - local y2 = ga[pc]; pc = pc + 1 - local x = ga[pc]; pc = pc + 1 - if st.bb_on then -- eventually update the figure bounding box - local hw = st.line_width/2 - local bx1 = x - hw - local bx2 = x + hw - if st.bb_x1 == nil then - st.bb_x1 = bx1 - st.bb_x2 = bx2 - st.bb_y1 = y1 - st.bb_y2 = y2 - else - if bx1 < st.bb_x1 then st.bb_x1 = bx1 end - if bx2 > st.bb_x2 then st.bb_x2 = bx2 end - if y1 < st.bb_y1 then st.bb_y1 = y1 end - if y2 > st.bb_y2 then st.bb_y2 = y2 end - end - end - if not drv.append_034 then - error("[InternalErr] unimplemented opcode 34 for "..drv._NAME) - end - drv.append_034(st, bf, xt, y1, y2, x) - return pc - end, - -- draw a group of vertical lines (vbar) - -- 36 - [36] = function(drv, st, pc, ga, bf, xt) -- vbar - local y1 = ga[pc]; pc = pc + 1 - local y2 = ga[pc]; pc = pc + 1 - local nbar = ga[pc]; pc = pc + 1 - assert(nbar > 0) - local h = y2 - y1 -- height common to every rectangle - assert(h > 0) - local pc_next = pc + 2 * nbar - if drv.append_036_start then - drv.append_036_start(st, bf, xt, nbar, y1, y2) - end - local bx1, bx2 - for i = pc, pc_next - 1, 2 do -- reading coordinates - local x = assert(ga[i], "[InternalErr] ga prematurely reached the end") - local w = assert(ga[i+1], "[InternalErr] ga prematurely reached the end") - drv.append_036_bar(st, bf, xt, x, w, y1, y2) - -- check the bounding box only if the corresponding flag is true - local x1 = x - w/2 - local x2 = x + w/2 - if st.bb_on then - if bx1 == nil then - bx1 = x1 - bx2 = x2 - else - if x1 < bx1 then bx1 = x1 end - if x2 > bx2 then bx2 = x2 end - end - end - end - if drv.append_036_stop then - drv.append_036_stop(st, bf, xt, nbar, y1, y2) - end - if st.bb_on then -- eventually update bbox - if st.bb_x1 == nil then - st.bb_x1 = bx1 - st.bb_x2 = bx2 - st.bb_y1 = y1 - st.bb_y2 = y2 - else - if bx1 < st.bb_x1 then st.bb_x1 = bx1 end - if bx2 > st.bb_x2 then st.bb_x2 = bx2 end - if y1 < st.bb_y1 then st.bb_y1 = y1 end - if y2 > st.bb_y2 then st.bb_y2 = y2 end - end - end - return pc_next - end, - -- draw a rectangle - -- 48 - [48] = function(drv, st, pc, ga, bf, xt) - local x1 = ga[pc]; pc = pc + 1 - local y1 = ga[pc]; pc = pc + 1 - local x2 = ga[pc]; pc = pc + 1 - local y2 = ga[pc]; pc = pc + 1 - -- check the bounding box only if the flag is true - if st.bb_on then - local hw = st.line_width/2 - local bx1, bx2 = x1 - hw, x2 + hw - local by1, by2 = y1 - hw, y2 + hw - if st.bb_x1 == nil then - st.bb_x1 = bx1 - st.bb_x2 = bx2 - st.bb_y1 = by1 - st.bb_y2 = by2 - else - if bx1 < st.bb_x1 then st.bb_x1 = bx1 end - if bx2 > st.bb_x2 then st.bb_x2 = bx2 end - if by1 < st.bb_y1 then st.bb_y1 = by1 end - if by2 > st.bb_y2 then st.bb_y2 = by2 end - end - end - if not drv.append_048 then - error("[InternalErr] unimplemented opcode 48 for "..drv._NAME) - end - drv.append_048(st, bf, xt, x1, y1, x2, y2) - return pc - end, - -- text - [130] = function(drv, st, pc, ga, bf, xt) -- text: ax ay xpos ypos string - local ax = ga[pc]; pc = pc + 1 - local ay = ga[pc]; pc = pc + 1 - local xpos = ga[pc]; pc = pc + 1 - local ypos = ga[pc]; pc = pc + 1 - assert(ga[pc] ~= 0, "[InternalErr] empty chars sequence") - while ga[pc] ~= 0 do - local c = ga[pc]; pc = pc + 1 - drv.append_130_char(st, bf, xt, c) - end - local x1, y1, x2, y2 = drv.append_130_stop(st, bf, xt, xpos, ypos, ax, ay) - -- bounding box checking - if st.bb_on then - if st.bb_x1 == nil then - st.bb_x1 = x1 - st.bb_x2 = x2 - st.bb_y1 = y1 - st.bb_y2 = y2 - else - if x1 < st.bb_x1 then st.bb_x1 = x1 end - if x2 > st.bb_x2 then st.bb_x2 = x2 end - if y1 < st.bb_y1 then st.bb_y1 = y1 end - if y2 > st.bb_y2 then st.bb_y2 = y2 end - end - end - return pc + 1 - end, - [131] = function(drv, st, pc, ga, bf, xt) -- text_xspaced x1 xgap ay ypos chars - local x1 = ga[pc]; pc = pc + 1 - local xgap = ga[pc]; pc = pc + 1 - local ay = ga[pc]; pc = pc + 1 - local ypos = ga[pc]; pc = pc + 1 - assert(ga[pc] ~= 0, "[InternalErr] empty chars sequence") - while ga[pc] ~= 0 do - local c = ga[pc]; pc = pc + 1 - drv.append_131_char(st, bf, xt, c, xgap) - end - local bx1, by1, bx2, by2 = drv.append_131_stop(st, bf, xt, x1, xgap, ypos, ay) - -- bounding box checking - if st.bb_on then -- eventually update bbox - if st.bb_x1 == nil then - st.bb_x1 = bx1 - st.bb_x2 = bx2 - st.bb_y1 = by1 -- no depth - st.bb_y2 = by2 - else - if bx1 < st.bb_x1 then st.bb_x1 = bx1 end - if bx2 > st.bb_x2 then st.bb_x2 = bx2 end - if by1 < st.bb_y1 then st.bb_y1 = by1 end - if by2 > st.bb_y2 then st.bb_y2 = by2 end - end - end - return pc + 1 - end, - -- text_xwidth - -- - [132] = function (drv, st, pc, ga, bf, xt) - local ay = ga[pc]; pc = pc + 1 -- y anchor - local x1 = ga[pc]; pc = pc + 1 -- left limit - local x2 = ga[pc]; pc = pc + 1 -- right limit - assert (x1 ~= x2, "[InternalErr] x coordinate are equal") - assert (x1 < x2, "[InternalErr] not ordered x1, x2 limits") - local ypos = ga[pc]; pc = pc + 1 -- y coordinate of anchor point - assert(ga[pc] ~= 0, "[InternalErr] empty chars sequence") - while ga[pc] ~= 0 do - local c = ga[pc]; pc = pc + 1 - drv.append_132_char(st, bf, xt, c) - end - local bx1, by1, bx2, by2 = drv.append_132_stop(st, bf, xt, x1, x2, ypos, ay) - -- bounding box checking - if st.bb_on then -- eventually update bbox - if st.bb_x1 == nil then - st.bb_x1 = bx1 - st.bb_x2 = bx2 - st.bb_y1 = by1 -- no depth - st.bb_y2 = by2 - else - if bx1 < st.bb_x1 then st.bb_x1 = bx1 end - if bx2 > st.bb_x2 then st.bb_x2 = bx2 end - if by1 < st.bb_y1 then st.bb_y1 = by1 end - if by2 > st.bb_y2 then st.bb_y2 = by2 end - end - end - return pc + 1 - end, -} - -return Driver - diff --git a/macros/luatex/generic/barracuda/lib/lib-driver/drv-pdfliteral.lua b/macros/luatex/generic/barracuda/lib/lib-driver/drv-pdfliteral.lua deleted file mode 100644 index 50baea1472..0000000000 --- a/macros/luatex/generic/barracuda/lib/lib-driver/drv-pdfliteral.lua +++ /dev/null @@ -1,284 +0,0 @@ --- --- ga graphic assembler or --- Intermediate Graphic Language for barcode drawing --- Copyright (C) 2019 Roberto Giacomelli --- --- All dimensions are in scaled point (sp) --- ga LuaTeX Driver (native implementation node+pdfliteral) - --- class for drawing elementary geometric elements -local PDFnative = { - _VERSION = "PDFnative v0.0.4", - _NAME = "PDFnative", - _DESCRIPTION = "A LuaTeX native pdfliteral driver for ga graphic stream", -} - -PDFnative.ext = "txt" -- file extension -PDFnative.buf_sep = "\n" -- separation string for buffer concat - -function PDFnative.init_buffer(st) --> buffer, text buffer - st.head = nil -- addition for text processing (to remember purpose) - st.last = nil - st.hbox = nil - st.cw = nil - st.x_hbox = nil - st.char_counter = nil - local bf = {"q"} -- create a new graphic stack - local xt = {} -- text buffer - return bf, xt -end - -function PDFnative.close_buffer(st, bf, xt) - bf[#bf + 1] = "Q" -- stack restoring -end - --- text utility special functions - -local function newglue(w) --> node - local n = node.new("glue") - n.width = w - return n -end - -local function newglyph(c) --> node -- ? U+2423 ␣ for whitespace? - if c == 32 then - return newglue(tex.sp "3.5pt") - end - local n = node.new("glyph") - n.char = c - n.font = font.current() - return n -end - -local function newpdfliteral(buf) --> node - local npdf = node.new("whatsit", "pdf_literal") - npdf.mode = 0 - npdf.data = table.concat(buf, "\n") - return npdf -end - -local function append_glyph(head, last, c) --> head, last, xdim - if c == 32 then -- space - local space = tex.sp "3.5pt" - head, last = node.insert_after(head, last, newglue(space)) - return head, last, space - else - local g = newglyph(c) - local xdim = g.width - head, last = node.insert_after(head, last, g) - return head, last, xdim - end -end - --- special drawing function -function PDFnative.hboxcreate(hboxname, st, buf, txt) --> ok, err - local node = assert(node, "This is not LuaTeX!") - local tex = assert(tex) - local font = assert(font) - if not tex.isbox(hboxname) then - return nil, string.format("Box register [%s] doesn’t exist", hboxname) - end - local bb_x1, bb_y1, bb_x2, bb_y2 = st.bb_x1, st.bb_y1, st.bb_x2, st.bb_y2 - local npdf = newpdfliteral(buf) -- node whatsit pdfliteral - -- vboxing, vertical correction - local vpdf = node.vpack(npdf) - vpdf.height = -bb_y1 - -- glue, for horizontal correction - local ng = newglue(-bb_x1) - local head, last = node.insert_after(ng, ng, vpdf) - local xprev = 0.0 - for _, t in ipairs(txt) do -- text processing - local gy = newglue(t[3] - bb_y1) -- n, x, y, w, h -- t[3] -t[5] - bb_y1 - local nvtxt = node.insert_after(t[1], t[1], gy) - local vtxt = node.vpack(nvtxt) - local gx = newglue(t[2]-xprev) - head, last = node.insert_after(head, last, gx) - head, last = node.insert_after(head, last, vtxt) - xprev = t[2] + t[4] - end - -- hboxing - local hbox = node.hpack(head) - hbox.width = bb_x2 - bb_x1 - hbox.height = bb_y2 - bb_y1 - tex.box[hboxname] = hbox - return true, nil -end - --- PDF literal encoding functions - --- 1 ; set line width -function PDFnative.append_001(st, bf, xt, w) - local bp = st.bp -- 1bp (sp) - bf[#bf + 1] = string.format("%0.6f w", w/bp) -end - --- 2 ; set line cap style -function PDFnative.append_002(st, bf, xt, cap) - bf[#bf + 1] = string.format("%d J", cap) -end - --- 3 ; set line join style -function PDFnative.append_003(st, bf, xt, j) - bf[#bf + 1] = string.format("%d j", j) -end - --- draw an horizontal line --- 33 -function PDFnative.append_033(st, bf, xt, x1, x2, y) - local bp = st.bp -- conversion factor bp -> sp - bf[#bf + 1] = string.format("% 0.6f %0.6f m", x1/bp, y/bp) - bf[#bf + 1] = string.format("% 0.6f %0.6f l", x2/bp, y/bp) - bf[#bf + 1] = "S" -- stroke -end - --- vline --- draw a vertical line --- 34 -function PDFnative.append_034(st, bf, xt, y1, y2, x) - local bp = st.bp -- conversion factor bp -> sp - bf[#bf + 1] = string.format("% 0.6f %0.6f m", x/bp, y1/bp) - bf[#bf + 1] = string.format("% 0.6f %0.6f l", x/bp, y2/bp) - bf[#bf + 1] = "S" -- stroke -end - --- Vbar --- draw a group of vertical lines --- 36 ... -function PDFnative.append_036_bar(st, bf, xt, x, w, y1, y2) - local bp = st.bp -- conversion factor bp -> sp - local fmt = "%0.6f %0.6f %0.6f %0.6f re" - local x1 = x - w/2 - local h = y2 - y1 - -- pdf literal insertion - bf[#bf + 1] = string.format(fmt, x1/bp, y1/bp, w/bp, h/bp) -end -function PDFnative.append_036_stop(st, bf, xt, nbar, y1, y2) - bf[#bf + 1] = "f" -- fill - bf[#bf + 1] = "S" -- stroke -end - --- draw a rectangle --- 48 -function PDFnative.append_048(st, bf, xt, x1, y1, x2, y2) - local w = x2 - x1 -- rectangle width - assert(w > 0) - local h = y2 - y1 -- rectangle height - assert(h > 0) - local bp = st.bp -- conversion factor - local fmt = "%0.6f %0.6f %0.6f %0.6f re S" - -- pdf literal string - bf[#bf + 1] = string.format(fmt, x1/bp, y1/bp, w/bp, h/bp) -end - --- 130 Text with several glyphs --- 130 -function PDFnative.append_130_char(st, bf, xt, c) - local head, last = st.head, st.last - head, last = append_glyph(head, last, c) - st.head = head - st.last = last -end --- return bounding box of the text object without deep -function PDFnative.append_130_stop(st, bf, xt, xpos, ypos, ax, ay) - local head = assert(st.head) - st.head = nil -- reset temporary reference - st.last = nil - local hbox = node.hpack(head) - local w, h, d = node.dimensions(hbox) - local x1 = xpos - ax*w -- text position - local y1; if ay > 0 then - y1 = ypos - h*ay - else - y1 = ypos - d*ay - end - xt[#xt + 1] = {hbox, x1, y1 - d, w, h} - return x1, y1, x1 + w, y1 + h -end - --- 131 , Text with glyphs equally spaced on its vertical axis --- 131 -function PDFnative.append_131_char(st, bf, xt, c, xgap) - local head, last, prec_cw = st.head, st.last, st.cw - local cw - if prec_cw then - local g = newglyph(c) - cw = g.width - local isp = xgap - (cw + prec_cw)/2 - local s = newglue(isp) - head, last = node.insert_after(head, last, s) - head, last = node.insert_after(head, last, g) - else -- first char - head, last, cw = append_glyph(head, last, c) - st.x_hbox = cw/2 - end - st.cw = cw - st.head = head - st.last = last -end -function PDFnative.append_131_stop(st, bf, xt, x1, xgap, ypos, ay) --> bb - local head = assert(st.head) - st.head = nil -- reset temporary reference - st.last = nil - st.cw = nil - local hbox = node.hpack(head) - local w, h, d = node.dimensions(hbox) - local bx1 = x1 - st.x_hbox - st.x_hbox = nil -- reset temporary references - local y1; if ay > 0 then - y1 = ypos - h*ay - else - y1 = ypos - d*ay - end - xt[#xt + 1] = {hbox, bx1, y1 - d, w, h} - return bx1, y1, bx1 + w, y1 + h -end - --- 132 Glyphs equally spaced on vertical axis between two x coordinates --- 132 -function PDFnative.append_132_char(st, bf, xt, c) - local head, last = st.head, st.last - if head then - local g = newglyph(c) - local s = newglue(1) - head, last = node.insert_after(head, last, s) - head, last = node.insert_after(head, last, g) - st.char_counter = st.char_counter + 1 - else -- first char - head, last, cw = append_glyph(head, last, c) - st.cw = cw - st.char_counter = 1 - end - st.head = head - st.last = last -end -function PDFnative.append_132_stop(st, bf, xt, x1, x2, ypos, ay) --> p1, p2 - local head, last = st.head, st.last - st.head = nil -- reset temporary registry - st.last = nil - local w_1 = st.cw - st.cw = nil - local i = st.char_counter - st.char_counter = nil - local w_n = last.width - local xgap = (x2 - x1 - (w_1 + w_n)/2)/(i - 1) - local c_curr = head - for _ = 1, i - 1 do - local g = c_curr.next - local c_next = g.next - local w_2 - w_1, w_2 = c_curr.width, c_next.width - g.width = xgap - (w_1 + w_2)/2 - c_curr = c_next - end - local hbox = node.hpack(head) - local w, h, d = node.dimensions(hbox) - local y; if ay > 0 then - y = ypos - h*ay - else - y = ypos - d*ay - end - xt[#xt + 1] = {hbox, x1, y - d, w, h} - return x1, y, x2, y + h -end - -return PDFnative diff --git a/macros/luatex/generic/barracuda/lib/lib-driver/drv-svg.lua b/macros/luatex/generic/barracuda/lib/lib-driver/drv-svg.lua deleted file mode 100644 index 7a2c5ab112..0000000000 --- a/macros/luatex/generic/barracuda/lib/lib-driver/drv-svg.lua +++ /dev/null @@ -1,260 +0,0 @@ --- --- ga Intermediate Graphic Language for barcode drawing --- SVG library --- Copyright (C) 2019 Roberto Giacomelli --- --- All dimension in the ga stream are scaled point (sp) --- 1 pt = 65536 sp - --- class for drawing elementary geometric elements -local SVG = { - _VERSION = "SVGdriver v0.0.1", - _NAME = "SVGdriver", - _DESCRIPTION = "A SVG driver for the ga graphic stream", -} - -SVG.ext = "svg" -- file extension -SVG.buf_sep = nil -- separation string for buffer concat - -function SVG.init_buffer(st) --> buffer, text buffer - local bf = { - '\n', - '\n', - '\n', - '\n', - } - -- additions for SVG driver to 'state' - st.ident_lvl = 1 -- identation level - st.char_buf = nil - local mm = st.mm - st.h_char = 2.1 * mm -- char height (mm) - st.w_char = st.h_char / 1.303 -- avg char width (mm) - st.d_char = st.h_char / 3.7 -- char deep (mm) - return bf, {} -end - -function SVG.close_buffer(st, bf, xt) - bf[#bf + 1] = '\n' -- close svg xml element - bf[#bf + 1] = '\n' -- a last empty line - local mm = st.mm - local x1, y1, x2, y2 = st.bb_x1, st.bb_y1, st.bb_x2, st.bb_y2 - local w = (x2 - x1)/mm - local h = (y2 - y1)/mm - local fmt_wh = bf[7] - bf[7] = string.format(fmt_wh, w, h) -- line 7 - local x, y = x1/mm, -y2/mm - local fmt_vw = bf[8] - bf[8] = string.format(fmt_vw, x, y, w, h) -end - --- SVG encoding functions - --- 1 ; set line width -function SVG.append_001(st, bf, xt, w) - -- nothing to do -end - --- draw an horizontal line --- 33 -function SVG.append_033(st, bf, xt, x1, x2, y) - local lvl = st.ident_lvl - local ident = string.rep(" ", lvl) -- a couple of spaces as indentation - local mm = st.mm -- conversion ratio sp -> bp - bf[#bf + 1] = string.format( -- element - '%s\n' -end - --- Vertical line: 34 -function SVG.append_034(st, bf, xt, y1, y2, x) - local lvl = st.ident_lvl - local ident = string.rep(" ", lvl) -- a couple of spaces as indentation - local mm = st.mm -- conversion ratio sp -> mm - bf[#bf + 1] = string.format( -- element - '%s\n' -end - --- Vbar --- draw a group of vertical lines --- 36 ... -function SVG.append_036_start(st, bf, xt, nbar, y1, y2) - local lvl = st.ident_lvl - local ident = string.rep(" ", lvl) - bf[#bf + 1] = ident..'\n' -- open a group - st.ident_lvl = lvl + 1 -end -function SVG.append_036_bar(st, bf, xt, x, w, y1, y2) - local lvl = st.ident_lvl - local ident = string.rep(" ", lvl) - local mm = st.mm -- conversion factor mm -> sp - bf[#bf + 1] = string.format( - '%s\n', - ident, x/mm, -y2/mm, -y1/mm, w/mm - ) -end -function SVG.append_036_stop(st, bf, xt, nbar, y1, y2) - st.ident_lvl = st.ident_lvl - 1 - local ident = string.rep(" ", st.ident_lvl) - bf[#bf + 1] = ident..'\n' -- end group -end - --- Text --- 130 Text with several glyphs --- 130 -function SVG.append_130_char(st, bf, xt, c) - local ch = string.char(c) - if not st.char_buf then - st.char_buf = {ch} - else - local chars = st.char_buf - chars[#chars + 1] = ch - end -end -function SVG.append_130_stop(st, bf, xt, xpos, ypos, ax, ay) --> p1, p2 - local c = st.char_buf - st.char_buf = nil - local txt = table.concat(c) - local w = st.w_char * #c -- approx dim - local h = st.h_char - local d = st.d_char - local anchor = "" - local x1 = xpos - local bx1 = xpos - if ax == 0 then -- start (default) - elseif ax == 0.5 then -- middle - anchor = ' text-anchor="middle"' - bx1 = bx1 - w/2 - elseif ax == 1 then -- end - anchor = ' text-anchor="end"' - bx1 = bx1 - w - else - x1 = x1 - ax*w - bx1 = x1 - end - local y1 = ypos - if ay > 0 then - y1 = y1 - h*ay - else - y1 = y1 - d*ay - end - local fs = st.h_char * 1.37 -- sp - local lvl = st.ident_lvl - local ident = string.rep(" ", lvl) - local mm = st.mm - bf[#bf + 1] = string.format( - '%s\n', - ident, x1/mm, -y1/mm, fs/mm, anchor - ) - bf[#bf + 1] = ident..txt - bf[#bf + 1] = ident..'\n' - return bx1, y1, bx1 + w, y1 + h -end - --- 131 , Text with glyphs equally spaced on its vertical axis --- 131 -function SVG.append_131_char(st, bf, xt, c, xgap) - local ch = string.char(c) - if not st.char_buf then - st.char_buf = {ch} - else - local chars = st.char_buf - chars[#chars + 1] = ch - end -end -function SVG.append_131_stop(st, bf, xt, x1, xgap, ypos, ay) --> p1, p2 - local chars = st.char_buf - st.char_buf = nil - local n = #chars - local h = st.h_char -- height - local d = st.d_char -- deep - local hw = st.w_char/2 -- sp half width - local y1 = ypos - if ay > 0 then - y1 = y1 - h*ay - else - y1 = y1 - d*ay - end - local lvl = st.ident_lvl - local ident = string.rep(" ", lvl) - local fs = st.h_char * 1.37 -- (sp) font-size -> inter baselines distance - local mm = st.mm - bf[#bf + 1] = string.format( - '%s\n', - ident, -y1/mm, fs/mm - ) - local x = x1 - for _, c in ipairs(chars) do - bf[#bf + 1] = string.format('%s%s\n', - ident, x/mm, c - ) - x = x + xgap - end - bf[#bf + 1] = ident..'\n' - local x2 = x1 + (n - 1)*xgap -- sp - return x1 - hw, y1, x2 + hw, y1 + h -- text group bounding box -end - --- 132 Glyphs equally spaced on vertical axis between two x coordinates --- 132 -function SVG.append_132_char(st, bf, xt, c, xgap) - local ch = string.char(c) - if not st.char_buf then - st.char_buf = {ch} - else - local chars = st.char_buf - chars[#chars + 1] = ch - end -end -function SVG.append_132_stop(st, bf, xt, x1, x2, ypos, ay) --> p1, p2 - local chars = st.char_buf; st.char_buf = nil - local n = #chars - local h = st.h_char -- height (approx) - local d = st.d_char -- deep (approx) - local cw = st.w_char -- (sp) char width (approx) - local xgap = (x2 - x1 - cw)/(n - 1) - local y1 = ypos - if ay > 0 then - y1 = y1 - h*ay - else - y1 = y1 - d*ay - end - local lvl = st.ident_lvl - local ident = string.rep(" ", lvl) - local fs = st.h_char * 1.37 -- font-size -> inter baselines distance - local mm = st.mm - bf[#bf + 1] = string.format( - '%s\n', - ident, -y1/mm, fs/mm - ) - local x = x1 + cw/2 - for _, c in ipairs(chars) do - bf[#bf + 1] = string.format('%s%s\n', - ident, x/mm, c - ) - x = x + xgap - end - bf[#bf + 1] = ident..'\n' - return x1, y1, x2, y1 + h -- text group bounding box -end - -return SVG diff --git a/macros/luatex/generic/barracuda/lib/lib-geo/gacanvas.lua b/macros/luatex/generic/barracuda/lib/lib-geo/gacanvas.lua deleted file mode 100644 index cccc68f447..0000000000 --- a/macros/luatex/generic/barracuda/lib/lib-geo/gacanvas.lua +++ /dev/null @@ -1,340 +0,0 @@ --- class gaCanvas --- Copyright (C) 2019 Roberto Giacomelli - --- ga -- basic function - -local gaCanvas = { - _VERSION = "gacanvas v0.0.4", - _NAME = "gaCanvas", - _DESCRIPTION = "A library for dealing with ga stream", -} -gaCanvas.__index = gaCanvas - --- ga specification: see the file ga-grammar.pdf in the doc directory - --- gaCanvas constructor -function gaCanvas:new() --> object - local o = { - _data = {}, - _v = 100, -- version of the ga format - } - setmetatable(o, self) - return o -end - --- Ipothetical another constructor --- function gaCanvas:from_tcp_server() --> err --- end - --- line width: opcode <1> -function gaCanvas:encode_linethick(w) --> err - if type(w) ~= "number" then return "[ArgErr] 'w' number expected" end - if w < 0 then return "[ArgErr] negative value for 'w'" end - local data = self._data - data[#data + 1] = 1 -- opcode for line thickness - data[#data + 1] = w -end - --- line cap style: opcode <2> --- 0 Butt cap --- 1 Round cap --- 2 Projecting square cap -function gaCanvas:encode_linecap(cap) --> err - if type(cap) ~= "number" then return "[ArgErr] 'cap' arg number expected" end - if cap == 0 or cap == 1 or cap == 2 then - local data = self._data - data[#data + 1] = 2 -- opcode for line cap style - data[#data + 1] = cap - else - return "[ArgErr] invalid value for 'cap'" - end -end - --- line cap style: opcode <3> --- 0 Miter join --- 1 Round join --- 2 Bevel join -function gaCanvas:encode_linejoin(join) --> err - if type(join) ~= "number" then return "[ArgErr] 'join' arg number expected" end - if join == 0 or join == 1 or join == 2 then - local data = self._data - data[#data + 1] = 3 -- opcode for line join style - data[#data + 1] = join - else - return "[ArgErr] invalid value for 'join'" - end -end - --- Stop checking the bounding box --- opcode: <30> -function gaCanvas:start_bbox_group() --> err - local data = self._data - data[#data + 1] = 30 -end - --- restart checking the bounding box --- and insert the specified bb for the entire object group --- code: <31> x1 y1 x2 y2 -function gaCanvas:stop_bbox_group(x1, y1, x2, y2) --> err - if type(x1) ~= "number" then return "[ArgErr] 'x1' number expected" end - if type(y1) ~= "number" then return "[ArgErr] 'y1' number expected" end - if type(x2) ~= "number" then return "[ArgErr] 'x2' number expected" end - if type(y2) ~= "number" then return "[ArgErr] 'y2' number expected" end - if x1 > x2 then x1, x2 = x2, x1 end -- reorder coordinates - if y1 > y2 then y1, y2 = y2, y1 end - local data = self._data - data[#data + 1] = 31 -- bounding box of the object group - data[#data + 1] = x1 - data[#data + 1] = y1 - data[#data + 1] = x2 - data[#data + 1] = y2 -end - --- insert a line from point (x1, y1) to the point (x2, y2) --- <32> x1 y1 x2 y2 -function gaCanvas:encode_line(x1, y1, x2, y2) --> err - if type(x1) ~= "number" then return "[ArgErr] 'x1' number expected" end - if type(y1) ~= "number" then return "[ArgErr] 'y1' number expected" end - if type(x2) ~= "number" then return "[ArgErr] 'x2' number expected" end - if type(y2) ~= "number" then return "[ArgErr] 'y2' number expected" end - local data = self._data - data[#data + 1] = 32 -- append line data - data[#data + 1] = x1 - data[#data + 1] = y1 - data[#data + 1] = x2 - data[#data + 1] = y2 -end - --- insert an horizontal line from point (x1, y) to point (x2, y) --- <33> x1 x2 y -function gaCanvas:encode_hline(x1, x2, y) --> err - if type(x1) ~= "number" then return "[ArgErr] 'x1' number expected" end - if type(x2) ~= "number" then return "[ArgErr] 'x2' number expected" end - if type(y) ~= "number" then return "[ArgErr] 'y2' number expected" end - local data = self._data - data[#data + 1] = 33 -- append hline data - data[#data + 1] = x1 - data[#data + 1] = x2 - data[#data + 1] = y -end - --- insert a rectangle from point (x1, x2) to (x2, y2) --- <48> -function gaCanvas:encode_rectangle(x1, y1, x2, y2) --> err - if type(x1) ~= "number" then return "[ArgErr] 'x1' number expected" end - if type(y1) ~= "number" then return "[ArgErr] 'y1' number expected" end - if type(x2) ~= "number" then return "[ArgErr] 'x2' number expected" end - if type(y2) ~= "number" then return "[ArgErr] 'y2' number expected" end - local d = self._data - d[#d + 1] = 48 -- append rectangle data - d[#d + 1] = x1 - d[#d + 1] = y1 - d[#d + 1] = x2 - d[#d + 1] = y2 -end - --- Vbar object: opcode <36> --- x0, y1, y2 ordinates -function gaCanvas:encode_Vbar(vbar, x0, y1, y2) --> err - if type(vbar) ~= "table" then - return "[ArgErr] table expected for 'vbar'" - end - if x0 == nil then - x0 = 0 - elseif type(x0) ~= "number" then - return "[ArgErr] 'x0' number expected" - end - if type(y1) ~= "number" then return "[ArgErr] 'y1' number expected" end - if type(y2) ~= "number" then return "[ArgErr] 'y2' number expected" end - -- ordinates - if y1 == y2 then return "[ArgErr] 'y1' 'y2' are the same value" end - if y1 > y2 then y1, y2 = y2, y1 end - local bars = assert(vbar._yline, "[InternalErr] no '_yline' field") - local bdim = #bars - if bdim == 0 then return "[InternalErr] number of bars is zero" end - if bdim % 2 ~= 0 then - return "[InternalErr] '_yline' does not have an even number of elements" - end - local data = self._data - data[#data + 1] = 36 -- vbar sequence start - data[#data + 1] = y1 - data[#data + 1] = y2 - data[#data + 1] = bdim / 2 -- the number of bars - for i = 1, bdim, 2 do - local coord = bars[i] - local width = bars[i + 1] - if type(coord) ~= "number" then - return "[Err] a coordinates is not a number" - end - if type(width) ~= "number" then - return "[Err] a width is not a number" - end - data[#data + 1] = coord + x0 - data[#data + 1] = width - end -end - --- [text] <130> ax ay x y chars -function gaCanvas:encode_Text(txt, xpos, ypos, ax, ay) --> err - if type(txt) ~= "table" then - return "[ArgErr] 'txt' object table expected" - end - if type(xpos) ~= "number" then - return "[ArgErr] 'xpos' number expected" - end - if type(ypos) ~= "number" then - return "[ArgErr] 'ypos' number expected" - end - if ax == nil then - ax = 0 - elseif type(ax) ~= "number" then - return "[ArgErr] 'ax' number expected" - end - if ay == nil then - ay = 0 - elseif type(ay) ~= "number" then - return "[ArgErr] 'ay' number expected" - end - local data = self._data - data[#data + 1] = 130 - data[#data + 1] = ax -- relative anchor x-coordinate - data[#data + 1] = ay -- relative anchor y-coordinate - data[#data + 1] = xpos -- text x-coordinate - data[#data + 1] = ypos -- text y-coordinate - local chars = assert(txt.codepoint, "[InternalErr] no 'codepoint' field in txt") - if #chars == 0 then return "[InternalErr] 'txt' has no chars" end - for _, c in ipairs(chars) do - data[#data + 1] = c - end - data[#data + 1] = 0 -- end string signal -end - --- glyphs equally spaced along the baseline --- [text_xspaced] <131> x1 xgap ay ypos chars -function gaCanvas:encode_Text_xspaced(txt, x1, xgap, ypos, ay) --> err - if type(txt)~= "table" then return "[ArgErr] 'txt' object table expected" end - local chars = assert(txt.codepoint, "[InternalErr] no 'codepoint' field in txt") - if #chars == 0 then return "[InternalErr] 'txt' has no chars" end - if type(x1) ~= "number" then return "[ArgErr] 'x1' number expected" end - if type(xgap) ~= "number" then return "[ArgErr] 'xgap' number expected" end - if xgap < 0 then - local n = #chars - x1 = x1 + (n - 1) * xgap - xgap = -xgap - end - if type(ypos) ~= "number" then return "[ArgErr] 'ypos' number expected" end - if ay == nil then - ay = 0 - elseif type(ay) ~= "number" then - return "[ArgErr] 'ay' number expected" - end - local data = self._data - data[#data + 1] = 131 - data[#data + 1] = x1 -- x-coordinate of the first axis from left to right - data[#data + 1] = xgap -- axial distance among gliphs - data[#data + 1] = ay -- anchor relative y-coordinate - data[#data + 1] = ypos -- text y-coordinate - for _, c in ipairs(chars) do - data[#data + 1] = c - end - data[#data + 1] = 0 -- end string signal -end - --- text_xwidth --- text equally spaced but within [x1, x2] coordinate interval --- <132> -function gaCanvas:encode_Text_xwidth(txt, x1, x2, ypos, ay) --> err - if type(txt)~= "table" then return "[ArgErr] 'txt' object table expected" end - if type(x1) ~= "number" then return "[ArgErr] 'x1' number expected" end - if type(x2) ~= "number" then return "[ArgErr] 'x2' number expected" end - if type(ypos) ~= "number" then return "[ArgErr] 'ypos' number expected" end - if ay == nil then - ay = 0 - elseif type(ay) ~= "number" then - return "[ArgErr] 'ay' number expected" - end - local chars = assert(txt.codepoint, "[InternalErr] no 'codepoint' field in txt") - if #chars == 0 then return "[InternalErr] 'txt' has no chars" end - if x1 > x2 then x1, x2 = x2, x1 end -- reorder coordinates - local data = self._data - data[#data + 1] = 132 - data[#data + 1] = ay -- anchor relative y-coordinate - data[#data + 1] = x1 -- left limit of the text box - data[#data + 1] = x2 -- right limit of the text box - data[#data + 1] = ypos -- text y-coordinate - for _, c in ipairs(chars) do - data[#data + 1] = c - end - data[#data + 1] = 0 -- end string signal -end - --- experimental code section --- new opcodes under assessment - --- [start_text_group] 140 -function gaCanvas:start_text_group() --> err - local data = self._data - data[#data + 1] = 140 -end - --- [gtext] 141 -function gaCanvas:gtext(chars) --> err - if type(chars) ~= "table" then return "[ArgErr] 'chars' table expected" end - local data = self._data - data[#data + 1] = 141 - for _, c in ipairs(chars) do - data[#data + 1] = c - end - data[#data + 1] = 0 -- end string signal -end - --- [gtext_spaced] 142 gap string -function gaCanvas:gtext_spaced(gap, chars) --> err - if type(gap) ~= "number" then return "[ArgErr] 'gap' number expected" end - if type(chars) ~= "table" then return "[ArgErr] 'chars' table expected" end - local data = self._data - data[#data + 1] = 142 - data[#data + 1] = gap - for _, c in ipairs(chars) do - data[#data + 1] = c - end - data[#data + 1] = 0 -- end string signal -end - --- [gtext_space] 143 gap -function gaCanvas:gtext_gap(gap) --> err - if type(gap) ~= "number" then return "[ArgErr] 'gap' number expected" end - local data = self._data - data[#data + 1] = 143 - data[#data + 1] = gap -end - - --- [end_text_group] 149 ax ay x y -function gaCanvas:end_text_group(xpos, ypos, ax, ay) --> err - if type(xpos) ~= "number" then return "[ArgErr] 'xpos' number expected" end - if type(ypos) ~= "number" then return "[ArgErr] 'ypos' number expected" end - if type(ax) ~= "number" then return "[ArgErr] 'ax' number expected" end - if type(ay) ~= "number" then return "[ArgErr] 'ay' number expected" end - local data = self._data - data[#data + 1] = 149 - data[#data + 1] = ax -- anchor relative x-coordinate - data[#data + 1] = ay -- anchor relative y-coordinate - data[#data + 1] = xpos -- text x-coordinate - data[#data + 1] = ypos -- text y-coordinate -end - --- amazing... -function gaCanvas:to_string() --> string - -end - -function gaCanvas:get_bbox() - -end - -function gaCanvas:check() --> boolean, err - -end - -return gaCanvas diff --git a/macros/luatex/generic/barracuda/lib/lib-geo/libgeo.lua b/macros/luatex/generic/barracuda/lib/lib-geo/libgeo.lua deleted file mode 100644 index fd53ca6509..0000000000 --- a/macros/luatex/generic/barracuda/lib/lib-geo/libgeo.lua +++ /dev/null @@ -1,289 +0,0 @@ - --- libgeo simple Geometric Library --- Copyright (C) 2018 Roberto Giacomelli - --- All dimension must be in scaled point (sp) - -local libgeo = { - _VERSION = "libgeo v0.0.3", - _NAME = "libgeo", - _DESCRIPTION = "simple geometric library", -} - --- VBar class --- a pure geometric entity of several infinite vertical lines -libgeo.Vbar = {} -local Vbar = libgeo.Vbar -Vbar.__index = Vbar - --- Vbar costructors - --- VBar costructor from an array [xcenter1, width1, xcenter2, width2, ...] -function Vbar:from_array(yl_arr) --> - assert(type(yl_arr) == "table", "'yline_array' is a mandatory arg") - -- stream scanning - local i = 1 - local xlim = 0.0 - while yl_arr[i] do - local x = yl_arr[i]; i = i + 1 - local w = yl_arr[i]; i = i + 1 - assert(type(x) == "number", "[InternalErr] not a number") - assert(type(w) == "number", "[InternalErr] not a number") - xlim = x + w/2 - end - assert(i % 2 == 0, "[InternalErr] the index is not even") - assert(i > 0, "[InternalErr] empty array") - local o = { - _yline = yl_arr, -- [, , ...] flat array - _x_lim = xlim, -- right external bounding box coordinates - } - setmetatable(o, self) - return o -end - --- costructor useful for Code128 encoder --- from an integer: 21231 -> binary 11 0 11 000 1 -> symbol 110110001 --- is_bar :: boolean :: bar or space as first element, default true -function Vbar:from_int(ngen, mod, is_bar) --> - assert(type(ngen) == "number", "Invalid argument for n") - assert(type(mod) == "number", "Invalid argument for module width") - if is_bar == nil then is_bar = true else - assert(type(is_bar) == "boolean", "Invalid argument for is_bar") - end - -- scan ngen for digits - local digits = {} - while ngen > 0 do - local d = ngen % 10 - digits[#digits + 1] = d - ngen = (ngen - d)/10 - end - local x0 = 0.0 -- axis reference - local yl = {} - for k = #digits, 1, -1 do - local d = digits[k] - local w = d*mod -- bar width - if is_bar then -- bar - yl[#yl + 1] = x0 + w/2 - yl[#yl + 1] = w - end - x0 = x0 + w - is_bar = not is_bar - end - local o = { - _yline = yl, -- [, , ...] flat array - _x_lim = x0, -- right external coordinate - } - setmetatable(o, self) - return o -end - --- from an integer to read from right to left --- 13212 ->rev 21231 ->binary 11 0 11 000 1 -> symbol 110110001 --- is_bar :: boolean :: bar or space for first, default true -function Vbar:from_int_revstep(ngen, mod, is_bar) --> - assert(type(ngen) == "number", "Invalid argument for n") - assert(type(mod) == "number", "Invalid argument for module width") - if is_bar == nil then is_bar = true else - assert(type(is_bar) == "boolean", "Invalid argument for is_bar") - end - -- - local x0 = 0.0 -- axis reference - local i = 0 - local yl = {} - while ngen > 0 do - local d = ngen % 10 -- first digit - local w = d*mod -- bar width - if is_bar then -- bar - i = i + 1; yl[i] = x0 + w/2 - i = i + 1; yl[i] = w - end - x0 = x0 + w - is_bar = not is_bar - ngen = (ngen - d)/10 - end - assert(not is_bar, "[InternalErr] the last element in not a bar") - local o = { - _yline = yl, -- [, , ...] flat array - _x_lim = x0, -- right external coordinate - } - setmetatable(o, self) - return o -end - --- costructor useful for Code39 encoder --- i.e. 11212 -> rev -> 2 1 2 1 1 -> decodes to -> B w B w b --- build a yline array from the integer definition. Digit decoding rule: --- mod: b or w => 1 -- narrow bar/space --- MOD: B or W => 2 -- wide bar/space --- is_bar: the first element is a bar not a space, default to true -function Vbar:from_int_revpair(ngen, mod, MOD, is_bar) --> - assert(type(ngen) == "number", "Invalid argument for n") - assert(type(mod) == "number", "Invalid argument for narrow module width") - assert(type(MOD) == "number", "Invalid argument for wide module width") - assert(mod < MOD, "Not ordered narrow/Wide values") - if is_bar == nil then - is_bar = true - else - assert(type(is_bar) == "boolean", "Invalid argument for 'is_bar'") - end - local yl = {} - local x0 = 0.0 - local k = 0 - while ngen > 0 do - local d = ngen % 10 -- digit - ngen = (ngen - d)/10 - local w; if d == 1 then - w = mod - elseif d == 2 then - w = MOD - end; assert(w, "[InternalErr] Allowed digits are only 1 or 2") - if is_bar then -- bars - k = k + 1; yl[k] = x0 + w/2 -- xcenter - k = k + 1; yl[k] = w -- width - end - is_bar = not is_bar - x0 = x0 + w - end - assert(not is_bar, "[InternalErr] the last element is not a bar") - local o = { - _yline = yl, -- [, , ...] flat array - _x_lim = x0, -- external x coordinate - } - setmetatable(o, self) - return o -end - --- return a Vbar inteleaving to sequence narrow/Wide --- tbar, tspace = {boolean sequence}, true -> narrow, false -> Wide -function Vbar:from_two_tab(tbar, tspace, mod, MOD) --> - assert(type(tbar) == "table", "tbar must be a table") - assert(type(tspace) == "table", "tspace must be a table") - assert(#tbar == #tspace, "tbar and tspace must be longer the same") - assert(type(mod) == "number", "Invalid argument for narrow module width") - assert(type(MOD) == "number", "Invalid argument for wide module width") - assert(mod < MOD, "Not ordered narrow/Wide values") - local x0 = 0.0 -- x-coordinate - local yl = {} - for i = 1, #tbar do - local is_narrow = tbar[i] - assert(type(is_narrow) == "boolean", "[InternalErr] found a not boolean value") - if is_narrow then - yl[#yl + 1] = x0 + mod/2 -- bar x-coordinate - yl[#yl + 1] = mod -- bar width - x0 = x0 + mod - else - yl[#yl + 1] = x0 + MOD/2 -- bar x-coordinate - yl[#yl + 1] = MOD -- bar width - x0 = x0 + MOD - end - local is_narrow_space = tspace[i] - assert(type(is_narrow_space) == "boolean", "[InternalErr] found a not boolean value") - if is_narrow_space then - x0 = x0 + mod - else - x0 = x0 + MOD - end - end - local o = { - _yline = yl, -- [, , ...] flat array - _x_lim = x0, -- external x coordinate - } - setmetatable(o, self) - return o -end - --- Text class - -libgeo.Text = {} -local Text = libgeo.Text -Text.__index = Text - --- costructors --- internally it keeps text as a sequence of codepoint -function Text:from_string(s) --> object - assert(type(s) == "string", "[ArgErr] 's' not a valid string") - assert(#s > 0, "[Err] 's' empty string not allowed") - - local cp = {} -- codepoint array - for b in string.gmatch(s, ".") do - cp[#cp + 1] = string.byte(b) - end - local o = { - codepoint = cp, - } - setmetatable(o, self) - return o -end - --- arr, array of single digit number --- i start index --- j stop index -function Text:from_digit_array(arr, i, j) --> object - assert(type(arr) == "table", "[ArgErr] 'arr' not a table") - assert(#arr > 0, "[ArgErr] 'arr' is an empty array") - local cp = {} -- codepoint array - if i ~= nil then - assert(type(i) == "number", "[ArgErr] 'i' is not a number") - else - i = 1 - end - if j ~= nil then - assert(type(j) == "number", "[ArgErr] 'j' is not a number") - assert(i <= j, "[ArgErr] not suitable pair of array index") - else - j = #arr - end - for k = i, j do - local d = arr[k] - assert(type(d) == "number", "[ArgErr] array contains a not number element") - assert(d == math.floor(d), "[ArgErr] array contains a not integer number") - assert(d >= 0 or d < 10, "[ArgErr] array contains a not single digit number") - cp[#cp + 1] = d + 48 - end - local o = { - codepoint = cp, - } - setmetatable(o, self) - return o -end - - --- from an array of chars -function Text:from_chars(chars) --> object - assert(type(chars) == "table", "[ArgErr] 'chars' must be a table") - local arr = {} - for _, c in ipairs(chars) do - arr[#arr + 1] = string.byte(c) - end - local o = { - codepoint = arr, - } - setmetatable(o, self) - return o -end - --- provide an integer to build a Text object -function Text:from_int(n) --> object - assert(type(n) == "number", "[ArgErr] 'n' must be a number") - assert( n > 0, "[Err] 'n' must be positive") - assert( n == math.floor(n), "[Err] 'n' must be an integer") - local cp = {} - while n > 0 do - local d = n % 10 - cp[#cp + 1] = d + 48 - n = (n - d)/10 - end - local digits = #cp - for i = 1, digits/2 do -- reverse the array - local d = cp[digits - i + 1] - cp[digits - i + 1] = cp[i] - cp[i] = d - end - local o = { - codepoint = cp, - } - setmetatable(o, self) - return o -end - -return libgeo diff --git a/macros/luatex/generic/barracuda/src/barracuda.lua b/macros/luatex/generic/barracuda/src/barracuda.lua new file mode 100644 index 0000000000..4d587ef952 --- /dev/null +++ b/macros/luatex/generic/barracuda/src/barracuda.lua @@ -0,0 +1,116 @@ +-- Welcome to the 'barracuda' barcode library +-- +-- Encode a message into a barcode symbol, in Lua or within a LuaTeX source file +-- +-- Copyright (C) 2019 Roberto Giacomelli +-- +-- 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 +-- the Free Software Foundation; either version 2 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +-- Basic Conventions: +-- fields that start with an undercore are private +-- class name follows the snake case naming convention +-- the 'barracuda' table is the only global object to access every package +-- modules. + +local Barracuda = { + _VERSION = "barracuda v0.0.9.1", + _NAME = "barracuda", + _DESCRIPTION = "Lua library for barcode printing", + _URL = "https://github.com/robitex/barracuda", + _LICENSE = "GNU GENERAL PUBLIC LICENSE, Version 2, June 1991", +} + +-- essential sub-module loading +Barracuda._libgeo = require "lib-geo.brcd-libgeo" -- basic vectorial objects +Barracuda._gacanvas = require "lib-geo.brcd-gacanvas" -- ga stream library +Barracuda._barcode = require "lib-barcode.brcd-barcode" -- barcode abstract class + +local Barcode = Barracuda._barcode +Barcode._libgeo = Barracuda._libgeo + +-- encoder builder +function Barracuda:get_barcode_class() --> Barcode class object + return self._barcode +end + +-- where we place output driver library +function Barracuda:get_driver() --> Driver object, err + if not self._lib_driver then + self._lib_driver = require "lib-driver.brcd-driver" + end + return self._lib_driver +end + +function Barracuda:new_canvas() --> driver + local gacanvas = self._gacanvas + return gacanvas:new() +end + +-- high level barcode functions +-- only default options +-- panic on error + +-- save barcode as a graphic external file +function Barracuda:save(bc_type, data, filename, id_drv) + local barcode = self:get_barcode_class() + local enc, err = barcode:new_encoder(bc_type) + assert(enc, err) + local arg_data = type(data) + local symb + if arg_data == "number" then + local err_data + symb, err_data = enc:from_uint(data) + asser(symb, err_data) + elseif arg_data == "string" then + local err_data + symb, err_data = enc:from_string(data) + assert(symb, err_data) + else + error("[argErr] unsupported 'data' type") + end + local canvas = self:new_canvas() + symb:append_ga(canvas) + local driver = self:get_driver() + id_drv = id_drv or "svg" + local ok, out_err = driver:save(id_drv, canvas, filename) + assert(ok, out_err) +end + +-- this is a only LuaTeX method +function Barracuda:hbox(bc_type, data, box_name) + local barcode = self:get_barcode_class() + local enc, err = barcode:new_encoder(bc_type) + assert(enc, err) + local arg_data = type(data) + local symb + if arg_data == "number" then + local err_data + symb, err_data = enc:from_uint(data) + asser(symb, err_data) + elseif arg_data == "string" then + local err_data + symb, err_data = enc:from_string(data) + assert(symb, err_data) + else + error("[argErr] unsupported 'data' type") + end + local canvas = self:new_canvas() + symb:append_ga(canvas) + local driver = self:get_driver() + local ok, err_hbox = driver:ga_to_hbox(canvas, box_name) + assert(ok, err_hbox) +end + +return Barracuda diff --git a/macros/luatex/generic/barracuda/src/lib-barcode/brcd-barcode.lua b/macros/luatex/generic/barracuda/src/lib-barcode/brcd-barcode.lua new file mode 100644 index 0000000000..415719a2f4 --- /dev/null +++ b/macros/luatex/generic/barracuda/src/lib-barcode/brcd-barcode.lua @@ -0,0 +1,544 @@ + +-- Barcode abstract class +-- Copyright (C) 2019 Roberto Giacomelli +-- Please see LICENSE.TXT for any legal information about present software + +local Barcode = { + _VERSION = "Barcode v0.0.9", + _NAME = "Barcode", + _DESCRIPTION = "Barcode abstract class", +} +Barcode.__index = Barcode + +-- barcode_type/submodule name +Barcode._available_enc = {-- keys must be lowercase + code39 = "lib-barcode.brcd-code39", -- Code 39 + code128 = "lib-barcode.brcd-code128", -- Code128 + ean = "lib-barcode.brcd-ean", -- EAN family (ISBN, EAN8, etc) + i2of5 = "lib-barcode.brcd-i2of5", -- Interleaved 2 of 5 +} +Barcode._builder_instances = {} -- encoder builder instances repository + +-- common parameters to all the barcode objects +Barcode._super_par_def = {} +local pardef = Barcode._super_par_def + +-- set an Anchor point (ax, ay) relatively to the barcode bounding box +-- without considering any text object +-- ax = 0, ay = 0 is the lower left corner of the symbol +-- ax = 1, ay = 1 is the upper right corner of the symbol +Barcode.ax = 0.0 +pardef.ax = { + default = 0.0, + unit = "sp", -- scaled point + isReserved = false, + order = 1, + fncheck = function (self, ax, _) --> boolean, err + if ax >= 0.0 and ax <= 1.0 then return true, nil end + return false, "[OutOfRange] 'ax' out of [0, 1] interval" + end, +} +Barcode.ay = 0.0 +pardef.ay = { + default = 0.0, + unit = "sp", -- scaled point + isReserved = false, + order = 2, + fncheck = function (self, ay, _) --> boolean, err + if ay >= 0.0 and ay <= 1.0 then return true, nil end + return false, "[OutOfRange] 'ay' out of [0, 1] interval" + end, +} + +-- Barcode.bbox_to_quietzone -- under assessment + +-- Barcode methods + +-- stateless iterator troughtout the ordered parameters collection +local function p_iter(state, i) + i = i + 1 + local t = state[i] + if t then + return i, t + end +end + +-- main iterator on parameter definitions +function Barcode:param_ord_iter() + local state = {} + -- append family parameter + local p2_family = self._par_def -- base family parameters + local fam_len = 0 + if p2_family then + for pname, pdef in pairs(p2_family) do + state[pdef.order] = { + pname = pname, + pdef = pdef, + isSuper = false, + } + fam_len = fam_len + 1 + end + assert(fam_len == #state) + end + -- append the variant parameters + local var_len = 0 + local var = self._variant + if var then -- specific variant parameters + local p2_variant = assert(self._par_def_variant[var]) + for pname, pdef in pairs(p2_variant) do + if state[pname] then + error("[InternalErr] overriding paramenter '"..pname.."'") + end + state[pdef.order + fam_len] = { + pname = pname, + pdef = pdef, + isSuper = false, + } + var_len = var_len + 1 + end + assert(fam_len + var_len == #state) + end + -- append the super class parameter to the iterator state + local p1 = self._super_par_def + local super_len = 0 + for pname, pdef in pairs(p1) do + if state[pname] then + error("[InternalError] overriding paramenter name '"..pname.."'") + end + state[fam_len + var_len + pdef.order] = { + pname = pname, + pdef = pdef, + isSuper = true, + } + super_len = super_len + 1 + end + assert(super_len + fam_len + var_len == #state) + return p_iter, state, 0 +end + +-- encoder costructor +-- Symbology can be a family with many variants. This is represented by the +-- first argument 'bc_type' formatted as -. +-- in more details: +-- if there are variants +-- if not +-- i.e. when 'bc_type' is the string "ean-13", "ean" is the barcode family and +-- "13" is its variant name. +-- For whose barcodes that do not have variants, 'bc_type' is simply the endoder id +-- such as "code128". +-- 'id_enc' is an optional identifier useful to retrive an encoder reference later +-- 'opt' is an optional table with the user-defined parameters setting up encoders +-- +function Barcode:new_encoder(bc_type, id_enc, opt) --> object, err + -- argument checking + if type(bc_type) ~= "string" then + return nil, "[ArgErr] 'bc_type' is not a string" + end + local pdash = string.find(bc_type, "-") + local family, variant + if pdash then + family = string.sub(bc_type, 1, pdash - 1) + variant = string.sub(bc_type, pdash + 1) + else + family = bc_type + end + local av_enc = self._available_enc + if not av_enc[family] then -- is the barcode type a real module? + return nil, "[Err] barcode type '"..family.."' not found" + end + if id_enc == nil then + id_enc = (variant or "") .. "_noname" + elseif type(id_enc) ~= "string" then + return nil, "[ArgErr] provided 'id_enc' is not a string" + end + if type(opt) == "table" or opt == nil then + opt = opt or {} + else + return nil, "[ArgErr] provided 'opt' is wrong" + end + local tenc = self._builder_instances + local builder; + if tenc[family] then -- is the encoder builder already loaded? + builder = tenc[family] + else -- loading the encoder builder + local mod_path = av_enc[family] + builder = require(mod_path) + tenc[family] = assert(builder, "[InternalErr] module not found!") + builder._enc_instances = {} + end + if builder._enc_instances[id_enc] then + return nil, "[Err] 'id_enc' already present" + end + local enc = {} -- the new encoder + enc.__index = enc + enc._variant = variant + setmetatable(enc, { + __index = function(_, k) + if builder[k] ~= nil then + return builder[k] + end + return self[k] + end + }) + builder._enc_instances[id_enc] = enc + -- param defition + for _, tpar in enc:param_ord_iter() do + local pname = tpar.pname + local pdef = tpar.pdef + local isSuper = tpar.isSuper + local val = opt[pname] -- param = val + if val ~= nil then + local ok, err = pdef:fncheck(val, enc) + if ok then + enc[pname] = val + else -- error! + return nil, err + end + else + -- load the default value of + local def_val; if pdef.fndefault then + def_val = pdef:fndefault(enc) + else + def_val = pdef.default + end + if not isSuper then + enc[pname] = def_val + end + end + end + if enc.config then -- this must be called after the parameter definition + enc:config(variant) + end + return enc, nil +end + +-- retrive encoder object already created +-- 'name' is optional in case you didn't assign one to the encoder +function Barcode:enc_by_name(bc_type, name) --> , + if type(bc_type) ~= "string" then + return nil, "[ArgErr] 'bc_type' must be a string" + end + local pdash = string.find(bc_type, "-") + local family, variant + if pdash then + family = string.sub(bc_type, 1, pdash - 1) + variant = string.sub(bc_type, pdash + 1) + else + family = bc_type + end + local av_enc = self._available_enc + if not av_enc[family] then -- is the barcode type a real module? + return nil, "[Err] barcode type '"..family.."' not found" + end + local builder = self._builder_instances[family] + if builder == nil then + return nil, "[Err] enc builder '"..family.."' not loaded, use 'new_encoder()' method" + end + if name == nil then + name = (variant or "") .. "_noname" + elseif type(name) ~= "string" then + return nil, "[ArgErr] 'name' must be a string" + end + local repo = builder._enc_instances + local enc = repo[name] + if enc == nil then + return nil, "[Err] encoder '"..name.."' not found" + else + return enc, nil + end +end + +-- base constructors common to all the encoders +-- for numeric only simbology +function Barcode:_check_char(c) --> elem, err + if type(c) ~= "string" or #c ~= 1 then + return nil, "[InternalErr] invalid char" + end + local n = string.byte(c) - 48 + if n < 0 or n > 9 then + return nil, "[ArgErr] found a not digit char" + end + return n, nil +end +function Barcode:_check_digit(n) --> elem, err + if type(n) ~= "number" then + return nil, "[InternalErr] not a number" + end + if n < 0 or n > 9 then + return nil, "[InternalErr] not a digit" + end + return n, nil +end + +-- not empty string --> Barcode object +function Barcode:from_string(symb, opt) --> object, err + assert(self._check_char, "[InternalErr] undefined _check_char() method") + if type(symb) ~= "string" then + return nil, "[ArgErr] 'symb' is not a string" + end + if #symb == 0 then + return nil, "[ArgErr] 'symb' is an empty string" + end + local chars = {} + local len = 0 + for c in string.gmatch(symb, ".") do + local elem, err = self:_check_char(c) + if err then + return nil, err + else + chars[#chars+1] = elem + len = len + 1 + end + end + -- build the barcode object + local o = { + _code_data = chars, -- array of chars + _code_len = len, -- symbol lenght + } + setmetatable(o, self) + if opt ~= nil then + if type(opt) ~= "table" then + return nil, "[ArgErr] 'opt' is not a table" + else + local ok, err = o:set_param(opt) + if not ok then + return nil, err + end + end + end + if o._finalize then + local ok, e = o:_finalize() + if not ok then return nil, e end + end + return o, nil +end + +-- positive integer --> Barcode object +function Barcode:from_uint(n, opt) --> object, err + assert(self._check_digit, "[InternalErr] undefined _check_digit() method") + if type(n) ~= "number" then return nil, "[ArgErr] 'n' is not a number" end + if n < 0 then return nil, "[ArgErr] 'n' must be a positive integer" end + if n - math.floor(n) ~= 0 then + return nil, "[ArgErr] 'n' is not an integer" + end + if opt ~= nil and type(opt) ~= "table" then + return nil, "[ArgErr] 'opt' is not a table" + end + local digits = {} + local i = 0 + if n == 0 then + local elem, err = self:_check_digit(0) + if err then + return nil, err + end + digits[1] = elem + i = 1 + else + while n > 0 do + local d = n % 10 + i = i + 1 + local elem, err = self:_check_digit(d) + if err then + return nil, err + end + digits[i] = elem + n = (n - d) / 10 + end + for k = 1, i/2 do -- reverse the array + local d = digits[k] + local h = i - k + 1 + digits[k] = digits[h] + digits[h] = d + end + end + -- build the barcode object + local o = { + _code_data = digits, -- array of digits + _code_len = i, -- symbol lenght + } + setmetatable(o, self) + if opt ~= nil then + if type(opt) ~= "table" then + return nil, "[ArgErr] 'opt' is not a table" + else + local ok, err = o:set_param(opt) + if not ok then + return nil, err + end + end + end + if o._finalize then + local ok, e = o:_finalize() + if not ok then return nil, e end + end + return o, nil +end + +-- check a parameter set +-- this method check also reserved parameter +-- argments: {k=v, ...}, "default" | "current" +-- if ref is "default" parameters are checked with default values +-- if ref is "current" parameters are checked with current values +function Barcode:check_param(opt, ref) --> boolean, check report + if type(opt) ~= "table" then + return nil, "[ArgErr] opt is not a table" + end + if ref == nil then + ref = "current" + else + if type(ref) ~= "string" then + return nil, "[ArgErr] ref is not a string" + end + if (ref ~= "current") or (ref ~= "default") then + return nil, "[ArgErr] ref can only be 'default' or 'current'" + end + end + -- checking process + local cktab = {} + local isOk = true + local err_rpt -- nil if no error + for _, tpar in self:param_ord_iter() do + local pname = tpar.pname + local pdef = tpar.pdef + -- load the default value of + local def_val; if pdef.fndefault then + def_val = pdef:fndefault(cktab) + else + def_val = pdef.default + end + local val = opt[pname] + if val ~= nil then + local ok, err = pdef:fncheck(val, cktab) + if ok then + cktab[pname] = val + else -- error! + isOk = false + if err_rpt == nil then err_rpt = {} end + err_rpt[#err_rpt + 1] = { + param = pname, + checked_val = val, + default_val = def_val, + isOk = ok, + err = err, + } + end + end + local v + if ref == "current" then + v = self[pname] + else + v = def_val + end + cktab[pname] = v + end + return isOk, err_rpt +end + +-- restore to the default values all the parameter +-- (reserved parameters are unmodified so no need to restore it) +-- this need further investigation about the conseguence of a restore +-- that reset the parameter but "locally" +-- so this method must be considered experimental +function Barcode:restore_param() --> self :FIXME: + for _, par in ipairs(self._par_id) do + local pdef = self[par.."_def"] + if not pdef.isReserved then + self[par] = pdef.default + end + end + return self +end + +-- create a table with the information of the current barcode encoder +function Barcode:info() --> table + local info = { + name = self._NAME, + version = self._VERSION, + description = self._DESCRIPTION, + param = {}, + } + local tpar = info.param + for _, pardef in self:param_ord_iter() do + local id = pardef.pname + local pdef = pardef.pdef + tpar[#tpar + 1] = { + name = id, + descr = nil, -- TODO: + value = self[id], + isReserved = pdef.isReserved, + unit = pdef.unit, + } + end + return info +end + +-- make accessible by name parameter values +-- id: parameter identifier +function Barcode:get_param(id) --> value, err + if type(id) ~= "string" then + return nil, "[ArgErr] 'id' must be a string" + end + local pardef = self._par_def + if not pardef[id] then + return nil, "[Err] Parameter '"..id.."' doesn't exist" + end + local res = assert(self[id], "[InternalErr] parameter value unreachable") + return res, nil +end + +-- set a barcode parameter only if it is not reserved +-- arguments: +-- :set_param{key = value, key = value, ...} +-- :set_param(key, value) +function Barcode:set_param(arg1, arg2) --> boolean, err + -- processing arguments + local targ + local isPair = true + if type(arg1) == "table" then + if arg2 ~= nil then + return false, "[ArgErr] Further arguments not allowed" + end + targ = arg1 + isPair = false + elseif type(arg1) == "string" then -- key/value + if arg2 == nil then + return false, "[ArgErr] 'value' as the second argument expected" + end + targ = {} + targ[arg1] = arg2 + else + return false, "[ArgErr] param name must be a string" + end + -- preparing to the checking process + local cktab = {} + local ckparam = {} + -- checking process + for _, tpar in self:param_ord_iter() do + local pname = tpar.pname + local pdef = tpar.pdef + local val = targ[pname] -- par = val + if val ~= nil then + if pdef.isReserved then + return false, "[Err] parameter '" .. pname .. + "' is reserved, create another encoder" + end + local ok, err = pdef:fncheck(val, cktab) + if ok then + cktab[pname] = val + ckparam[pname] = val + else -- error! + return false, err + end + else -- no val in user option + cktab[pname] = self[pname] + end + end + for p, v in pairs(ckparam) do + self[p] = v + end + return true, nil +end + +return Barcode + +-- diff --git a/macros/luatex/generic/barracuda/src/lib-barcode/brcd-code128.lua b/macros/luatex/generic/barracuda/src/lib-barcode/brcd-code128.lua new file mode 100644 index 0000000000..317b3de8f8 --- /dev/null +++ b/macros/luatex/generic/barracuda/src/lib-barcode/brcd-code128.lua @@ -0,0 +1,341 @@ +-- Code128 barcode generator module +-- Copyright (C) 2019 Roberto Giacomelli +-- +-- All dimension must be in scaled point (sp) +-- every fields that starts with an undercore sign are intended as private + +local Code128 = { + _VERSION = "code128 v0.0.5", + _NAME = "Code128", + _DESCRIPTION = "Code128 barcode encoder", +} + +Code128._int_def_bar = {-- code bar definitions + [0] = 212222, 222122, 222221, 121223, 121322, 131222, 122213, 122312, + 132212, 221213, 221312, 231212, 112232, 122132, 122231, 113222, 123122, + 123221, 223211, 221132, 221231, 213212, 223112, 312131, 311222, 321122, + 321221, 312212, 322112, 322211, 212123, 212321, 232121, 111323, 131123, + 131321, 112313, 132113, 132311, 211313, 231113, 231311, 112133, 112331, + 132131, 113123, 113321, 133121, 313121, 211331, 231131, 213113, 213311, + 213131, 311123, 311321, 331121, 312113, 312311, 332111, 314111, 221411, + 431111, 111224, 111422, 121124, 121421, 141122, 141221, 112214, 112412, + 122114, 122411, 142112, 142211, 241211, 221114, 413111, 241112, 134111, + 111242, 121142, 121241, 114212, 124112, 124211, 411212, 421112, 421211, + 212141, 214121, 412121, 111143, 111341, 131141, 114113, 114311, 411113, + 411311, 113141, 114131, 311141, 411131, 211412, 211214, 211232, + 2331112, -- this is the stop char at index 106 +} + +Code128._codeset = { + A = 103, -- Start char for Codeset A + B = 104, -- Start char for Codeset B + C = 105, -- Start char for Codeset C + stopChar = 106, -- Stop char + shift = 98, -- A to B or B to A +} + +Code128._switch = { -- codes for switching from a codeset to another one + [103] = {[104] = 100, [105] = 99}, -- from A to B or C + [104] = {[103] = 101, [105] = 99}, -- from B to A or C + [105] = {[103] = 101, [104] = 100}, -- from C to A or B +} + +-- parameters definition +Code128._par_def = {} +local pardef = Code128._par_def + +-- module main parameter +pardef.xdim = { + default = 0.21 * 186467, -- X dimension + unit = "sp", -- scaled point + isReserved = true, + order = 1, -- the one first to be modified + fncheck = function (self, x, _) --> boolean, err + if x >= self.default then + return true, nil + else + return false, "[OutOfRange] too small value for xdim" + end + end, +} + +pardef.ydim = { + default = 10 * 186467, -- Y dimension + unit = "sp", + isReserved = false, + order = 2, + fncheck = function (self, y, tpar) --> boolean, err + local xdim = tpar.xdim + if y >= 10*xdim then + return true, nil + else + return false, "[OutOfRange] too small value for ydim" + end + end, +} + +pardef.quietzone_factor = { + default = 10, + unit = "absolute-number", + isReserved = false, + order = 3, + fncheck = function (self, z, _) --> boolean, err + if z >= 10 then + return true, nil + else + return false, "[OutOfRange] too small value for quietzone_factor" + end + end, +} + +-- create vbar objects +function Code128:config() --> ok, err + -- build Vbar object for the start/stop symbol + local mod = self.xdim + local sc = self._codeset.stopChar -- build the stop char + local n = self._int_def_bar[sc] + local Vbar = self._libgeo.Vbar -- Vbar class + self._vbar = {} + local b = self._vbar + b[sc] = Vbar:from_int(n, mod, true) + return true, nil +end + +-- utility functions + +-- the number of consecutive digits from the index 'i' in the code array +local function count_digits_from(arr, i) + local start = i + local dim = #arr + while i <= dim and (arr[i] > 47 and arr[i] < 58) do + i = i + 1 + end + return i - start +end + +-- evaluate the check digit of the data representation +local function check_digit(code) + local sum = code[1] -- this is the start character + for i = 2, #code do + sum = sum + code[i]*(i-1) + end + return sum % 103 +end + +-- return a pair of boolean the first one is true +-- if a control char and a lower case char occurs in the data +-- and the second one is true if the control char occurs before +-- the lower case char +local function ctrl_or_lowercase(pos, data) --> boolean, boolean|nil + local len = #data + local ctrl_occur, lower_occur = false, false + for i = pos, len do + local c = data[i] + if (not ctrl_occur) and (c >= 0 and c < 32) then + -- [0,31] control chars + if lower_occur then + return true, false -- lowercase char < ctrl char + else + ctrl_occur = true + end + elseif (not lower_occur) and (c > 95 and c < 128) then + -- [96, 127] lower case chars + if ctrl_occur then + return true, true -- ctrl char < lowercase char + else + lower_occur = true + end + end + end + return false -- no such data +end + +-- encode the provided char against a codeset +-- in the future this function will consider FN data +local function encode_char(t, codesetAorB, char_code, codesetA) + local code + if codesetAorB == codesetA then -- codesetA + if char_code < 32 then + code = char_code + 64 + elseif char_code > 31 and char_code < 96 then + code = char_code - 32 + else + error("Not implemented or wrong code") + end + else -- codesetB + if char_code > 31 and char_code < 128 then + code = char_code - 32 + else + error("Not implemented or wrong code") + end + end + t[#t + 1] = code +end + +-- encode the message in a sequence of Code128 symbol minimizing its lenght +local function encode128(arr, codeset, switch) --> data, err :TODO: + local res = {} -- the result array (the check character will be appended) + -- find the Start Character A, B, or C + local cur_codeset + local ndigit = count_digits_from(arr, 1) + local len = #arr + --local no_ctrl_lower_char + if (ndigit == 2 and len == 2) or ndigit > 3 then -- start char code C + cur_codeset = codeset.C + else + local ok, ctrl_first = ctrl_or_lowercase(1, arr) + if ok and ctrl_first then + cur_codeset = codeset.A + else + cur_codeset = codeset.B + end + end + res[#res + 1] = cur_codeset + local pos = 1 -- symbol's index to encode + while pos <= len do + if cur_codeset == codeset.C then + if arr[pos] < 48 or arr[pos] > 57 then -- not numeric char + local ok, ctrl_first = ctrl_or_lowercase(pos, arr) + if ok and ctrl_first then + cur_codeset = codeset.A + else + cur_codeset = codeset.B + end + res[#res + 1] = switch[codeset.C][cur_codeset] + else + local imax = pos + 2*math.floor(ndigit/2) - 1 + for idx = pos, imax, 2 do + res[#res + 1] = (arr[idx] - 48)*10 + arr[idx+1] - 48 + end + pos = pos + imax + ndigit = ndigit - imax + if ndigit == 1 then + -- cur_codeset setup + local ok, ctrl_first = ctrl_or_lowercase(pos + 1, arr) + if ok and ctrl_first then + cur_codeset = codeset.A + else + cur_codeset = codeset.B + end + res[#res + 1] = switch[codeset.C][cur_codeset] + end + end + else --- current codeset is A or B + if ndigit > 3 then + if ndigit % 2 > 1 then -- odd number of digits + encode_char(res, cur_codeset, arr[pos], codeset.A) + pos = pos + 1 + ndigit = ndigit - 1 + end + res[#res + 1] = switch[cur_codeset][codeset.C] + cur_codeset = codeset.C + elseif (cur_codeset == codeset.B) and + (arr[pos] >= 0 and arr[pos] < 32) then -- ops a control char + local ok, ctrl_first = ctrl_or_lowercase(pos + 1, arr) + if ok and (not ctrl_first) then -- shift to codeset A + res[#res + 1] = codeset.shift + encode_char(res, codeset.A, arr[pos], codeset.A) + pos = pos + 1 + ndigit = count_digits_from(pos, arr) + else -- switch to code set A + res[#res + 1] = switch[cur_codeset][codeset.A] + cur_codeset = codeset.A + end + elseif (cur_codeset == codeset.A) and + (arr[pos] > 95 and arr[pos] < 128) then -- ops a lower case char + local ok, ctrl_first = ctrl_or_lowercase(pos+1, arr) + if ok and ctrl_first then -- shift to codeset B + res[#res + 1] = codeset.shift + encode_char(res, codeset.B, arr[pos], codeset.A) + pos = pos + 1 + ndigit = count_digits_from(arr, pos) + else -- switch to code set B + res[#res + 1] = switch[cur_codeset][codeset.B] + cur_codeset = codeset.B + end + else + -- insert char + encode_char(res, cur_codeset, arr[pos], codeset.A) + pos = pos + 1 + ndigit = count_digits_from(arr, pos) + end + end + end + res[#res + 1] = check_digit(res) + res[#res + 1] = codeset.stopChar + return res +end + +-- Code 128 internal functions used by Barcode costructors + +function Code128:_check_char(c) --> elem, err + if type(c) ~= "string" or #c ~= 1 then + return nil, "[InternalErr] invalid char" + end + local b = string.byte(c) + if b > 127 then + local fmt = "[unimplemented] the '%d' is an ASCII extented char" + return nil, string.format(fmt, c) + end + return b, nil +end + +function Code128:_check_digit(n) --> elem, err + if type(n) ~= "number" then + return nil, "[InternalErr] invalid digit" + end + return n + 48, nil +end + +function Code128:_finalize() --> ok, err + local chr = assert(self._code_data, "[InternalErr] '_code_data' field is nil") + local data, err = encode128(chr, self._codeset, self._switch) + if err then return false, err end + -- load dynamically required Vbar objects + local vbar = self._vbar + local oVbar = self._libgeo.Vbar + for _, c in ipairs(data) do + if not vbar[c] then + local n = self._int_def_bar[c] + local mod = self.xdim + vbar[c] = oVbar:from_int(n, mod, true) + end + end + self._enc_data = data + return true, nil +end + +-- Drawing into the provided channel the geometrical barcode data +-- tx, ty is the optional translator vector +-- the function return the canvas reference to allow call chaining +function Code128:append_ga(canvas, tx, ty) --> canvas + local xdim, h = self.xdim, self.ydim + local sw = 11*xdim -- the width of a symbol + local data = self._enc_data + local w = #data * sw + 2 * xdim -- total symbol width + local ax, ay = self.ax, self.ay + local x0 = (tx or 0) - ax * w + local y0 = (ty or 0) - ay * h + local x1 = x0 + w + local y1 = y0 + h + local xpos = x0 + -- drawing the symbol + local err + err = canvas:start_bbox_group() + assert(not err, err) + for _, c in ipairs(data) do + local vb = self._vbar[c] + err = canvas:encode_Vbar(vb, xpos, y0, y1) + assert(not err, err) + xpos = xpos + sw + end + -- bounding box setting + local qz = self.quietzone_factor * xdim + -- { xmin, ymin, xmax, ymax } + err = canvas:stop_bbox_group(x0 - qz, y0, x1 + qz, y1) + assert(not err, err) + return canvas +end + +return Code128 +-- \ No newline at end of file diff --git a/macros/luatex/generic/barracuda/src/lib-barcode/brcd-code39.lua b/macros/luatex/generic/barracuda/src/lib-barcode/brcd-code39.lua new file mode 100644 index 0000000000..a639619c63 --- /dev/null +++ b/macros/luatex/generic/barracuda/src/lib-barcode/brcd-code39.lua @@ -0,0 +1,381 @@ +-- Code39 barcode encoder implementation +-- Copyright (C) 2019 Roberto Giacomelli +-- +-- All dimensions must be in scaled point (sp) +-- every fields that starts with an undercore sign are intended as private + +local Code39 = { + _VERSION = "code39 v0.0.5", + _NAME = "Code39", + _DESCRIPTION = "Code39 barcode encoder", +} + +Code39._symb_def = {-- symbol definition + ["0"] = 112122111, ["1"] = 211112112, ["2"] = 211112211, + ["3"] = 111112212, ["4"] = 211122111, ["5"] = 111122112, + ["6"] = 111122211, ["7"] = 212112111, ["8"] = 112112112, + ["9"] = 112112211, ["A"] = 211211112, ["B"] = 211211211, + ["C"] = 111211212, ["D"] = 211221111, ["E"] = 111221112, + ["F"] = 111221211, ["G"] = 212211111, ["H"] = 112211112, + ["I"] = 112211211, ["J"] = 112221111, ["K"] = 221111112, + ["L"] = 221111211, ["M"] = 121111212, ["N"] = 221121111, + ["O"] = 121121112, ["P"] = 121121211, ["Q"] = 222111111, + ["R"] = 122111112, ["S"] = 122111211, ["T"] = 122121111, + ["U"] = 211111122, ["V"] = 211111221, ["W"] = 111111222, + ["X"] = 211121121, ["Y"] = 111121122, ["Z"] = 111121221, + ["-"] = 212111121, ["."] = 112111122, [" "] = 112111221, + ["$"] = 111212121, ["/"] = 121112121, ["+"] = 121211121, + ["%"] = 121212111, +} +Code39._star_def = 112121121 -- '*' start/stop character + +-- parameters definition +Code39._par_def = {} +local pardef = Code39._par_def + +-- module main parameter +pardef.module = { + -- Narrow element X-dimension is the width of the smallest element in a + -- barcode symbol. + -- The X-dimension impacts scan-ability. Within the allowed range, it is + -- recommended to use the largest possible X-dimension that is consistent + -- with label or form design. + -- The module width (width of narrow element) should be at least 7.5 mils + -- or 0.1905mm (a mil is 1/1000 inch). + default = 7.5 * 0.0254 * 186467, -- 7.5 mils (sp) unit misure, + unit = "sp", -- scaled point + isReserved = true, + order = 1, -- the one first to be modified + fncheck = function (self, mod, _) --> boolean, err + if mod >= self.default then return true, nil end + return false, "[OutOfRange] too small value for module" + end, +} + +pardef.ratio = { + -- The "wide" element is a multiple of the "narrow" element and this + -- multiple must remain the same throughout the symbol. This multiple can + -- range between 2.0 and 3.0. Preferred value is 3.0. + -- The multiple for the wide element should be between 2.0 and 3.0 if the + -- narrow element is greater than 20 mils. If the narrow element is less + -- than 20 mils (0.508mm), the multiple can only range between 2.0 and 2.2. + default = 2.0, -- the minimum + unit = "absolute-number", + isReserved = true, + order = 2, + fncheck = function (self, ratio, tparcheck) --> boolean, err + local mils = 0.0254 * 186467 + local mod = tparcheck.module + local maxr; if mod < 20*mils then maxr = 2.2 else maxr = 3.0 end + if ratio < 2.0 then + return false, "[OutOfRange] too small ratio (min 2.0)" + end + if ratio > maxr then + return false, "[OutOfRange] too big ratio (max "..maxr..")" + end + return true, nil + end, +} + +pardef.quietzone = { + -- It is recommended to use the largest possible quiet zone, that is + -- consistent with label or form design. + -- Quiet zones must be at least 10 times the module width or 0.10 inches, + -- whichever is larger. Default value (100 mils) + default = 2.54 * 186467, -- 0.1 inches equal to 100*mils + unit = "sp", -- scaled point + isReserved = false, + order = 3, + fncheck = function (self, qz, tparcheck) --> boolean, err + local mils = 0.0254 * 186467 + local mod = tparcheck.module + local min = math.max(10*mod, 100*mils) + if qz >= min then + return true, nil + end + return false, "[OutOfRange] quietzone too small" + end, + fndefault = function(self, tck) --> default value respect to a set of param + local mod = tck.module + return math.max(10*mod, self.default) + end, +} + +pardef.interspace = { -- Intercharacter gap + -- The intercharacter gap width (igw) is 5.3 times the module width (mw) if + -- mw is less than 10 mils. If mw is 10 mils or greater, the value for igw + -- is 3mw or 53 mils, whichever is greater. However, for quality printers, + -- igw often equals mw. + default = 7.5 * 0.0254 * 186467, -- 1 module, for quality printer + unit = "sp", -- scaled point + isReserved = false, + order = 4, + fncheck = function (self, igw, tparcheck) --> boolean, err + local mod = tparcheck.module + if igw >= mod then return true, nil end + return false, "[OutOfRange] interspace too small" + end, + fndefault = function(self, tck) --> default value respect to a set of param + return tck.module + end, +} + +pardef.height = { + -- To enhance readability, it is recommended that the barcode be designed + -- to be as tall as possible, taking into consideration the aspects of label + -- and forms design. + -- The height should be at least 0.15 times the barcode's length or 0.25 inch. + default = 8 * 186467, -- 8 mm -- TODO: better assessment for symbol length + unit = "sp", -- scaled point + isReserved = false, + order = 5, + fncheck = function (self, h, _) --> boolean, err + local mils = 0.0254 * 186467 + if h >= 250*mils then return true, nil end + return false, "[OutOfRange] height too small" + end, +} + +-- text yes or not +pardef.text_enabled = { -- boolean type + -- enable/disable a text label upon the barcode symbol + default = true, + isReserved = false, + order = 6, + fncheck = function (self, flag, _) --> boolean, err + if type(flag) == "boolean" then + return true, nil + else + return false, "[TypeErr] not a boolean value" + end + end, +} + +-- define the text label vertical position +pardef.text_vpos = { -- enumeration + default = "bottom", + isReserved = false, + order = 7, + policy_enum = { + top = true, -- place text at the top of symbol + bottom = true, -- place text under the symbol + }, + fncheck = function (self, e, _) --> boolean, err + if type(e) ~= "string" then return false, "[TypeError] not a string" end + local keys = self.policy_enum + if keys[e] == true then + return true, nil + else + return false, "[Err] enumeration value '"..e.."' not found" + end + end, +} + +-- define the text label horizontal position +pardef.text_hpos = { -- enumeration + default = "left", + isReserved = false, + order = 8, + policy_enum = { + left = true, + center = true, + right = true, + spaced = true, + }, + fncheck = function (self, e, _) --> boolean, err + if type(e) ~= "string" then return false, "[TypeError] not a string" end + local keys = self.policy_enum + if keys[e] == true then + return true, nil + else + return false, "[Err] enumeration value '"..e.."' not found" + end + end, +} + +-- vertical dimension between symbol and text +pardef.text_gap = { + default = 2.2 * 65536, -- 2.2 pt + isReserved = false, + order = 9, + unit = "em", --> TODO: please put this under further analisys asap + fncheck = function(self, g, _) --> boolean, err + if type(g) == "number" then + if g > 0 then + return true, nil + else + return false, "[OptErr] negative number" + end + else + return false, "[TypeErr] not valid type for gap opt" + end + end, +} + +-- star character appearing +pardef.text_star = { + default = false, + isReserved = false, + order = 10, + fncheck = function(self, flag, _) --> boolean, err + if type(flag) == "boolean" then + return true, nil + else + return false, "[TypeErr] not a boolean value" + end + end, +} + +-- configuration function +function Code39:config() --> ok, err + -- build Vbar object for the start/stop symbol + local mod, ratio = self.module, self.ratio + local n_star = self._star_def + local Vbar = self._libgeo.Vbar -- Vbar class + self._vbar = {['*'] = Vbar:from_int_revpair(n_star, mod, mod*ratio)} + return true, nil +end + +-- overriding Barcode method +function Code39:_check_char(c) --> elem, err + if type(c) ~= "string" or #c ~= 1 then + return nil, "[InternalErr] invalid char" + end + local symb_def = self._symb_def + local n = symb_def[c] + if not n then + local fmt = "[ArgErr] '%s' is not a valid Code 39 symbol" + return nil, string.format(fmt, c) + end + return c, nil +end + +-- overriding Barcode method +function Code39:_check_digit(n) --> elem, err + if type(n) ~= "number" then + return nil, "[InteranlErr] not a number" + end + if n < 0 or n > 9 then + return nil, "[InternalErr] not a digit" + end + return tostring(n), nil +end + +function Code39:_finalize() --> ok, err + local v = assert(self._code_data, "[InternalErr] '_code_data' field is nil") + local vbar = self._vbar + local g_Vbar = self._libgeo.Vbar + local mod, ratio = self.module, self.ratio + local symb_def = self._symb_def + for _, c in ipairs(v) do + if not vbar[c] then + local n1 = symb_def[c] + vbar[c] = g_Vbar:from_int_revpair(n1, mod, mod*ratio) + end + end + return true, nil +end + +-- tx, ty is an optional translator vector +function Code39:append_ga(canvas, tx, ty) --> canvas + local code = self._code_data + local ns = self._code_len -- number of chars inside the symbol + local mod = self.module + local ratio = self.ratio + local interspace = self.interspace + local h = self.height + local xs = mod*(6 + 3*ratio) + local xgap = xs + interspace + local w = xgap*(ns + 1) + xs -- (ns + 2)*xgap - interspace + local ax, ay = self.ax, self.ay + local x0 = (tx or 0) - ax * w + local y0 = (ty or 0) - ay * h + local x1 = x0 + w + local y1 = y0 + h + local xpos = x0 + local err + err = canvas:start_bbox_group() + assert(not err, err) + local vbar = self._vbar + -- start/stop symbol + local term_vbar = vbar['*'] + -- draw start symbol + err = canvas:encode_Vbar(term_vbar, xpos, y0, y1) + assert(not err, err) + for _, c in ipairs(code) do -- draw code symbols + xpos = xpos + xgap + local vb = vbar[c] + err = canvas:encode_Vbar(vb, xpos, y0, y1) + assert(not err, err) + end + -- draw stop symbol + err = canvas:encode_Vbar(term_vbar, xpos + xgap, y0, y1) + assert(not err, err) + -- bounding box setting + local qz = self.quietzone + err = canvas:stop_bbox_group(x0 - qz, y0, x1 + qz, y1) + assert(not err, err) + -- check height as the minimum of 15% of length + -- TODO: message could warn the user + -- if 0.15 * w > h then + -- message("The height of the barcode is to small") + -- end + if self.text_enabled then -- human readable text + local chars; if self.text_star then + chars = {"*"} + for _, c in ipairs(code) do + chars[#chars + 1] = c + end + chars[#chars + 1] = "*" + else + chars = {} + for _, c in ipairs(code) do + chars[#chars + 1] = c + end + end + local Text = self._libgeo.Text + local txt = Text:from_chars(chars) + -- setup text position + local txt_vpos = self.text_vpos + local txt_gap = self.text_gap + local ypos, tay; if txt_vpos == "top" then -- vertical setup + ypos = y1 + txt_gap + tay = 0.0 + elseif txt_vpos == "bottom" then + ypos = y0 - txt_gap + tay = 1.0 + else + error("[IntenalErr] text vertical placement option is wrong") + end + local txt_hpos = self.text_hpos + if txt_hpos == "spaced" then -- horizontal setup + local xaxis = x0 + if not self.text_star then + xaxis = xaxis + xgap + end + xaxis = xaxis + xs/2 + err = canvas:encode_Text_xspaced(txt, xaxis, xgap, ypos, tay) + assert(not err, err) + else + local xpos, tax + if txt_hpos == "left" then + xpos = x0 + tax = 0.0 + elseif txt_hpos == "center" then + xpos = (x1 + x0)/2 + tax = 0.5 + elseif txt_hpos == "right" then + xpos = x1 + tax = 1.0 + else + error("[InternalErr] wrong option for text_pos") + end + err = canvas:encode_Text(txt, xpos, ypos, tax, tay) + assert(not err, err) + end + end + return canvas +end + +return Code39 +-- \ No newline at end of file diff --git a/macros/luatex/generic/barracuda/src/lib-barcode/brcd-ean.lua b/macros/luatex/generic/barracuda/src/lib-barcode/brcd-ean.lua new file mode 100644 index 0000000000..6893550a5c --- /dev/null +++ b/macros/luatex/generic/barracuda/src/lib-barcode/brcd-ean.lua @@ -0,0 +1,790 @@ +-- EAN family barcode generator +-- +-- Copyright (C) 2019 Roberto Giacomelli +-- see LICENSE.txt file +-- +-- variant identifiers of the EAN family barcodes: +-- "13" EAN13 +-- "8" EAN8 +-- "5" EAN5 add-on +-- "2" EAN2 add-on +-- "13+5" EAN13 with EAN5 add-on +-- "13+2" EAN13 with EAN2 add-on +-- "8+5" EAN8 with EAN5 add-on +-- "8+2" EAN8 with EAN2 add-on + +local EAN = { + _VERSION = "ean v0.0.5", + _NAME = "ean", + _DESCRIPTION = "EAN barcode encoder", +} + +EAN._codeset_seq = {-- 1 -> A, 2 -> B, 3 -> C +[0]={1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3}, + {1, 1, 2, 1, 2, 2, 3, 3, 3, 3, 3, 3}, + {1, 1, 2, 2, 1, 2, 3, 3, 3, 3, 3, 3}, + {1, 1, 2, 2, 2, 1, 3, 3, 3, 3, 3, 3}, + {1, 2, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3}, + {1, 2, 2, 1, 1, 2, 3, 3, 3, 3, 3, 3}, + {1, 2, 2, 2, 1, 1, 3, 3, 3, 3, 3, 3}, + {1, 2, 1, 2, 1, 2, 3, 3, 3, 3, 3, 3}, + {1, 2, 1, 2, 2, 1, 3, 3, 3, 3, 3, 3}, + {1, 2, 2, 1, 2, 1, 3, 3, 3, 3, 3, 3}, +} + +EAN._codeset14_8 = 1 +EAN._codeset58_8 = 3 + +EAN._codeset_5 = { -- check digit => structure +[0]={2, 2, 1, 1, 1}, -- 0 GGLLL + {2, 1, 2, 1, 1}, -- 1 GLGLL + {2, 1, 1, 2, 1}, -- 2 GLLGL + {2, 1, 1, 1, 2}, -- 3 GLLLG + {1, 2, 2, 1, 1}, -- 4 LGGLL + {1, 1, 2, 2, 1}, -- 5 LLGGL + {1, 1, 1, 2, 2}, -- 6 LLLGG + {1, 2, 1, 2, 1}, -- 7 LGLGL + {1, 2, 1, 1, 2}, -- 8 LGLLG + {1, 1, 2, 1, 2}, -- 9 LLGLG +} + +EAN._symbol = { -- codesets A, B, and C + [1] = {[0] = 3211, 2221, 2122, 1411, 1132, 1231, 1114, 1312, 1213, 3112,}, + [2] = {[0] = 1123, 1222, 2212, 1141, 2311, 1321, 4111, 2131, 3121, 2113,}, + [3] = {[0] = 3211, 2221, 2122, 1411, 1132, 1231, 1114, 1312, 1213, 3112,}, +} + +EAN._is_first_bar = {false, false, true} +EAN._start = {111, true} +EAN._stop = {11111, false} + +-- family parameters + +EAN._par_def = {}; local pardef = EAN._par_def + +-- standard module is 0.33 mm but it can vary from 0.264 to 0.66mm +pardef.mod = { + default = 0.33 * 186467, -- (mm to sp) X dimension (original value 0.33) + unit = "sp", -- scaled point + isReserved = true, + order = 1, -- the one first to be modified + fncheck = function (self, x, _) --> boolean, err + local mm = 186467 + local min, max = 0.264 * mm, 0.660 * mm + if x < min then + return false, "[OutOfRange] too small value for mod" + elseif x > max then + return false, "[OutOfRange] too big value for mod" + end + return true, nil + end, +} + +pardef.height = { + default = 22.85 * 186467, -- 22.85 mm + unit = "sp", + isReserved = false, + order = 2, + fncheck = function (self, h, _) --> boolean, err + if h > 0 then + return true, nil + else + return false, "[OutOfRange] non positive value for height" + end + end, +} + +pardef.quietzone_left_factor = { + default = 11, + unit = "absolute-number", + isReserved = false, + order = 3, + fncheck = function (self, qzf, _) --> boolean, err + if qzf > 0 then + return true, nil + else + return false, "[OutOfRange] non positive value for quietzone_left_factor" + end + end, +} + +pardef.quietzone_right_factor = { + default = 7, + unit = "absolute-number", + isReserved = false, + order = 4, + fncheck = function (self, qzf, _) --> boolean, err + if qzf > 0 then + return true, nil + else + return false, "[OutOfRange] non positive value for quietzone_right_factor" + end + end, +} + +pardef.bars_depth_factor = { + default = 5, + unit = "absolute-number", + isReserved = false, + order = 5, + fncheck = function (self, b, _) --> boolean, err + if b >= 0 then + return true, nil + else + return false, "[OutOfRange] non positive value for bars_depth_factor" + end + end, +} + +-- enable/disable a text label upon the barcode symbol +pardef.text_enabled = { -- boolean type + default = true, + isReserved = false, + order = 6, + fncheck = function (self, flag, _) --> boolean, err + if type(flag) == "boolean" then + return true, nil + else + return false, "[TypeErr] not a boolean value for text_enabled" + end + end, +} + +pardef.text_ygap_factor = { + default = 1.0, + unit = "absolute-number", + isReserved = false, + order = 7, + fncheck = function (self, t, _) --> boolean, err + if t >= 0 then + return true, nil + else + return false, "[OutOfRange] non positive value for text_ygap_factor" + end + end, +} + +pardef.text_xgap_factor = { + default = 0.75, + unit = "absolute-number", + isReserved = false, + order = 8, + fncheck = function (self, t, _) --> boolean, err + if t >= 0 then + return true, nil + else + return false, "[OutOfRange] non positive value for text_xgap_factor" + end + end, +} + +-- variant parameters + +EAN._par_def_variant = { + ["13"] = {}, -- EAN13 + ["8"] = {}, -- EAN8 + ["5"] = {}, -- add-on EAN5 + ["2"] = {}, -- add-on EAN2 + ["13+5"] = {}, -- EAN13 with EAN5 add-on + ["13+2"] = {}, -- EAN13 with EAN2 add-on + ["8+5"] = {}, -- EAN8 with EAN5 add-on + ["8+2"] = {}, -- EAN8 with EAN2 add-on +} + +-- ean13_pardef.text_ISBN parameter -- TODO: + +-- EAN 13/8 + add-on parameters +local addon_xgap_factor = {-- distance between symbol + default = 10, + unit = "absolute-number", + isReserved = false, + order = 1, + fncheck = function (self, t, _) --> boolean, err + if t >= 7 then + return true, nil + else + return false, "[OutOfRange] not positive value for xgap_factor" + end + end, +} +EAN._par_def_variant["13+5"].addon_xgap_factor = addon_xgap_factor +EAN._par_def_variant["13+2"].addon_xgap_factor = addon_xgap_factor +EAN._par_def_variant["8+5"].addon_xgap_factor = addon_xgap_factor +EAN._par_def_variant["8+2"].addon_xgap_factor = addon_xgap_factor + +-- configuration functions + +-- utility for generic configuration of full symbol, add-on included +-- n1 length of main symbol, 8 or 13 +-- n2 length of add-on symbol, 2 or 5 +local function config_full(ean, Vbar, mod, n1, n2) + local i1 = tostring(n1) + local fn_1 = assert(ean._config_variant[i1]) + fn_1(ean, Vbar, mod) + local i2 = tostring(n2) + local fn_2 = assert(ean._config_variant[i2]) + fn_2(ean, Vbar, mod) + ean._main_len = n1 + ean._addon_len = n2 + ean._is_last_checksum = true +end + +EAN._config_variant = { + ["13"] = function (ean13, Vbar, mod) + ean13._main_len = 13 + ean13._is_last_checksum = true + local start = ean13._start + local stop = ean13._stop + ean13._13_start_stop_vbar = Vbar:from_int(start[1], mod, start[2]) + ean13._13_ctrl_center_vbar = Vbar:from_int(stop[1], mod, stop[2]) + ean13._13_codeset_vbar = {} + local tvbar = ean13._13_codeset_vbar + for i_cs, codetab in ipairs(ean13._symbol) do + tvbar[i_cs] = {} + local tv = tvbar[i_cs] + local isbar = ean13._is_first_bar[i_cs] + for i = 0, 9 do + tv[i] = Vbar:from_int(codetab[i], mod, isbar) + end + end + end, + ["8"] = function (ean8, Vbar, mod) + ean8._main_len = 8 + ean8._is_last_checksum = true + local start = ean8._start + local stop = ean8._stop + ean8._8_start_stop_vbar = Vbar:from_int(start[1], mod, start[2]) + ean8._8_ctrl_center_vbar = Vbar:from_int(stop[1], mod, stop[2]) + ean8._8_codeset_vbar = {} + local tvbar = ean8._8_codeset_vbar + for k = 1, 3, 2 do -- only codeset A and C (k == 1, 3) + tvbar[k] = {} + local codetab = ean8._symbol[k] + local isbar = ean8._is_first_bar[k] + local tv = tvbar[k] + for i = 0, 9 do + tv[i] = Vbar:from_int(codetab[i], mod, isbar) + end + end + end, + ["5"] = function (ean5, Vbar, mod) -- add-on EAN5 + ean5._main_len = 5 + ean5._is_last_checksum = false + ean5._5_start_vbar = Vbar:from_int(112, mod, true) + ean5._5_sep_vbar = Vbar:from_int(11, mod, false) + ean5._5_codeset_vbar = {} + local tvbar = ean5._5_codeset_vbar + local symbols = ean5._symbol + for c = 1, 2 do + tvbar[c] = {} + local tcs = tvbar[c] + local isbar = false + local sb = symbols[c] + for i = 0, 9 do + tcs[i] = Vbar:from_int(sb[i], mod, false) + end + end + end, + ["2"] = function (ean2, Vbar, mod) -- add-on EAN2 + ean2._main_len = 2 + ean2._is_last_checksum = false + ean2._2_start_vbar = Vbar:from_int(112, mod, true) + ean2._2_sep_vbar = Vbar:from_int(11, mod, false) + ean2._2_codeset_vbar = {} + local tvbar = ean2._2_codeset_vbar + local symbols = ean2._symbol + for c = 1, 2 do + tvbar[c] = {} + local tcs = tvbar[c] + local isbar = false + local sb = symbols[c] + for i = 0, 9 do + tcs[i] = Vbar:from_int(sb[i], mod, false) + end + end + end, + ["13+5"] = function (ean, Vbar, mod) -- EAN13 with EAN5 add-on + config_full(ean, Vbar, mod, 13, 5) + end, + ["13+2"] = function(ean, Vbar, mod) -- EAN13 with EAN2 add-on + config_full(ean, Vbar, mod, 13, 2) + end, + ["8+5"] = function(ean, Vbar, mod) -- EAN8 with EAN5 add-on + config_full(ean, Vbar, mod, 8, 5) + end, + ["8+2"] = function(ean, Vbar, mod) -- EAN8 with EAN2 add-on + config_full(ean, Vbar, mod, 8, 2) + end, +} + +-- config function +-- create all the possible VBar object +function EAN:config(variant) --> ok, err + if not type(variant) == "string" then + return false, "[ArgErr] incorrect type for 'variant', string expected" + end + local fnconfig = self._config_variant[variant] + if not fnconfig then + return false, "[Err] EAN variant '".. variant .."' not found" + end + local Vbar = self._libgeo.Vbar -- Vbar class + local mod = self.mod + fnconfig(self, Vbar, mod) + return true, nil +end + +-- utility function + +-- the checksum of EAN8 or EAN13 code +-- 'data' is an array of digits +local function checksum_8_13(data, stop_index) + local s1 = 0; for i = 2, stop_index, 2 do + s1 = s1 + data[i] + end + local s2 = 0; for i = 1, stop_index, 2 do + s2 = s2 + data[i] + end + local sum; if stop_index % 2 == 0 then + sum = 3 * s1 + s2 + else + sum = s1 + 3 * s2 + end + return (10 - (sum % 10)) % 10 +end + +-- return the checksum digit of an EAN 5 or EAN 2 add-on +-- this digits will not be part of the code +-- 'data' is an array of digits +-- i is the index where the code starts +-- len is the length of the code +local function checksum_5_2(data, i, len) --> checksum digit or nil + if len == 5 then -- EAN 5 add-on + local c1 = data[i] + data[i + 2] + data[i + 4] + local c2 = data[i + 1] + data[i + 3] + local ck = 3 * c1 + 9 * c2 + return ck % 10 + elseif len == 2 then -- EAN 2 add-on + local ck = 10 * data[i] + data[i + 1] + return ck % 4 + end +end + +-- public methods + +-- return the checksum digit of the argument or an error +-- respect to the encoder variant EAN8 or EAN13 +-- 'n' can be an integer, a string of digits or an array of digits +function EAN:checksum(n) --> n, err + local arr; + if type(n) == "number" then + if n <= 0 then + return nil, "[ArgErr] number must be a positive integer" + end + if n - math.floor(n) > 0 then + return nil, "[ArgErr] 'n' is not an integer" + end + arr = {} + local i = 0 + while n > 0 do + i = i + 1 + arr[i] = n % 10 + n = (n - arr[i]) / 10 + end + -- array reversing + local len = #arr + 1 + for i = 1, #arr/2 do + local dt = arr[i] + arr[i] = arr[len - i] + arr[len - i] = dt + end + elseif type(n) == "table" then + if not #n > 0 then return nil, "[ArgErr] empty array" end + for _, d in ipairs(n) do + if type(d) ~= "number" then + return nil, "[ArgErr] array 'n' contains a not digit element" + end + if d < 0 or d > 9 then + return nil, "[ArgErr] array contains a not digit number" + end + end + arr = n + elseif type(n) == "string" then + arr = {} + for c in string.gmatch(n, ".") do + local d = tonumber(c) + if (not d) or d > 9 then + return nil, "[ArgErr] 's' contains a not digit char" + end + arr[#arr + 1] = d + end + else + return nil, "[ArgErr] not a number, a string or an array of digits" + end + local i = #arr + if i == 7 or i == 8 then + return checksum_8_13(arr, 7) + elseif i == 12 or i == 13 then + return checksum_8_13(arr, 12) + else + return nil, "[Err] unsuitable data length for EAN8 or EAN13 checksum" + end +end + +function EAN:get_code() --> string + local var = self._variant + local code = self.code13 -- TODO: + return table.concat(code) +end + +-- internal methods for Barcode costructors + +function EAN:_finalize() --> ok, err + local l1 = self._main_len + local l2 = self._addon_len + local ok_len = l1 + (l2 or 0) + local symb_len = self._code_len + if symb_len ~= ok_len then + return false, "[ArgErr] not a "..ok_len.."-digits long array" + end + if self._is_last_checksum then -- is the last digit ok? + local data = self._code_data + local ck = checksum_8_13(data, l1 - 1) + if ck ~= data[l1] then + return false, "[Err] wrong checksum digit" + end + end + return true, nil +end + +-- drawing functions + +EAN._append_ga_variant = {} +local fn_append_ga_variant = EAN._append_ga_variant + +-- draw EAN13 symbol +fn_append_ga_variant["13"] = function (ean, canvas, tx, ty, ax, ay) + local code = ean._code_data + local mod = ean.mod + local bars_depth = mod * ean.bars_depth_factor + local w, h = 95*mod, ean.height + bars_depth + local x0 = (tx or 0) - ax * w + local y0 = (ty or 0) - ay * h + local x1 = x0 + w + local y1 = y0 + h + local xpos = x0 -- current insertion x-coord + local ys = y0 + bars_depth + local s_width = 7*mod + local code_seq = ean._codeset_seq[code[1]] + -- draw the start symbol + local err + err = canvas:start_bbox_group(); assert(not err, err) + local be = ean._13_start_stop_vbar + err = canvas:encode_Vbar(be, xpos, y0, y1); assert(not err, err) + xpos = xpos + 3*mod + -- draw the first 6 numbers + for i = 2, 7 do + local codeset = code_seq[i-1] + local n = code[i] + local vbar = ean._13_codeset_vbar[codeset][n] + err = canvas:encode_Vbar(vbar, xpos, ys, y1); assert(not err, err) + xpos = xpos + s_width + end + -- draw the control symbol + local ctrl = ean._13_ctrl_center_vbar + err = canvas:encode_Vbar(ctrl, xpos, y0, y1); assert(not err, err) + xpos = xpos + 5*mod + -- draw the last 6 numbers + for i = 8, 13 do + local codeset = code_seq[i-1] + local n = code[i] + local vbar = ean._13_codeset_vbar[codeset][n] + err = canvas:encode_Vbar(vbar, xpos, ys, y1); assert(not err, err) + xpos = xpos + s_width + end + -- draw the stop char + err = canvas:encode_Vbar(be, xpos, y0, y1); assert(not err, err) + -- bounding box set up + local qzl = ean.quietzone_left_factor * mod + local qzr = ean.quietzone_right_factor * mod + local err = canvas:stop_bbox_group(x0 - qzl, y0, x1 + qzr, y1) + assert(not err, err) + if ean.text_enabled then -- human readable text + local Text = ean._libgeo.Text + local txt_1 = Text:from_digit_array(code, 1, 1) + local txt_2 = Text:from_digit_array(code, 2, 7) + local txt_3 = Text:from_digit_array(code, 8, 13) + local y_bl = ys - ean.text_ygap_factor * mod + local mx = ean.text_xgap_factor + local err + err = canvas:encode_Text(txt_1, x0 - qzl, y_bl, 0, 1) + assert(not err, err) + local x2_1 = x0 + (3+mx)*mod + local x2_2 = x0 + (46-mx)*mod + err = canvas:encode_Text_xwidth(txt_2, x2_1, x2_2, y_bl, 1) + assert(not err, err) + local x3_1 = x0 + (49+mx)*mod + local x3_2 = x0 + (92-mx)*mod + err = canvas:encode_Text_xwidth(txt_3, x3_1, x3_2, y_bl, 1) + assert(not err, err) + end +end + +-- draw EAN8 symbol +fn_append_ga_variant["8"] = function (ean, canvas, tx, ty, ax, ay) + local code = ean._code_data + local mod = ean.mod + local bars_depth = mod * ean.bars_depth_factor + local w, h = 67*mod, ean.height + bars_depth + local x0 = (tx or 0) - ax * w + local y0 = (ty or 0) - ay * h + local x1 = x0 + w + local y1 = y0 + h + local xpos = x0 -- current insertion x-coord + local ys = y0 + bars_depth + local s_width = 7*mod + -- draw the start symbol + local err + err = canvas:start_bbox_group(); assert(not err, err) + local be = ean._8_start_stop_vbar + err = canvas:encode_Vbar(be, xpos, y0, y1); assert(not err, err) + xpos = xpos + 3*mod + -- draw the first 4 numbers + local t_vbar = ean._8_codeset_vbar + local cs14 = ean._codeset14_8 + for i = 1, 4 do + local n = code[i] + local vbar = t_vbar[cs14][n] + err = canvas:encode_Vbar(vbar, xpos, ys, y1); assert(not err, err) + xpos = xpos + s_width + end + -- draw the control symbol + local ctrl = ean._8_ctrl_center_vbar + err = canvas:encode_Vbar(ctrl, xpos, y0, y1); assert(not err, err) + xpos = xpos + 5*mod + -- draw the product code + local cs58 = ean._codeset58_8 + for i = 5, 8 do + local n = code[i] + local vbar = t_vbar[cs58][n] + err = canvas:encode_Vbar(vbar, xpos, ys, y1); assert(not err, err) + xpos = xpos + s_width + end + -- draw the stop char + err = canvas:encode_Vbar(be, xpos, y0, y1); assert(not err, err) + -- bounding box set up + local qzl = ean.quietzone_left_factor * mod + local qzr = ean.quietzone_right_factor * mod + local err = canvas:stop_bbox_group(x0 - qzl, y0, x1 + qzr, y1) + assert(not err, err) + if ean.text_enabled then -- human readable text + local Text = ean._libgeo.Text + local t_1 = Text:from_digit_array(code, 1, 4) + local t_2 = Text:from_digit_array(code, 5, 8) + local y_bl = ys - ean.text_ygap_factor * mod + local mx = ean.text_xgap_factor + local x1_1 = x0 + ( 3 + mx)*mod + local x1_2 = x0 + (32 - mx)*mod + err = canvas:encode_Text_xwidth(t_1, x1_1, x1_2, y_bl, 1) + assert(not err, err) + local x2_1 = x0 + (35+mx)*mod + local x2_2 = x0 + (64-mx)*mod + err = canvas:encode_Text_xwidth(t_2, x2_1, x2_2, y_bl, 1) + assert(not err, err) + end +end + +-- draw EAN5 add-on symbol +fn_append_ga_variant["5"] = function (ean, canvas, tx, ty, ax, ay, h) + local code = ean._code_data + local l1 = ean._main_len + local i1; if l1 == 5 then + i1 = 1 + else + i1 = l1 + 1 + end + local i2 = i1 + 4 + local mod = ean.mod + local w = 47*mod + h = h or ean.height + local x0 = (tx or 0) - ax * w + local y0 = (ty or 0) - ay * h + local x1 = x0 + w + local y1 = y0 + h + local xpos = x0 -- current insertion x-coord + local sym_w = 7*mod + local sep_w = 2*mod + -- draw the start symbol + local err + err = canvas:start_bbox_group(); assert(not err, err) + local start = ean._5_start_vbar + err = canvas:encode_Vbar(start, xpos, y0, y1); assert(not err, err) + xpos = xpos + 4*mod + local ck = checksum_5_2(code, i1, 5) + local codeset = ean._codeset_5[ck] + local sep = ean._5_sep_vbar + local t_vbar = ean._5_codeset_vbar + -- draw the five digits + local k = 0 + for i = i1, i2 do + k = k + 1 + local cs = codeset[k] -- 1 or 2 + local d = code[i] + local vbar = t_vbar[cs][d] + err = canvas:encode_Vbar(vbar, xpos, y0, y1); assert(not err, err) + xpos = xpos + sym_w + if k < 5 then + err = canvas:encode_Vbar(sep, xpos, y0, y1); assert(not err, err) + xpos = xpos + sep_w + end + end + -- bounding box set up + local qzl = ean.quietzone_left_factor * mod + local qzr = ean.quietzone_right_factor * mod + local err = canvas:stop_bbox_group(x0 - qzl, y0, x1 + qzr, y1) + assert(not err, err) + if ean.text_enabled then -- human readable text + local Text = ean._libgeo.Text + local txt = Text:from_digit_array(code, i1, i2) + local y_bl = y1 + ean.text_ygap_factor * mod + local x1_1 = x0 + 3*mod + local x1_2 = x1 - 3*mod + err = canvas:encode_Text_xwidth(txt, x1_1, x1_2, y_bl, 0) + assert(not err, err) + end +end + +-- draw EAN2 symbol +fn_append_ga_variant["2"] = function (ean, canvas, tx, ty, ax, ay, h) + local code = ean._code_data + local l1 = ean._main_len + local i1; if l1 == 2 then + i1 = 1 + else + i1 = l1 + 1 + end + local mod = ean.mod + local w = 20*mod + h = h or ean.height + local x0 = (tx or 0.0) - ax * w + local y0 = (ty or 0.0) - ay * h + local x1 = x0 + w + local y1 = y0 + h + local xpos = x0 -- current insertion x-coord + local sym_w = 7*mod + local sep_w = 2*mod + -- draw the start symbol + local err + err = canvas:start_bbox_group(); assert(not err, err) + local start = ean._2_start_vbar + err = canvas:encode_Vbar(start, xpos, y0, y1); assert(not err, err) + xpos = xpos + 4*mod + local r = checksum_5_2(code, i1, 2) + local s1, s2 + if r == 0 then -- LL scheme + s1, s2 = 1, 1 + elseif r == 1 then -- LG scheme + s1, s2 = 1, 2 + elseif r == 2 then -- GL scheme + s1, s2 = 2, 1 + else -- r == 3 -- GG scheme + s1, s2 = 2, 2 + end + local t_vbar = ean._2_codeset_vbar + local d1 = code[i1] -- render the first digit + local vb1 = t_vbar[s1][d1] + err = canvas:encode_Vbar(vb1, xpos, y0, y1); assert(not err, err) + xpos = xpos + sym_w + local sep = ean._2_sep_vbar + err = canvas:encode_Vbar(sep, xpos, y0, y1); assert(not err, err) + xpos = xpos + sep_w + local d2 = code[i1 + 1] -- render the second digit + local vb2 = t_vbar[s2][d2] + err = canvas:encode_Vbar(vb2, xpos, y0, y1); assert(not err, err) + -- bounding box set up + local qzl = ean.quietzone_left_factor * mod + local qzr = ean.quietzone_right_factor * mod + local err = canvas:stop_bbox_group(x0 - qzl, y0, x1 + qzr, y1) + assert(not err, err) + if ean.text_enabled then -- human readable text + local Text = ean._libgeo.Text + local txt = Text:from_digit_array(code, i1, i1 + 1) + local y_bl = y1 + ean.text_ygap_factor * mod + local x1_1 = x0 + 3*mod + local x1_2 = x1 - 3*mod + err = canvas:encode_Text_xwidth(txt, x1_1, x1_2, y_bl, 0) + assert(not err, err) + end +end + +fn_append_ga_variant["13+5"] = function (ean, canvas, tx, ty, ax, ay) + local mod = ean.mod + local bars_depth = mod * ean.bars_depth_factor + local h = ean.height + bars_depth + local w = (142 + ean.addon_xgap_factor) * mod + local x0 = (tx or 0) - ax * w + local y0 = (ty or 0) - ay * h + local x1 = x0 + w + local fn_ga = ean._append_ga_variant + local fn_1 = fn_ga["13"] + local fn_2 = fn_ga["5"] + fn_1(ean, canvas, x0, y0, 0, 0) + fn_2(ean, canvas, x1, y0, 1, 0, 0.85 * h) +end + +fn_append_ga_variant["13+2"] = function (ean, canvas, tx, ty, ax, ay) + local mod = ean.mod + local bars_depth = mod * ean.bars_depth_factor + local h = ean.height + bars_depth + local w = (115 + ean.addon_xgap_factor) * mod + local x0 = (tx or 0) - ax * w + local y0 = (ty or 0) - ay * h + local x1 = x0 + w + local fn_ga = ean._append_ga_variant + local fn_1 = fn_ga["13"] + local fn_2 = fn_ga["2"] + fn_1(ean, canvas, x0, y0, 0, 0) + fn_2(ean, canvas, x1, y0, 1, 0, 0.85 * h) +end + +fn_append_ga_variant["8+5"] = function (ean, canvas, tx, ty, ax, ay) + local mod = ean.mod + local bars_depth = mod * ean.bars_depth_factor + local h = ean.height + bars_depth + local w = (114 + ean.addon_xgap_factor) * mod + local x0 = (tx or 0) - ax * w + local y0 = (ty or 0) - ay * h + local x1 = x0 + w + local fn_ga = ean._append_ga_variant + local fn_1 = fn_ga["8"] + local fn_2 = fn_ga["5"] + fn_1(ean, canvas, x0, y0, 0, 0) + fn_2(ean, canvas, x1, y0, 1, 0, 0.85 * h) +end + +fn_append_ga_variant["8+2"] = function (ean, canvas, tx, ty, ax, ay) + local mod = ean.mod + local bars_depth = mod * ean.bars_depth_factor + local h = ean.height + bars_depth + local w = (87 + ean.addon_xgap_factor) * mod + local x0 = (tx or 0) - ax * w + local y0 = (ty or 0) - ay * h + local x1 = x0 + w + local fn_ga = ean._append_ga_variant + local fn_1 = fn_ga["8"] + local fn_2 = fn_ga["2"] + fn_1(ean, canvas, x0, y0, 0, 0) + fn_2(ean, canvas, x1, y0, 1, 0, 0.85 * h) +end + +-- Drawing into the provided channel geometrical data +-- tx, ty is the optional translation vector +-- the function return the canvas reference to allow call chaining +function EAN:append_ga(canvas, tx, ty) --> canvas + local var = self._variant + local fn_append_ga = assert(self._append_ga_variant[var]) + local ax, ay = self.ax, self.ay + fn_append_ga(self, canvas, tx, ty, ax, ay) + return canvas +end + +return EAN diff --git a/macros/luatex/generic/barracuda/src/lib-barcode/brcd-i2of5.lua b/macros/luatex/generic/barracuda/src/lib-barcode/brcd-i2of5.lua new file mode 100644 index 0000000000..8097b855f7 --- /dev/null +++ b/macros/luatex/generic/barracuda/src/lib-barcode/brcd-i2of5.lua @@ -0,0 +1,378 @@ +-- Interleaved 2 of 5 (ITF) barcode generator +-- +-- Copyright (C) 2019 Roberto Giacomelli +-- see LICENSE.txt file + +local ITF = { -- main container + _VERSION = "ITF v0.0.1", + _NAME = "ITF", + _DESCRIPTION = "Interleaved 2 of 5 barcode encoder", +} + +ITF._start = 111 -- nnnn +ITF._stop = 112 -- Wnn (integer must be in reverse order) + +ITF._pattern = { -- true -> narrow, false -> Wide + [0] = {true, true, false, false, true}, + [1] = {false, true, true, true, false}, + [2] = {true, false, true, true, false}, + [3] = {false, false, true, true, true}, + [4] = {true, true, false, true, false}, + [5] = {false, true, false, true, true}, + [6] = {true, false, false, true, true}, + [7] = {true, true, true, false, false}, + [8] = {false, true, true, false, true}, + [9] = {true, false, true, false, true}, +} + +-- define parameters +ITF._par_def = {} +local pardef = ITF._par_def + +-- module main parameter +pardef.module = { + -- Narrow element X-dimension is the width of the smallest element. + -- The module width (width of narrow element) should be at least 7.5 mils + -- that is exactly 0.1905mm (1 mil is 1/1000 inch). + default = 7.5 * 0.0254 * 186467, -- 7.5 mils (sp) unit misure, + unit = "sp", -- scaled point + isReserved = true, + order = 1, -- the one first to be modified + fncheck = function (self, mod, _) --> boolean, err + if mod >= self.default then return true, nil end + return false, "[OutOfRange] too small lenght for X-dim" + end, +} + +pardef.ratio = { + -- The "wide" element is a multiple of the "narrow" element that can + -- range between 2.0 and 3.0. Preferred value is 3.0. + -- The multiple for the wide element should be between 2.0 and 3.0 if the + -- narrow element is greater than 20 mils. If the narrow element is less + -- than 20 mils (0.508mm), the ratio must exceed 2.2. + default = 3.0, + unit = "absolute-number", + isReserved = true, + order = 2, + fncheck = function (_, ratio, tpardef) --> boolean, err + local mils = 0.0254 * 186467 + local mod = tpardef.module + local minr; if mod < 20*mils then minr = 2.2 else minr = 2.0 end + if ratio < minr then + return false, "[OutOfRange] too small ratio (the min is "..minr..")" + end + if ratio > 3.0 then + return false, "[OutOfRange] too big ratio (the max is 3.0)" + end + return true, nil + end, +} + +pardef.height = { + -- The height should be at least 0.15 times the barcode's length or 0.25 inch. + default = 15 * 186467, -- 15mm -- TODO: better assessment for symbol length + unit = "sp", -- scaled point + isReserved = false, + order = 3, + fncheck = function (_self, h, _opt) --> boolean, err + local mils = 0.0254 * 186467 + if h >= 250*mils then + return true, nil + end + return false, "[OutOfRange] height too small" + end, +} + +pardef.quietzone = { + -- Quiet zones must be at least 10 times the module width or 0.25 inches, + -- whichever is larger + default = 250 * 0.0254 * 186467, -- 0.25 inch (250 mils) + unit = "sp", -- scaled point + isReserved = false, + order = 4, + fncheck = function (self, qz, _opt) --> boolean, err + local mils = 0.0254 * 186467 + local mod = self.module + local min = math.max(10*mod, 250*mils) + if qz >= min then + return true, nil + else + return false, "[OutOfRange] quietzone too small" + end + end, +} + +pardef.check_digit_policy = { -- enumeration + default = "none", + isReserved = false, + policy_enum = { + add = true, -- add a check digit to the symbol + verify = true, -- check the last digit of the symbol as check digit + none = true, -- do nothing + }, + order = 5, + fncheck = function (self, e, _) --> boolean, err + if type(e) ~= "string" then return false, "[TypeError] not a string" end + local keys = self.policy_enum + if keys[e] == true then + return true, nil + else + return false, "[Err] enum value not found" + end + end, +} + +pardef.check_digit_method = { -- enumeration + -- determine the algorithm for the check digit calculation + default = "mod_10", + isReserved = false, + order = 6, + method_enum = { + mod_10 = true, -- MOD 10 check digits method + }, + fncheck = function (self, e, _) --> boolean, err + if type(e) ~= "string" then return false, "[TypeError] not a string" end + local keys = self.method_enum + if keys[e] == true then + return true, nil + else + return false, "[Err] enum value not found" + end + end, +} + +pardef.bearer_bars_enabled = { -- boolean type + -- enable/disable Bearer bars around the barcode symbol + default = false, + isReserved = false, + order = 7, + fncheck = function (_, flag, _) --> boolean, err + if type(flag) == "boolean" then + return true, nil + else + return false, "[TypeErr] not a boolean value" + end + end, +} + +pardef.bearer_bars_thickness = { -- dimension + default = 37.5 * 0.0254 * 186467, -- 5 modules + unit = "sp", -- scaled point + isReserved = false, + order = 8, + fncheck = function (_self, thick, tpardef) --> boolean, err + local module = tpardef.module + if thick >= 2*module then + return true, nil + end + return false, "[OutOfRange] thickness too small" + end, +} + +pardef.bearer_bars_layout = { -- enumeration + -- determine the algorithm for the check digit calculation + default = "hbar", + isReserved = false, + order = 9, + method_enum = { + frame = true, -- a rectangle around the symbol + hbar = true, -- top and bottom horizontal bars + }, + fncheck = function (self, e, _) --> boolean, err + if type(e) ~= "string" then return false, "[TypeError] not a string" end + local keys = self.method_enum + if keys[e] == true then + return true, nil + else + return false, "[Err] enum value not found" + end + end, +} + +-- auxiliary functions + +-- separate a non negative integer in its digits {d_n-1, ..., d_1, d_0} +local function n_to_arr(n) --> len, digits + local digits = {} + local slen + if n == 0 then + digits[#digits + 1] = 0 + slen = 1 + else + slen = 0 + while n > 0 do + local d = n % 10 + digits[#digits + 1] = d + n = (n - d) / 10 + slen = slen + 1 + end + end + for k = 1, slen/2 do -- array reversing + local h = slen - k + 1 + local d = digits[k] + digits[k] = digits[h] + digits[h] = d + end + return slen, digits +end + +local function rshift(t) + local tlen = #t + for i = tlen, 1, -1 do + t[i + 1] = t[i] + end + t[1] = 0 +end + + +local function check_mod10(t, last) + local sum = 0 + local w = true + for i = last, 1, -1 do + if w then + sum = sum + 3*t[i] + else + sum = sum + t[i] + end + w = not w + end + local m = sum % 10 + if m == 0 then return 0 else return 10 - m end +end + +local function checkdigit(t, last, method) + if method == "mod_10" then + return check_mod10(t, last) + else + assert(false, "[InternalErr] unknow method") + end +end + + +-- configuration function +function ITF:config() --> ok, err + -- init Vbar objects + local narrow = self.module + local wide = narrow * self.ratio + -- start symbol + local Vbar = self._libgeo.Vbar -- Vbar class + self._vbar_start = Vbar:from_int_revpair(self._start, narrow, wide) + self._vbar_stop = Vbar:from_int_revpair(self._stop, narrow, wide) + + -- build every possible pair of digits from 00 to 99 + self._vbar_data = {} + local vbar = self._vbar_data + local pattern = self._pattern + for dec = 0, 9 do + for unit = 0, 9 do + local t1 = pattern[dec] + local t2 = pattern[unit] + local n = dec*10 + unit + vbar[n] = Vbar:from_two_tab(t1, t2, narrow, wide) + end + end + return true, nil +end + +-- public functions + +function ITF:get_checkdigit(n, method) + if type(n) ~= "number" then return nil, "[ArgErr] 'n' is not a number" end + if n < 0 then return nil, "[ArgErr] found a negative number" end + if n - math.floor(n) ~= 0 then return nil, "[ArgErr] found a float number" end + method = method or self.check_digit_method + local last, t = n_to_arr(n) + return checkdigit(t, last, method) +end + +-- internal methods for constructors + +function ITF:_finalize() --> ok, err + -- check digit action + local policy = self.check_digit_policy + local slen = self._code_len + local is_even = (slen % 2 == 0) + local digits = self._code_data + if policy == "none" then + if not is_even then + rshift(digits) -- add a heading zero for padding + slen = slen + 1 + end + elseif policy == "add" then + if is_even then + rshift(digits) -- add a heading zero for padding + slen = slen + 1 + end + local c = checkdigit(digits, slen, self.check_digit_method) + digits[#digits + 1] = c + elseif policy == "verify" then + if not is_even then + rshift(digits) + slen = slen + 1 + end + local c = checkdigit(digits, slen - 1, self.check_digit_method) + if c ~= digits[slen] then + return false, "[DataErr] wrong check digit" + end + else + return false, "[InternalError] wrong enum value" + end + self._code_len = slen + return true, nil +end + +-- drawing function +-- tx, ty is an optional translator vector +function ITF:append_ga(canvas, tx, ty) --> canvas + local err = canvas:start_bbox_group(); assert(not err, err) + -- draw the start symbol + local xdim = self.module + local ratio = self.ratio + local symb_len = 2 * xdim * (3 + 2*ratio) + local x0 = tx or 0 + local xpos = x0 + local y0 = ty or 0 + local y1 = y0 + self.height + local start = self._vbar_start + local err + err = canvas:encode_Vbar(start, xpos, y0, y1); assert(not err, err) + xpos = xpos + 4 * xdim + -- draw the code symbol + local digits = self._code_data + local vbars = self._vbar_data + for i = 1, #digits, 2 do + local index = 10 * digits[i] + digits[i+1] + local b = vbars[index] + err = canvas:encode_Vbar(b, xpos, y0, y1); assert(not err, err) + xpos = xpos + symb_len + end + -- draw the stop symbol + local stop = self._vbar_stop + err = canvas:encode_Vbar(stop, xpos, y0, y1); assert(not err, err) + -- bounding box setting + local x1 = xpos + (2 + ratio)*xdim + local qz = self.quietzone + local b1x, b1y = x0 - qz, y0 + local b2x, b2y = x1 + qz, y1 + if self.bearer_bars_enabled then + local w = self.bearer_bars_thickness + err = canvas:encode_linethick(w); assert(not err, err) + b1y, b2y = b1y - w, b2y + w + local layout = self.bearer_bars_layout + if layout == "hbar" then + err = canvas:encode_hline(b1x, b2x, y0 - w/2); assert(not err, err) + err = canvas:encode_hline(b1x, b2x, y1 + w/2); assert(not err, err) + elseif layout == "frame" then + err = canvas:encode_rectangle(b1x - w/2, y0 - w/2, b2x + w/2, y1 + w/2) + assert(not err, err) + b1x, b2x = b1x - w, b2x + w + else + error("[IntenalErr] bearer bars layout option is wrong") + end + end + local err = canvas:stop_bbox_group(b1x, b1y, b2x, b2y) + assert(not err, err) + return canvas +end + +return ITF diff --git a/macros/luatex/generic/barracuda/src/lib-driver/brcd-driver.lua b/macros/luatex/generic/barracuda/src/lib-driver/brcd-driver.lua new file mode 100644 index 0000000000..4827a190c5 --- /dev/null +++ b/macros/luatex/generic/barracuda/src/lib-driver/brcd-driver.lua @@ -0,0 +1,399 @@ +-- +-- ga Intermediate Graphic Language for barcode drawing +-- Copyright (C) 2019 Roberto Giacomelli +-- +-- Basic driver interface +-- drawing elementary vector shape +-- All dimensions are in scaled point (sp) + +local Driver = { + _VERSION = "Driver v0.0.9", + _NAME = "Driver", + _DESCRIPTION = "Driver for ga graphic assembler stream", +} + +Driver.__index = Driver +Driver._drv_instance = {} -- driver instances repository + +-- driver_type/submodule name +Driver._drv_available_drv = { -- lowercase keys please + native = "lib-driver.brcd-drv-pdfliteral", -- only LuaTeX driver + svg = "lib-driver.brcd-drv-svg", +} + +function Driver:_get_driver(id_drv) --> object, err + if type(id_drv) ~= "string" then + return nil, "[ArgErr] 'id_drv' is not a string" + end + if not self._drv_available_drv[id_drv] then + return nil, "[ArgErr] driver '"..id_drv.."' not found" + end + local t_drv = self._drv_instance + if t_drv[id_drv] then -- is the repo already loaded? + return t_drv[id_drv], nil + else -- loading driver + local module = self._drv_available_drv[id_drv] + local channel = require(module) + t_drv[id_drv] = channel + return channel, nil + end +end + +function Driver:_new_state() --> a new state + return { + line_width = 65781.76, -- line width 1bp (in scaled point sp) + line_cap = 0, -- line cap style + line_join = 0, -- line join style + gtext = false, -- text group off + bb_on = true, -- bounding box checking activation + bb_x1 = nil, -- bounding box coordinates in sp (nil means no data) + bb_y1 = nil, + bb_x2 = nil, + bb_y2 = nil, + mm = 186467.98110236, -- conversion factor sp -> mm (millimeter) + bp = 65781.76, -- conversion factor sp -> bp (big point) + } +end + +function Driver:_ga_process(drv, ga, st, bf, xt) + local op_fn = self._opcode_v001 + local pc = 1 -- program counter + local data = ga._data + while data[pc] do -- stream processing + local opcode = data[pc] + local fn = assert(op_fn[opcode], "[InternalErr] unimpl opcode ".. opcode) + pc = fn(drv, st, pc + 1, data, bf, xt) + end +end + +-- save graphic data in an external file with the 'id_drv' format +-- id_drv: specific driver output +-- ga: ga object +-- filename: file name +-- ext: file extension (optional) +function Driver:save(id_drv, ga, filename, ext) --> ok, err + -- retrive the output library + local drv, err = self:_get_driver(id_drv) + if err then return false, err end + -- init + local state = self:_new_state() + local buf, txt_buf = drv.init_buffer(state) -- a new buffer and text_buffer + -- processing + self:_ga_process(drv, ga, state, buf, txt_buf) + -- buffer finalizing + drv.close_buffer(state, buf, txt_buf) -- finalize the istruction + -- file saving + local sep = drv.buf_sep + ext = ext or drv.ext + local fn = io.open(filename.."."..ext, "w") -- output the file + fn:write(table.concat(buf, sep)) -- concat the buffer + fn:close() + return true, nil +end + +-- insert a ga drawing in a TeX box +-- PDFnative only function +function Driver:ga_to_hbox(ga, boxname) --> ok, err + -- retrive the output library + local id_drv = "native" + local drv, err = self:_get_driver(id_drv) + if err then return false, err end + -- init process + local state = self:_new_state() + local buf, txt_buf = drv.init_buffer(state) -- a new buffer and text_buffer + -- processing + self:_ga_process(drv, ga, state, buf, txt_buf) + -- finalizing + drv.close_buffer(state, buf, txt_buf) -- finalize the istruction sequence + -- build hbox + local ok, err = drv.hboxcreate(boxname, state, buf, txt_buf) + return ok, err +end + + +-- operational functions +-- _op_v001 corresponds to the version 1 of ga graphic assembler specification. +-- The table indexes every opcode to a function that takes these arguments and +-- return the updated program counter pointed to the next operation: +-- fn: format specific driver library +-- st: state +-- pc: program counter +-- ga: read only ga stream +-- bf: the output buffer +-- xt: the output text object buffer +Driver._opcode_v001 = { + [1] = function (drv, st, pc, ga, bf, xt) -- 1 ; set line width + local w = ga[pc] + st.line_width = w + if not drv.append_001 then + error("[InternalErr] unimplemented opcode 1 for "..drv._NAME) + end + drv.append_001(st, bf, xt, w) + return pc + 1 + end, + [2] = function (drv, st, pc, ga, bf, xt) -- 2 ; set line cap style + local style = ga[pc] + st.line_cap = style + if not drv.append_002 then + error("[InternalErr] unimplemented opcode 2 for "..drv._NAME) + end + drv.append_002(st, bf, xt, style) + return pc + 1 + end, + [3] = function (drv, st, pc, ga, bf, xt) -- 3 ; set line join style + local join = ga[pc] + if not drv.append_003 then + error("[InternalErr] unimplemented opcode 3 for "..drv._NAME) + end + drv.append_003(st, bf, xt, join) + return pc + 1 + end, + [30] = function (drv, st, pc, ga, bf, xt) -- start_bbox_group + assert(st.bb_on) + st.bb_on = false + return pc + end, + [31] = function (drv, st, pc, ga, bf, xt) -- end_bbox_group + assert(st.bb_on == false) + st.bb_on = true + local x1 = ga[pc]; pc = pc + 1 + local y1 = ga[pc]; pc = pc + 1 + local x2 = ga[pc]; pc = pc + 1 + local y2 = ga[pc]; pc = pc + 1 + if st.bb_x1 == nil then + st.bb_x1 = x1 + st.bb_y1 = y1 + st.bb_x2 = x2 + st.bb_y2 = y2 + else + if x1 < st.bb_x1 then st.bb_x1 = x1 end + if x2 > st.bb_x2 then st.bb_x2 = x2 end + if y1 < st.bb_y1 then st.bb_y1 = y1 end + if y2 > st.bb_y2 then st.bb_y2 = y2 end + end + return pc + end, + -- draw an horizontal line + -- 33 + [33] = function (drv, st, pc, ga, bf, xt) + local x1 = ga[pc]; pc = pc + 1 + local x2 = ga[pc]; pc = pc + 1 + local y = ga[pc]; pc = pc + 1 + if st.bb_on then -- eventually update bbox + local hw = st.line_width/2 + local by1 = y - hw + local by2 = y + hw + if st.bb_x1 == nil then + st.bb_x1 = x1 + st.bb_x2 = x2 + st.bb_y1 = by1 + st.bb_y2 = by2 + else + if x1 < st.bb_x1 then st.bb_x1 = x1 end + if x2 > st.bb_x2 then st.bb_x2 = x2 end + if by1 < st.bb_y1 then st.bb_y1 = by1 end + if by2 > st.bb_y2 then st.bb_y2 = by2 end + end + end + if not drv.append_033 then + error("[InternalErr] unimplemented opcode 33 for "..drv._NAME) + end + drv.append_033(st, bf, xt, x1, x2, y) + return pc + end, + -- draw a vertical line + [34] = function (drv, st, pc, ga, bf, xt) -- 34 + local y1 = ga[pc]; pc = pc + 1 + local y2 = ga[pc]; pc = pc + 1 + local x = ga[pc]; pc = pc + 1 + if st.bb_on then -- eventually update the figure bounding box + local hw = st.line_width/2 + local bx1 = x - hw + local bx2 = x + hw + if st.bb_x1 == nil then + st.bb_x1 = bx1 + st.bb_x2 = bx2 + st.bb_y1 = y1 + st.bb_y2 = y2 + else + if bx1 < st.bb_x1 then st.bb_x1 = bx1 end + if bx2 > st.bb_x2 then st.bb_x2 = bx2 end + if y1 < st.bb_y1 then st.bb_y1 = y1 end + if y2 > st.bb_y2 then st.bb_y2 = y2 end + end + end + if not drv.append_034 then + error("[InternalErr] unimplemented opcode 34 for "..drv._NAME) + end + drv.append_034(st, bf, xt, y1, y2, x) + return pc + end, + -- draw a group of vertical lines (vbar) + -- 36 + [36] = function(drv, st, pc, ga, bf, xt) -- vbar + local y1 = ga[pc]; pc = pc + 1 + local y2 = ga[pc]; pc = pc + 1 + local nbar = ga[pc]; pc = pc + 1 + assert(nbar > 0) + local h = y2 - y1 -- height common to every rectangle + assert(h > 0) + local pc_next = pc + 2 * nbar + if drv.append_036_start then + drv.append_036_start(st, bf, xt, nbar, y1, y2) + end + local bx1, bx2 + for i = pc, pc_next - 1, 2 do -- reading coordinates + local x = assert(ga[i], "[InternalErr] ga prematurely reached the end") + local w = assert(ga[i+1], "[InternalErr] ga prematurely reached the end") + drv.append_036_bar(st, bf, xt, x, w, y1, y2) + -- check the bounding box only if the corresponding flag is true + local x1 = x - w/2 + local x2 = x + w/2 + if st.bb_on then + if bx1 == nil then + bx1 = x1 + bx2 = x2 + else + if x1 < bx1 then bx1 = x1 end + if x2 > bx2 then bx2 = x2 end + end + end + end + if drv.append_036_stop then + drv.append_036_stop(st, bf, xt, nbar, y1, y2) + end + if st.bb_on then -- eventually update bbox + if st.bb_x1 == nil then + st.bb_x1 = bx1 + st.bb_x2 = bx2 + st.bb_y1 = y1 + st.bb_y2 = y2 + else + if bx1 < st.bb_x1 then st.bb_x1 = bx1 end + if bx2 > st.bb_x2 then st.bb_x2 = bx2 end + if y1 < st.bb_y1 then st.bb_y1 = y1 end + if y2 > st.bb_y2 then st.bb_y2 = y2 end + end + end + return pc_next + end, + -- draw a rectangle + -- 48 + [48] = function(drv, st, pc, ga, bf, xt) + local x1 = ga[pc]; pc = pc + 1 + local y1 = ga[pc]; pc = pc + 1 + local x2 = ga[pc]; pc = pc + 1 + local y2 = ga[pc]; pc = pc + 1 + -- check the bounding box only if the flag is true + if st.bb_on then + local hw = st.line_width/2 + local bx1, bx2 = x1 - hw, x2 + hw + local by1, by2 = y1 - hw, y2 + hw + if st.bb_x1 == nil then + st.bb_x1 = bx1 + st.bb_x2 = bx2 + st.bb_y1 = by1 + st.bb_y2 = by2 + else + if bx1 < st.bb_x1 then st.bb_x1 = bx1 end + if bx2 > st.bb_x2 then st.bb_x2 = bx2 end + if by1 < st.bb_y1 then st.bb_y1 = by1 end + if by2 > st.bb_y2 then st.bb_y2 = by2 end + end + end + if not drv.append_048 then + error("[InternalErr] unimplemented opcode 48 for "..drv._NAME) + end + drv.append_048(st, bf, xt, x1, y1, x2, y2) + return pc + end, + -- text + [130] = function(drv, st, pc, ga, bf, xt) -- text: ax ay xpos ypos string + local ax = ga[pc]; pc = pc + 1 + local ay = ga[pc]; pc = pc + 1 + local xpos = ga[pc]; pc = pc + 1 + local ypos = ga[pc]; pc = pc + 1 + assert(ga[pc] ~= 0, "[InternalErr] empty chars sequence") + while ga[pc] ~= 0 do + local c = ga[pc]; pc = pc + 1 + drv.append_130_char(st, bf, xt, c) + end + local x1, y1, x2, y2 = drv.append_130_stop(st, bf, xt, xpos, ypos, ax, ay) + -- bounding box checking + if st.bb_on then + if st.bb_x1 == nil then + st.bb_x1 = x1 + st.bb_x2 = x2 + st.bb_y1 = y1 + st.bb_y2 = y2 + else + if x1 < st.bb_x1 then st.bb_x1 = x1 end + if x2 > st.bb_x2 then st.bb_x2 = x2 end + if y1 < st.bb_y1 then st.bb_y1 = y1 end + if y2 > st.bb_y2 then st.bb_y2 = y2 end + end + end + return pc + 1 + end, + [131] = function(drv, st, pc, ga, bf, xt) -- text_xspaced x1 xgap ay ypos chars + local x1 = ga[pc]; pc = pc + 1 + local xgap = ga[pc]; pc = pc + 1 + local ay = ga[pc]; pc = pc + 1 + local ypos = ga[pc]; pc = pc + 1 + assert(ga[pc] ~= 0, "[InternalErr] empty chars sequence") + while ga[pc] ~= 0 do + local c = ga[pc]; pc = pc + 1 + drv.append_131_char(st, bf, xt, c, xgap) + end + local bx1, by1, bx2, by2 = drv.append_131_stop(st, bf, xt, x1, xgap, ypos, ay) + -- bounding box checking + if st.bb_on then -- eventually update bbox + if st.bb_x1 == nil then + st.bb_x1 = bx1 + st.bb_x2 = bx2 + st.bb_y1 = by1 -- no depth + st.bb_y2 = by2 + else + if bx1 < st.bb_x1 then st.bb_x1 = bx1 end + if bx2 > st.bb_x2 then st.bb_x2 = bx2 end + if by1 < st.bb_y1 then st.bb_y1 = by1 end + if by2 > st.bb_y2 then st.bb_y2 = by2 end + end + end + return pc + 1 + end, + -- text_xwidth + -- + [132] = function (drv, st, pc, ga, bf, xt) + local ay = ga[pc]; pc = pc + 1 -- y anchor + local x1 = ga[pc]; pc = pc + 1 -- left limit + local x2 = ga[pc]; pc = pc + 1 -- right limit + assert (x1 ~= x2, "[InternalErr] x coordinate are equal") + assert (x1 < x2, "[InternalErr] not ordered x1, x2 limits") + local ypos = ga[pc]; pc = pc + 1 -- y coordinate of anchor point + assert(ga[pc] ~= 0, "[InternalErr] empty chars sequence") + while ga[pc] ~= 0 do + local c = ga[pc]; pc = pc + 1 + drv.append_132_char(st, bf, xt, c) + end + local bx1, by1, bx2, by2 = drv.append_132_stop(st, bf, xt, x1, x2, ypos, ay) + -- bounding box checking + if st.bb_on then -- eventually update bbox + if st.bb_x1 == nil then + st.bb_x1 = bx1 + st.bb_x2 = bx2 + st.bb_y1 = by1 -- no depth + st.bb_y2 = by2 + else + if bx1 < st.bb_x1 then st.bb_x1 = bx1 end + if bx2 > st.bb_x2 then st.bb_x2 = bx2 end + if by1 < st.bb_y1 then st.bb_y1 = by1 end + if by2 > st.bb_y2 then st.bb_y2 = by2 end + end + end + return pc + 1 + end, +} + +return Driver + diff --git a/macros/luatex/generic/barracuda/src/lib-driver/brcd-drv-pdfliteral.lua b/macros/luatex/generic/barracuda/src/lib-driver/brcd-drv-pdfliteral.lua new file mode 100644 index 0000000000..50baea1472 --- /dev/null +++ b/macros/luatex/generic/barracuda/src/lib-driver/brcd-drv-pdfliteral.lua @@ -0,0 +1,284 @@ +-- +-- ga graphic assembler or +-- Intermediate Graphic Language for barcode drawing +-- Copyright (C) 2019 Roberto Giacomelli +-- +-- All dimensions are in scaled point (sp) +-- ga LuaTeX Driver (native implementation node+pdfliteral) + +-- class for drawing elementary geometric elements +local PDFnative = { + _VERSION = "PDFnative v0.0.4", + _NAME = "PDFnative", + _DESCRIPTION = "A LuaTeX native pdfliteral driver for ga graphic stream", +} + +PDFnative.ext = "txt" -- file extension +PDFnative.buf_sep = "\n" -- separation string for buffer concat + +function PDFnative.init_buffer(st) --> buffer, text buffer + st.head = nil -- addition for text processing (to remember purpose) + st.last = nil + st.hbox = nil + st.cw = nil + st.x_hbox = nil + st.char_counter = nil + local bf = {"q"} -- create a new graphic stack + local xt = {} -- text buffer + return bf, xt +end + +function PDFnative.close_buffer(st, bf, xt) + bf[#bf + 1] = "Q" -- stack restoring +end + +-- text utility special functions + +local function newglue(w) --> node + local n = node.new("glue") + n.width = w + return n +end + +local function newglyph(c) --> node -- ? U+2423 ␣ for whitespace? + if c == 32 then + return newglue(tex.sp "3.5pt") + end + local n = node.new("glyph") + n.char = c + n.font = font.current() + return n +end + +local function newpdfliteral(buf) --> node + local npdf = node.new("whatsit", "pdf_literal") + npdf.mode = 0 + npdf.data = table.concat(buf, "\n") + return npdf +end + +local function append_glyph(head, last, c) --> head, last, xdim + if c == 32 then -- space + local space = tex.sp "3.5pt" + head, last = node.insert_after(head, last, newglue(space)) + return head, last, space + else + local g = newglyph(c) + local xdim = g.width + head, last = node.insert_after(head, last, g) + return head, last, xdim + end +end + +-- special drawing function +function PDFnative.hboxcreate(hboxname, st, buf, txt) --> ok, err + local node = assert(node, "This is not LuaTeX!") + local tex = assert(tex) + local font = assert(font) + if not tex.isbox(hboxname) then + return nil, string.format("Box register [%s] doesn’t exist", hboxname) + end + local bb_x1, bb_y1, bb_x2, bb_y2 = st.bb_x1, st.bb_y1, st.bb_x2, st.bb_y2 + local npdf = newpdfliteral(buf) -- node whatsit pdfliteral + -- vboxing, vertical correction + local vpdf = node.vpack(npdf) + vpdf.height = -bb_y1 + -- glue, for horizontal correction + local ng = newglue(-bb_x1) + local head, last = node.insert_after(ng, ng, vpdf) + local xprev = 0.0 + for _, t in ipairs(txt) do -- text processing + local gy = newglue(t[3] - bb_y1) -- n, x, y, w, h -- t[3] -t[5] - bb_y1 + local nvtxt = node.insert_after(t[1], t[1], gy) + local vtxt = node.vpack(nvtxt) + local gx = newglue(t[2]-xprev) + head, last = node.insert_after(head, last, gx) + head, last = node.insert_after(head, last, vtxt) + xprev = t[2] + t[4] + end + -- hboxing + local hbox = node.hpack(head) + hbox.width = bb_x2 - bb_x1 + hbox.height = bb_y2 - bb_y1 + tex.box[hboxname] = hbox + return true, nil +end + +-- PDF literal encoding functions + +-- 1 ; set line width +function PDFnative.append_001(st, bf, xt, w) + local bp = st.bp -- 1bp (sp) + bf[#bf + 1] = string.format("%0.6f w", w/bp) +end + +-- 2 ; set line cap style +function PDFnative.append_002(st, bf, xt, cap) + bf[#bf + 1] = string.format("%d J", cap) +end + +-- 3 ; set line join style +function PDFnative.append_003(st, bf, xt, j) + bf[#bf + 1] = string.format("%d j", j) +end + +-- draw an horizontal line +-- 33 +function PDFnative.append_033(st, bf, xt, x1, x2, y) + local bp = st.bp -- conversion factor bp -> sp + bf[#bf + 1] = string.format("% 0.6f %0.6f m", x1/bp, y/bp) + bf[#bf + 1] = string.format("% 0.6f %0.6f l", x2/bp, y/bp) + bf[#bf + 1] = "S" -- stroke +end + +-- vline +-- draw a vertical line +-- 34 +function PDFnative.append_034(st, bf, xt, y1, y2, x) + local bp = st.bp -- conversion factor bp -> sp + bf[#bf + 1] = string.format("% 0.6f %0.6f m", x/bp, y1/bp) + bf[#bf + 1] = string.format("% 0.6f %0.6f l", x/bp, y2/bp) + bf[#bf + 1] = "S" -- stroke +end + +-- Vbar +-- draw a group of vertical lines +-- 36 ... +function PDFnative.append_036_bar(st, bf, xt, x, w, y1, y2) + local bp = st.bp -- conversion factor bp -> sp + local fmt = "%0.6f %0.6f %0.6f %0.6f re" + local x1 = x - w/2 + local h = y2 - y1 + -- pdf literal insertion + bf[#bf + 1] = string.format(fmt, x1/bp, y1/bp, w/bp, h/bp) +end +function PDFnative.append_036_stop(st, bf, xt, nbar, y1, y2) + bf[#bf + 1] = "f" -- fill + bf[#bf + 1] = "S" -- stroke +end + +-- draw a rectangle +-- 48 +function PDFnative.append_048(st, bf, xt, x1, y1, x2, y2) + local w = x2 - x1 -- rectangle width + assert(w > 0) + local h = y2 - y1 -- rectangle height + assert(h > 0) + local bp = st.bp -- conversion factor + local fmt = "%0.6f %0.6f %0.6f %0.6f re S" + -- pdf literal string + bf[#bf + 1] = string.format(fmt, x1/bp, y1/bp, w/bp, h/bp) +end + +-- 130 Text with several glyphs +-- 130 +function PDFnative.append_130_char(st, bf, xt, c) + local head, last = st.head, st.last + head, last = append_glyph(head, last, c) + st.head = head + st.last = last +end +-- return bounding box of the text object without deep +function PDFnative.append_130_stop(st, bf, xt, xpos, ypos, ax, ay) + local head = assert(st.head) + st.head = nil -- reset temporary reference + st.last = nil + local hbox = node.hpack(head) + local w, h, d = node.dimensions(hbox) + local x1 = xpos - ax*w -- text position + local y1; if ay > 0 then + y1 = ypos - h*ay + else + y1 = ypos - d*ay + end + xt[#xt + 1] = {hbox, x1, y1 - d, w, h} + return x1, y1, x1 + w, y1 + h +end + +-- 131 , Text with glyphs equally spaced on its vertical axis +-- 131 +function PDFnative.append_131_char(st, bf, xt, c, xgap) + local head, last, prec_cw = st.head, st.last, st.cw + local cw + if prec_cw then + local g = newglyph(c) + cw = g.width + local isp = xgap - (cw + prec_cw)/2 + local s = newglue(isp) + head, last = node.insert_after(head, last, s) + head, last = node.insert_after(head, last, g) + else -- first char + head, last, cw = append_glyph(head, last, c) + st.x_hbox = cw/2 + end + st.cw = cw + st.head = head + st.last = last +end +function PDFnative.append_131_stop(st, bf, xt, x1, xgap, ypos, ay) --> bb + local head = assert(st.head) + st.head = nil -- reset temporary reference + st.last = nil + st.cw = nil + local hbox = node.hpack(head) + local w, h, d = node.dimensions(hbox) + local bx1 = x1 - st.x_hbox + st.x_hbox = nil -- reset temporary references + local y1; if ay > 0 then + y1 = ypos - h*ay + else + y1 = ypos - d*ay + end + xt[#xt + 1] = {hbox, bx1, y1 - d, w, h} + return bx1, y1, bx1 + w, y1 + h +end + +-- 132 Glyphs equally spaced on vertical axis between two x coordinates +-- 132 +function PDFnative.append_132_char(st, bf, xt, c) + local head, last = st.head, st.last + if head then + local g = newglyph(c) + local s = newglue(1) + head, last = node.insert_after(head, last, s) + head, last = node.insert_after(head, last, g) + st.char_counter = st.char_counter + 1 + else -- first char + head, last, cw = append_glyph(head, last, c) + st.cw = cw + st.char_counter = 1 + end + st.head = head + st.last = last +end +function PDFnative.append_132_stop(st, bf, xt, x1, x2, ypos, ay) --> p1, p2 + local head, last = st.head, st.last + st.head = nil -- reset temporary registry + st.last = nil + local w_1 = st.cw + st.cw = nil + local i = st.char_counter + st.char_counter = nil + local w_n = last.width + local xgap = (x2 - x1 - (w_1 + w_n)/2)/(i - 1) + local c_curr = head + for _ = 1, i - 1 do + local g = c_curr.next + local c_next = g.next + local w_2 + w_1, w_2 = c_curr.width, c_next.width + g.width = xgap - (w_1 + w_2)/2 + c_curr = c_next + end + local hbox = node.hpack(head) + local w, h, d = node.dimensions(hbox) + local y; if ay > 0 then + y = ypos - h*ay + else + y = ypos - d*ay + end + xt[#xt + 1] = {hbox, x1, y - d, w, h} + return x1, y, x2, y + h +end + +return PDFnative diff --git a/macros/luatex/generic/barracuda/src/lib-driver/brcd-drv-svg.lua b/macros/luatex/generic/barracuda/src/lib-driver/brcd-drv-svg.lua new file mode 100644 index 0000000000..7a2c5ab112 --- /dev/null +++ b/macros/luatex/generic/barracuda/src/lib-driver/brcd-drv-svg.lua @@ -0,0 +1,260 @@ +-- +-- ga Intermediate Graphic Language for barcode drawing +-- SVG library +-- Copyright (C) 2019 Roberto Giacomelli +-- +-- All dimension in the ga stream are scaled point (sp) +-- 1 pt = 65536 sp + +-- class for drawing elementary geometric elements +local SVG = { + _VERSION = "SVGdriver v0.0.1", + _NAME = "SVGdriver", + _DESCRIPTION = "A SVG driver for the ga graphic stream", +} + +SVG.ext = "svg" -- file extension +SVG.buf_sep = nil -- separation string for buffer concat + +function SVG.init_buffer(st) --> buffer, text buffer + local bf = { + '\n', + '\n', + '\n', + '\n', + } + -- additions for SVG driver to 'state' + st.ident_lvl = 1 -- identation level + st.char_buf = nil + local mm = st.mm + st.h_char = 2.1 * mm -- char height (mm) + st.w_char = st.h_char / 1.303 -- avg char width (mm) + st.d_char = st.h_char / 3.7 -- char deep (mm) + return bf, {} +end + +function SVG.close_buffer(st, bf, xt) + bf[#bf + 1] = '\n' -- close svg xml element + bf[#bf + 1] = '\n' -- a last empty line + local mm = st.mm + local x1, y1, x2, y2 = st.bb_x1, st.bb_y1, st.bb_x2, st.bb_y2 + local w = (x2 - x1)/mm + local h = (y2 - y1)/mm + local fmt_wh = bf[7] + bf[7] = string.format(fmt_wh, w, h) -- line 7 + local x, y = x1/mm, -y2/mm + local fmt_vw = bf[8] + bf[8] = string.format(fmt_vw, x, y, w, h) +end + +-- SVG encoding functions + +-- 1 ; set line width +function SVG.append_001(st, bf, xt, w) + -- nothing to do +end + +-- draw an horizontal line +-- 33 +function SVG.append_033(st, bf, xt, x1, x2, y) + local lvl = st.ident_lvl + local ident = string.rep(" ", lvl) -- a couple of spaces as indentation + local mm = st.mm -- conversion ratio sp -> bp + bf[#bf + 1] = string.format( -- element + '%s\n' +end + +-- Vertical line: 34 +function SVG.append_034(st, bf, xt, y1, y2, x) + local lvl = st.ident_lvl + local ident = string.rep(" ", lvl) -- a couple of spaces as indentation + local mm = st.mm -- conversion ratio sp -> mm + bf[#bf + 1] = string.format( -- element + '%s\n' +end + +-- Vbar +-- draw a group of vertical lines +-- 36 ... +function SVG.append_036_start(st, bf, xt, nbar, y1, y2) + local lvl = st.ident_lvl + local ident = string.rep(" ", lvl) + bf[#bf + 1] = ident..'\n' -- open a group + st.ident_lvl = lvl + 1 +end +function SVG.append_036_bar(st, bf, xt, x, w, y1, y2) + local lvl = st.ident_lvl + local ident = string.rep(" ", lvl) + local mm = st.mm -- conversion factor mm -> sp + bf[#bf + 1] = string.format( + '%s\n', + ident, x/mm, -y2/mm, -y1/mm, w/mm + ) +end +function SVG.append_036_stop(st, bf, xt, nbar, y1, y2) + st.ident_lvl = st.ident_lvl - 1 + local ident = string.rep(" ", st.ident_lvl) + bf[#bf + 1] = ident..'\n' -- end group +end + +-- Text +-- 130 Text with several glyphs +-- 130 +function SVG.append_130_char(st, bf, xt, c) + local ch = string.char(c) + if not st.char_buf then + st.char_buf = {ch} + else + local chars = st.char_buf + chars[#chars + 1] = ch + end +end +function SVG.append_130_stop(st, bf, xt, xpos, ypos, ax, ay) --> p1, p2 + local c = st.char_buf + st.char_buf = nil + local txt = table.concat(c) + local w = st.w_char * #c -- approx dim + local h = st.h_char + local d = st.d_char + local anchor = "" + local x1 = xpos + local bx1 = xpos + if ax == 0 then -- start (default) + elseif ax == 0.5 then -- middle + anchor = ' text-anchor="middle"' + bx1 = bx1 - w/2 + elseif ax == 1 then -- end + anchor = ' text-anchor="end"' + bx1 = bx1 - w + else + x1 = x1 - ax*w + bx1 = x1 + end + local y1 = ypos + if ay > 0 then + y1 = y1 - h*ay + else + y1 = y1 - d*ay + end + local fs = st.h_char * 1.37 -- sp + local lvl = st.ident_lvl + local ident = string.rep(" ", lvl) + local mm = st.mm + bf[#bf + 1] = string.format( + '%s\n', + ident, x1/mm, -y1/mm, fs/mm, anchor + ) + bf[#bf + 1] = ident..txt + bf[#bf + 1] = ident..'\n' + return bx1, y1, bx1 + w, y1 + h +end + +-- 131 , Text with glyphs equally spaced on its vertical axis +-- 131 +function SVG.append_131_char(st, bf, xt, c, xgap) + local ch = string.char(c) + if not st.char_buf then + st.char_buf = {ch} + else + local chars = st.char_buf + chars[#chars + 1] = ch + end +end +function SVG.append_131_stop(st, bf, xt, x1, xgap, ypos, ay) --> p1, p2 + local chars = st.char_buf + st.char_buf = nil + local n = #chars + local h = st.h_char -- height + local d = st.d_char -- deep + local hw = st.w_char/2 -- sp half width + local y1 = ypos + if ay > 0 then + y1 = y1 - h*ay + else + y1 = y1 - d*ay + end + local lvl = st.ident_lvl + local ident = string.rep(" ", lvl) + local fs = st.h_char * 1.37 -- (sp) font-size -> inter baselines distance + local mm = st.mm + bf[#bf + 1] = string.format( + '%s\n', + ident, -y1/mm, fs/mm + ) + local x = x1 + for _, c in ipairs(chars) do + bf[#bf + 1] = string.format('%s%s\n', + ident, x/mm, c + ) + x = x + xgap + end + bf[#bf + 1] = ident..'\n' + local x2 = x1 + (n - 1)*xgap -- sp + return x1 - hw, y1, x2 + hw, y1 + h -- text group bounding box +end + +-- 132 Glyphs equally spaced on vertical axis between two x coordinates +-- 132 +function SVG.append_132_char(st, bf, xt, c, xgap) + local ch = string.char(c) + if not st.char_buf then + st.char_buf = {ch} + else + local chars = st.char_buf + chars[#chars + 1] = ch + end +end +function SVG.append_132_stop(st, bf, xt, x1, x2, ypos, ay) --> p1, p2 + local chars = st.char_buf; st.char_buf = nil + local n = #chars + local h = st.h_char -- height (approx) + local d = st.d_char -- deep (approx) + local cw = st.w_char -- (sp) char width (approx) + local xgap = (x2 - x1 - cw)/(n - 1) + local y1 = ypos + if ay > 0 then + y1 = y1 - h*ay + else + y1 = y1 - d*ay + end + local lvl = st.ident_lvl + local ident = string.rep(" ", lvl) + local fs = st.h_char * 1.37 -- font-size -> inter baselines distance + local mm = st.mm + bf[#bf + 1] = string.format( + '%s\n', + ident, -y1/mm, fs/mm + ) + local x = x1 + cw/2 + for _, c in ipairs(chars) do + bf[#bf + 1] = string.format('%s%s\n', + ident, x/mm, c + ) + x = x + xgap + end + bf[#bf + 1] = ident..'\n' + return x1, y1, x2, y1 + h -- text group bounding box +end + +return SVG diff --git a/macros/luatex/generic/barracuda/src/lib-geo/brcd-gacanvas.lua b/macros/luatex/generic/barracuda/src/lib-geo/brcd-gacanvas.lua new file mode 100644 index 0000000000..cccc68f447 --- /dev/null +++ b/macros/luatex/generic/barracuda/src/lib-geo/brcd-gacanvas.lua @@ -0,0 +1,340 @@ +-- class gaCanvas +-- Copyright (C) 2019 Roberto Giacomelli + +-- ga -- basic function + +local gaCanvas = { + _VERSION = "gacanvas v0.0.4", + _NAME = "gaCanvas", + _DESCRIPTION = "A library for dealing with ga stream", +} +gaCanvas.__index = gaCanvas + +-- ga specification: see the file ga-grammar.pdf in the doc directory + +-- gaCanvas constructor +function gaCanvas:new() --> object + local o = { + _data = {}, + _v = 100, -- version of the ga format + } + setmetatable(o, self) + return o +end + +-- Ipothetical another constructor +-- function gaCanvas:from_tcp_server() --> err +-- end + +-- line width: opcode <1> +function gaCanvas:encode_linethick(w) --> err + if type(w) ~= "number" then return "[ArgErr] 'w' number expected" end + if w < 0 then return "[ArgErr] negative value for 'w'" end + local data = self._data + data[#data + 1] = 1 -- opcode for line thickness + data[#data + 1] = w +end + +-- line cap style: opcode <2> +-- 0 Butt cap +-- 1 Round cap +-- 2 Projecting square cap +function gaCanvas:encode_linecap(cap) --> err + if type(cap) ~= "number" then return "[ArgErr] 'cap' arg number expected" end + if cap == 0 or cap == 1 or cap == 2 then + local data = self._data + data[#data + 1] = 2 -- opcode for line cap style + data[#data + 1] = cap + else + return "[ArgErr] invalid value for 'cap'" + end +end + +-- line cap style: opcode <3> +-- 0 Miter join +-- 1 Round join +-- 2 Bevel join +function gaCanvas:encode_linejoin(join) --> err + if type(join) ~= "number" then return "[ArgErr] 'join' arg number expected" end + if join == 0 or join == 1 or join == 2 then + local data = self._data + data[#data + 1] = 3 -- opcode for line join style + data[#data + 1] = join + else + return "[ArgErr] invalid value for 'join'" + end +end + +-- Stop checking the bounding box +-- opcode: <30> +function gaCanvas:start_bbox_group() --> err + local data = self._data + data[#data + 1] = 30 +end + +-- restart checking the bounding box +-- and insert the specified bb for the entire object group +-- code: <31> x1 y1 x2 y2 +function gaCanvas:stop_bbox_group(x1, y1, x2, y2) --> err + if type(x1) ~= "number" then return "[ArgErr] 'x1' number expected" end + if type(y1) ~= "number" then return "[ArgErr] 'y1' number expected" end + if type(x2) ~= "number" then return "[ArgErr] 'x2' number expected" end + if type(y2) ~= "number" then return "[ArgErr] 'y2' number expected" end + if x1 > x2 then x1, x2 = x2, x1 end -- reorder coordinates + if y1 > y2 then y1, y2 = y2, y1 end + local data = self._data + data[#data + 1] = 31 -- bounding box of the object group + data[#data + 1] = x1 + data[#data + 1] = y1 + data[#data + 1] = x2 + data[#data + 1] = y2 +end + +-- insert a line from point (x1, y1) to the point (x2, y2) +-- <32> x1 y1 x2 y2 +function gaCanvas:encode_line(x1, y1, x2, y2) --> err + if type(x1) ~= "number" then return "[ArgErr] 'x1' number expected" end + if type(y1) ~= "number" then return "[ArgErr] 'y1' number expected" end + if type(x2) ~= "number" then return "[ArgErr] 'x2' number expected" end + if type(y2) ~= "number" then return "[ArgErr] 'y2' number expected" end + local data = self._data + data[#data + 1] = 32 -- append line data + data[#data + 1] = x1 + data[#data + 1] = y1 + data[#data + 1] = x2 + data[#data + 1] = y2 +end + +-- insert an horizontal line from point (x1, y) to point (x2, y) +-- <33> x1 x2 y +function gaCanvas:encode_hline(x1, x2, y) --> err + if type(x1) ~= "number" then return "[ArgErr] 'x1' number expected" end + if type(x2) ~= "number" then return "[ArgErr] 'x2' number expected" end + if type(y) ~= "number" then return "[ArgErr] 'y2' number expected" end + local data = self._data + data[#data + 1] = 33 -- append hline data + data[#data + 1] = x1 + data[#data + 1] = x2 + data[#data + 1] = y +end + +-- insert a rectangle from point (x1, x2) to (x2, y2) +-- <48> +function gaCanvas:encode_rectangle(x1, y1, x2, y2) --> err + if type(x1) ~= "number" then return "[ArgErr] 'x1' number expected" end + if type(y1) ~= "number" then return "[ArgErr] 'y1' number expected" end + if type(x2) ~= "number" then return "[ArgErr] 'x2' number expected" end + if type(y2) ~= "number" then return "[ArgErr] 'y2' number expected" end + local d = self._data + d[#d + 1] = 48 -- append rectangle data + d[#d + 1] = x1 + d[#d + 1] = y1 + d[#d + 1] = x2 + d[#d + 1] = y2 +end + +-- Vbar object: opcode <36> +-- x0, y1, y2 ordinates +function gaCanvas:encode_Vbar(vbar, x0, y1, y2) --> err + if type(vbar) ~= "table" then + return "[ArgErr] table expected for 'vbar'" + end + if x0 == nil then + x0 = 0 + elseif type(x0) ~= "number" then + return "[ArgErr] 'x0' number expected" + end + if type(y1) ~= "number" then return "[ArgErr] 'y1' number expected" end + if type(y2) ~= "number" then return "[ArgErr] 'y2' number expected" end + -- ordinates + if y1 == y2 then return "[ArgErr] 'y1' 'y2' are the same value" end + if y1 > y2 then y1, y2 = y2, y1 end + local bars = assert(vbar._yline, "[InternalErr] no '_yline' field") + local bdim = #bars + if bdim == 0 then return "[InternalErr] number of bars is zero" end + if bdim % 2 ~= 0 then + return "[InternalErr] '_yline' does not have an even number of elements" + end + local data = self._data + data[#data + 1] = 36 -- vbar sequence start + data[#data + 1] = y1 + data[#data + 1] = y2 + data[#data + 1] = bdim / 2 -- the number of bars + for i = 1, bdim, 2 do + local coord = bars[i] + local width = bars[i + 1] + if type(coord) ~= "number" then + return "[Err] a coordinates is not a number" + end + if type(width) ~= "number" then + return "[Err] a width is not a number" + end + data[#data + 1] = coord + x0 + data[#data + 1] = width + end +end + +-- [text] <130> ax ay x y chars +function gaCanvas:encode_Text(txt, xpos, ypos, ax, ay) --> err + if type(txt) ~= "table" then + return "[ArgErr] 'txt' object table expected" + end + if type(xpos) ~= "number" then + return "[ArgErr] 'xpos' number expected" + end + if type(ypos) ~= "number" then + return "[ArgErr] 'ypos' number expected" + end + if ax == nil then + ax = 0 + elseif type(ax) ~= "number" then + return "[ArgErr] 'ax' number expected" + end + if ay == nil then + ay = 0 + elseif type(ay) ~= "number" then + return "[ArgErr] 'ay' number expected" + end + local data = self._data + data[#data + 1] = 130 + data[#data + 1] = ax -- relative anchor x-coordinate + data[#data + 1] = ay -- relative anchor y-coordinate + data[#data + 1] = xpos -- text x-coordinate + data[#data + 1] = ypos -- text y-coordinate + local chars = assert(txt.codepoint, "[InternalErr] no 'codepoint' field in txt") + if #chars == 0 then return "[InternalErr] 'txt' has no chars" end + for _, c in ipairs(chars) do + data[#data + 1] = c + end + data[#data + 1] = 0 -- end string signal +end + +-- glyphs equally spaced along the baseline +-- [text_xspaced] <131> x1 xgap ay ypos chars +function gaCanvas:encode_Text_xspaced(txt, x1, xgap, ypos, ay) --> err + if type(txt)~= "table" then return "[ArgErr] 'txt' object table expected" end + local chars = assert(txt.codepoint, "[InternalErr] no 'codepoint' field in txt") + if #chars == 0 then return "[InternalErr] 'txt' has no chars" end + if type(x1) ~= "number" then return "[ArgErr] 'x1' number expected" end + if type(xgap) ~= "number" then return "[ArgErr] 'xgap' number expected" end + if xgap < 0 then + local n = #chars + x1 = x1 + (n - 1) * xgap + xgap = -xgap + end + if type(ypos) ~= "number" then return "[ArgErr] 'ypos' number expected" end + if ay == nil then + ay = 0 + elseif type(ay) ~= "number" then + return "[ArgErr] 'ay' number expected" + end + local data = self._data + data[#data + 1] = 131 + data[#data + 1] = x1 -- x-coordinate of the first axis from left to right + data[#data + 1] = xgap -- axial distance among gliphs + data[#data + 1] = ay -- anchor relative y-coordinate + data[#data + 1] = ypos -- text y-coordinate + for _, c in ipairs(chars) do + data[#data + 1] = c + end + data[#data + 1] = 0 -- end string signal +end + +-- text_xwidth +-- text equally spaced but within [x1, x2] coordinate interval +-- <132> +function gaCanvas:encode_Text_xwidth(txt, x1, x2, ypos, ay) --> err + if type(txt)~= "table" then return "[ArgErr] 'txt' object table expected" end + if type(x1) ~= "number" then return "[ArgErr] 'x1' number expected" end + if type(x2) ~= "number" then return "[ArgErr] 'x2' number expected" end + if type(ypos) ~= "number" then return "[ArgErr] 'ypos' number expected" end + if ay == nil then + ay = 0 + elseif type(ay) ~= "number" then + return "[ArgErr] 'ay' number expected" + end + local chars = assert(txt.codepoint, "[InternalErr] no 'codepoint' field in txt") + if #chars == 0 then return "[InternalErr] 'txt' has no chars" end + if x1 > x2 then x1, x2 = x2, x1 end -- reorder coordinates + local data = self._data + data[#data + 1] = 132 + data[#data + 1] = ay -- anchor relative y-coordinate + data[#data + 1] = x1 -- left limit of the text box + data[#data + 1] = x2 -- right limit of the text box + data[#data + 1] = ypos -- text y-coordinate + for _, c in ipairs(chars) do + data[#data + 1] = c + end + data[#data + 1] = 0 -- end string signal +end + +-- experimental code section +-- new opcodes under assessment + +-- [start_text_group] 140 +function gaCanvas:start_text_group() --> err + local data = self._data + data[#data + 1] = 140 +end + +-- [gtext] 141 +function gaCanvas:gtext(chars) --> err + if type(chars) ~= "table" then return "[ArgErr] 'chars' table expected" end + local data = self._data + data[#data + 1] = 141 + for _, c in ipairs(chars) do + data[#data + 1] = c + end + data[#data + 1] = 0 -- end string signal +end + +-- [gtext_spaced] 142 gap string +function gaCanvas:gtext_spaced(gap, chars) --> err + if type(gap) ~= "number" then return "[ArgErr] 'gap' number expected" end + if type(chars) ~= "table" then return "[ArgErr] 'chars' table expected" end + local data = self._data + data[#data + 1] = 142 + data[#data + 1] = gap + for _, c in ipairs(chars) do + data[#data + 1] = c + end + data[#data + 1] = 0 -- end string signal +end + +-- [gtext_space] 143 gap +function gaCanvas:gtext_gap(gap) --> err + if type(gap) ~= "number" then return "[ArgErr] 'gap' number expected" end + local data = self._data + data[#data + 1] = 143 + data[#data + 1] = gap +end + + +-- [end_text_group] 149 ax ay x y +function gaCanvas:end_text_group(xpos, ypos, ax, ay) --> err + if type(xpos) ~= "number" then return "[ArgErr] 'xpos' number expected" end + if type(ypos) ~= "number" then return "[ArgErr] 'ypos' number expected" end + if type(ax) ~= "number" then return "[ArgErr] 'ax' number expected" end + if type(ay) ~= "number" then return "[ArgErr] 'ay' number expected" end + local data = self._data + data[#data + 1] = 149 + data[#data + 1] = ax -- anchor relative x-coordinate + data[#data + 1] = ay -- anchor relative y-coordinate + data[#data + 1] = xpos -- text x-coordinate + data[#data + 1] = ypos -- text y-coordinate +end + +-- amazing... +function gaCanvas:to_string() --> string + +end + +function gaCanvas:get_bbox() + +end + +function gaCanvas:check() --> boolean, err + +end + +return gaCanvas diff --git a/macros/luatex/generic/barracuda/src/lib-geo/brcd-libgeo.lua b/macros/luatex/generic/barracuda/src/lib-geo/brcd-libgeo.lua new file mode 100644 index 0000000000..fd53ca6509 --- /dev/null +++ b/macros/luatex/generic/barracuda/src/lib-geo/brcd-libgeo.lua @@ -0,0 +1,289 @@ + +-- libgeo simple Geometric Library +-- Copyright (C) 2018 Roberto Giacomelli + +-- All dimension must be in scaled point (sp) + +local libgeo = { + _VERSION = "libgeo v0.0.3", + _NAME = "libgeo", + _DESCRIPTION = "simple geometric library", +} + +-- VBar class +-- a pure geometric entity of several infinite vertical lines +libgeo.Vbar = {} +local Vbar = libgeo.Vbar +Vbar.__index = Vbar + +-- Vbar costructors + +-- VBar costructor from an array [xcenter1, width1, xcenter2, width2, ...] +function Vbar:from_array(yl_arr) --> + assert(type(yl_arr) == "table", "'yline_array' is a mandatory arg") + -- stream scanning + local i = 1 + local xlim = 0.0 + while yl_arr[i] do + local x = yl_arr[i]; i = i + 1 + local w = yl_arr[i]; i = i + 1 + assert(type(x) == "number", "[InternalErr] not a number") + assert(type(w) == "number", "[InternalErr] not a number") + xlim = x + w/2 + end + assert(i % 2 == 0, "[InternalErr] the index is not even") + assert(i > 0, "[InternalErr] empty array") + local o = { + _yline = yl_arr, -- [, , ...] flat array + _x_lim = xlim, -- right external bounding box coordinates + } + setmetatable(o, self) + return o +end + +-- costructor useful for Code128 encoder +-- from an integer: 21231 -> binary 11 0 11 000 1 -> symbol 110110001 +-- is_bar :: boolean :: bar or space as first element, default true +function Vbar:from_int(ngen, mod, is_bar) --> + assert(type(ngen) == "number", "Invalid argument for n") + assert(type(mod) == "number", "Invalid argument for module width") + if is_bar == nil then is_bar = true else + assert(type(is_bar) == "boolean", "Invalid argument for is_bar") + end + -- scan ngen for digits + local digits = {} + while ngen > 0 do + local d = ngen % 10 + digits[#digits + 1] = d + ngen = (ngen - d)/10 + end + local x0 = 0.0 -- axis reference + local yl = {} + for k = #digits, 1, -1 do + local d = digits[k] + local w = d*mod -- bar width + if is_bar then -- bar + yl[#yl + 1] = x0 + w/2 + yl[#yl + 1] = w + end + x0 = x0 + w + is_bar = not is_bar + end + local o = { + _yline = yl, -- [, , ...] flat array + _x_lim = x0, -- right external coordinate + } + setmetatable(o, self) + return o +end + +-- from an integer to read from right to left +-- 13212 ->rev 21231 ->binary 11 0 11 000 1 -> symbol 110110001 +-- is_bar :: boolean :: bar or space for first, default true +function Vbar:from_int_revstep(ngen, mod, is_bar) --> + assert(type(ngen) == "number", "Invalid argument for n") + assert(type(mod) == "number", "Invalid argument for module width") + if is_bar == nil then is_bar = true else + assert(type(is_bar) == "boolean", "Invalid argument for is_bar") + end + -- + local x0 = 0.0 -- axis reference + local i = 0 + local yl = {} + while ngen > 0 do + local d = ngen % 10 -- first digit + local w = d*mod -- bar width + if is_bar then -- bar + i = i + 1; yl[i] = x0 + w/2 + i = i + 1; yl[i] = w + end + x0 = x0 + w + is_bar = not is_bar + ngen = (ngen - d)/10 + end + assert(not is_bar, "[InternalErr] the last element in not a bar") + local o = { + _yline = yl, -- [, , ...] flat array + _x_lim = x0, -- right external coordinate + } + setmetatable(o, self) + return o +end + +-- costructor useful for Code39 encoder +-- i.e. 11212 -> rev -> 2 1 2 1 1 -> decodes to -> B w B w b +-- build a yline array from the integer definition. Digit decoding rule: +-- mod: b or w => 1 -- narrow bar/space +-- MOD: B or W => 2 -- wide bar/space +-- is_bar: the first element is a bar not a space, default to true +function Vbar:from_int_revpair(ngen, mod, MOD, is_bar) --> + assert(type(ngen) == "number", "Invalid argument for n") + assert(type(mod) == "number", "Invalid argument for narrow module width") + assert(type(MOD) == "number", "Invalid argument for wide module width") + assert(mod < MOD, "Not ordered narrow/Wide values") + if is_bar == nil then + is_bar = true + else + assert(type(is_bar) == "boolean", "Invalid argument for 'is_bar'") + end + local yl = {} + local x0 = 0.0 + local k = 0 + while ngen > 0 do + local d = ngen % 10 -- digit + ngen = (ngen - d)/10 + local w; if d == 1 then + w = mod + elseif d == 2 then + w = MOD + end; assert(w, "[InternalErr] Allowed digits are only 1 or 2") + if is_bar then -- bars + k = k + 1; yl[k] = x0 + w/2 -- xcenter + k = k + 1; yl[k] = w -- width + end + is_bar = not is_bar + x0 = x0 + w + end + assert(not is_bar, "[InternalErr] the last element is not a bar") + local o = { + _yline = yl, -- [, , ...] flat array + _x_lim = x0, -- external x coordinate + } + setmetatable(o, self) + return o +end + +-- return a Vbar inteleaving to sequence narrow/Wide +-- tbar, tspace = {boolean sequence}, true -> narrow, false -> Wide +function Vbar:from_two_tab(tbar, tspace, mod, MOD) --> + assert(type(tbar) == "table", "tbar must be a table") + assert(type(tspace) == "table", "tspace must be a table") + assert(#tbar == #tspace, "tbar and tspace must be longer the same") + assert(type(mod) == "number", "Invalid argument for narrow module width") + assert(type(MOD) == "number", "Invalid argument for wide module width") + assert(mod < MOD, "Not ordered narrow/Wide values") + local x0 = 0.0 -- x-coordinate + local yl = {} + for i = 1, #tbar do + local is_narrow = tbar[i] + assert(type(is_narrow) == "boolean", "[InternalErr] found a not boolean value") + if is_narrow then + yl[#yl + 1] = x0 + mod/2 -- bar x-coordinate + yl[#yl + 1] = mod -- bar width + x0 = x0 + mod + else + yl[#yl + 1] = x0 + MOD/2 -- bar x-coordinate + yl[#yl + 1] = MOD -- bar width + x0 = x0 + MOD + end + local is_narrow_space = tspace[i] + assert(type(is_narrow_space) == "boolean", "[InternalErr] found a not boolean value") + if is_narrow_space then + x0 = x0 + mod + else + x0 = x0 + MOD + end + end + local o = { + _yline = yl, -- [, , ...] flat array + _x_lim = x0, -- external x coordinate + } + setmetatable(o, self) + return o +end + +-- Text class + +libgeo.Text = {} +local Text = libgeo.Text +Text.__index = Text + +-- costructors +-- internally it keeps text as a sequence of codepoint +function Text:from_string(s) --> object + assert(type(s) == "string", "[ArgErr] 's' not a valid string") + assert(#s > 0, "[Err] 's' empty string not allowed") + + local cp = {} -- codepoint array + for b in string.gmatch(s, ".") do + cp[#cp + 1] = string.byte(b) + end + local o = { + codepoint = cp, + } + setmetatable(o, self) + return o +end + +-- arr, array of single digit number +-- i start index +-- j stop index +function Text:from_digit_array(arr, i, j) --> object + assert(type(arr) == "table", "[ArgErr] 'arr' not a table") + assert(#arr > 0, "[ArgErr] 'arr' is an empty array") + local cp = {} -- codepoint array + if i ~= nil then + assert(type(i) == "number", "[ArgErr] 'i' is not a number") + else + i = 1 + end + if j ~= nil then + assert(type(j) == "number", "[ArgErr] 'j' is not a number") + assert(i <= j, "[ArgErr] not suitable pair of array index") + else + j = #arr + end + for k = i, j do + local d = arr[k] + assert(type(d) == "number", "[ArgErr] array contains a not number element") + assert(d == math.floor(d), "[ArgErr] array contains a not integer number") + assert(d >= 0 or d < 10, "[ArgErr] array contains a not single digit number") + cp[#cp + 1] = d + 48 + end + local o = { + codepoint = cp, + } + setmetatable(o, self) + return o +end + + +-- from an array of chars +function Text:from_chars(chars) --> object + assert(type(chars) == "table", "[ArgErr] 'chars' must be a table") + local arr = {} + for _, c in ipairs(chars) do + arr[#arr + 1] = string.byte(c) + end + local o = { + codepoint = arr, + } + setmetatable(o, self) + return o +end + +-- provide an integer to build a Text object +function Text:from_int(n) --> object + assert(type(n) == "number", "[ArgErr] 'n' must be a number") + assert( n > 0, "[Err] 'n' must be positive") + assert( n == math.floor(n), "[Err] 'n' must be an integer") + local cp = {} + while n > 0 do + local d = n % 10 + cp[#cp + 1] = d + 48 + n = (n - d)/10 + end + local digits = #cp + for i = 1, digits/2 do -- reverse the array + local d = cp[digits - i + 1] + cp[digits - i + 1] = cp[i] + cp[i] = d + end + local o = { + codepoint = cp, + } + setmetatable(o, self) + return o +end + +return libgeo diff --git a/macros/luatex/generic/barracuda/test/test-barracuda-package/01-barracuda-latex-test.pdf b/macros/luatex/generic/barracuda/test/test-barracuda-package/01-barracuda-latex-test.pdf new file mode 100644 index 0000000000..a075d25db1 Binary files /dev/null and b/macros/luatex/generic/barracuda/test/test-barracuda-package/01-barracuda-latex-test.pdf differ diff --git a/macros/luatex/generic/barracuda/test/test-barracuda-package/01-barracuda-latex-test.tex b/macros/luatex/generic/barracuda/test/test-barracuda-package/01-barracuda-latex-test.tex new file mode 100644 index 0000000000..33a81aeb5d --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-barracuda-package/01-barracuda-latex-test.tex @@ -0,0 +1,13 @@ +% !TeX program = LuaLaTeX +% Copyright (C) 2019 Roberto Giacomelli + +% test file: make a Code39 barcodes in a LaTeX document + +\documentclass{article} +\usepackage{barracuda} + +\begin{document} +A\barracuda{code39}{123QWE}A +\end{document} + + diff --git a/macros/luatex/generic/barracuda/test/test-code128/001-code128-test.lua b/macros/luatex/generic/barracuda/test/test-code128/001-code128-test.lua new file mode 100644 index 0000000000..78645612dc --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-code128/001-code128-test.lua @@ -0,0 +1,32 @@ +-- Copyright (C) 2018 Roberto Giacomelli + +local barracuda = require "barracuda" +local barcode = barracuda:get_barcode_class() +local c128, err = barcode:new_encoder("code128") +assert(not err, err) + +print(c128._NAME) +print(c128._VERSION) + +local info = c128:info() +print("encoder name = ", info.name) +print("description = ", info.description) +for k, tp in ipairs(info.param) do + print(k, tp.name, tp.value) +end + +local symb = c128:from_string("123") +print("Symbol char list:") +for _, c in ipairs(symb._code_data) do + print(c) +end + +local canvas = barracuda:new_canvas() + +symb:append_ga(canvas) + +-- driver library +local drv = barracuda:get_driver() +drv:save("svg", canvas, "c128-123") + + diff --git a/macros/luatex/generic/barracuda/test/test-code128/002-code128-test.pdf b/macros/luatex/generic/barracuda/test/test-code128/002-code128-test.pdf new file mode 100644 index 0000000000..c3c8460bc7 Binary files /dev/null and b/macros/luatex/generic/barracuda/test/test-code128/002-code128-test.pdf differ diff --git a/macros/luatex/generic/barracuda/test/test-code128/002-code128-test.tex b/macros/luatex/generic/barracuda/test/test-code128/002-code128-test.tex new file mode 100644 index 0000000000..eeaf60e483 --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-code128/002-code128-test.tex @@ -0,0 +1,125 @@ +% !TeX program = LuaTeX +% Copyright (C) 2019 Roberto Giacomelli + +\newbox\mybox +\nopagenumbers + +Code 128 encoder test. + +Test 1: one simple barcode with default parameter: + +\directlua{ +barracuda = require "barracuda" +} + +\directlua{ +local barcode = barracuda:get_barcode_class() + +local c128, err = barcode:new_encoder("code128") +assert(not err, err) + +local symbo, err = c128:from_string("5465468132546812") +assert(not err, err) + +local canvas = barracuda:new_canvas() +symbo:append_ga(canvas) + +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\vrule A\vrule\box\mybox \vrule A\vrule + +Test 2: two symbols, different anchor. The first symbol (more longer than the +second one) takes the anchor parameters from the super class Barcode, while +the second one takes anchors from itself: + +\directlua{ +local barcode = barracuda:get_barcode_class() +local ok, err = barcode:set_param{ax = 1, ay = 1} % super class set up +assert(ok, err) +assert(barcode.ax == 1, "barcode ax is "..tostring(barcode.ax)) + +local c128, err = barcode:enc_by_name("code128") +assert(c128.ax == 1, "c128 ax is "..tostring(c128.ax)) + +local s1, err = c128:from_string("12345678901234567890"); assert(s1, err) +local s2, err = c128:from_string("0987654321", {ax = 0, ay = 0}); assert(s2, err) + +local s1_ax = s1:get_param("ax") +assert(s1.ax == 1, "1 ax is "..tostring(s1.ax)) +local s2_ax = s2:get_param("ax") +assert(s2.ax == 0, "0 ax is "..tostring(s2.ax)) + +local canvas = barracuda:new_canvas() +s1:append_ga(canvas) +s2:append_ga(canvas) + +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +}\box\mybox + +Test 3: play with the barcodes height (ydim parameter). The vertical anchor ay +will take to super class Barcode, previously set to 1.0. So, the symbols will +be aligned to the top: + +\directlua{ +local c128, err = barracuda:get_barcode_class() + :enc_by_name "code128"; assert(c128, err) + +local s, err = c128:from_string("123456"); assert(s, err) +local canvas = barracuda:new_canvas() +s:append_ga(canvas) + +local ok, err = s:set_param("ydim", tex.sp "30mm") +s:append_ga(canvas, tex.sp "20mm") + +local ok, err = s:set_param("ydim", tex.sp "60mm") +s:append_ga(canvas, tex.sp "40mm") + +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +}\box\mybox + +Test 4: set up vertical anchor globally to 0.0, locally to the encoder to 0.5 +and locally to 1.0: + +\directlua{ +local barcode = barracuda:get_barcode_class() +% set ay globally to 0.0 +local ok, err = barcode:set_param("ay", 0); assert(ok, err) + +local c128, err = barcode:enc_by_name "code128"; assert(c128, err) +local s, err = c128:from_string("ABCDEFGHI"); assert(s, err) + +local canvas = barracuda:new_canvas() +local _, err = s:append_ga(canvas); assert(not err, err) + +% set ay to 0.5 for the encoder +local ok, err = c128:set_param("ay", 0.5); assert(ok, err) +local _, err = s:append_ga(canvas, tex.sp "30mm"); assert(not err, err) +% set locally to the symbol ay to 1.0 +local ok, err = s:set_param("ay", 1) +local _, err = s:append_ga(canvas, tex.sp "60mm"); assert(not err, err) + +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +}\box\mybox + +Test 5: uint() costructor and save a file with PDF literal code: + +\directlua{ +local barcode = barracuda:get_barcode_class() +local c128, err = barcode:enc_by_name("code128"); assert(c128, err) +local s, e = c128:from_uint(1234567890); assert(s, e) +local canvas = barracuda:new_canvas() +local _, errc = s:append_ga(canvas); assert(not errc, errc) +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +drv:save("native", canvas, "02-05-pdfliteral") +}\box\mybox + +That's all folk! + +\bye + +function Driver:save(id_drv, ga, filename, ext) --> ok, err \ No newline at end of file diff --git a/macros/luatex/generic/barracuda/test/test-code128/02-05-pdfliteral.txt b/macros/luatex/generic/barracuda/test/test-code128/02-05-pdfliteral.txt new file mode 100644 index 0000000000..fe16d33c50 --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-code128/02-05-pdfliteral.txt @@ -0,0 +1,43 @@ +q +-53.574521 -14.173154 1.190545 28.346308 re +-51.788704 -14.173154 0.595272 28.346308 re +-50.002887 -14.173154 1.785817 28.346308 re +f +S +-47.026524 -14.173154 0.595272 28.346308 re +-45.835979 -14.173154 1.190545 28.346308 re +-43.454889 -14.173154 1.785817 28.346308 re +f +S +-40.478527 -14.173154 0.595272 28.346308 re +-38.097437 -14.173154 0.595272 28.346308 re +-36.906892 -14.173154 1.190545 28.346308 re +f +S +-33.930530 -14.173154 1.785817 28.346308 re +-30.358895 -14.173154 0.595272 28.346308 re +-29.168350 -14.173154 1.190545 28.346308 re +f +S +-27.382533 -14.173154 1.190545 28.346308 re +-23.810898 -14.173154 0.595272 28.346308 re +-22.620353 -14.173154 0.595272 28.346308 re +f +S +-20.834536 -14.173154 1.190545 28.346308 re +-19.048719 -14.173154 2.381090 28.346308 re +-16.072356 -14.173154 1.190545 28.346308 re +f +S +-14.286539 -14.173154 0.595272 28.346308 re +-12.500722 -14.173154 2.381090 28.346308 re +-8.929087 -14.173154 0.595272 28.346308 re +f +S +-7.738542 -14.173154 1.190545 28.346308 re +-4.762180 -14.173154 1.785817 28.346308 re +-2.381090 -14.173154 0.595272 28.346308 re +-1.190545 -14.173154 1.190545 28.346308 re +f +S +Q \ No newline at end of file diff --git a/macros/luatex/generic/barracuda/test/test-code128/c128-123.svg b/macros/luatex/generic/barracuda/test/test-code128/c128-123.svg new file mode 100644 index 0000000000..9f5b5847aa --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-code128/c128-123.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macros/luatex/generic/barracuda/test/test-code39/001-code39-test.lua b/macros/luatex/generic/barracuda/test/test-code39/001-code39-test.lua new file mode 100644 index 0000000000..e4a8569e93 --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-code39/001-code39-test.lua @@ -0,0 +1,41 @@ +-- Copyright (C) 2019 Roberto Giacomelli +-- test Code 39 encoder + +local barracuda = require "barracuda" + +for k, v in pairs(barracuda) do + print(k,v) +end + +local barcode = barracuda:get_barcode_class() + +local c39, err = barcode:new_encoder("code39") +assert(not err, err) + +print(c39._NAME) +print(c39._VERSION) + +local info = c39:info() + +print("encoder name = ", info.name) +print("description = ", info.description) + +for k, tp in ipairs(info.param) do + print(k, tp.name, tp.value) +end + +local symb = c39:from_string("123") + +print("print internal representation of chars") +for _, c in ipairs(symb.code) do + print(c) +end +print() + +local canvas = barracuda:new_canvas() +symb:append_ga(canvas) + +-- native driver +local drv = barracuda:get_driver() + +for _, code in ipairs(canvas._data) do print(code) end diff --git a/macros/luatex/generic/barracuda/test/test-code39/002-code39-test.pdf b/macros/luatex/generic/barracuda/test/test-code39/002-code39-test.pdf new file mode 100644 index 0000000000..060a61e892 Binary files /dev/null and b/macros/luatex/generic/barracuda/test/test-code39/002-code39-test.pdf differ diff --git a/macros/luatex/generic/barracuda/test/test-code39/002-code39-test.tex b/macros/luatex/generic/barracuda/test/test-code39/002-code39-test.tex new file mode 100644 index 0000000000..73f91aac43 --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-code39/002-code39-test.tex @@ -0,0 +1,120 @@ +% !TeX program = LuaTeX +% Copyright (C) 2019 Roberto Giacomelli + +\newbox\mybox +\nopagenumbers + +Test 1: Code 39 symbol with default parameters: + +\directlua{ +local barracuda = require "barracuda" +local c39, err = barracuda:get_barcode_class() + :new_encoder("code39") +assert(not err, err) + +local symbol, err = c39:from_string("ABC12QJ31") +assert(not err, err) + +local canvas = barracuda:new_canvas() +symbol:append_ga(canvas) +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\box\mybox + +Test 2: get the reference of the previous encoder and typeset two +Code 39 symbols on the same canvas, one above to the other: + +\directlua{ +local barracuda = require "barracuda" +local c39, err = barracuda:get_barcode_class() + :enc_by_name("code39") + assert(c39, err) + +local s1, err = c39:from_string("ZKPQJ31"); assert(s1, err) +local s2, err = c39:from_string("RTFG746", {text_vpos="top"}); assert(s2, err) + +local canvas = barracuda:new_canvas() +s1:append_ga(canvas) + +local h2 = s2:get_param("height") +s2:append_ga(canvas, 0.0, h2 + tex.sp "5pt") +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\box\mybox + +Test 3: with the same encoder print a symbol, change globally the height, +and reprint the same symbol again on the same canvas: + +\directlua{ +local barracuda = require "barracuda" +local c39, err = barracuda:get_barcode_class() + :enc_by_name("code39") + assert(c39, err) + +local s1, err = c39:from_string("ZKPQJ31"); assert(s1, err) + +local canvas = barracuda:new_canvas() +s1:append_ga(canvas) + +local h = s1:get_param("height") +c39:set_param("height", 2*h) +c39:set_param {text_vpos = "top"} + +s1:append_ga(canvas, 0.0, h + tex.sp "5pt") + +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\box\mybox + +Test 4: do the same in test 3 but change locally parameters as +height and text properties: + +\directlua{ +local barracuda = require "barracuda" +local c39, err = barracuda:get_barcode_class() + :enc_by_name("code39") + assert(c39, err) + +local s1, err = c39:from_string("0123456789"); assert(s1, err) + +local canvas = barracuda:new_canvas() +s1:append_ga(canvas) +local h, err = s1:get_param("height"); assert(h, err) +local ok, err = s1:set_param{ + height = h/2, + text_enabled = true, + text_vpos = "bottom", + text_hpos = "spaced", + text_star = true, + ay = 1, +}; assert(ok, err) +s1:append_ga(canvas, 0.0, - tex.sp "5pt") + +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\box\mybox + +Test 5: create a new encoder with a large module value: + +\directlua{ +local barracuda = require "barracuda" +local barcode = barracuda:get_barcode_class() + +local c39, err = barcode:new_encoder("code39", "e2", {module = tex.sp "0.5mm"}) +assert(c39, err) + +local s1, err = c39:from_string("02040608"); assert(s1, err) + +local canvas = barracuda:new_canvas() +s1:append_ga(canvas) + +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\box\mybox + +\bye diff --git a/macros/luatex/generic/barracuda/test/test-code39/003-code39-test.pdf b/macros/luatex/generic/barracuda/test/test-code39/003-code39-test.pdf new file mode 100644 index 0000000000..66b04e61e3 Binary files /dev/null and b/macros/luatex/generic/barracuda/test/test-code39/003-code39-test.pdf differ diff --git a/macros/luatex/generic/barracuda/test/test-code39/003-code39-test.tex b/macros/luatex/generic/barracuda/test/test-code39/003-code39-test.tex new file mode 100644 index 0000000000..a4ba3d6e81 --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-code39/003-code39-test.tex @@ -0,0 +1,53 @@ +% !TeX program = LuaTeX +% Copyright (C) 2019 Roberto Giacomelli + +\newbox\mybox +\nopagenumbers + +Test 3: the same Code 39 symbol drawing multiple time on the same canvas + +\directlua{ +local barracuda = require "barracuda" +local c39, err = barracuda:get_barcode_class() + :new_encoder("code39") +assert(not err, err) +local err +local symbol +symbol, err = c39:from_string("ABCDEF12QJ31+") +assert(not err, err) + +local ok, err = c39:set_param("text_vpos", "top") +assert(ok, err) + +local canvas = barracuda:new_canvas() +symbol:append_ga(canvas) + +local ok, err = symbol:set_param("text_hpos", "center") +assert(ok, err) +symbol:append_ga(canvas, tex.sp "4.5cm") + +local ok, err = symbol:set_param("text_hpos", "right") +assert(ok, err) +symbol:append_ga(canvas, tex.sp "9.0cm") + +local ok, err = c39:set_param("text_vpos", "bottom") +assert(ok, err) + +local ok, err = symbol:set_param("text_hpos", "left") +symbol:append_ga(canvas, 0, tex.sp "-2.0cm") + +local ok, err = symbol:set_param("text_hpos", "center") +assert(ok, err) +symbol:append_ga(canvas, tex.sp "4.5cm", tex.sp "-2.0cm") + +local ok, err = symbol:set_param("text_hpos", "right") +assert(ok, err) +symbol:append_ga(canvas, tex.sp "9.0cm", tex.sp "-2.0cm") + +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\box\mybox +\bye + + diff --git a/macros/luatex/generic/barracuda/test/test-code39/004-code39-test.pdf b/macros/luatex/generic/barracuda/test/test-code39/004-code39-test.pdf new file mode 100644 index 0000000000..3c96d9233b Binary files /dev/null and b/macros/luatex/generic/barracuda/test/test-code39/004-code39-test.pdf differ diff --git a/macros/luatex/generic/barracuda/test/test-code39/004-code39-test.tex b/macros/luatex/generic/barracuda/test/test-code39/004-code39-test.tex new file mode 100644 index 0000000000..559dc94383 --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-code39/004-code39-test.tex @@ -0,0 +1,46 @@ +% !TeX program = LuaTeX +% Copyright (C) 2019 Roberto Giacomelli + +\newbox\mybox +\nopagenumbers + +Test 4: check uint costructor: + +\directlua{ +barracuda = require "barracuda" +local c39, err = barracuda:get_barcode_class() + :new_encoder("code39") +assert(not err, err) +local err +local symbol +symbol, err = c39:from_uint(0, {text_hpos="center"}) +assert(not err, err) + +local canvas = barracuda:new_canvas() +symbol:append_ga(canvas) + +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\box\mybox + +\directlua{ +local c39, err = barracuda:get_barcode_class() + :enc_by_name("code39") +assert(c39, err) +local e +local symbol +symbol, e = c39:from_uint(0123456789, {text_hpos="spaced",text_star=true}) +assert(not e, e) + +local canvas = barracuda:new_canvas() +symbol:append_ga(canvas) + +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\box\mybox + +\bye + + diff --git a/macros/luatex/generic/barracuda/test/test-code39/005-code39-test.lua b/macros/luatex/generic/barracuda/test/test-code39/005-code39-test.lua new file mode 100644 index 0000000000..4ac0ff171d --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-code39/005-code39-test.lua @@ -0,0 +1,8 @@ + +-- Code 39 test file number 5 + +local barracuda = require "barracuda" +barracuda:save("code39", "ABCDEFG", "my_barcode") + +-- end of test file + diff --git a/macros/luatex/generic/barracuda/test/test-code39/006-code39-test.lua b/macros/luatex/generic/barracuda/test/test-code39/006-code39-test.lua new file mode 100644 index 0000000000..d33ad4ffaf --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-code39/006-code39-test.lua @@ -0,0 +1,45 @@ + +local cm = 1864679.8110236 -- sp + +local barracuda = require "barracuda" +local c39, err = barracuda:get_barcode_class() + :new_encoder("code39") +assert(not err, err) +local err +local symbol +symbol, err = c39:from_string("ABCDEF12QJ31+") +assert(not err, err) + +local ok, err = c39:set_param("text_vpos", "top") +assert(ok, err) + +local canvas = barracuda:new_canvas() +symbol:append_ga(canvas) + +local ok, err = symbol:set_param("text_hpos", "center") +assert(ok, err) +symbol:append_ga(canvas, 4.5*cm) + +local ok, err = symbol:set_param("text_hpos", "right") +assert(ok, err) +symbol:append_ga(canvas, 9.0*cm) + +local ok, err = c39:set_param("text_vpos", "bottom") +assert(ok, err) + +local ok, err = symbol:set_param("text_hpos", "left") +symbol:append_ga(canvas, 0, -2.0*cm) + +local ok, err = symbol:set_param("text_hpos", "center") +assert(ok, err) +symbol:append_ga(canvas, 4.5*cm, -2.0*cm) + +local ok, err = symbol:set_param("text_hpos", "right") +assert(ok, err) +symbol:append_ga(canvas, 9.0*cm, -2.0*cm) + +local drv = barracuda:get_driver() +drv:save("svg", canvas, "006-six") + + + diff --git a/macros/luatex/generic/barracuda/test/test-code39/006-six.svg b/macros/luatex/generic/barracuda/test/test-code39/006-six.svg new file mode 100644 index 0000000000..25ce8bb34c --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-code39/006-six.svg @@ -0,0 +1,653 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ABCDEF12QJ31+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ABCDEF12QJ31+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ABCDEF12QJ31+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ABCDEF12QJ31+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ABCDEF12QJ31+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ABCDEF12QJ31+ + + diff --git a/macros/luatex/generic/barracuda/test/test-code39/my_barcode.svg b/macros/luatex/generic/barracuda/test/test-code39/my_barcode.svg new file mode 100644 index 0000000000..426fb3de86 --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-code39/my_barcode.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ABCDEFG + + diff --git a/macros/luatex/generic/barracuda/test/test-ean/001-13-ean-test.pdf b/macros/luatex/generic/barracuda/test/test-ean/001-13-ean-test.pdf new file mode 100644 index 0000000000..0e8abb933f Binary files /dev/null and b/macros/luatex/generic/barracuda/test/test-ean/001-13-ean-test.pdf differ diff --git a/macros/luatex/generic/barracuda/test/test-ean/001-13-ean-test.tex b/macros/luatex/generic/barracuda/test/test-ean/001-13-ean-test.tex new file mode 100644 index 0000000000..c0a4db3894 --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-ean/001-13-ean-test.tex @@ -0,0 +1,220 @@ +% !TeX program = LuaTeX +% Copyright (C) 2019 Roberto Giacomelli + +\newbox\mybox +\nopagenumbers + +EAN encoder test. + +Test 1: one simple barcode EAN13 with default parameter: + +\directlua{ +local barracuda = require "barracuda" +local barcode = barracuda:get_barcode_class() + +local ean13, err = barcode:new_encoder("ean-13") +assert(not err, err) + +local symbo, err = ean13:from_string("8006194056290") +assert(not err, err) + +local canvas = barracuda:new_canvas() +symbo:append_ga(canvas) + +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\vrule A\vrule\box\mybox \vrule A\vrule + +\medskip +Test 2: one simple EAN8 barcode with default parameter: + +\directlua{ +local barracuda = require "barracuda" +local barcode = barracuda:get_barcode_class() + +local ean8, err = barcode:new_encoder("ean-8") +assert(not err, err) + +local symbo, err = ean8:from_string("96385074") +assert(not err, err) + +local canvas = barracuda:new_canvas() +symbo:append_ga(canvas) + +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\vrule A\vrule\box\mybox \vrule A\vrule + +\medskip +Test 3: one simple EAN5 barcode with default parameter: + +\directlua{ +local barracuda = require "barracuda" +local barcode = barracuda:get_barcode_class() +local ean5, err = barcode:new_encoder("ean-5") +assert(not err, err) +local symbo, err = ean5:from_string("54495") +assert(not err, err) +local canvas = barracuda:new_canvas() +symbo:append_ga(canvas) +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\vrule A\vrule\box\mybox \vrule A\vrule + +\medskip +Test 4: one simple EAN2 barcode with default parameter: + +\directlua{ +local barracuda = require "barracuda" +local barcode = barracuda:get_barcode_class() +local ean2, err = barcode:new_encoder("ean-2") +assert(not err, err) +local symbo, err = ean2:from_string("53") +assert(not err, err) +local canvas = barracuda:new_canvas() +symbo:append_ga(canvas) +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\vrule A\vrule\box\mybox \vrule A\vrule + +\medskip +Test 5: EAN13 + EAN5 barcode with default parameter: + +\directlua{ +local barracuda = require "barracuda" +local barcode = barracuda:get_barcode_class() +local ean, err = barcode:new_encoder("ean-13+5"); assert(not err, err) +local n = 123456789012 +local c = ean:checksum(n) +local s = n .. c +local symbo, err = ean:from_string(s.."12345") +assert(not err, err) +local canvas = barracuda:new_canvas() +symbo:append_ga(canvas) +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\vrule Test 5\vrule\box\mybox \vrule Test 5\vrule + +\medskip +Test 6: EAN13 + EAN2 barcode with default parameter: + +\directlua{ +local barracuda = require "barracuda" +local barcode = barracuda:get_barcode_class() +local ean, err = barcode:new_encoder("ean-13+2"); assert(not err, err) +local n = 123456789012 +local c = ean:checksum(n) +local s = n .. c +local symbo, err = ean:from_string(s.."12") +assert(not err, err) +local canvas = barracuda:new_canvas() +symbo:append_ga(canvas) +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\vrule Test 6\vrule\box\mybox \vrule Test 6\vrule + +\medskip +Test 7: EAN8 + EAN5 barcode with default parameter: + +\directlua{ +local barracuda = require "barracuda" +local barcode = barracuda:get_barcode_class() +local ean, err = barcode:new_encoder("ean-8+5"); assert(not err, err) +local n = 1234567 +local c = ean:checksum(n) +local s = n .. c +local symbo, err = ean:from_string(s.."12345") +assert(not err, err) +local canvas = barracuda:new_canvas() +symbo:append_ga(canvas) +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\vrule Test 7\vrule\box\mybox \vrule Test 7\vrule + +\medskip +Test 8: EAN8 + EAN2 barcode with default parameter: + +\directlua{ +local barracuda = require "barracuda" +local barcode = barracuda:get_barcode_class() +local ean, err = barcode:new_encoder("ean-8+2"); assert(not err, err) +local n = 7865431 +local c = ean:checksum(n) +local s = n .. c +local symbo, err = ean:from_string(s.."88") +assert(not err, err) +local canvas = barracuda:new_canvas() +symbo:append_ga(canvas) +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\vrule Test 8\vrule\box\mybox \vrule Test 8\vrule + +\medskip +Test 9: draw an EAN13 symbol with a user defined height. + +\smallskip +We will test also the function barcode:enc\_by\_name(bc\_type, name), +reusing encoders generated previuosly. The height parameter remain local +to the object symbol. +\smallskip + +\directlua{ +local barracuda = require "barracuda" +local barcode = barracuda:get_barcode_class() +local ean, err = barcode:enc_by_name("ean-13"); assert(not err, err) +local n = 818571884348 +local c = ean:checksum(n) +local s = n .. c +local symbo, err = ean:from_string(s); assert(not err, err) +local ok, err = symbo:set_param("height", tex.sp "5mm"); assert(ok, err) +local canvas = barracuda:new_canvas() +symbo:append_ga(canvas) + +local s2, err = ean:from_uint(8001120972163); assert(not err, err) +s2:append_ga(canvas, tex.sp "45mm", 0) + +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\vrule Test 9\vrule\box\mybox \vrule Test 9\vrule + +\medskip +Test 10: draw EAN13 symbols with a user defined height. + +\smallskip +The parameter height is setting up in the encoder so it will be global. +\smallskip + +\directlua{ +local barracuda = require "barracuda" +local barcode = barracuda:get_barcode_class() +local ean, err = barcode:enc_by_name("ean-13"); assert(not err, err) +local ok, err = ean:set_param("height", tex.sp "5mm"); assert(ok, err) +local n = 758458535897; local c = ean:checksum(n); local s = n .. c +local s1, err = ean:from_string(s); assert(not err, err) +local canvas = barracuda:new_canvas() +s1:append_ga(canvas) +local s2, err = ean:from_uint(8001120972163); assert(not err, err) +s2:append_ga(canvas, tex.sp "40mm", 0) +local s3, err = ean:from_uint(8000570000310); assert(not err, err) +local ok, e = s3:set_param{height = tex.sp "10mm"}; assert(ok, e) +s3:append_ga(canvas, tex.sp "90mm", 0) +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\vrule Test 10\vrule\box\mybox \vrule Test 10\vrule + +\medskip +That's all folk! + +\bye + + diff --git a/macros/luatex/generic/barracuda/test/test-ean/002-ean-test.pdf b/macros/luatex/generic/barracuda/test/test-ean/002-ean-test.pdf new file mode 100644 index 0000000000..568050371c Binary files /dev/null and b/macros/luatex/generic/barracuda/test/test-ean/002-ean-test.pdf differ diff --git a/macros/luatex/generic/barracuda/test/test-ean/002-ean-test.tex b/macros/luatex/generic/barracuda/test/test-ean/002-ean-test.tex new file mode 100644 index 0000000000..2c82373b61 --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-ean/002-ean-test.tex @@ -0,0 +1,12 @@ +% !TeX program = LuaTeX +\nopagenumbers +\newbox\mybox +\directlua{ + local barracuda = require "barracuda" + barracuda:hbox("ean-13", "8006194056290", "mybox") +} +\pagewidth=80mm +\pageheight=60mm +\box\mybox +\bye + diff --git a/macros/luatex/generic/barracuda/test/test-ean/003-ean-test.pdf b/macros/luatex/generic/barracuda/test/test-ean/003-ean-test.pdf new file mode 100644 index 0000000000..baa5a5b9cd Binary files /dev/null and b/macros/luatex/generic/barracuda/test/test-ean/003-ean-test.pdf differ diff --git a/macros/luatex/generic/barracuda/test/test-ean/003-ean-test.tex b/macros/luatex/generic/barracuda/test/test-ean/003-ean-test.tex new file mode 100644 index 0000000000..59b17c4c07 --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-ean/003-ean-test.tex @@ -0,0 +1,16 @@ +% !TeX program = LuaLaTeX +\documentclass{standalone} +\usepackage{fontspec} +\setmainfont{ocrb10.otf} +\newbox\mybox +\directlua{ + local barracuda = require "barracuda" + barracuda:hbox("ean-13", "8006194056290", "mybox") +} + +\begin{document} +\box\mybox +\end{document} + + + diff --git a/macros/luatex/generic/barracuda/test/test-ean/004-ean-test.lua b/macros/luatex/generic/barracuda/test/test-ean/004-ean-test.lua new file mode 100644 index 0000000000..017e0725b8 --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-ean/004-ean-test.lua @@ -0,0 +1,9 @@ + +local barracuda = require "barracuda" +barracuda:save("ean-13", "8006194056290", "8006194056290") + + + + + + diff --git a/macros/luatex/generic/barracuda/test/test-ean/8006194056290.svg b/macros/luatex/generic/barracuda/test/test-ean/8006194056290.svg new file mode 100644 index 0000000000..f7965e94d4 --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-ean/8006194056290.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 + + 0 + 0 + 6 + 1 + 9 + 4 + + + 0 + 5 + 6 + 2 + 9 + 0 + + + diff --git a/macros/luatex/generic/barracuda/test/test-ga-pdfliteral/001-ga-pdfliteral-test.pdf b/macros/luatex/generic/barracuda/test/test-ga-pdfliteral/001-ga-pdfliteral-test.pdf new file mode 100644 index 0000000000..b8a7477c7f Binary files /dev/null and b/macros/luatex/generic/barracuda/test/test-ga-pdfliteral/001-ga-pdfliteral-test.pdf differ diff --git a/macros/luatex/generic/barracuda/test/test-ga-pdfliteral/001-ga-pdfliteral-test.tex b/macros/luatex/generic/barracuda/test/test-ga-pdfliteral/001-ga-pdfliteral-test.tex new file mode 100644 index 0000000000..1a5ed80d0c --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-ga-pdfliteral/001-ga-pdfliteral-test.tex @@ -0,0 +1,740 @@ +% !TeX program = LuaTeX +% test for ga-canvas pdfliteral driver +% +% Copyright (C) 2019 Roberto Giacomelli +% see LICENSE.txt file + +---ga--- is a binary format as an istruction set similar to +a sort of assembler language that describes simple graphic +objects like lines and rectangles. +This file contains tests aiming to check the pdfliteral +driver capability to render such ga streams---usually a Lua +array. + +The pdfliteral driver directly inserts PDF vector graphic +primitives within the output and should be intented as the +"native" driver of barracuda package. + +The complete reference of the ---ga--- format is available +throgh out the content of the "ga-grammar.tex" file. + +Please note that all dimensions are in scaled point, the +very small \TeX{} internal unit, in fact we have that +65536sp = 1pt. + +Running the source file with luatex. The typesetting engine +executes the directlua macro, so vector graphics appear in +the PDF output file. + +\newbox\mybox +\directlua{ + driver = require [[lib-driver.brcd-driver]] % global Lua variables + pt = tex.sp [[1pt]] % 1pt = 65536sp +} + +Let's start drawing an horizontal line 100pt long: +\directlua{ + local ga = {_data = {33, 0*pt, 100*pt, 0*pt}} + driver:ga_to_hbox(ga, [[mybox]]) +}\box\mybox + +or two different parallel lines 24pt long: +\directlua{ + local ga = {_data = {33, 0*pt, 24*pt, 0*pt, 33, 0*pt, 24*pt, 5*pt}} + driver:ga_to_hbox(ga, [[mybox]]) +}\box\mybox + +and again two horizontal lines 10pt thick, touching a corner: +\directlua{ + local ga = {_data = { + 1, 10*pt, + 33, -24*pt, 0*pt, -5*pt, + 33, 0*pt, 24*pt, 5*pt, + }} + driver:ga_to_hbox(ga, [[mybox]]) +}\box\mybox + +Several vertical lines with its horizontal limits: +\directlua{ + local ga = { _data = { + 34, -20*pt, 20*pt, 0*pt, + 34, -15*pt, 15*pt, 5*pt, + 34, -10*pt, 10*pt, 10*pt, + 34, -5*pt, 5*pt, 15*pt, + 34, -.5*pt, .5*pt, 20*pt, + 34, -5*pt, 5*pt, 25*pt, + 34, -10*pt, 10*pt, 30*pt, + 34, -15*pt, 15*pt, 35*pt, + 34, -20*pt, 20*pt, 40*pt, + 1, .05*pt, + 33, 0*pt, 40*pt, -20*pt, + 33, 0*pt, 40*pt, 20*pt, + }} + driver:ga_to_hbox(ga, [[mybox]]) +}\box\mybox + +Finally a little rectangle: +\directlua{ + local ga = {_data = { + 1, 5*pt, + 48, 0*pt, 0*pt, 15*pt, 10*pt, + }} + driver:ga_to_hbox(ga, [[mybox]]) +}\box\mybox + +\bigskip +Test number 1: a vbar 2pt width, 20pt height: +\directlua{ + % vbar: <36> y1 y2 x1 w1 x2 w2 ... xn wn + local ga = {_data = {36, 0, 20*pt, 1, 0.0, 2*pt}} + driver:ga_to_hbox(ga, [[mybox]]) +}\box\mybox + +\bigskip +Test number 2: ten vbars in a row equally spaced by 10pt: +\directlua{ + local ga = {36, 0, 10*pt, 10,} + for i = 0, 9 do + ga[i*2 + 5] = 5*pt + i*20*pt + ga[i*2 + 6] = 10*pt + end + driver:ga_to_hbox({_data = ga}, [[mybox]]) +}\vrule\box\mybox\vrule + +\bigskip +Test number 3: two series of vbars 10pt and 5pt large: +\directlua{ + local ga = {36, 0, 10*pt, 10,} + for i = 0, 9 do + ga[i*2 + 5] = 5*pt + i*20*pt + ga[i*2 + 6] = 10*pt + end + ga[25] = 36 % vbar opcode + ga[26] = 2.5*pt % y1 + ga[27] = 7.5*pt % y2 + ga[28] = 9 % number of bars + for i = 0, 8 do + ga[i*2 + 29] = 15*pt + i*20*pt + ga[i*2 + 30] = 5*pt + end + driver:ga_to_hbox({_data = ga}, [[mybox]]) +}\vrule\box\mybox\vrule + +\bigskip +Test number 4: a bunch of thin vertical bars (25): +\directlua{ + local ga = {} + ga[1] = 36 % vbar opcode + ga[2] = 5*pt % y1 + ga[3] = 25*pt % y2 + ga[4] = 25 % number of bars + for i = 0, 24 do + ga[i*2 + 5] = 1*pt + i*4*pt + ga[i*2 + 6] = 2*pt + end + driver:ga_to_hbox({_data = ga}, [[mybox]]) +}\vrule A\box\mybox A\vrule + +\bigskip +Test number 5: two rows of a bunch of thin bars: +\directlua{ + local ga = {} + ga[1] = 36 % vbar opcode + ga[2] = 5*pt % y1 + ga[3] = 25*pt % y2 + ga[4] = 25 % number of bars + for i = 0, 24 do + ga[i*2 + 5] = 1*pt + i*4*pt + ga[i*2 + 6] = 2*pt + end + ga[55] = 36 % vbar opcode + ga[56] = 25*pt % y1 + ga[57] = 45*pt % y2 + ga[58] = 24 % number of bars + for i = 0, 23 do + ga[i*2 + 59] = 3*pt + i*4*pt + ga[i*2 + 60] = 2*pt + end + driver:ga_to_hbox({_data = ga}, [[mybox]]) +}\vrule\box\mybox\vrule + +\bigskip +Test number 6: staircase of Vbars (manually data definition): +\directlua{ + local ga = { + 36, % vbar opcode + 0*pt, % y1 + 20*pt, % y2 + 1, % number of bars + 5*pt, % x + 10*pt, % w + 36, % vbar opcode + 20*pt, % y1 + 40*pt, % y2 + 1, % number of bars + 15*pt, % x + 10*pt, % w + 36, % vbar opcode + 40*pt, % y1 + 60*pt, % y2 + 1, % number of bars + 25*pt, % x + 10*pt, % w + } + driver:ga_to_hbox({_data = ga}, [[mybox]]) +}\vrule\box\mybox\vrule + +\bigskip +Test number 7: vbars with spaced text, in three different rows: +\directlua{ + local ga = {} + ga[1] = 36 % vbar opcode + ga[2] = 0*pt % y1 + ga[3] = 20*pt % y2 + ga[4] = 8 % number of bars + for i = 1,8 do + ga[3 + i*2] = i * 2 * 5*pt % x coordinate of bar axis + ga[4 + i*2] = 5*pt % bar width + end + ga[21] = 36 % vbar opcode + ga[22] = 30*pt % y1 + ga[23] = 50*pt % y2 + ga[24] = 8 % number of bars + for i = 1,8 do + ga[23 + i*2] = i * 2 * 5*pt % x coordinate of bar axis + ga[24 + i*2] = 5*pt % bar width + end + % 131 + ga[41] = 131 % opcode text_xspaced + ga[42] = 10*pt % x coordinate of the first glyph axis + ga[43] = 10*pt % x gap among glyphs + ga[44] = 0.5 % half height + ga[45] = 25*pt % y coordinate of glyps + ga[46] = 65 % A + ga[47] = 66 % B + ga[48] = 67 % C + ga[49] = 68 % D + ga[50] = 69 % E + ga[51] = 70 % F + ga[52] = 71 % G + ga[53] = 72 % H + ga[54] = 0 + driver:ga_to_hbox({_data = ga}, [[mybox]]) +}\vrule\box\mybox\vrule + +\bigskip +Test number 8: spaced text (checking the correct vertical alignment): +\directlua{ + local ga = {} + ga[1] = 36 % vbar opcode + ga[2] = 0*pt % y1 + ga[3] = 20*pt % y2 + ga[4] = 8 % number of bars + for i = 1,8 do + ga[3 + i*2] = i * 2 * 5*pt % x coordinate of bar axis + ga[4 + i*2] = 1*pt % bar width + end + ga[21] = 36 % vbar opcode + ga[22] = 40*pt % y1 + ga[23] = 60*pt % y2 + ga[24] = 8 % number of bars + for i = 1,8 do + ga[23 + i*2] = i * 2 * 5*pt % x coordinate of bar axis + ga[24 + i*2] = 1*pt % bar width + end + % 131 + ga[41] = 131 % opcode text_xspaced + ga[42] = 10*pt % x coordinate of the first glyph axis + ga[43] = 10*pt % x gap among glyphs + ga[44] = 0.0 % half height + ga[45] = 30*pt % y coordinate of glyps + ga[46] = 65 % A + ga[47] = 66 % B + ga[48] = 67 % C + ga[49] = string.byte("Q") + ga[50] = 69 % E + ga[51] = 70 % F + ga[52] = 71 % G + ga[53] = 72 % H + ga[54] = 0 + ga[55] = 131 % opcode text_xspaced + ga[56] = 10*pt % x coordinate of the first glyph axis + ga[57] = 10*pt % x gap among glyphs + ga[58] = 1.0 % half height + ga[59] = 30*pt % y coordinate of glyps + ga[60] = 49 % 1 + ga[61] = 50 % 2 + ga[62] = 51 % 3 + ga[63] = 52 % 4 + ga[64] = 53 % 5 + ga[65] = 54 % 6 + ga[66] = 55 % 7 + ga[67] = 56 % 8 + ga[68] = 0 + driver:ga_to_hbox({_data = ga}, [[mybox]]) +}\vrule\box\mybox\vrule + +\bigskip +Test number 9: spaced text, check correct vertical alignment: +\directlua{ + local ga = {} + ga[1] = 36 % vbar opcode + ga[2] = 0*pt % y1 + ga[3] = 20*pt % y2 + ga[4] = 8 % number of bars + for i = 1,8 do + ga[3 + i*2] = i * 2 * 5*pt % x coordinate of bar axis + ga[4 + i*2] = 8*pt % bar width + end + ga[21] = 36 % vbar opcode + ga[22] = 40*pt % y1 + ga[23] = 60*pt % y2 + ga[24] = 8 % number of bars + for i = 1,8 do + ga[23 + i*2] = i * 2 * 5*pt % x coordinate of bar axis + ga[24 + i*2] = 8*pt % bar width + end + % 131 + ga[41] = 131 % opcode text_xspaced + ga[42] = 10*pt % x coordinate of the first glyph axis + ga[43] = 10*pt % x gap among glyphs + ga[44] = 0.0 % half height + ga[45] = 20*pt % y coordinate of glyps + ga[46] = 65 % A + ga[47] = 66 % B + ga[48] = 67 % C + ga[49] = 68 % D + ga[50] = 69 % E + ga[51] = 70 % F + ga[52] = 71 % G + ga[53] = 72 % H + ga[54] = 0 + ga[55] = 131 % opcode text_xspaced + ga[56] = 10*pt % x coordinate of the first glyph axis + ga[57] = 10*pt % x gap among glyphs + ga[58] = 1.0 % half height + ga[59] = 40*pt % y coordinate of glyps + ga[60] = 49 % 1 + ga[61] = 50 % 2 + ga[62] = 51 % 3 + ga[63] = 52 % 4 + ga[64] = 53 % 5 + ga[65] = 54 % 6 + ga[66] = 55 % 7 + ga[67] = 56 % 8 + ga[68] = 0 + driver:ga_to_hbox({_data = ga}, [[mybox]]) +}\vrule\box\mybox\vrule + +\bigskip +Test number 10: two centered texts aligned to the baseline: +\directlua{ + local ga = {} + % 130 + ga[ 1] = 130 % opcode text + ga[ 2] = 0.5 % ax relative x coordinate + ga[ 3] = 1.0 % ay relative y coordinate + ga[ 4] = 0.0 % x position + ga[ 5] = 0.0 % y position + ga[ 6] = 65 % A + ga[ 7] = string.byte("Q") % Q depth glyph + ga[ 8] = 67 % C + ga[ 9] = 0 + ga[10] = 130 % opcode text + ga[11] = 0.5 % ax + ga[12] = 0.0 % ay + ga[13] = 0.0 % x + ga[14] = 0.0 % y + ga[15] = 48 % 0 + ga[16] = 49 % 1 + ga[17] = 50 % 2 + ga[18] = 51 % 3 + ga[19] = 52 % 4 + ga[20] = 53 % 5 + ga[21] = 54 % 6 + ga[22] = 55 % 7 + ga[23] = 56 % 8 + ga[24] = 57 % 9 + ga[25] = 0 + driver:ga_to_hbox({_data = ga}, [[mybox]]) +}\vrule\box\mybox\vrule + +\bigskip +So far, we have manually build data for ga stream. Next we are going to +use the ga-canvas library. + +\bigskip +In fact, all the previous tests are rebuild with the ga-canvas library. + +Test 1: a vbar 2pt width, 20pt height: +\directlua{ + gacanvas = require "lib-geo.brcd-gacanvas" + local ga = gacanvas:new() + local vbar = {_yline = {0.0, 2*pt}} + local err = ga:encode_Vbar(vbar, 0.0, 0.0, 20*pt) % x, w + assert(not err, err) + driver:ga_to_hbox(ga, [[mybox]]) +}\box\mybox + +\bigskip +Test 2: ten vbars equally spaced by 10pt: +\directlua{ + local ga = gacanvas:new() + local data = {} + for i = 0, 9 do + data[i*2 + 1] = 5*pt + i*20*pt % x + data[i*2 + 2] = 10*pt % w + end + local bars = {_yline = data} + local err = ga:encode_Vbar(bars, 0.0, 0.0, 10*pt) + assert(not err, err) + driver:ga_to_hbox(ga, [[mybox]]) +}\vrule\box\mybox\vrule + +\bigskip +Test 3: two series of vbars 10pt and 5pt large: +\directlua{ + local b1 = {} + for i = 0, 9 do + b1[i*2 + 1] = i*20*pt + b1[i*2 + 2] = 10*pt + end + local b2 = {} + for i = 0, 8 do + b2[i*2 + 1] = i*20*pt + b2[i*2 + 2] = 5*pt + end + local ga = gacanvas:new() + local err = ga:encode_Vbar({_yline=b1}, 0.0, 0.0, 10*pt) + assert(not err, err) + err = ga:encode_Vbar({_yline=b2}, 10.0*pt, 2.5*pt, 7.5*pt) + assert(not err, err) + driver:ga_to_hbox(ga, [[mybox]]) +}\vrule\box\mybox\vrule + +\bigskip +Test 4: a bunch of thin bars: +\directlua{ + local b = {} + for i = 0, 24 do + b[i*2 + 1] = 1*pt + i*4*pt + b[i*2 + 2] = 2*pt + end + local ga = gacanvas:new() + local err = ga:encode_Vbar({_yline=b}, 0.0, 5*pt, 25*pt) + assert(not err, err) + driver:ga_to_hbox(ga, [[mybox]]) +}\vrule{ }\box\mybox{ }\vrule + +\bigskip +Test 5: two levels of a bunch of thin bars: +\directlua{ + local b = {} + for i = 0, 24 do + b[i*2 + 1] = i*4*pt + b[i*2 + 2] = 2*pt + end + local b = {_yline=b} + local ga = gacanvas:new() + local err = ga:encode_Vbar(b, 0.0, 5*pt, 25*pt) + assert(not err, err) + err = ga:encode_Vbar(b, 2*pt, 25*pt, 45*pt, b) + driver:ga_to_hbox(ga, [[mybox]]) +}\vrule\box\mybox\vrule + +\bigskip +Test number 6: staircase of bars (manual insertion of data): +\directlua{ + local b = {_yline={0.0, 10*pt}} + local ga = gacanvas:new() + local err = ga:encode_Vbar(b, 0.0, 0.0, 20*pt) + assert(not err, err) + err = ga:encode_Vbar(b, 10*pt, 20*pt, 40*pt) + assert(not err, err) + err = ga:encode_Vbar(b, 20*pt, 40*pt, 60*pt) + assert(not err, err) + driver:ga_to_hbox(ga, [[mybox]]) +}\vrule\box\mybox\vrule + +\bigskip +Test number 7: vbars with spaced text, all in three rows: +\directlua{ + local b = {} + for i = 0,7 do + b[i*2+1] = i*10*pt + b[i*2+2] = 5*pt + end + local vb = {_yline=b} + local ga = gacanvas:new() + local err = ga:encode_Vbar(vb, 0.0, 0.0, 20*pt) + assert(not err, err) + local err = ga:encode_Vbar(vb, 0.0, 30*pt, 50*pt) + assert(not err, err) + local txt = {codepoint = { + 65, % A + 66, % B + 67, % C + 68, % D + 69, % E + 70, % F + 71, % G + 72, % H + }} + err = ga:encode_Text_xspaced(txt, 0.0, 10*pt, 25*pt, 0.5) + assert(not err, err) + driver:ga_to_hbox(ga, [[mybox]]) +}\vrule\box\mybox\vrule + +\bigskip +Test 8: spaced text, check correct vertical alignment: +\directlua{ + local b = {} + for i = 0,7 do + b[i*2+1] = i*10*pt + b[i*2+2] = 2*pt + end + b = {_yline=b} + local ga = gacanvas:new() + local err = ga:encode_Vbar(b, 0.0, 0.0, 20*pt) + assert(not err, err) + local err = ga:encode_Vbar(b, 0.0, 40*pt, 60*pt) + assert(not err, err) + local c = { codepoint = { + 65, % A + 66, % B + 67, % C + string.byte("Q"), + 69, % E + 70, % F + 71, % G + 72, % H + }} + err = ga:encode_Text_xspaced(c, 0.0, 10*pt, 30*pt, 0.0) + assert(not err, err) + local n = { codepoint = { + 49, % 1 + 50, % 2 + 51, % 3 + 52, % 4 + 53, % 5 + 54, % 6 + 55, % 7 + 56, % 8 + }} + err = ga:encode_Text_xspaced(n, 0.0, 10*pt, 30*pt, 1.0) + assert(not err, err) + driver:ga_to_hbox(ga, [[mybox]]) +}\vrule\box\mybox\vrule + +\bigskip +Test number 9: spaced text, check correct vertical alignment: +\directlua{ + local b = {} + for i = 0,7 do + b[i*2+1] = i*10*pt + b[i*2+2] = 8*pt + end + b = {_yline = b} + local ga = gacanvas:new() + local err = ga:encode_Vbar(b, 0.0, 0.0, 20*pt) + assert(not err, err) + local err = ga:encode_Vbar(b, 0.0, 40*pt, 60*pt) + assert(not err, err) + local c = { codepoint = { + 65, % A + 66, % B + 67, % C + string.byte("Q"), + 69, % E + 70, % F + 71, % G + 72, % H + }} + err = ga:encode_Text_xspaced(c, 0.0, 10*pt, 20*pt, 0.0) + assert(not err, err) + local n = { codepoint = { + 49, % 1 + 50, % 2 + 51, % 3 + 52, % 4 + 53, % 5 + 54, % 6 + 55, % 7 + 56, % 8 + }} + err = ga:encode_Text_xspaced(n, 0.0, 10*pt, 40*pt, 1.0) + assert(not err, err) + driver:ga_to_hbox(ga, [[mybox]]) +}\vrule{ }\box\mybox{ }\vrule + +\bigskip +Test number 10: two centered texts and baseline aligned: +\directlua{ + local n = { codepoint = { + 48, % 0 + 49, % 1 + 50, % 2 + 51, % 3 + 52, % 4 + 53, % 5 + 54, % 6 + 55, % 7 + 56, % 8 + 57, % 9 + }} + local ga = gacanvas:new() + local err = ga:encode_Text(n, 0, 0, 0.5, 0) + assert(not err, err) + local a = { codepoint = { + 65, % A + string.byte("Q"), % Q + 67, % C + }} + err = ga:encode_Text(a, 0, 0, 0.5, 1) + assert(not err, err) + driver:ga_to_hbox(ga, [[mybox]]) +}\vrule\box\mybox\vrule + +\bigskip +Test number 11: two centered texts aligned: +\directlua{ + local n = { codepoint = { + 48, % 0 + 49, % 1 + 50, % 2 + 51, % 3 + 52, % 4 + 53, % 5 + 54, % 6 + 55, % 7 + 56, % 8 + 57, % 9 + }} + local ga = gacanvas:new() + local err = ga:encode_Text(n, 0, 0, 0.5, 1) + assert(not err, err) + local a = { codepoint = { + 65, % A + string.byte("Q"), % Q + 67, % C + }} + err = ga:encode_Text(a, 0, 0, 0.5, 0) + assert(not err, err) + driver:ga_to_hbox(ga, [[mybox]]) +}\vrule\box\mybox\vrule + +\bigskip +Test number 12: text\_xwidth opcode: + +\directlua{ + local n = { codepoint = { + 48, % 0 + 49, % 1 + 50, % 2 + 51, % 3 + 52, % 4 + 53, % 5 + 54, % 6 + 55, % 7 + 56, % 8 + 57, % 9 + }} + local ga = gacanvas:new() + local err = ga:encode_Text_xwidth(n, 0, tex.sp "5cm", 0, 0) + assert(not err, err) + driver:ga_to_hbox(ga, [[mybox]]) +}\vrule\box\mybox\vrule + +\vrule\hbox to 5cm{0 \hfill9}\vrule + +\bigskip +Test number 13: text\_xwidth with different size: +\smallskip + +\directlua{ + local n = {codepoint = { + 48, % 0 + 49, % 1 + 50, % 2 + 51, % 3 + 52, % 4 + 53, % 5 + 54, % 6 + 55, % 7 + 56, % 8 + 57, % 9 + }} + local ga = gacanvas:new() + % (txt, x1, x2, ypos, ay) --> err + local err = ga:encode_Text_xwidth(n, tex.sp "0mm", tex.sp "50mm", 0, 0) + assert(not err, err) + local err = ga:encode_Text_xwidth(n, tex.sp "5mm", tex.sp "45mm", tex.sp "3mm", 0) + assert(not err, err) + local err = ga:encode_Text_xwidth(n, tex.sp "10mm", tex.sp "40mm", tex.sp "6mm", 0) + assert(not err, err) + local err = ga:encode_Text_xwidth(n, tex.sp "15mm", tex.sp "35mm", tex.sp "9mm", 0) + assert(not err, err) + local err = ga:encode_Text_xwidth(n, tex.sp "20mm", tex.sp "30mm", tex.sp "12mm", 0) + assert(not err, err) + local err = ga:encode_Text_xwidth(n, tex.sp "24mm", tex.sp "26mm", tex.sp "15mm", 0) + assert(not err, err) + driver:ga_to_hbox(ga, [[mybox]]) +}\vrule\box\mybox\vrule + +\bigskip +Test number 14: place bars and text as text\_xwidth: +\smallskip + +\directlua{ + local b = {} + for i = 0, 9 do + b[i*2 + 1] = i*12*pt + b[i*2 + 2] = 0.4*pt + end + b = {_yline = b} + local n = {codepoint = { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,}} + local ga = gacanvas:new() + % (vbar, x0, y1, y2) --> err + local err = ga:encode_Vbar(b, 0.0, 0*pt, 25*pt) + local err = ga:encode_Vbar(b, 0.0, 32*pt, 42*pt) + assert(not err, err) + % (txt, x1, x2, ypos, ay) --> err + local err = ga:encode_Text_xwidth(n, 0*pt, 108*pt, 25*pt, 0) + assert(not err, err) + driver:ga_to_hbox(ga, [[mybox]]) +}\vrule\box\mybox\vrule + +\smallskip +\directlua{ + local b = {} + for i = 0, 8 do + b[i*2 + 1] = i*12*pt + b[i*2 + 2] = 0.2*pt + end + b = {_yline = b} + local n = { 48, 49, 50, 51, string.byte([[x]]), 53, 54, 55, 56,} + n = {codepoint = n} + local ga = gacanvas:new() + % x0, y1, y2, bars + local err = ga:encode_Vbar(b, 0.0, 0*pt, 25*pt) + local err = ga:encode_Vbar(b, 0.0, 32*pt, 42*pt) + assert(not err, err) + % (txt, x1, x2, ypos, ay) --> err + local err = ga:encode_Text_xwidth(n, 0*pt, 96*pt, 25*pt, 0) + assert(not err, err) + driver:ga_to_hbox(ga, [[mybox]]) +}\vrule\box\mybox\vrule + +\bigskip +Test number 15: place text\_xwidth when text is only two chars long: + +\directlua{ + local n = {codepoint = { 48, 56,}} % 0 and 8 + local ga = gacanvas:new() + % (txt, x1, x2, ypos, ay) --> err + local err = ga:encode_Text_xwidth(n, 0*pt, 32*pt, 25*pt, 0) + assert(not err, err) + driver:ga_to_hbox(ga, [[mybox]]) +}\vrule\box\mybox\vrule + +\bye diff --git a/macros/luatex/generic/barracuda/test/test-ga-svg/001-ga-svg-test.lua b/macros/luatex/generic/barracuda/test/test-ga-svg/001-ga-svg-test.lua new file mode 100644 index 0000000000..2f932235cb --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-ga-svg/001-ga-svg-test.lua @@ -0,0 +1,28 @@ +-- test SVG driver output + +local barracuda = require "barracuda" +local driver = barracuda:get_driver() + +local mm = 186467.9811 -- 1 mm in sp +local ga1 = { _data = { 1, 1*mm, + 34, 10*mm, 100*mm, 0*mm, -- vline, y1, y2, x + 34, 20*mm, 90*mm, 10*mm, + 34, 30*mm, 80*mm, 20*mm, + 34, 40*mm, 70*mm, 30*mm, + 34, 50*mm, 60*mm, 40*mm, +}} + +driver:save("svg", ga1, "test-01") + +local ga2 = { _data = { + 1, 5*mm, + 34, 0*mm, 50*mm, 2.5*mm, + 33, 0*mm, 50*mm, 40*mm, +}} + +driver:save("svg", ga2, "test-02") + + + + + diff --git a/macros/luatex/generic/barracuda/test/test-ga-svg/002-ga-svg-test.lua b/macros/luatex/generic/barracuda/test/test-ga-svg/002-ga-svg-test.lua new file mode 100644 index 0000000000..8f10d6dfbf --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-ga-svg/002-ga-svg-test.lua @@ -0,0 +1,18 @@ +-- test SVG driver output + +local barracuda = require "barracuda" +local barcode = barracuda:get_barcode_class() +local driver = barracuda:get_driver() + +local opt = {module = 15 * 0.0254 * 186467, height = 12 * 186467} + +local c39, err = barcode:new_encoder("code39", nil, opt) +assert(not err, err) + +local symbol, err = c39:from_string("ABC000Z") +assert(not err, err) + +local canvas = barracuda:new_canvas() +symbol:append_ga(canvas) + +driver:save("svg", canvas, "test-code39") \ No newline at end of file diff --git a/macros/luatex/generic/barracuda/test/test-ga-svg/test-01.svg b/macros/luatex/generic/barracuda/test/test-ga-svg/test-01.svg new file mode 100644 index 0000000000..77e3ba6e0c --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-ga-svg/test-01.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + diff --git a/macros/luatex/generic/barracuda/test/test-ga-svg/test-02.svg b/macros/luatex/generic/barracuda/test/test-ga-svg/test-02.svg new file mode 100644 index 0000000000..ff7862b12f --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-ga-svg/test-02.svg @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/macros/luatex/generic/barracuda/test/test-ga-svg/test-code39.svg b/macros/luatex/generic/barracuda/test/test-ga-svg/test-code39.svg new file mode 100644 index 0000000000..8453a6bdeb --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-ga-svg/test-code39.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ABC000Z + + diff --git a/macros/luatex/generic/barracuda/test/test-i2of5/001-i2of5-test.pdf b/macros/luatex/generic/barracuda/test/test-i2of5/001-i2of5-test.pdf new file mode 100644 index 0000000000..3aa107681c Binary files /dev/null and b/macros/luatex/generic/barracuda/test/test-i2of5/001-i2of5-test.pdf differ diff --git a/macros/luatex/generic/barracuda/test/test-i2of5/001-i2of5-test.tex b/macros/luatex/generic/barracuda/test/test-i2of5/001-i2of5-test.tex new file mode 100644 index 0000000000..43c652d66a --- /dev/null +++ b/macros/luatex/generic/barracuda/test/test-i2of5/001-i2of5-test.tex @@ -0,0 +1,187 @@ +% !TeX program = LuaTeX +% Copyright (C) 2019 Roberto Giacomelli + +\newbox\mybox +\nopagenumbers + +\directlua{barracuda = require "barracuda"} + +Interleaved 2 of 5 encoder test. + +Test 1: one simple barcode with default parameters: + +\directlua{ +local barcode = barracuda:get_barcode_class() + +local enc, err = barcode:new_encoder("i2of5"); assert(not err, err) +local symbo, err = enc:from_uint(54654681); assert(not err, err) +local canvas = barracuda:new_canvas(); symbo:append_ga(canvas) +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\vrule A\vrule\box\mybox \vrule A\vrule + +\bigskip +Test 2: one simple barcode with default parameter: + +\directlua{ +local barcode = barracuda:get_barcode_class() +local enc, err = barcode:enc_by_name("i2of5"); assert(not err, err) +local symbo, err = enc:from_uint(1234567895); assert(not err, err) +local canvas = barracuda:new_canvas(); symbo:append_ga(canvas) +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\vrule A\vrule\box\mybox \vrule A\vrule + +% check digit tests + +\directlua{% verify check digits, the last one +local code = { + 7352621, + 9624764, + 7592881, + 5344147, + 742238, + 199766, + 4544739, + 2774794, + 8509895, + 8285157, + 5387564, + 5534371, + 2155678, + 4529545, + 4689164, + 1674910, + 5317837, + 4117698, +} +local barcode = barracuda:get_barcode_class() +local enc, err = barcode:enc_by_name("i2of5"); assert(not err, err) +for _, n in ipairs(code) do + local smbl, err = enc:from_uint(n, {check_digit_policy="verify"}) + assert(not err, err) +end +} + +\directlua{% check digits evaluation +local code = { + ["735262"] = 1, + ["962476"] = 4, + ["759288"] = 1, + ["534414"] = 7, + ["74223"] = 8, + ["19976"] = 6, + ["454473"] = 9, + ["277479"] = 4, + ["850989"] = 5, + ["828515"] = 7, + ["538756"] = 4, + ["553437"] = 1, + ["215567"] = 8, + ["452954"] = 5, + ["468916"] = 4, + ["167491"] = 0, + ["531783"] = 7, + ["411769"] = 8, +} +local barcode = barracuda:get_barcode_class() +local enc, err = barcode:enc_by_name("i2of5"); assert(not err, err) +for sc, ck in pairs(code) do + local n = tonumber(sc) + local c, err = enc:get_checkdigit(n) + assert(not err, err) + assert(c == ck, "Wrong check digit "..c.." vs "..ck .." for "..sc) +end +} + +\bigskip +Test 3: one simple barcode with check digit automatically added: + +\directlua{ +local barcode = barracuda:get_barcode_class() +local enc, err = barcode:enc_by_name("i2of5"); assert(not err, err) +local symbo, err = enc:from_uint(454473, {check_digit_policy="add"}) +assert(not err, err) +local canvas = barracuda:new_canvas(); symbo:append_ga(canvas) +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\vrule A\vrule\box\mybox \vrule A\vrule + +\bigskip +Test 4: a second simple barcode with check digit automatically added: + +\directlua{ +local barcode = barracuda:get_barcode_class() +local enc, err = barcode:enc_by_name("i2of5"); assert(not err, err) +local symbo, err = enc:from_uint(74223, {check_digit_policy="add"}) +assert(not err, err) +local canvas = barracuda:new_canvas(); symbo:append_ga(canvas) +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\vrule A\vrule\box\mybox \vrule A\vrule + +\bigskip +Test 5: a symbol with native check digits: + +\directlua{ +local barcode = barracuda:get_barcode_class() +local enc, err = barcode:enc_by_name("i2of5"); assert(not err, err) +local symbo, err = enc:from_uint(121891259, {check_digit_policy="verify"}) +assert(not err, err) +local canvas = barracuda:new_canvas(); symbo:append_ga(canvas) +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\vrule A\vrule\box\mybox \vrule A\vrule + +\bigskip +Test 6: bearer bars please: + +\directlua{ +local barcode = barracuda:get_barcode_class() +local enc, err = barcode:enc_by_name("i2of5"); assert(not err, err) +local symbo, err = enc:from_uint(747867239, {bearer_bars_enabled = true}) +assert(not err, err) +local canvas = barracuda:new_canvas(); symbo:append_ga(canvas) +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\vrule A\vrule\box\mybox \vrule A\vrule + +\bigskip +Test 7: bearer bars all around the symbol: + +\directlua{ +local barcode = barracuda:get_barcode_class() +local enc, err = barcode:enc_by_name("i2of5"); assert(not err, err) +local symbo, err = enc:from_uint(986790868, {bearer_bars_enabled = true, bearer_bars_layout="frame"}) +assert(not err, err) +local canvas = barracuda:new_canvas(); symbo:append_ga(canvas) +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\vrule A\vrule\box\mybox \vrule A\vrule + +\bigskip +Test 8: bearer bars all around the symbol (with string costructor): + +\directlua{ +local barcode = barracuda:get_barcode_class() +local enc, err = barcode:enc_by_name("i2of5"); assert(not err, err) +local symbo, err = enc:from_string("986790868", {bearer_bars_enabled = true, bearer_bars_layout="frame"}) +assert(not err, err) +local canvas = barracuda:new_canvas(); symbo:append_ga(canvas) +local drv = barracuda:get_driver() +drv:ga_to_hbox(canvas, "mybox") +} +\vrule A\vrule\box\mybox \vrule A\vrule + +That's all folks! + +\bye + + -- cgit v1.2.3