summaryrefslogtreecommitdiff
path: root/macros
diff options
context:
space:
mode:
Diffstat (limited to 'macros')
-rw-r--r--macros/generic/tracklang/CHANGES19
-rw-r--r--macros/generic/tracklang/README4
-rw-r--r--macros/generic/tracklang/samples/animals/animals.sty14
-rw-r--r--macros/generic/tracklang/samples/animals/sample-animals-babel.pdfbin14843 -> 14843 bytes
-rw-r--r--macros/generic/tracklang/samples/animals/sample-animals-de-poly.pdfbin3817 -> 3821 bytes
-rw-r--r--macros/generic/tracklang/samples/animals/sample-animals-de.pdfbin13613 -> 13613 bytes
-rw-r--r--macros/generic/tracklang/samples/animals/sample-animals-poly.pdfbin3555 -> 3556 bytes
-rw-r--r--macros/generic/tracklang/samples/animals/sample-animals.pdfbin12644 -> 12644 bytes
-rw-r--r--macros/generic/tracklang/samples/animals/sample-animals2-de.pdfbin13613 -> 13613 bytes
-rw-r--r--macros/generic/tracklang/samples/animals/sample-animals2-de2.pdfbin13613 -> 13613 bytes
-rw-r--r--macros/generic/tracklang/samples/animals/sample-animals2-de3.pdfbin13595 -> 13595 bytes
-rw-r--r--macros/generic/tracklang/samples/animals/sample-animals2-de4.pdfbin3818 -> 3817 bytes
-rw-r--r--macros/generic/tracklang/samples/animals/sample-animals2-poly.pdfbin3556 -> 3556 bytes
-rw-r--r--macros/generic/tracklang/samples/animals/sample-animals2.pdfbin12644 -> 12644 bytes
-rw-r--r--macros/generic/tracklang/samples/regions/sample-regions.pdfbin13148 -> 13148 bytes
-rw-r--r--macros/generic/tracklang/samples/regions/sample-regions2-manx.pdfbin19773 -> 19773 bytes
-rw-r--r--macros/generic/tracklang/samples/regions/sample-regions2-map.pdfbin25988 -> 25988 bytes
-rw-r--r--macros/generic/tracklang/samples/regions/sample-regions2-map2.pdfbin25840 -> 25840 bytes
-rw-r--r--macros/generic/tracklang/samples/regions/sample-regions2-map3.pdfbin24912 -> 24912 bytes
-rw-r--r--macros/generic/tracklang/samples/regions/sample-regions2-nomap.pdfbin25456 -> 25456 bytes
-rw-r--r--macros/generic/tracklang/samples/regions/sample-regions2.pdfbin14704 -> 14704 bytes
-rw-r--r--macros/generic/tracklang/samples/sample-tracklang.pdfbin19540 -> 19540 bytes
-rw-r--r--macros/generic/tracklang/samples/sample-tracklang2.pdfbin19790 -> 19790 bytes
-rw-r--r--macros/generic/tracklang/samples/sample-tracklang3.pdfbin19802 -> 19802 bytes
-rw-r--r--macros/generic/tracklang/samples/sample-tracklang4.pdfbin6199 -> 6198 bytes
-rw-r--r--macros/generic/tracklang/samples/sample-tracklang5.pdfbin16902 -> 16902 bytes
-rw-r--r--macros/generic/tracklang/samples/sample-tracklang6.pdfbin19885 -> 19885 bytes
-rw-r--r--macros/generic/tracklang/tracklang.dtx3234
-rw-r--r--macros/generic/tracklang/tracklang.ins2
-rw-r--r--macros/generic/tracklang/tracklang.pdfbin678702 -> 738081 bytes
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/american-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/apa6.bbx78
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/apa6.cbx24
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/apa6.dbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/austrian-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/biblatex-apa-test.pdfbin221809 -> 0 bytes
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/biblatex-apa6-test.pdfbin38864 -> 109742 bytes
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/biblatex-apa6.pdfbin92720 -> 92716 bytes
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/biblatex-apa6.tex16
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/brazilian-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/british-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/danish-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/dutch-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/english-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/french-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/galician-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/german-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/greek-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/italian-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/naustrian-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/ngerman-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/norsk-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/norwegian-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/nswissgerman-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/nynorsk-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/portuguese-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/russian-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/slovene-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/spanish-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/swedish-apa6.lbx2
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-apa6/swissgerman-apa6.lbx2
-rw-r--r--macros/latex/contrib/hvqrurl/Changes3
-rw-r--r--macros/latex/contrib/hvqrurl/README6
-rw-r--r--macros/latex/contrib/hvqrurl/doc/hvqrurl.pdfbin95763 -> 96082 bytes
-rw-r--r--macros/latex/contrib/hvqrurl/doc/hvqrurl.tex20
-rw-r--r--macros/latex/contrib/hvqrurl/latex/hvqrurl.sty2
-rw-r--r--macros/luatex/generic/barracuda/INSTALL.txt30
-rw-r--r--macros/luatex/generic/barracuda/LICENSE.txt339
-rw-r--r--macros/luatex/generic/barracuda/README.md77
-rw-r--r--macros/luatex/generic/barracuda/barracuda.pdfbin0 -> 54826 bytes
-rw-r--r--macros/luatex/generic/barracuda/barracuda.sty21
-rw-r--r--macros/luatex/generic/barracuda/example/001-13-ean-test.pdfbin0 -> 23619 bytes
-rw-r--r--macros/luatex/generic/barracuda/example/001-13-ean-test.tex220
-rw-r--r--macros/luatex/generic/barracuda/example/001-code128-test.lua32
-rw-r--r--macros/luatex/generic/barracuda/example/001-i2of5-test.pdfbin0 -> 19127 bytes
-rw-r--r--macros/luatex/generic/barracuda/example/001-i2of5-test.tex187
-rw-r--r--macros/luatex/generic/barracuda/example/003-code39-test.pdfbin0 -> 19827 bytes
-rw-r--r--macros/luatex/generic/barracuda/example/003-code39-test.tex53
-rw-r--r--macros/luatex/generic/barracuda/example/003-ean-test.pdfbin0 -> 3988 bytes
-rw-r--r--macros/luatex/generic/barracuda/example/003-ean-test.tex16
-rw-r--r--macros/luatex/generic/barracuda/example/004-ean-test.lua9
-rw-r--r--macros/luatex/generic/barracuda/example/006-code39-test.lua45
-rw-r--r--macros/luatex/generic/barracuda/example/006-six.svg653
-rw-r--r--macros/luatex/generic/barracuda/example/01-latex-code39.pdfbin0 -> 3621 bytes
-rw-r--r--macros/luatex/generic/barracuda/example/01-latex-code39.tex14
-rw-r--r--macros/luatex/generic/barracuda/example/8006194056290.svg89
-rw-r--r--macros/luatex/generic/barracuda/example/c128-123.svg42
-rw-r--r--macros/luatex/generic/barracuda/lib/barracuda.lua116
-rw-r--r--macros/luatex/generic/barracuda/lib/lib-barcode/barcode.lua544
-rw-r--r--macros/luatex/generic/barracuda/lib/lib-barcode/code128.lua341
-rw-r--r--macros/luatex/generic/barracuda/lib/lib-barcode/code39.lua381
-rw-r--r--macros/luatex/generic/barracuda/lib/lib-barcode/ean.lua790
-rw-r--r--macros/luatex/generic/barracuda/lib/lib-barcode/i2of5.lua378
-rw-r--r--macros/luatex/generic/barracuda/lib/lib-driver/driver.lua400
-rw-r--r--macros/luatex/generic/barracuda/lib/lib-driver/drv-pdfliteral.lua284
-rw-r--r--macros/luatex/generic/barracuda/lib/lib-driver/drv-svg.lua260
-rw-r--r--macros/luatex/generic/barracuda/lib/lib-geo/gacanvas.lua340
-rw-r--r--macros/luatex/generic/barracuda/lib/lib-geo/libgeo.lua289
98 files changed, 8801 insertions, 621 deletions
diff --git a/macros/generic/tracklang/CHANGES b/macros/generic/tracklang/CHANGES
index 90d299adc3..452a7d0727 100644
--- a/macros/generic/tracklang/CHANGES
+++ b/macros/generic/tracklang/CHANGES
@@ -1,3 +1,22 @@
+v1.4 (2019-11-30):
+
+ * tracklang.tex:
+
+ - Changed \TrackLangIfFileExists to also include script and
+ variant in file search (search order has changed slightly).
+
+ - Added \TrackLangRedefHook
+
+ - New commands provided to assist integration with language
+ packages:
+
+ \TrackLangAddExtraRegionFile
+ \TrackLangAddExtraScriptFile
+ \TrackLangProvidePredefinedLanguage
+ \TrackLangProvidePredefinedDialect
+
+ - New switch \ifTrackLangShowVerbose for debugging
+
v1.3.9 (2019-11-11):
* tracklang.tex:
diff --git a/macros/generic/tracklang/README b/macros/generic/tracklang/README
index 6c9b86401c..b3e7de27b1 100644
--- a/macros/generic/tracklang/README
+++ b/macros/generic/tracklang/README
@@ -1,6 +1,6 @@
-Generic TeX Bundle : tracklang v1.3.9
+Generic TeX Bundle : tracklang v1.4
-Last Modified : 2019-11-11
+Last Modified : 2019-11-30
Author : Nicola Talbot
diff --git a/macros/generic/tracklang/samples/animals/animals.sty b/macros/generic/tracklang/samples/animals/animals.sty
index 8b14d3b4ee..6d26c98621 100644
--- a/macros/generic/tracklang/samples/animals/animals.sty
+++ b/macros/generic/tracklang/samples/animals/animals.sty
@@ -1,9 +1,17 @@
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{animals}[2016/10/06 v1.2 (NLCT) Sample package to test tracklang.sty]
+\ProvidesPackage{animals}[2019/11/30 v1.2.1 (NLCT) Sample package to test tracklang.sty]
-\RequirePackage{tracklang}[2016/10/07]
+\RequirePackage{tracklang}[2019/11/30]
-\DeclareOption*{\TrackLanguageTag{\CurrentOption}}
+\DeclareOption*{%
+ \TrackIfKnownLanguage{\CurrentOption}%
+ {\PackageInfo{animals}{Tracking language `\CurrentOption'}}% successful
+ {% failed
+ \PackageError{animals}%
+ {Unknown language specification `\CurrentOption'}%
+ {You need to supply either a known dialect label or a valid language tag}%
+ }%
+}
\ProcessOptions
diff --git a/macros/generic/tracklang/samples/animals/sample-animals-babel.pdf b/macros/generic/tracklang/samples/animals/sample-animals-babel.pdf
index 330ff6a026..2485ee53c7 100644
--- a/macros/generic/tracklang/samples/animals/sample-animals-babel.pdf
+++ b/macros/generic/tracklang/samples/animals/sample-animals-babel.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/animals/sample-animals-de-poly.pdf b/macros/generic/tracklang/samples/animals/sample-animals-de-poly.pdf
index 509be5eb63..88669915f9 100644
--- a/macros/generic/tracklang/samples/animals/sample-animals-de-poly.pdf
+++ b/macros/generic/tracklang/samples/animals/sample-animals-de-poly.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/animals/sample-animals-de.pdf b/macros/generic/tracklang/samples/animals/sample-animals-de.pdf
index d1448c319d..07962fd91a 100644
--- a/macros/generic/tracklang/samples/animals/sample-animals-de.pdf
+++ b/macros/generic/tracklang/samples/animals/sample-animals-de.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/animals/sample-animals-poly.pdf b/macros/generic/tracklang/samples/animals/sample-animals-poly.pdf
index 1075134907..476f2f418d 100644
--- a/macros/generic/tracklang/samples/animals/sample-animals-poly.pdf
+++ b/macros/generic/tracklang/samples/animals/sample-animals-poly.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/animals/sample-animals.pdf b/macros/generic/tracklang/samples/animals/sample-animals.pdf
index c799fb8f3a..3ec9a8145c 100644
--- a/macros/generic/tracklang/samples/animals/sample-animals.pdf
+++ b/macros/generic/tracklang/samples/animals/sample-animals.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/animals/sample-animals2-de.pdf b/macros/generic/tracklang/samples/animals/sample-animals2-de.pdf
index 07c8bf0ec6..a509e00866 100644
--- a/macros/generic/tracklang/samples/animals/sample-animals2-de.pdf
+++ b/macros/generic/tracklang/samples/animals/sample-animals2-de.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/animals/sample-animals2-de2.pdf b/macros/generic/tracklang/samples/animals/sample-animals2-de2.pdf
index 292dcd486f..c6a6e94de9 100644
--- a/macros/generic/tracklang/samples/animals/sample-animals2-de2.pdf
+++ b/macros/generic/tracklang/samples/animals/sample-animals2-de2.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/animals/sample-animals2-de3.pdf b/macros/generic/tracklang/samples/animals/sample-animals2-de3.pdf
index 095c57d130..09f9b2eb4d 100644
--- a/macros/generic/tracklang/samples/animals/sample-animals2-de3.pdf
+++ b/macros/generic/tracklang/samples/animals/sample-animals2-de3.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/animals/sample-animals2-de4.pdf b/macros/generic/tracklang/samples/animals/sample-animals2-de4.pdf
index 86802c70d3..271acfcba4 100644
--- a/macros/generic/tracklang/samples/animals/sample-animals2-de4.pdf
+++ b/macros/generic/tracklang/samples/animals/sample-animals2-de4.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/animals/sample-animals2-poly.pdf b/macros/generic/tracklang/samples/animals/sample-animals2-poly.pdf
index d0faec29a6..5f1807767c 100644
--- a/macros/generic/tracklang/samples/animals/sample-animals2-poly.pdf
+++ b/macros/generic/tracklang/samples/animals/sample-animals2-poly.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/animals/sample-animals2.pdf b/macros/generic/tracklang/samples/animals/sample-animals2.pdf
index bd3e154a86..8ef941783a 100644
--- a/macros/generic/tracklang/samples/animals/sample-animals2.pdf
+++ b/macros/generic/tracklang/samples/animals/sample-animals2.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/regions/sample-regions.pdf b/macros/generic/tracklang/samples/regions/sample-regions.pdf
index 693d8b75e9..78c1c87385 100644
--- a/macros/generic/tracklang/samples/regions/sample-regions.pdf
+++ b/macros/generic/tracklang/samples/regions/sample-regions.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/regions/sample-regions2-manx.pdf b/macros/generic/tracklang/samples/regions/sample-regions2-manx.pdf
index 40eab364f8..83340a0ce7 100644
--- a/macros/generic/tracklang/samples/regions/sample-regions2-manx.pdf
+++ b/macros/generic/tracklang/samples/regions/sample-regions2-manx.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/regions/sample-regions2-map.pdf b/macros/generic/tracklang/samples/regions/sample-regions2-map.pdf
index 033fec24ce..635f2c1f79 100644
--- a/macros/generic/tracklang/samples/regions/sample-regions2-map.pdf
+++ b/macros/generic/tracklang/samples/regions/sample-regions2-map.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/regions/sample-regions2-map2.pdf b/macros/generic/tracklang/samples/regions/sample-regions2-map2.pdf
index 85f8f1f150..e664c00877 100644
--- a/macros/generic/tracklang/samples/regions/sample-regions2-map2.pdf
+++ b/macros/generic/tracklang/samples/regions/sample-regions2-map2.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/regions/sample-regions2-map3.pdf b/macros/generic/tracklang/samples/regions/sample-regions2-map3.pdf
index bbd85ced7b..aac08c391d 100644
--- a/macros/generic/tracklang/samples/regions/sample-regions2-map3.pdf
+++ b/macros/generic/tracklang/samples/regions/sample-regions2-map3.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/regions/sample-regions2-nomap.pdf b/macros/generic/tracklang/samples/regions/sample-regions2-nomap.pdf
index 46f836a3e3..df2d0bc468 100644
--- a/macros/generic/tracklang/samples/regions/sample-regions2-nomap.pdf
+++ b/macros/generic/tracklang/samples/regions/sample-regions2-nomap.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/regions/sample-regions2.pdf b/macros/generic/tracklang/samples/regions/sample-regions2.pdf
index 6c39680885..0b26023e24 100644
--- a/macros/generic/tracklang/samples/regions/sample-regions2.pdf
+++ b/macros/generic/tracklang/samples/regions/sample-regions2.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/sample-tracklang.pdf b/macros/generic/tracklang/samples/sample-tracklang.pdf
index a2c23d601b..aca2dd6c84 100644
--- a/macros/generic/tracklang/samples/sample-tracklang.pdf
+++ b/macros/generic/tracklang/samples/sample-tracklang.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/sample-tracklang2.pdf b/macros/generic/tracklang/samples/sample-tracklang2.pdf
index b8bad2af52..ef391b9912 100644
--- a/macros/generic/tracklang/samples/sample-tracklang2.pdf
+++ b/macros/generic/tracklang/samples/sample-tracklang2.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/sample-tracklang3.pdf b/macros/generic/tracklang/samples/sample-tracklang3.pdf
index 61b4f28c70..fa54737ec5 100644
--- a/macros/generic/tracklang/samples/sample-tracklang3.pdf
+++ b/macros/generic/tracklang/samples/sample-tracklang3.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/sample-tracklang4.pdf b/macros/generic/tracklang/samples/sample-tracklang4.pdf
index d42a97d715..ec3ffb3d4d 100644
--- a/macros/generic/tracklang/samples/sample-tracklang4.pdf
+++ b/macros/generic/tracklang/samples/sample-tracklang4.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/sample-tracklang5.pdf b/macros/generic/tracklang/samples/sample-tracklang5.pdf
index 8c05bc36f1..48c0ad786b 100644
--- a/macros/generic/tracklang/samples/sample-tracklang5.pdf
+++ b/macros/generic/tracklang/samples/sample-tracklang5.pdf
Binary files differ
diff --git a/macros/generic/tracklang/samples/sample-tracklang6.pdf b/macros/generic/tracklang/samples/sample-tracklang6.pdf
index 47c5c053fd..037e2dade1 100644
--- a/macros/generic/tracklang/samples/sample-tracklang6.pdf
+++ b/macros/generic/tracklang/samples/sample-tracklang6.pdf
Binary files differ
diff --git a/macros/generic/tracklang/tracklang.dtx b/macros/generic/tracklang/tracklang.dtx
index e7e28decc4..e071563fe3 100644
--- a/macros/generic/tracklang/tracklang.dtx
+++ b/macros/generic/tracklang/tracklang.dtx
@@ -1,16 +1,16 @@
%\iffalse
% tracklang.dtx generated using makedtx version 1.2 (c) Nicola Talbot
% Command line args:
-% -section "chapter"
-% -author "Nicola Talbot"
% -doc "tracklang-manual.tex"
+% -author "Nicola Talbot"
% -src "tracklang.sty\Z=>tracklang.sty"
% -src "tracklang.tex\Z=>tracklang.tex"
% -src "tracklang-region-codes.tex\Z=>tracklang-region-codes.tex"
% -src "tracklang-scripts.sty\Z=>tracklang-scripts.sty"
% -src "tracklang-scripts.tex\Z=>tracklang-scripts.tex"
+% -section "chapter"
% tracklang
-% Created on 2019/11/11 16:00
+% Created on 2019/12/1 17:41
%\fi
%\iffalse
%<*package>
@@ -59,7 +59,7 @@
pdfauthor={Nicola L.C. Talbot},
pdftitle={tracklang: tracking language options}]{hyperref}
-\CheckSum{3986}
+\CheckSum{6156}
\appto\MacroFont{\scriptsize}
\renewcommand*{\usage}[1]{\textit{\hyperpage{#1}}}
@@ -278,11 +278,11 @@ and~\ref{tab:nonisoopts}}
%
%\MakeShortVerb{"}
%
-%\title{tracklang v1.3.9:
+%\title{tracklang v1.4:
%tracking language options}
%\author{Nicola L. C. Talbot\\\url{http://www.dickimaw-books.com/}}
%
-%\date{2019-11-11}
+%\date{2019-11-30}
%\maketitle
%
%\begin{abstract}
@@ -326,9 +326,14 @@ and~\ref{tab:nonisoopts}}
%hard-coding the various language labels used by different language
%packages.
%
-%Related article: \qt{Localisation of \TeX\ documents:
+%Related articles: \qt{Localisation of \TeX\ documents:
%\styfmt{tracklang}.} TUGBoat, Volume~37 (2016), No.~3
-%(\url{http://www.tug.org/TUGboat/tb37-3/tb117talbot.pdf}).
+%(\url{http://www.tug.org/TUGboat/tb37-3/tb117talbot.pdf}),
+%\href{https://www.dickimaw-books.com/latex/tracklang}{Localisation
+%with \texttt{tracklang.tex}},
+%and
+%\href{https://www.dickimaw-books.com/faq.php?action=view&category=tracklang}{\texttt{tracklang}
+%FAQ}.
%
%\clearpage
%\tableofcontents
@@ -381,10 +386,15 @@ and~\ref{tab:nonisoopts}}
%which is suboptimal but at least provides some information.
%(\sty{polyglossia} now provides \cs{xpg@loaded}, which
%\sty{tracklang} uses to track the root languages, but the language variant
-%command \cs{xpg@vloaded} only seems to be set when the language
+%command \cs{xpg@loaded} only seems to be set when the language
%changes, which doesn't occur until the start of the \env{document}
%environment.)
%
+%I also can't find any way of detecting a list of languages loaded
+%through \sty{babel}'s new \ics{babelprovide} command. As far as I
+%can tell, the only stored list is in \cs{bbl@loaded} which only
+%contains the languages loaded through package options.
+%
%If the \sty{ngerman} package has been loaded, \styfmt{tracklang}
%effectively does
%\begin{verbatim}
@@ -484,11 +494,11 @@ and~\ref{tab:nonisoopts}}
%operating system:
%\begin{verbatim}
%\input texosquery
-%\input tracklang %v1.3
+%\input tracklang % v1.3
%\TrackLangFromEnv
%% load packages that use tracklang for localisation
%\end{verbatim}
-%Or (\sty{texosquery} v1.2 currently pending)
+%Or (\sty{texosquery} v1.2)
%\begin{verbatim}
%\input texosquery % v1.2
%\input tracklang % v1.3
@@ -497,9 +507,10 @@ and~\ref{tab:nonisoopts}}
%\TrackLanguageTag{\langtag}
%% load packages that use tracklang for localisation
%\end{verbatim}
-%Anticipate the release of \styfmt{texosquery} v1.2:
+%Linux user who may or may not have \app{texosquery} setup to run in the
+%shell escape:
%\begin{verbatim}
-%\input texosquery
+%\input texosquery
%\input tracklang % v1.3
%
%\ifx\TeXOSQueryLangTag\undefined
@@ -620,20 +631,23 @@ and~\ref{tab:nonisoopts}}
%
%Let's suppose you are developing a package called
%\texttt{mypackage.sty} or \texttt{mypackage.tex} and you want
-%to find out what languages the document author has requested.
+%to find out what languages the document author has requested. (See also:
+%\href{https://www.dickimaw-books.com/latex/tracklang/otherpkg.shtml}{Using
+%\texttt{tracklang.tex} in Packages with Localisation Features}.)
%
%Generic use:
%\begin{verbatim}
%\input tracklang
%\end{verbatim}
%(Most of the commands used in this section require at least
-%\styfmt{tracklang} version 1.3.)
+%\styfmt{tracklang} version 1.3 but 1.4 is better if you want to
+%include the script tag in the ldf files.)
%Note that \texttt{tracklang.tex} has a check to determine if
%it's already been loaded, so you don't need to worry about that.
%
%\LaTeX\ use:
%\begin{verbatim}
-%\RequirePackage{tracklang}[2016/10/07]% at least v1.3
+%\RequirePackage{tracklang}[2019/11/30]% at least v1.4
%\end{verbatim}
%This will picked up any language options supplied in the document
%class options and will also detect if \sty{babel} or
@@ -648,6 +662,19 @@ and~\ref{tab:nonisoopts}}
%\begin{verbatim}
%\usepackage[hy-Latn-IT-arevela]{mypackage}
%\end{verbatim}
+%With at least version 1.4, it's better to use \ics{TrackIfKnownLanguage}:
+%\begin{verbatim}
+%\DeclareOption*{%
+% \TrackIfKnownLanguage{\CurrentOption}%
+% {\PackageInfo{mypackage}{Tracking language `\CurrentOption'}}% successful
+% {% failed
+% \PackageError{mypackage}%
+% {Unknown language specification `\CurrentOption'}%
+% {You need to supply either a known dialect label or a valid language tag}%
+% }%
+%}
+%\end{verbatim}
+%
%The rest of the example package in this section uses generic code.
%
%If you want to fetch the locale information from the operating
@@ -685,11 +712,14 @@ and~\ref{tab:nonisoopts}}
%\end{verbatim}
%
%Each resource file has the naming scheme \meta{prefix}\texttt{-}
-%\meta{tag}\texttt{.ldf}. In this example, the \meta{prefix} is
-%\texttt{mypackage}. The \meta{tag} may be the language or dialect label
+%\meta{localeid}\texttt{.ldf}. In this example, the \meta{prefix} is
+%\texttt{mypackage}. The \meta{localeid} part may be the language or dialect label
%(for example, \texttt{english} or \texttt{british}) or a combination of the ISO
%language and region codes (for example, \texttt{en-GB} or
-%\texttt{en} or \texttt{GB}).
+%\texttt{en} or \texttt{GB}). As from version 1.4, \meta{localeid} may
+%also include the script or variant. (See the definition of
+%\ics{IfTrackedLanguageFileExists} on page~\pageref{pg:filesearch}
+%for further details.)
%
%The simplest scheme is to use the root language label (not the
%dialect label) for the base language settings and use the ISO
@@ -708,6 +738,11 @@ and~\ref{tab:nonisoopts}}
%found). For other hooks, such as \cs{date\ldots}, use
%\ics{TrackLangAddToHook}\marg{code}\marg{hook type} instead.
%
+%With pre-v1.4 versions of \sty{tracklang}, the script isn't included
+%in the file search. If it's needed then either require at least v1.4
+%or have a base ldf file that tries to load a version for the
+%particular script (which can be accessed with
+%\cs{CurrentTrackedScript}).
%Here's an example for a language with different writing systems.
%The resource file for Serbian \texttt{mypackage-serbian.ldf}:
%\begin{verbatim}
@@ -737,6 +772,9 @@ and~\ref{tab:nonisoopts}}
%}
%\end{verbatim}
%
+%With v1.4+ you would just need \texttt{mypackage-sr-Latn.ldf},
+%\texttt{mypackage-sr-Cyrl.ldf} for the regionless versions.
+%
%\section{Language Packages}
%\label{sec:summary-langpkg}
%
@@ -747,7 +785,9 @@ and~\ref{tab:nonisoopts}}
%the document author has requested. You can use the
%\styfmt{tracklang} package to identify this information
%by tracking the requested localisation, so that other packages
-%can have a consistent way of querying it.
+%can have a consistent way of querying it. (See also:
+%\href{https://www.dickimaw-books.com/latex/tracklang/langpkg.shtml}{Integrating
+%\texttt{tracklang.tex} into Language Packages}.)
%
%Generic use:
%\begin{verbatim}
@@ -755,7 +795,7 @@ and~\ref{tab:nonisoopts}}
%\end{verbatim}
%Alternative \LaTeX\ use:
%\begin{verbatim}
-%\RequirePackage{tracklang}[2016/10/07] % v1.3
+%\RequirePackage{tracklang}[2019/11/30] % v1.4
%\end{verbatim}
%Unlike \cs{input}, \cs{RequirePackage} will allow \styfmt{tracklang}
%to pick up the document class options, but using \cs{RequirePackage}
@@ -795,9 +835,8 @@ and~\ref{tab:nonisoopts}}
%\texttt{british}, but the above method will change that mapping
%to \texttt{UKenglish}.)
%
-%This now means that \cs{TrackLangAddToCaptions} command used
-%at the end of \sectionref{sec:summary-localepkg} above can
-%find your caption hook. You don't need the map if your dialect
+%This now means that \cs{TrackLangAddToHook} and \cs{TrackLangRedefHook} commands can
+%find your language hooks. You don't need the map if your dialect
%label is the same as \styfmt{tracklang}'s root language label
%for that locale. For example:
%\begin{verbatim}
@@ -820,11 +859,13 @@ and~\ref{tab:nonisoopts}}
%tracked with that language. For example:
%\begin{verbatim}
%\def\selectlanguage#1{%
-% % set up hyphenation patterns etc
% \SetCurrentTrackedDialect{#1}%
+% % set up hyphenation patterns etc
%}
%\end{verbatim}
-%See the example in \sectionref{sec:summary-doc}.
+%See the example in \sectionref{sec:summary-doc} or the example in
+%\href{https://www.dickimaw-books.com/latex/tracklang/langpkg.shtml}{Integrating
+%\texttt{tracklang.tex} into Language Packages}.
%
%\chapter{Generic Use}
%\label{sec:generic}
@@ -1342,9 +1383,9 @@ and~\ref{tab:nonisoopts}}
%\end{verbatim}
%will add a new dialect with the label \texttt{xxYYmod} and
%\begin{verbatim}
-%\TrackLanguageTag{xx-YY-Latn}
+%\TrackLanguageTag{xx-Latn-YY}
%\end{verbatim}
-%will add a new dialect with the label \texttt{xxYYLatn}.
+%will add a new dialect with the label \texttt{xxLatnYY}.
%
%\begin{important}
%If \cs{TrackLocale} or \cs{TrackLangFromEnv} find a modifier, the
@@ -1412,8 +1453,8 @@ and~\ref{tab:nonisoopts}}
%\begin{verbatim}
%\input tracklang
%\TrackLanguageTag{en-826}
-%Has en-GB-Latn been tracked?
-%\GetTrackedDialectFromLanguageTag{en-GB-Latn}{\thisdialect}%
+%Has en-Latn-GB been tracked?
+%\GetTrackedDialectFromLanguageTag{en-Latn-GB}{\thisdialect}%
%\ifx\thisdialect\empty
% No!
%\else
@@ -1834,22 +1875,22 @@ and~\ref{tab:nonisoopts}}
%that each language module has a different maintainer will the
%maintainers know what tag to use for their language?
%
-%To help with this, \styfmt{tracklang} provides:
+%\label{pg:filesearch}To help with this, \styfmt{tracklang} provides:
%\begin{definition}
%\ics{IfTrackedLanguageFileExists}\marg{dialect}\marg{prefix}\marg{suffix}\marg{true part}\marg{false part}
%\end{definition}
%This attempts to find the file called
-%\meta{prefix}\meta{tag}\meta{suffix} where \meta{tag} is determined
-%from \meta{dialect}. If the file is found
+%\meta{prefix}\meta{localeid}\meta{suffix} where \meta{localeid} is determined
+%from \meta{dialect} (see below). If the file is found
%\begin{definition}
%\ics{CurrentTrackedTag}
%\end{definition}
-%is set to \meta{tag} and \meta{true part} is done, otherwise
+%is set to \meta{localeid} and \meta{true part} is done, otherwise
%\meta{false part} is done. If this command
%is empty, then the dialect hasn't been detected. If the dialect
%has been detected, but no file can be found, then
%\ics{CurrentTrackedTag} is set to the final attempt at determining
-%\meta{tag}.
+%\meta{localeid}.
%
%There's a convenient shortcut command new to version 1.3:
%\begin{definition}[\DescribeMacro\TrackLangRequireDialect]
@@ -1908,12 +1949,11 @@ and~\ref{tab:nonisoopts}}
%Otherwise it may be empty or it may expand to the
%ISO~639-1 or ISO~639-2 or ISO~639-3 code.
%
-%As from version 1.3, the following are also available, but
-%don't contribute to the tag.
%\begin{definition}
%\ics{CurrentTrackedDialectModifier}
%\end{definition}
-%The dialect's modifier or empty if not set.
+%The dialect's modifier or empty if not set. (This is set but not
+%used in the set of possible \meta{localeid} values.)
%
%\begin{definition}
%\ics{CurrentTrackedDialectVariant}
@@ -1939,83 +1979,110 @@ and~\ref{tab:nonisoopts}}
%\begin{definition}
%\ics{CurrentTrackedDialectScript}
%\end{definition}
-%The dialect's script. If the
-%dialect doesn't have the script set, the default script
-%is used instead. For example, the file \texttt{foo-serbian.ldf}
-%could test for the existence of the file
-%\begin{verbatim}
-%foo-serbian-\CurrentTrackedDialectScript.ldf
-%\end{verbatim}
-%and load it if it exists. The most convenient way is to
-%use \cs{TrackLangRequestResource} (described below):
-%\begin{verbatim}
-%\TrackLangRequestResource
-% {serbian-\CurrentTrackedDialectScript}
-% {}% not found, set default code here
-%\end{verbatim}
-%The Cyrillic settings could then be placed in
-%\texttt{foo-serbian-Cyrl.ldf} and the Latin settings in
-%\texttt{foo-serbian-Latn.ldf}.
+%The dialect's script. If the dialect doesn't have the script set,
+%the default script for the language is used instead.
%
-%The \meta{tag} is determined as follows:
-%\begin{enumerate}
+%\cs{IfTrackedLanguageFileExists} behaves as follows:
+%\begin{itemize}
% \item If no dialect with the given label has been
% detected, the condition evaluates to \emph{false} and
% \ics{CurrentTrackedTag} is empty.
+% \item If a dialect with the given label has been detected, then:
+% \begin{itemize}
+% \item For each possible \meta{localeid} in an ordered set of tags determined by
+% the dialect label (see below), the first file matching
+% \meta{prefix}\meta{localeid}\meta{suffix} that's found on
+% \TeX's path results in the condition evaluating to \emph{true} and
+% \ics{CurrentTrackedTag} is set to the current \meta{localeid} in the
+% set. The rest of the set of possible values of \meta{localeid} is skipped.
+% \item If no file matching \meta{prefix}\meta{localeid}\meta{suffix} is
+% found on \TeX's path, then the condition evaluates to \emph{false}
+% and \ics{CurrentTrackedTag} is set to the final \meta{localeid} in the
+% set (the language label).
+% \end{itemize}
+%\end{itemize}
%
-% \item If there is no language code (ISO~639-1 or 639-2 or 639-3):
-%
-% \begin{enumerate}
-% \item If there's also no ISO~3166-1 code (\ics{CurrentTrackedRegion}
-% is empty), then \meta{tag} (\ics{CurrentTrackedTag}) is set to the
-% root language (\ics{CurrentTrackedLanguage}). If the file
-% \meta{prefix}\meta{tag}\meta{suffix} exists, the condition will evaluate to
-% \emph{true} otherwise it will evaluate to \emph{false}.
-%
-% \item If there is an ISO~3166-1 code, then \meta{tag}
-% (\ics{CurrentTrackedTag}) will be set to \ics{CurrentTrackedRegion}
-% and if the file \meta{prefix}\meta{tag}\meta{suffix} exists,
-% the condition will evaluate to \emph{true} otherwise it will evaluate
-% to \emph{false}.
-% \end{enumerate}
-%
-% \item If \ics{CurrentTrackedRegion} is empty (no ISO~3166-1
-% territory code)
-% then the \meta{tag} (\ics{CurrentTrackedTag}) is set to just
-% \ics{CurrentTrackedIsoCode}.
-%
-% If the file \meta{prefix}\meta{tag}\meta{suffix} exists, the condition will
-% evaluate to \emph{true}. If the file doesn't exist and
-% there are additional ISO language codes available (639-2 or 639-3)
-% then the test will be repeated for the next code.
-% If the test still fails, then the condition evaluates to \emph{false}.
-%
-% \item\label{itm:lang-country} The \meta{tag} (\ics{CurrentTrackedTag}) is then set to
-%\begin{verbatim}
-%\CurrentTrackedIsoCode-\CurrentTrackedRegion
-%\end{verbatim}
-% and if the file \meta{prefix}\meta{tag}\meta{suffix} exists,
-% the condition evaluates to \emph{true}.
-%
-% \item The \meta{tag} (\ics{CurrentTrackedTag}) is then set to
-% just \ics{CurrentTrackedIsoCode}, and if the file
-% \meta{prefix}\meta{tag}\meta{suffix} exists,
-% the condition evaluates to \emph{true}. If the file doesn't exist
-% and there are other ISO codes (639-2 or 639-3),
-% then \ics{CurrentTrackedIsoCode} is set to the next available
-% language code and step~\ref{itm:lang-country} is retried.
-%
-% \item If there is an ISO~3166-1 region code, the
-% \meta{tag} (\ics{CurrentTrackedTag}) is then set to
-% \ics{CurrentTrackedRegion},
-% and if the file \meta{prefix}\meta{tag}\meta{suffix} exists,
-% the condition evaluates to \emph{true}.
-%
-% \item Finally, the \meta{tag} (\ics{CurrentTrackedTag}) is set to
-% the root language label and if the file
-% \meta{prefix}\meta{tag}\meta{suffix} exist the condition
-% evaluates to \emph{true} otherwise it evaluates to \emph{false}.
-%
+%The ordered set of possible values of \meta{localeid} is determined from
+%the given dialect.
+%\begin{important}
+%The ordering has changed in version 1.4, which now also includes the
+%script and variant. This new ordering should typically make the more
+%common combinations closer to the start of the search.
+%\end{important}
+%The possible values of \meta{localeid} are listed below in the order of priority used
+%by \cs{IfTrackedLanguageFileExists}. Note that the set may contain
+%repetitions (for example, if the dialect label is the same as the
+%root language label). If an item contains an element that hasn't
+%been set (such as the ISO~639-3 code or a sub-language \meta{sublang} or variant) then
+%that item is skipped.
+%\begin{enumerate}
+%\item \meta{localeid} is just the value of \ics{CurrentTrackedLanguageTag}.
+%\item \meta{localeid} is just the dialect label.
+%
+%\item \meta{localeid} is
+%\meta{ISO~639-1}\texttt{-}\meta{sublang}\texttt{-}\meta{script}\texttt{-}\meta{region}.
+%\item \meta{localeid} is
+%\meta{ISO~639-1}\texttt{-}\meta{script}\texttt{-}\meta{region}.
+%\item \meta{localeid} is
+%\meta{ISO~639-1}\texttt{-}\meta{sublang}\texttt{-}\meta{region} (if there's no script or if
+%the script is the default for the given language).
+%\meta{ISO~639-1}\texttt{-}\meta{region} (if there's no script or if
+%the script is the default for the given language).
+%\item \meta{localeid} is
+%\meta{ISO~639-1}\texttt{-}\meta{sublang}\texttt{-}\meta{script}.
+%\item \meta{localeid} is
+%\meta{ISO~639-1}\texttt{-}\meta{script}.
+%\item \meta{localeid} is \meta{ISO~639-1}\texttt{-}\meta{sublang}.
+%\item \meta{localeid} is just \meta{ISO~639-1}.
+%
+%\item \meta{localeid} is
+%\meta{ISO~639-2}\texttt{-}\meta{sublang}\texttt{-}\meta{script}\texttt{-}\meta{region}.
+%\item \meta{localeid} is
+%\meta{ISO~639-2}\texttt{-}\meta{script}\texttt{-}\meta{region}.
+%\item \meta{localeid} is
+%\meta{ISO~639-2}\texttt{-}\meta{sublang}\texttt{-}\meta{region} (if there's no script or if
+%the script is the default for the given language).
+%\meta{ISO~639-2}\texttt{-}\meta{region} (if there's no script or if
+%the script is the default for the given language).
+%\item \meta{localeid} is
+%\meta{ISO~639-2}\texttt{-}\meta{sublang}\texttt{-}\meta{script}.
+%\item \meta{localeid} is
+%\meta{ISO~639-2}\texttt{-}\meta{script}.
+%\item \meta{localeid} is \meta{ISO~639-2}\texttt{-}\meta{sublang}.
+%\item \meta{localeid} is just \meta{ISO~639-2}.
+%
+%\item \meta{localeid} is
+%\meta{ISO~639-3}\texttt{-}\meta{sublang}\texttt{-}\meta{script}\texttt{-}\meta{region}.
+%\item \meta{localeid} is
+%\meta{ISO~639-3}\texttt{-}\meta{script}\texttt{-}\meta{region}.
+%\item \meta{localeid} is
+%\meta{ISO~639-3}\texttt{-}\meta{sublang}\texttt{-}\meta{region} (if there's no script or if
+%the script is the default for the given language).
+%\meta{ISO~639-3}\texttt{-}\meta{region} (if there's no script or if
+%the script is the default for the given language).
+%\item \meta{localeid} is
+%\meta{ISO~639-3}\texttt{-}\meta{sublang}\texttt{-}\meta{script}.
+%\item \meta{localeid} is
+%\meta{ISO~639-3}\texttt{-}\meta{script}.
+%\item \meta{localeid} is \meta{ISO~639-3}\texttt{-}\meta{sublang}.
+%\item \meta{localeid} is just \meta{ISO~639-3}.
+%
+%\item \meta{localeid} is just \meta{region}.
+%
+%\item \meta{localeid} is
+%\meta{ISO~639-1}\texttt{-}\meta{sublang}\texttt{-}\meta{variant}
+%or \meta{ISO~639-1}\texttt{-}\meta{variant} if \meta{sublang} is missing.
+%
+%\item \meta{localeid} is
+%\meta{ISO~639-2}\texttt{-}\meta{sublang}\texttt{-}\meta{variant}
+%or \meta{ISO~639-2}\texttt{-}\meta{variant} if \meta{sublang} is missing.
+%
+%\item \meta{localeid} is
+%\meta{ISO~639-3}\texttt{-}\meta{sublang}\texttt{-}\meta{variant}
+%or \meta{ISO~639-3}\texttt{-}\meta{variant} if \meta{sublang} is missing.
+%
+%\item \meta{localeid} is just the value of \ics{CurrentTrackedLanguage}
+%(the root language label).
%\end{enumerate}
%
%For example (pre v1.3):
@@ -2055,35 +2122,82 @@ and~\ref{tab:nonisoopts}}
%If, for example, \ics{ThisDialect} is \texttt{british}, then the file search will
%be in the order:
%\begin{enumerate}
-%\item \texttt{mypackage-british.ldf}
-%\item \texttt{mypackage-en-GB.ldf}
-%\item \texttt{mypackage-eng-GB.ldf}
-%\item \texttt{mypackage-en.ldf}
-%\item \texttt{mypackage-eng.ldf}
-%\item \texttt{mypackage-GB.ldf}
-%\item \texttt{mypackage-english.ldf}
+%\item \texttt{mypackage-en-GB.ldf} (language tag)
+%\item \texttt{mypackage-british.ldf} (dialect label)
+%
+%\item \texttt{mypackage-en-Latn-GB.ldf} (639-1 language code, script, region)
+%\item \texttt{mypackage-en-GB.ldf} (639-1 language code, region)
+%\item \texttt{mypackage-en-Latn.ldf} (639-1 language code, script)
+%\item \texttt{mypackage-en.ldf} (639-1 language code)
+%
+%\item \texttt{mypackage-eng-Latn-GB.ldf} (639-2 language code, script, region)
+%\item \texttt{mypackage-eng-GB.ldf} (639-2 language code, region)
+%\item \texttt{mypackage-eng-Latn.ldf} (639-2 language code, script)
+%\item \texttt{mypackage-eng.ldf} (639-2 language code)
+%
+%\item \texttt{mypackage-GB.ldf} (region)
+%\item \texttt{mypackage-english.ldf} (language label)
+%\end{enumerate}
+%
+%If, for example, \ics{ThisDialect} is \texttt{naustrian}, then the file search will
+%be in the order:
+%\begin{enumerate}
+%\item \texttt{mypackage-de-AT-1996.ldf} (language tag)
+%\item \texttt{mypackage-naustrian.ldf} (dialect label)
+%
+%\item \texttt{mypackage-de-Latn-AT.ldf} (639-1 language code, script, region)
+%\item \texttt{mypackage-de-AT.ldf} (639-1 language code, region)
+%\item \texttt{mypackage-de-Latn.ldf} (639-1 language code, script)
+%\item \texttt{mypackage-de.ldf} (639-1 language code)
+%
+%\item \texttt{mypackage-deu-Latn-AT.ldf} (639-2 language code, script, region)
+%\item \texttt{mypackage-deu-AT.ldf} (639-2 language code, region)
+%\item \texttt{mypackage-deu-Latn.ldf} (639-2 language code, script)
+%\item \texttt{mypackage-deu.ldf} (639-2 language code)
+%
+%\item \texttt{mypackage-AT.ldf} (region)
+%
+%\item \texttt{mypackage-de-1996.ldf} (639-1 language code, variant)
+%\item \texttt{mypackage-deu-1996.ldf} (639-2 language code, variant)
+%
+%\item \texttt{mypackage-german.ldf} (language label)
%\end{enumerate}
%
%If, for example, \ics{ThisDialect} is \texttt{francais}, then the file search will
%be in the order:
%\begin{enumerate}
-%\item \texttt{mypackage-francais.ldf}
-%\item \texttt{mypackage-fr.ldf}
-%\item \texttt{mypackage-fra.ldf}
-%\item \texttt{mypackage-french.ldf}
+%\item \texttt{mypackage-fr.ldf} (language tag)
+%\item \texttt{mypackage-francais.ldf} (dialect label)
+%\item \texttt{mypackage-fr-Latn.ldf} (639-1 language code, script)
+%\item \texttt{mypackage-fr.ldf} (639-1 language code)
+%\item \texttt{mypackage-fra-Latn.ldf} (639-2 language code, script)
+%\item \texttt{mypackage-fra.ldf} (639-2 language code)
+%\item \texttt{mypackage-french.ldf} (language)
%\end{enumerate}
%This is because the predefined \texttt{francais} option has no
%region assigned to it. Be careful if the dialect label is the actual
%root language. For example, if \cs{ThisDialect} is \texttt{french},
%then the file search will be in the order:
%\begin{enumerate}
-%\item \texttt{mypackage-french.ldf}
-%\item \texttt{mypackage-fr.ldf}
-%\item \texttt{mypackage-fra.ldf}
-%\item \texttt{mypackage-french.ldf}
+%\item \texttt{mypackage-fr.ldf} (language tag)
+%\item \texttt{mypackage-french.ldf} (dialect label)
+%\item \texttt{mypackage-fr-Latn.ldf} (639-1 language code, script)
+%\item \texttt{mypackage-fr.ldf} (639-1 language code)
+%\item \texttt{mypackage-fra-Latn.ldf} (639-2 language code, script)
+%\item \texttt{mypackage-fra.ldf} (639-2 language code)
+%\item \texttt{mypackage-french.ldf} (language)
%\end{enumerate}
%Note that the last try will always fail in this case since if the
-%file exists, it will be found on the first try.
+%file exists, it will be found on the second try.
+%
+%If the dialect label is identical to the root language label then it
+%means that all associated information is the default
+%for that language. For example, in the above case of \texttt{french},
+%the script is \texttt{Latn} and the region is unspecified. The root
+%language label can therefore be used as the fallback in the event of
+%no other match but for the specific case where the dialect is
+%identical to the root language then all unnecessary file name checks
+%can be skipped.
%
%If you're only providing support for the root languages (pre v1.3):
%\begin{verbatim}
@@ -2128,7 +2242,7 @@ and~\ref{tab:nonisoopts}}
%input through some other method.
%
%Within the resource file
-%\meta{pkgname}\texttt{-}\meta{tag}\texttt{.ldf},
+%\meta{pkgname}\texttt{-}\meta{localeid}\texttt{.ldf},
%you can identify the file using (new to version 1.3):
%\begin{definition}[\DescribeMacro\TrackLangProvidesResource]
%\cs{TrackLangProvidesResource}\marg{tag}\oarg{version info}
@@ -2139,10 +2253,10 @@ and~\ref{tab:nonisoopts}}
%suitable for other \TeX\ formats.
%
%The resource file can load another resource file
-%\meta{pkgname}\texttt{-}\meta{tag2}\texttt{.ldf},
+%\meta{pkgname}\texttt{-}\meta{localeid2}\texttt{.ldf},
%using (new to version 1.3):
%\begin{definition}[\DescribeMacro\TrackLangRequireResource]
-%\cs{TrackLangRequireResource}\marg{tag2}
+%\cs{TrackLangRequireResource}\marg{localeid2}
%\end{definition}
%For example, the dialect file \texttt{foo-en-GB.ldf} might need to
%load the root language resource file \texttt{foo-english.ldf}:
@@ -2158,13 +2272,13 @@ and~\ref{tab:nonisoopts}}
%\meta{code1} if it's loaded at this point or \meta{code2} if it's
%already been loaded then you can use (new to version 1.3):
%\begin{definition}[\DescribeMacro\TrackLangRequireResourceOrDo]
-%\cs{TrackLangRequireResourceOrDo}\marg{tag2}\marg{code1}\marg{code2}
+%\cs{TrackLangRequireResourceOrDo}\marg{localeid2}\marg{code1}\marg{code2}
%\end{definition}
%
%If you want to load a resource file if it exists (without an
%error if it doesn't exist), then you can use
%\begin{definition}[\DescribeMacro\TrackLangRequestResource]
-%\cs{TrackLangRequestResource}\marg{tag2}\marg{not found code}
+%\cs{TrackLangRequestResource}\marg{localeid2}\marg{not found code}
%\end{definition}
%If the file doesn't exist, \meta{not found code} is done.
%
@@ -2235,6 +2349,16 @@ and~\ref{tab:nonisoopts}}
%This is equivalent to
%\cs{TrackLangAddToHook}\marg{code}\verb|{captions}|.
%
+%There may be some hooks, such as \cs{date}\meta{label}, that need
+%redefining rather than appending to. As from v1.4, there's an
+%analogous command:
+%\begin{definition}[\DescribeMacro\TrackLangRedefHook]
+%\cs{TrackLangRedefHook}\marg{code}\marg{type}
+%\end{definition}
+%which will redefined the hook to do \meta{code}.
+%
+%Note that no expansion is performed on \meta{code} when appending or
+%redefining a hook.
%
%\section{Examples}
%\label{sec:examples}
@@ -2258,10 +2382,20 @@ and~\ref{tab:nonisoopts}}
% \NeedsTeXFormat{LaTeX2e}
% \ProvidesPackage{animals}
%
-% \RequirePackage{tracklang}[2016/10/07] %v1.3
+% \RequirePackage{tracklang}[2019/11/30] %v1.4
%
% % Any undeclared options are language settings:
-% \DeclareOption*{\TrackLanguageTag{\CurrentOption}}
+%
+% \DeclareOption*{%
+% \TrackIfKnownLanguage{\CurrentOption}%
+% {\PackageInfo{animals}{Tracking language `\CurrentOption'}}% successful
+% {% failed
+% \PackageError{animals}%
+% {Unknown language specification `\CurrentOption'}%
+% {You need to supply either a known dialect label or a valid language tag}%
+% }%
+% }
+%
% \ProcessOptions
%
% % Default definitions
@@ -2496,12 +2630,12 @@ and~\ref{tab:nonisoopts}}
%
%Earlier, I~mentioned the search order for
%\ics{IfTrackedLanguageFileExists} where if, for example, the dialect
-%is \texttt{british}, the file search will be:
+%is \texttt{british}, the file search (v1.4+) will be:
%\begin{enumerate}
%\item \texttt{mypackage-british.ldf}
%\item \texttt{mypackage-en-GB.ldf}
-%\item \texttt{mypackage-eng-GB.ldf}
%\item \texttt{mypackage-en.ldf}
+%\item \texttt{mypackage-eng-GB.ldf}
%\item \texttt{mypackage-eng.ldf}
%\item \texttt{mypackage-GB.ldf}
%\item \texttt{mypackage-english.ldf}
@@ -2511,7 +2645,7 @@ and~\ref{tab:nonisoopts}}
%countries have multiple official languages, which means that the country code on its
%own may not indicate the language.
%
-%The reason for including just the country code as the \meta{tag} in the
+%The reason for including just the country code as the \meta{localeid} in the
%file search is to allow for region rather than language dependent
%settings. For example, suppose I~want to write a package that needs
%to know whether to use imperial or metric measurements in the
@@ -2524,7 +2658,7 @@ and~\ref{tab:nonisoopts}}
%
%\cs{TrackLangRequireDialect} has an optional argument for adjusting
%the way the resource files are loaded. Suppose I have
-%\texttt{regions-}\meta{tag}\texttt{.ldf} resource files, then
+%\texttt{regions-}\meta{localeid}\texttt{.ldf} resource files, then
%\begin{verbatim}
%\TrackLangRequireDialect{regions}{\this@dialect}
%\end{verbatim}
@@ -2699,7 +2833,7 @@ and~\ref{tab:nonisoopts}}
%\end{document}
%\end{verbatim}
%
-%This works because the \meta{tag} search looks for the
+%This works because the \meta{localeid} search looks for the
%country code before the root language label. However, this will fail if
%the dialect label is the same as a root language label that has an
%associated territory, marked with \fnregion\ in
@@ -2913,7 +3047,9 @@ and~\ref{tab:nonisoopts}}
%than a package that provides multilingual support if the user has
%already loaded a language package) then you can load \styfmt{tracklang}
%and use the commands below to help other packages track your
-%provided languages.
+%provided languages. (See also:
+%\href{https://www.dickimaw-books.com/latex/tracklang/langpkg.shtml}{Integrating
+%\texttt{tracklang.tex} into Language Packages}.)
%
%The \styfmt{tracklang} package can be loaded using
%\begin{verbatim}
@@ -2927,7 +3063,7 @@ and~\ref{tab:nonisoopts}}
%When using \LaTeX, there's a difference between the two.
%The first case prevents \styfmt{tracklang} from picking up
%the document class options but skips the check for known
-%language packages. This check is redundant since this is
+%language packages. This check is redundant since your package is
%the language package, so you need to decide is whether or
%not to allow the user to set up the localisation information
%through the document class options.
@@ -2945,12 +3081,96 @@ and~\ref{tab:nonisoopts}}
%
%If you just use \cs{input}, there's a test at the start of
%\texttt{tracklang.tex} to determine if it's already been loaded, so
-%you don't need to worry if the user has already loaded it.
+%you don't need to worry if the document has already loaded it.
+%
+%To integrate \sty{tracklang} into your language package, you need to consider the following
+%steps:
+%\begin{enumerate}
+%\item Does \sty{tracklang} define your supported ISO~15924 language
+%scripts in the \texttt{tracklang-scripts.tex} file?
+%
+%If yes, then skip this step. Otherwise create a file with the
+%relevant \ics{TrackLangScriptMap} command for each unknown script and identify
+%this new file with \ics{TrackLangAddExtraScriptFile} (see
+%\sectionref{sec:newscripts}). This usually
+%won't be necessary unless you have a custom script or a child script
+%(a script that's a sub-category of another script).
+%
+%\item Does \sty{tracklang} recognise the root language?
+%
+%If yes, then skip this step.
+%
+%If your package is setting up a language that \sty{tracklang}
+%doesn't recognise then you will need to define the root language
+%using \cs{TrackLangNewLanguage} (see \sectionref{sec:newlanguages}).
+%
+%This usually won't be the case as \sty{tracklang} should support all
+%languages that have an official ISO~639-1 alpha-2 code.
+%
+%If you simply have a different label from \sty{tracklang} identifying the root language,
+%then you can just set up your label as a dialect using
+%\cs{TrackLangProvidePredefinedDialect} (see \sectionref{sec:predefinedlabels}).
+%
+%\item Does \sty{tracklang} define the relevant ISO~3166 region codes
+%in the \texttt{tracklang-region-codes.tex} file?
+%
+%If yes, then skip this step. Otherwise create a file with the
+%relevant \ics{TrackLangRegionMap} command for each new region and
+%identify this new file with \ics{TrackLangAddExtraRegionFile} (see
+%\sectionref{sec:newregions}). This usually won't be necessary as
+%\sty{tracklang} should recognise all countries that have an alpha-2
+%region code, but you may require it if you need a broader region,
+%such as EU.
+%
+%\item Do you want to define some convenient dialect labels that can
+%be used with \ics{TrackPredefinedDialect}?
+%
+%If no, then skip this step. Otherwise you can use
+%\ics{TrackLangProvidePredefinedLanguage} for root languages
+%and \ics{TrackLangProvidePredefinedDialect} for dialects with
+%additional information, such as a region, sub-language or script
+%(see \sectionref{sec:predefinedlabels}).
+%
+%\item In your language initialisation code, add the \sty{tracklang}
+%code to track the particular dialect (for example, use
+%\cs{TrackPredefinedDialect} for recognised dialect labels or
+%use the \cs{AddTracked}\ldots\ set of commands). See
+%\sectionref{sec:initnewlang}.
+%
+%\item In your language selection code (such as \cs{selectlanguage}), add
+%\cs{SetCurrentTrackedDialect}\marg{label} to allow the document
+%author to easily query the current localisation settings (such as
+%the region). See \sectionref{sec:selectlanguage}.
+%\end{enumerate}
+%
+%\section{Initialising a New Language or Dialect}
+%\label{sec:initnewlang}
+%
+%When the user requests a particular dialect through your language
+%package, you can notify \styfmt{tracklang} of this choice using
+%\begin{definition}
+%\cs{TrackPredefinedDialect}\marg{dialect}
+%\end{definition}
+%provided the dialect label is recognised by \styfmt{tracklang} (all those
+%listed in \refoptstables).
+%
+%If there's no matching dialect predefined by \styfmt{tracklang}, you
+%can just use \cs{TrackLocale} or \cs{TrackLanguageTag}
+%(described in \sectionref{sec:generic})
+%with the appropriate ISO codes \emph{if you're not providing caption
+%hooks}.
+%
+%If you are providing a captions hook mechanism
+%in the form \ics{captions\meta{dialect}}, then if \meta{dialect}
+%doesn't match the corresponding \styfmt{tracklang} dialect label,
+%you can provide a mapping using
+%\cs{SetTrackedDialectLabelMap}, described below.
%
-%When the language is set (using commands like \cs{selectlanguage}
-%)
-%it would be convenient to users and other packages if the
-%following command is also used:
+%\section{Switching Language or Dialect}
+%\label{sec:selectlanguage}
+%
+%When the document author switches to a different language or
+%dialect, the current localisation information can be set with:
%\begin{definition}[\DescribeMacro\SetCurrentTrackedDialect]
%\cs{SetCurrentTrackedDialect}\marg{dialect}
%\end{definition}
@@ -2994,25 +3214,118 @@ and~\ref{tab:nonisoopts}}
%to \meta{dialect}. See the accompanying sample file
%\texttt{sample-setlang.tex} for an example.)
%
-%When the user requests a particular dialect through your language
-%package, you can notify \styfmt{tracklang} of this choice using
-%\begin{definition}
-%\cs{TrackPredefinedDialect}\marg{dialect}
+%\section{Defining New Scripts}
+%\label{sec:newscripts}
+%
+%The \texttt{tracklang-scripts.tex} file isn't automatically loaded,
+%but if it is then, as from v1.4, it contains a hook at the end of
+%the file that can be used to load additional files that define
+%supplementary scripts. This entails creating a file called, say,
+%\texttt{mypackage-scripts.tex} that contains:
+%\begin{definition}[\DescribeMacro\TrackLangScriptMap]
+%\cs{TrackLangScriptMap}\marg{alpha code}\marg{numeric
+%code}\marg{name}\marg{direction}\marg{parent}
+%\end{definition}
+%The first argument \meta{alpha code} is the four-letter ISO~15924 code (such as
+%\texttt{Latn}), the second argument is the numeric code (such as
+%215), the third argument \meta{name} is the name of the script (such
+%as \texttt{Latin}), the fourth argument is the direction (such as
+%\texttt{LR} for left-to-right) and the final argument is the parent
+%script (leave blank if there's no parent). Note that this command will override any previous
+%mapping for those codes. No check is performed to determine if they
+%have already been defined.
+%
+%The supplementary file should be identified with:
+%\begin{definition}[\DescribeMacro\TrackLangAddExtraScriptFile]
+%\cs{TrackLangAddExtraScriptFile}\marg{filename}
+%\end{definition}
+%
+%\section{Defining New Regions}
+%\label{sec:newregions}
+%
+%The \texttt{tracklang-region-codes.tex} file isn't automatically loaded,
+%but if it is then, as from v1.4, it contains a hook at the end of
+%the file that can be used to load additional files that define
+%supplementary regions. This entails creating a file called, say,
+%\texttt{mypackage-regions.tex} that contains:
+%\begin{definition}[\DescribeMacro\TrackLangRegionMap]
+%\cs{TrackLangRegionMap}\marg{numeric code}\marg{alpha-2 code}\marg{alpha-3 code}
+%\end{definition}
+%where the first argument is the numeric region code (such as 826),
+%the second argument is the alpha-2 region code (such as \texttt{GB})
+%and the third argument is the alpha-3 region code (such as
+%\texttt{GBR}). Note that this command will override any previous
+%mapping for those codes. No check is performed to determine if they
+%have already been defined.
+%
+%The supplementary file should be identified with:
+%\begin{definition}[\DescribeMacro\TrackLangAddExtraRegionFile]
+%\cs{TrackLangAddExtraRegionFile}\marg{filename}
+%\end{definition}
+%
+%\section{Defining a New Language}
+%\label{sec:newlanguages}
+%
+%(New to version 1.3.)
+%If the root language isn't recognised by \styfmt{tracklang}
+%(not listed in \tableref{tab:rootlangopts}), then
+%it can be defined (but not tracked at this point) using:
+%\begin{definition}[\DescribeMacro\TrackLangNewLanguage]
+%\cs{TrackLangNewLanguage}\marg{language name}\marg{639-1
+%code}\marg{639-2 (T)}\marg{639-2 (B)}\marg{639-3}\marg{3166-1}\marg{default
+%script}
%\end{definition}
-%if the dialect label is recognised by \styfmt{tracklang} (all those
-%listed in \refoptstables).
+%where \meta{language name} is the root language name,
+%\meta{639-1 code} is the ISO 639-1 code for that language (may be
+%empty if there isn't one), \meta{639-2 (T)} is the ISO 639-2 (T)
+%code for that language (may be empty if there isn't one),
+%\meta{639-2 (B)} is the ISO 639-2 (B) code for that language (may be
+%empty if it's the same as \meta{639-2 (T)}), \meta{639-3} is the ISO
+%639-3 code for that language (empty if the same as the 639-2
+%code), \meta{3166-1} is the territory ISO code for languages that are only spoken in one
+%territory (should be empty if the language is spoken in multiple
+%territories), and \meta{default script} is the default script (empty
+%if disputed or varies according to region).
%
-%If there's no matching dialect predefined by \styfmt{tracklang}, you
-%can just use \cs{TrackLocale} or \cs{TrackLanguageTag}
-%(described in \sectionref{sec:generic})
-%with the appropriate ISO codes \emph{if you're not providing caption
-%hooks}.
+%You can then track this language using \cs{AddTrackedDialect} for
+%dialects or, if no regional variant is needed, you can instead use:
+%\begin{definition}[\DescribeMacro\AddTrackedLanguage]
+%\cs{AddTrackedLanguage}\marg{root language label}
+%\end{definition}
+%This is equivalent to \ics{AddTrackedDialect}\marg{root language
+%label}\marg{root language label}.
%
-%If you are providing a captions hook mechanism
-%in the form \ics{captions\meta{dialect}}, then if \meta{dialect}
-%doesn't match the corresponding \styfmt{tracklang} dialect label,
-%you can provide a mapping using
-%\cs{SetTrackedDialectLabelMap}, described below.
+%
+%\section{Defining New \styfmt{tracklang} Labels}
+%\label{sec:predefinedlabels}
+%
+%A dialect label may be predefined with associated information that
+%allows that particular combination to be easily tracked with
+%\cs{TrackPredefinedDialect}. In the case of a dialect label that
+%only requires the information provided in \cs{TrackLangNewLanguage}
+%you can use:
+%\begin{definition}[\DescribeMacro\TrackLangProvidePredefinedLanguage]
+%\cs{TrackLangProvidePredefinedLanguage}\marg{label}
+%\end{definition}
+%where \meta{label} corresponds to the language label used in
+%\cs{TrackLangNewLanguage}. This allows
+%\cs{TrackPredefinedDialect}\marg{label} to not only track the root
+%language but also the associated ISO codes.
+%
+%If the dialect label doesn't match the root language label then use:
+%\begin{definition}[\DescribeMacro\TrackLangProvidePredefinedDialect]
+%\cs{TrackLangProvidePredefinedDialect}\marg{dialect}\marg{language}\marg{region}\marg{modifier}\marg{variant}\marg{map}\marg{script}
+%\end{definition}
+%where \meta{dialect} is the new \sty{tracklang} dialect label,
+%\marg{language} is the \sty{tracklang} root language label,
+%\meta{region} is the ISO~3166-1 region code (may be empty),
+%\meta{modifier} is the modifier (may be empty), \meta{variant}
+%is the variant information (may be empty), \meta{map} is your
+%package's language label that corresponds to the \sty{tracklang}
+%dialect label supplied in the first argument (may be empty if
+%identical), and \meta{script} is the ISO~15914 alpha-4 script code
+%(may be empty if it's the same as the default script for the root
+%language).
%
%For compatibility with pre version 1.3,
%if the dialect isn't predefined by
@@ -3153,34 +3466,7 @@ and~\ref{tab:nonisoopts}}
%where \meta{dialect} is the dialect label and \meta{value} is the
%additional information.
%
-%(New to version 1.3.)
-%If the root language isn't recognised by \styfmt{tracklang}
-%(not listed in \tableref{tab:rootlangopts}), then
-%it can be defined (but not tracked at this point) using:
-%\begin{definition}[\DescribeMacro\TrackLangNewLanguage]
-%\cs{TrackLangNewLanguage}\marg{language name}\marg{639-1
-%code}\marg{639-2 (T)}\marg{639-2 (B)}\marg{639-3}\marg{3166-1}\marg{default
-%script}
-%\end{definition}
-%where \meta{language name} is the root language name,
-%\meta{639-1 code} is the ISO 639-1 code for that language (may be
-%empty if there isn't one), \meta{639-2 (T)} is the ISO 639-2 (T)
-%code for that language (may be empty if there isn't one),
-%\meta{639-2 (B)} is the ISO 639-2 (B) code for that language (may be
-%empty if it's the same as \meta{639-2 (T)}), \meta{639-3} is the ISO
-%639-3 code for that language (empty if the same as the 639-2
-%code), \meta{3166-1} is the territory ISO code for languages that are only spoken in one
-%territory (should be empty if the language is spoken in multiple
-%territories), and \meta{default script} is the default script (empty
-%if disputed or varies according to region).
-%
-%You can then track this language using \cs{AddTrackedDialect} for
-%dialects or, if no regional variant is needed, you can instead use:
-%\begin{definition}[\DescribeMacro\AddTrackedLanguage]
-%\cs{AddTrackedLanguage}\marg{root language label}
-%\end{definition}
-%This is equivalent to \ics{AddTrackedDialect}\marg{root language
-%label}\marg{root language label}.
+%\section{Example}
%
%Suppose I want to create a language package \texttt{alien.sty} that defines the
%\texttt{martian} language with regional dialects
@@ -3227,7 +3513,7 @@ and~\ref{tab:nonisoopts}}
% }
%\end{verbatim}
%The caption commands and language set up are in the files
-%\texttt{alien-}\meta{tag}\texttt{.ldf} as in the examples from
+%\texttt{alien-}\meta{localeid}\texttt{.ldf} as in the examples from
%\sectionref{sec:examples}. This allows for the user having already
%loaded \styfmt{tracklang} before \styfmt{alien} and used \cs{TrackLangFromEnv} to pick up
%the locale from the operating system's environment variables.
@@ -3297,7 +3583,7 @@ and~\ref{tab:nonisoopts}}
% packages such as \styfmt{etoolbox}.
% \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{tracklang}[2019/11/11 v1.3.9 (NLCT) Track Languages]
+\ProvidesPackage{tracklang}[2019/11/30 v1.4 (NLCT) Track Languages]
% \end{macrocode}
%\begin{macro}{\@tracklang@declareoption}
% Set up package options.
@@ -3593,7 +3879,7 @@ and~\ref{tab:nonisoopts}}
% Version info.
% \begin{macrocode}
\expandafter\def\csname ver@tracklang.tex\endcsname{%
- 2019/11/11 v1.3.9 (NLCT) Track Languages Generic Code}
+ 2019/11/30 v1.4 (NLCT) Track Languages Generic Code}
% \end{macrocode}
% Define a long command for determining the existence of a control
% sequence by its name. (\cs{relax} is considered undefined.)
@@ -3729,6 +4015,29 @@ and~\ref{tab:nonisoopts}}
% \end{macrocode}
%\end{macro}
%
+%\begin{macro}{\@tracklang@ifcseqcsname}
+%\changes{1.4}{2019-11-30}{new}
+%\begin{definition}
+%\cs{@tracklang@ifcseqcsname}\marg{cs}\marg{csname}\marg{true}\marg{false}
+%\end{definition}
+%Compares two commands, the first is reference as a control sequence
+%the second is referenced as a control sequence name. Condition is
+%false if the second isn't defined (no check for the existence of
+%the first).
+% \begin{macrocode}
+\def\@tracklang@ifcseqcsname#1#2#3#4{%
+ \@tracklang@ifundef{#2}{#4}%
+ {%
+ \expandafter\ifx\expandafter#1\csname#2\endcsname
+ #3%
+ \else
+ #4%
+ \fi
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
%\begin{macro}{\@tracklang@sanitize}
%\changes{1.3}{2016-10-07}{new}
% \begin{macrocode}
@@ -3745,15 +4054,17 @@ and~\ref{tab:nonisoopts}}
%
%\begin{macro}{\@tracklang@firstoftwo}
%\changes{1.3}{2016-10-07}{new}
+%\changes{1.4}{2019-11-30}{made long}
% \begin{macrocode}
-\def\@tracklang@firstoftwo#1#2{#1}
+\long\def\@tracklang@firstoftwo#1#2{#1}
% \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@tracklang@secondoftwo}
%\changes{1.3}{2016-10-07}{new}
+%\changes{1.4}{2019-11-30}{made long}
% \begin{macrocode}
-\def\@tracklang@secondoftwo#1#2{#2}
+\long\def\@tracklang@secondoftwo#1#2{#2}
% \end{macrocode}
%\end{macro}
%
@@ -3842,6 +4153,28 @@ and~\ref{tab:nonisoopts}}
% \end{macrocode}
%\end{macro}
%
+%\begin{macro}{\ifTrackLangShowVerbose}
+%\changes{1.4}{2019-11-30}{new}
+% Allow user to switch verbose (debugging) information messages on or off.
+% Note that verbose information will be off regardless of this
+% switch if the info switch is off.
+% \begin{macrocode}
+\newif\ifTrackLangShowVerbose
+\TrackLangShowVerbosefalse
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@verbose}
+%\changes{1.4}{2019-11-30}{new}
+% \begin{macrocode}
+\def\@tracklang@verbose#1{%
+ \ifTrackLangShowVerbose
+ \@tracklang@info{#1}%
+ \fi
+}%
+% \end{macrocode}
+%\end{macro}
+%
%\begin{macro}{\@tracklang@IfFileExists}
% \begin{macrocode}
\ifx\IfFileExists\undefined
@@ -5201,9 +5534,11 @@ and~\ref{tab:nonisoopts}}
% \begin{macrocode}
\def\SetCurrentTrackedDialect#1{%
\edef\CurrentTrackedDialect{#1}%
+ \@tracklang@verbose{Setting current tracked dialect `\CurrentTrackedDialect'}%
\IfTrackedDialect{\CurrentTrackedDialect}%
{}%
{%
+ \@tracklang@verbose{Not a recognised tracklang label}%
% \end{macrocode}
% Has a mapping from this dialect to a tracklang dialect been supplied?
% \begin{macrocode}
@@ -5213,6 +5548,7 @@ and~\ref{tab:nonisoopts}}
{%
\edef\CurrentTrackedDialect{\GetTrackedDialectFromMapping
{\CurrentTrackedDialect}}%
+ \@tracklang@verbose{Mapping found to tracklang label `\CurrentTrackedDialect'}%
}%
{%
% \end{macrocode}
@@ -5220,32 +5556,41 @@ and~\ref{tab:nonisoopts}}
% \begin{macrocode}
\IfTrackedLanguage{#1}%
{%
+ \@tracklang@verbose{Supplied label is a root language.
+ Finding last tracked dialect for language `#1'}%
% \end{macrocode}
% Get the last dialect to be tracked with this language.
-% \begin{macrocode}
+% \begin{macrocode}
\edef\@tracklang@dialects{\TrackedDialectsFromLanguage{#1}}%
\@tracklang@for\@tracklang@dialect:=\@tracklang@dialects\do{%
\let\CurrentTrackedDialect\@tracklang@dialect
}%
}%
- {}%
+ {%
+ \@tracklang@verbose{No tracklang dialect found for label `#1'}%
+ }%
}%
}%
{%
+ \@tracklang@verbose{No mapping found}%
% \end{macrocode}
% Has the root language name been supplied?
% \begin{macrocode}
\IfTrackedLanguage{#1}%
{%
+ \@tracklang@verbose{Supplied label is a root language.
+ Finding last tracked dialect for language `#1'}%
% \end{macrocode}
% Get the last dialect to be tracked with this language.
-% \begin{macrocode}
+% \begin{macrocode}
\edef\@tracklang@dialects{\TrackedDialectsFromLanguage{#1}}%
\@tracklang@for\@tracklang@dialect:=\@tracklang@dialects\do{%
\let\CurrentTrackedDialect\@tracklang@dialect
}%
}%
- {}%
+ {%
+ \@tracklang@verbose{No tracklang dialect found for label `#1'}%
+ }%
}%
}%
\IfTrackedDialect{\CurrentTrackedDialect}%
@@ -5308,6 +5653,17 @@ and~\ref{tab:nonisoopts}}
}%
}%
}%
+ \@tracklang@verbose{Current tracked dialect: `\CurrentTrackedDialect'.\MessageBreak
+ Language: `\CurrentTrackedLanguage'.\MessageBreak
+ ISO code: `\CurrentTrackedIsoCode'.\MessageBreak
+ Sub-lang: `\CurrentTrackedDialectSubLang'.\MessageBreak
+ Modifier: `\CurrentTrackedDialectModifier'.\MessageBreak
+ Variant: `\CurrentTrackedDialectVariant'.\MessageBreak
+ Script: `\CurrentTrackedDialectScript'.\MessageBreak
+ Region: `\CurrentTrackedRegion'.\MessageBreak
+ Additional: `\CurrentTrackedDialectAdditional'.\MessageBreak
+ Tag: `\CurrentTrackedLanguageTag'.
+ }%
}%
{%
\@tracklang@warn{Unknown dialect label `#1' passed to
@@ -6157,6 +6513,86 @@ and~\ref{tab:nonisoopts}}
% \end{macrocode}
%\end{macro}
%
+%\begin{macro}{\@tracklang@input@extra@region@filelist}
+%\changes{1.4}{2019-11-30}{new}
+% \begin{macrocode}
+\def\@tracklang@extra@region@filelist{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\TrackLangAddExtraRegionFile}
+%\changes{1.4}{2019-11-30}{new}
+% Add a file name to the list of extra region code files that should
+% be input by tracklang-regions-codes.tex
+% \begin{macrocode}
+\def\TrackLangAddExtraRegionFile#1{%
+ \ifx\TrackLangRegionMap\undefined
+ \else
+% \end{macrocode}
+% tracklang-region-codes.tex has already been loaded so input the file
+% now.
+% \begin{macrocode}
+ \@tracklang@input #1\relax
+ \fi
+ \@tracklang@add{#1}{\@tracklang@extra@region@filelist}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@input@extra@region@files}
+%\changes{1.4}{2019-11-30}{new}
+% Iterate through list of extra region files to allow other packages
+% to define new regions.
+% \begin{macrocode}
+\def\@tracklang@input@extra@region@files{%
+ \@tracklang@for\@tracklang@currfile:=\@tracklang@extra@region@filelist\do
+ {%
+ \@tracklang@input\@tracklang@currfile
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@input@extra@script@filelist}
+%\changes{1.4}{2019-11-30}{new}
+% \begin{macrocode}
+\def\@tracklang@extra@script@filelist{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\TrackLangAddExtraScriptFile}
+%\changes{1.4}{2019-11-30}{new}
+% Add the given file name to the list of files that should be
+% automatically loaded by tracklang-scripts.tex
+% \begin{macrocode}
+\def\TrackLangAddExtraScriptFile#1{%
+ \ifx\TrackLangScriptMap\undefined
+ \else
+% \end{macrocode}
+% tracklang-scripts.tex has already been loaded so input the file
+% now.
+% \begin{macrocode}
+ \@tracklang@input #1\relax
+ \fi
+ \@tracklang@add{#1}{\@tracklang@extra@script@filelist}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@input@extra@script@files}
+%\changes{1.4}{2019-11-30}{new}
+% Iterate through list of extra script files to allow other packages
+% to define new scripts.
+% \begin{macrocode}
+\def\@tracklang@input@extra@script@files{%
+ \@tracklang@for\@tracklang@currfile:=\@tracklang@extra@script@filelist\do
+ {%
+ \@tracklang@input\@tracklang@currfile
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
%\begin{macro}{\GetTrackedDialectFromLanguageTag}
%\changes{1.3}{2016-10-07}{new}
%\begin{definition}
@@ -6589,6 +7025,21 @@ and~\ref{tab:nonisoopts}}
% \end{macrocode}
%\end{macro}
%
+%\begin{macro}{\TrackLangProvidePredefinedLanguage}
+%\changes{1.4}{2019-11-30}{new}
+% Set up a language label for use with \cs{TrackPredefinedDialect}.
+% Note that this doesn't check if already defined.
+% \begin{macrocode}
+\def\TrackLangProvidePredefinedLanguage#1{%
+ \@tracklang@namedef{@tracklang@add@#1}{%
+ \AddTrackedLanguage{#1}%
+ \AddTrackedLanguageIsoCodes{#1}%
+ \AddTrackedCountryIsoCode{#1}%
+ }%
+}
+% \end{macrocode}
+%\end{macro}
+%
%\begin{macro}{\TrackLangDeclareLanguageOption}
%\changes{1.3}{2016-10-07}{new}
%\begin{definition}
@@ -6605,11 +7056,7 @@ and~\ref{tab:nonisoopts}}
\@tracklang@ifundef{@tracklang@add@#1}%
{%
\TrackLangNewLanguage{#1}{#2}{#3}{#4}{#5}{#6}{#7}%
- \@tracklang@namedef{@tracklang@add@#1}{%
- \AddTrackedLanguage{#1}%
- \AddTrackedLanguageIsoCodes{#1}%
- \AddTrackedCountryIsoCode{#1}%
- }%
+ \TrackLangProvidePredefinedLanguage{#1}%
\@tracklang@declareoption{#1}%
}%
{%
@@ -7949,21 +8396,20 @@ and~\ref{tab:nonisoopts}}
%\subsection{Predefined Dialects}\label{sec:predefined}
%
% Provide some predefined dialects.
-%\begin{macro}{\TrackLangDeclareDialectOption}
-%\changes{1.3}{2016-10-07}{new}
+%\begin{macro}{\TrackLangProvidePredefinedDialect}
+%\changes{1.4}{2019-11-30}{new}
%\begin{definition}
-%\cs{TrackLangDeclareDialectOption}\marg{dialect}\marg{root
+%\cs{TrackLangProvidePredefinedDialect}\marg{dialect}\marg{root
%language}\marg{3166-1
%code}\marg{modifier}\marg{variant}\marg{map}\marg{script}
%\end{definition}
-%The option name is the same as the dialect name. The arguments
+%This defines a predefined dialect label that can be used
+%by \cs{TrackPredefinedDialect}. The arguments
%must be expanded before use. The final argument \meta{map} is the
%mapping from \meta{dialect} to the closest \styfmt{babel} dialect
-%label. May be empty if no relevant mapping.
+%label.
% \begin{macrocode}
-\def\TrackLangDeclareDialectOption#1#2#3#4#5#6#7{%
- \@tracklang@ifundef{@tracklang@add@#1}%
- {%
+\def\TrackLangProvidePredefinedDialect#1#2#3#4#5#6#7{
\ifx\relax#3\relax
% \end{macrocode}
% No region.
@@ -8108,6 +8554,26 @@ and~\ref{tab:nonisoopts}}
\expandafter\def\csname @tracklang@add@#1\expandafter\endcsname
\expandafter{\@tracklang@tmp\SetTrackedDialectScript{#1}{#7}}%
\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\TrackLangDeclareDialectOption}
+%\changes{1.3}{2016-10-07}{new}
+%\begin{definition}
+%\cs{TrackLangDeclareDialectOption}\marg{dialect}\marg{root
+%language}\marg{3166-1
+%code}\marg{modifier}\marg{variant}\marg{map}\marg{script}
+%\end{definition}
+%The option name is the same as the dialect name. The arguments
+%must be expanded before use. The final argument \meta{map} is the
+%mapping from \meta{dialect} to the closest \styfmt{babel} dialect
+%label. May be empty if no relevant mapping.
+% \begin{macrocode}
+\def\TrackLangDeclareDialectOption#1#2#3#4#5#6#7{%
+ \@tracklang@ifundef{@tracklang@add@#1}%
+ {%
+ \TrackLangProvidePredefinedDialect{#1}{#2}{#3}{#4}{#5}{#6}{#7}%
\@tracklang@declareoption{#1}%
}%
{%
@@ -9369,21 +9835,20 @@ and~\ref{tab:nonisoopts}}
%part}\marg{false part}
%\end{definition}
% Determines if the file \meta{prefix}\meta{tag}\meta{suffix}
-% exists, where \meta{tag} is an ISO code or ISO codes identifying
+% exists, where \meta{tag} is an ISO code or ISO codes or label identifying
% the language. If \meta{dialect} hasn't been identified
% as a tracked dialect, this just does \meta{false part},
-% otherwise this first tries with \meta{tag} set to
-% \meta{dialect}, then tries with \meta{tag} set to the root
-% language label for \meta{dialect}, then tries with \meta{tag} set to \meta{ISO
-% 639-1 code}\texttt{-}\meta{ISO 3166-1 code}, then tries with
-% \meta{tag} set to \meta{ISO 639-1 code}, then tries with
-% \meta{tag} set to \meta{ISO 639-2 code}\texttt{-}\meta{ISO 3166-1
-% code}, then tries with \meta{tag} set to \meta{ISO 639-2 code}.
+% otherwise this tries various different combinations for \meta{tag}.
% If the file \meta{prefix}\meta{tag}\meta{suffix} exists,
% \cs{CurrentTrackedTag} is set to \meta{tag} and \meta{true part}
% is performed, otherwise \meta{false part} is performed.
+% The order of priority has changed with version 1.4 and now
+% includes a check for variations that include the script. If the
+% original ordering is specifically required, the old behaviour can
+% be obtained with \cs{IfTrackedLanguageFileExists@orig}.
% \begin{macrocode}
\long\def\IfTrackedLanguageFileExists#1#2#3#4#5{%
+ \@tracklang@verbose{Finding file for dialect `#1'}%
% \end{macrocode}
%Initialise.
% \begin{macrocode}
@@ -9395,16 +9860,1756 @@ and~\ref{tab:nonisoopts}}
\IfTrackedDialect{#1}%
{%
% \end{macrocode}
-% Try just the dialect label.
+% Save the three types of language codes to for reference.
% \begin{macrocode}
+ \edef\CurrentTrackedIsoCodeI{\TrackedIsoCodeFromLanguage
+ {639-1}{\CurrentTrackedLanguage}}%
+ \edef\CurrentTrackedIsoCodeII{\TrackedIsoCodeFromLanguage
+ {639-2}{\CurrentTrackedLanguage}}%
+ \edef\CurrentTrackedIsoCodeIII{\TrackedIsoCodeFromLanguage
+ {639-3}{\CurrentTrackedLanguage}}%
+% \end{macrocode}
+%\changes{1.4}{2019-11-30}{added check for scripts}
+% Earlier versions of this had too many nested conditionals, which
+% was confusing and hard to follow. This is a rewrite that removes
+% the nesting and adds extra checks for dialect scripts.
+% \begin{macrocode}
+ \@tracklang@test@if@file@exists@for@tag{#1}{#2}{#3}%
+ \@tracklang@if@file@exists{#4}{#5}%
+ }%
+ {#5}% unknown dialect
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@noop}
+%\changes{1.4}{2019-11-30}{new}
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@noop#1#2#3{}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@tag}
+%\changes{1.4}{2019-11-30}{new}
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@tag#1#2#3{%
+ \let\CurrentTrackedTag\CurrentTrackedLanguageTag
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@secondoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@dialect
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@dialect}
+%\changes{1.4}{2019-11-30}{new}
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@dialect#1#2#3{%
+ \edef\CurrentTrackedTag{#1}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \IfTrackedLanguageHasIsoCode{639-1}{\CurrentTrackedLanguage}%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIscriptregion
+ }%
+ {%
+ \IfTrackedLanguageHasIsoCode{639-2}{\CurrentTrackedLanguage}%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIscriptregion
+ }%
+ {%
+ \IfTrackedLanguageHasIsoCode{639-3}{\CurrentTrackedLanguage}%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIscriptregion
+ }%
+ {%
+ \let\CurrentTrackedIsoCode\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@scriptregion
+ }%
+ }%
+ }%
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIscriptregion}
+%\changes{1.4}{2019-11-30}{new}
+% Test \meta{639-1}-\meta{sublang}-\meta{script}-\meta{region} combination.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIscriptregion#1#2#3{%
+ \let\CurrentTrackedIsoCode\CurrentTrackedIsoCodeI
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \ifx\CurrentTrackedDialectScript\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectScript}%
+ \fi
+ \ifx\CurrentTrackedRegion\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedRegion}%
+ \fi
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedRegion\empty
+ \ifx\CurrentTrackedDialectScript\empty
+% \end{macrocode}
+%No script or region set. If there's a sub-language code then try
+%again without it.
+% \begin{macrocode}
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langII
+ \else
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langII
+ }%
+ \fi
+ \else
+% \end{macrocode}
+%No region set. If there's a sub-language code then try
+%again without it.
+% \begin{macrocode}
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIskipscript
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedDialectScript}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIskipscript
+ }%
+ \fi
+ \fi
+ \else
+ \ifx\CurrentTrackedDialectScript\empty
+% \end{macrocode}
+% Region is set but no script. If there's a sub-language code
+% then try again without it.
+% \begin{macrocode}
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIskipregion
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedRegion}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIskipregion
+ }%
+ \fi
+ \else
+% \end{macrocode}
+% Region and script set. If there's a sub-language code
+% then try again without it.
+% \begin{macrocode}
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIskipscriptregion
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedDialectScript
+ -\CurrentTrackedRegion}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIskipscriptregion
+ }%
+ \fi
+ \fi
+ \fi
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIIscriptregion}
+%\changes{1.4}{2019-11-30}{new}
+% Test \meta{639-2}-\meta{sublang}-\meta{script}-\meta{region} combination.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIIscriptregion#1#2#3{%
+ \let\CurrentTrackedIsoCode\CurrentTrackedIsoCodeII
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \ifx\CurrentTrackedDialectScript\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectScript}%
+ \fi
+ \ifx\CurrentTrackedRegion\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedRegion}%
+ \fi
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedRegion\empty
+ \ifx\CurrentTrackedDialectScript\empty
+% \end{macrocode}
+%No script or region set. If there's a sub-language code then try
+%again without it.
+% \begin{macrocode}
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIII
+ \else
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIII
+ }%
+ \fi
+ \else
+% \end{macrocode}
+%No region set. If there's a sub-language code then try
+%again without it.
+% \begin{macrocode}
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIskipscript
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedDialectScript}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIskipscript
+ }%
+ \fi
+ \fi
+ \else
+ \ifx\CurrentTrackedDialectScript\empty
+% \end{macrocode}
+% Region is set but no script. If there's a sub-language code
+% then try again without it.
+% \begin{macrocode}
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIskipregion
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedRegion}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIskipregion
+ }%
+ \fi
+ \else
+% \end{macrocode}
+% Both region and script are set. If there's a sub-language code
+% then try again without it.
+% \begin{macrocode}
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIskipscriptregion
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedDialectScript
+ -\CurrentTrackedRegion}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIskipscriptregion
+ }%
+ \fi
+ \fi
+ \fi
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIIIscriptregion}
+%\changes{1.4}{2019-11-30}{new}
+% Test \meta{639-3}-\meta{sublang}-\meta{script}-\meta{region} combination.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIIIscriptregion#1#2#3{%
+ \let\CurrentTrackedIsoCode\CurrentTrackedIsoCodeIII
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \ifx\CurrentTrackedDialectScript\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectScript}%
+ \fi
+ \ifx\CurrentTrackedRegion\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedRegion}%
+ \fi
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedRegion\empty
+ \ifx\CurrentTrackedDialectScript\empty
+% \end{macrocode}
+%No script or region set. If there's a sub-language code then try
+%again without it.
+% \begin{macrocode}
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langvariant
+ \else
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langvariant
+ }%
+ \fi
+ \else
+% \end{macrocode}
+%No region set. If there's a sub-language code then try
+%again without it.
+% \begin{macrocode}
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIskipscript
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedDialectScript}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIskipscript
+ }%
+ \fi
+ \fi
+ \else
+ \ifx\CurrentTrackedDialectScript\empty
+% \end{macrocode}
+% Region is set but no script. If there's a sub-language code
+% then try again without it.
+% \begin{macrocode}
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIskipregion
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedRegion}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIskipregion
+ }%
+ \fi
+ \else
+% \end{macrocode}
+% Both region and script are set. If there's a sub-language code
+% then try again without it.
+% \begin{macrocode}
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIskipscriptregion
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedDialectScript
+ -\CurrentTrackedRegion}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIskipscriptregion
+ }%
+ \fi
+ \fi
+ \fi
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIskipscript}
+%\changes{1.4}{2019-11-30}{new}
+%No region. Has a script but already tested with 639-1 and script.
+%Just test language code alone.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIskipscript#1#2#3{%
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \IfTrackedLanguageHasIsoCode
+ {639-2}{\CurrentTrackedLanguage}
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIscript
+ }%
+ {%
+ \IfTrackedLanguageHasIsoCode
+ {639-3}{\CurrentTrackedLanguage}
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIscript
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langvariant
+ }%
+ }%
+ \else
+% \end{macrocode}
+% Try without sub-language code.
+% \begin{macrocode}
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \IfTrackedLanguageHasIsoCode
+ {639-2}{\CurrentTrackedLanguage}
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIscript
+ }%
+ {%
+ \IfTrackedLanguageHasIsoCode
+ {639-3}{\CurrentTrackedLanguage}
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIscript
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langvariant
+ }%
+ }%
+ }%
+ \fi
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIIscript}
+%\changes{1.4}{2019-11-30}{new}
+%No region but has a script.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIIscript#1#2#3{%
+ \let\CurrentTrackedIsoCode\CurrentTrackedIsoCodeII
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectScript}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIskipscript
+ \else
+% \end{macrocode}
+% Try without sub-language.
+% \begin{macrocode}
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedDialectScript}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIskipscript
+ }%
+ \fi
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIIskipscript}
+%\changes{1.4}{2019-11-30}{new}
+%No region. Has a script but already checked.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIIskipscript#1#2#3{%
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \IfTrackedLanguageHasIsoCode
+ {639-3}{\CurrentTrackedLanguage}
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIscript
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langvariant
+ }%
+ \else
+% \end{macrocode}
+% Try without sub-language.
+% \begin{macrocode}
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \IfTrackedLanguageHasIsoCode
+ {639-3}{\CurrentTrackedLanguage}
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIscript
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langvariant
+ }%
+ }%
+ \fi
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIIIscript}
+%\changes{1.4}{2019-11-30}{new}
+%No region but has a script.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIIIscript#1#2#3{%
+ \let\CurrentTrackedIsoCode\CurrentTrackedIsoCodeIII
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectScript}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIskipscript
+ \else
+% \end{macrocode}
+% Try without sub-language.
+% \begin{macrocode}
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedDialectScript}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIskipscript
+ }%
+ \fi
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIIIskipscript}
+%\changes{1.4}{2019-11-30}{new}
+%No region. Has a script but already checked.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIIIskipscript#1#2#3{%
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langvariant
+ \else
+% \end{macrocode}
+% Try without sub-language.
+% \begin{macrocode}
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langvariant
+ }%
+ \fi
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIskipregion}
+%\changes{1.4}{2019-11-30}{new}
+%No script. Has a region but already tested with 639-1 and script.
+%Just test language code alone.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIskipregion#1#2#3{%
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \IfTrackedLanguageHasIsoCode
+ {639-2}{\CurrentTrackedLanguage}
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIregion
+ }%
+ {%
+ \IfTrackedLanguageHasIsoCode
+ {639-3}{\CurrentTrackedLanguage}
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIregion
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langvariant
+ }%
+ }%
+ \else
+% \end{macrocode}
+% Try without sub-language code.
+% \begin{macrocode}
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \IfTrackedLanguageHasIsoCode
+ {639-2}{\CurrentTrackedLanguage}
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIregion
+ }%
+ {%
+ \IfTrackedLanguageHasIsoCode
+ {639-3}{\CurrentTrackedLanguage}
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIregion
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langvariant
+ }%
+ }%
+ }%
+ \fi
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIIregion}
+%\changes{1.4}{2019-11-30}{new}
+%No script but has a region.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIIregion#1#2#3{%
+ \let\CurrentTrackedIsoCode\CurrentTrackedIsoCodeII
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectScript}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIskipregion
+ \else
+% \end{macrocode}
+% Try without sub-language.
+% \begin{macrocode}
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedDialectScript}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIskipregion
+ }%
+ \fi
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIIskipregion}
+%\changes{1.4}{2019-11-30}{new}
+%No script. Has a region but already tested with 639-2 and region.
+%Just test language code alone.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIIskipregion#1#2#3{%
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \IfTrackedLanguageHasIsoCode
+ {639-3}{\CurrentTrackedLanguage}
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIregion
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langvariant
+ }%
+ \else
+% \end{macrocode}
+% Try without sub-language code.
+% \begin{macrocode}
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \IfTrackedLanguageHasIsoCode
+ {639-3}{\CurrentTrackedLanguage}
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIregion
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langvariant
+ }%
+ }%
+ \fi
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIIregion}
+%\changes{1.4}{2019-11-30}{new}
+%No script but has a region.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIIregion#1#2#3{%
+ \let\CurrentTrackedIsoCode\CurrentTrackedIsoCodeII
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectScript}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIskipregion
+ \else
+% \end{macrocode}
+% Try without sub-language.
+% \begin{macrocode}
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedDialectScript}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIskipregion
+ }%
+ \fi
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIIIskipregion}
+%\changes{1.4}{2019-11-30}{new}
+%No script. Has a region but already tested with 639-3 and region.
+%Just test language code alone.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIIskipregion#1#2#3{%
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langvariant
+ \else
+% \end{macrocode}
+% Try without sub-language code.
+% \begin{macrocode}
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langvariant
+ }%
+ \fi
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIIIregion}
+%\changes{1.4}{2019-11-30}{new}
+%No script but has a region.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIIIregion#1#2#3{%
+ \let\CurrentTrackedIsoCode\CurrentTrackedIsoCodeIII
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectScript}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIskipregion
+ \else
+% \end{macrocode}
+% Try without sub-language.
+% \begin{macrocode}
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedDialectScript}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIskipregion
+ }%
+ \fi
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIskipscriptregion}
+%\changes{1.4}{2019-11-30}{new}
+%Already tested script and region. Test without script if the script
+%is the default then without region.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIskipscriptregion#1#2#3{%
+% \end{macrocode}
+% Is the script the default for this dialect?
+% \begin{macrocode}
+ \@tracklang@ifcseqcsname\CurrentTrackedDialectScript
+ {@tracklang@knowniso@script@\CurrentTrackedLanguage}%
+ {%
+% \end{macrocode}
+% Try just language code and region.
+% \begin{macrocode}
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedRegion}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+% \end{macrocode}
+% Try just language code and script.
+% \begin{macrocode}
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIscriptskipregion
+ \else
+% \end{macrocode}
+% Try without sub-language.
+% \begin{macrocode}
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedRegion}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIscriptskipregion
+ }%
+ \fi
+ }%
+ }%
+ {%
+% \end{macrocode}
+% Script isn't the default.
+% \begin{macrocode}
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIscriptskipregion
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIscriptskipregion}
+%\changes{1.4}{2019-11-30}{new}
+%Test with script and without region.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIscriptskipregion#1#2#3{%
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectScript}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+% \end{macrocode}
+% Try just language code.
+% \begin{macrocode}
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIskipscriptskipregion
+ \else
+% \end{macrocode}
+% Try without sub-language.
+% \begin{macrocode}
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedDialectScript}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIskipscriptskipregion
+ }%
+ \fi
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIskipscriptskipregion}
+%\changes{1.4}{2019-11-30}{new}
+%Test without script and without region.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIskipscriptskipregion#1#2#3{%
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+% \end{macrocode}
+% Try other language codes with script and region.
+% \begin{macrocode}
+ \IfTrackedLanguageHasIsoCode
+ {639-2}{\CurrentTrackedLanguage}
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIscriptregion
+ }%
+ {%
+ \IfTrackedLanguageHasIsoCode
+ {639-3}{\CurrentTrackedLanguage}
+ {%
+ \let\CurrentTrackedIsoCode\CurrentTrackedIsoCodeIII
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIscriptregion
+ }%
+ {%
+% \end{macrocode}
+% No other language codes. Try just the region.
+% \begin{macrocode}
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@region
+ }%
+ }%
+ \else
+% \end{macrocode}
+% Try just language code.
+% \begin{macrocode}
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+% \end{macrocode}
+% Try other language codes with script and region.
+% \begin{macrocode}
+ \IfTrackedLanguageHasIsoCode
+ {639-2}{\CurrentTrackedLanguage}
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIscriptregion
+ }%
+ {%
+ \IfTrackedLanguageHasIsoCode
+ {639-3}{\CurrentTrackedLanguage}
+ {%
+ \let\CurrentTrackedIsoCode\CurrentTrackedIsoCodeIII
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIscriptregion
+ }%
+ {%
+% \end{macrocode}
+% No other language codes. Try just the region.
+% \begin{macrocode}
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@region
+ }%
+ }%
+ }%
+ \fi
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIIskipscriptregion}
+%\changes{1.4}{2019-11-30}{new}
+%Already tested script and region. Test without script if the script
+%is the default then without region.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIIskipscriptregion#1#2#3{%
+% \end{macrocode}
+% Is the script the default for this dialect?
+% \begin{macrocode}
+ \@tracklang@ifcseqcsname\CurrentTrackedDialectScript
+ {@tracklang@knowniso@script@\CurrentTrackedLanguage}%
+ {%
+% \end{macrocode}
+% Try just language code and region.
+% \begin{macrocode}
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedRegion}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+% \end{macrocode}
+% Try just language code and script.
+% \begin{macrocode}
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIscriptskipregion
+ \else
+% \end{macrocode}
+% Try without sub-language.
+% \begin{macrocode}
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedRegion}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIscriptskipregion
+ }%
+ \fi
+ }%
+ }%
+ {%
+% \end{macrocode}
+% Script isn't the default.
+% \begin{macrocode}
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIscriptskipregion
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIIscriptskipregion}
+%\changes{1.4}{2019-11-30}{new}
+%Test with script and without region.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIIscriptskipregion#1#2#3{%
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectScript}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+% \end{macrocode}
+% Try just language code.
+% \begin{macrocode}
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIskipscriptskipregion
+ \else
+% \end{macrocode}
+% Try without sub-language.
+% \begin{macrocode}
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedDialectScript}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIskipscriptskipregion
+ }%
+ \fi
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIIskipscriptskipregion}
+%\changes{1.4}{2019-11-30}{new}
+%Test without script and without region.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIIskipscriptskipregion#1#2#3{%
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+% \end{macrocode}
+% Try other language code with script and region.
+% \begin{macrocode}
+ \IfTrackedLanguageHasIsoCode
+ {639-3}{\CurrentTrackedLanguage}
+ {%
+ \let\CurrentTrackedIsoCode\CurrentTrackedIsoCodeIII
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIscriptregion
+ }%
+ {%
+% \end{macrocode}
+% No other language codes. Try just the region.
+% \begin{macrocode}
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@region
+ }%
+ \else
+% \end{macrocode}
+% Try just language code.
+% \begin{macrocode}
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+% \end{macrocode}
+% Try other language codes with script and region.
+% \begin{macrocode}
+ \IfTrackedLanguageHasIsoCode
+ {639-3}{\CurrentTrackedLanguage}
+ {%
+ \let\CurrentTrackedIsoCode\CurrentTrackedIsoCodeIII
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIscriptregion
+ }%
+ {%
+% \end{macrocode}
+% No other language codes. Try just the region.
+% \begin{macrocode}
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@region
+ }%
+ }%
+ \fi
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIIIskipscriptregion}
+%\changes{1.4}{2019-11-30}{new}
+%Already tested script and region. Test without script if the script
+%is the default then without region.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIIIskipscriptregion#1#2#3{%
+% \end{macrocode}
+% Is the script the default for this dialect?
+% \begin{macrocode}
+ \@tracklang@ifcseqcsname\CurrentTrackedDialectScript
+ {@tracklang@knowniso@script@\CurrentTrackedLanguage}%
+ {%
+% \end{macrocode}
+% Try just language code and region.
+% \begin{macrocode}
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedRegion}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+% \end{macrocode}
+% Try just language code and script.
+% \begin{macrocode}
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIscriptskipregion
+ \else
+% \end{macrocode}
+% Try without sub-language.
+% \begin{macrocode}
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedRegion}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIscriptskipregion
+ }%
+ \fi
+ }%
+ }%
+ {%
+% \end{macrocode}
+% Script isn't the default.
+% \begin{macrocode}
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIscriptskipregion
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIIIscriptskipregion}
+%\changes{1.4}{2019-11-30}{new}
+%Test with script and without region.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIIIscriptskipregion#1#2#3{%
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectScript}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+% \end{macrocode}
+% Try just language code.
+% \begin{macrocode}
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIskipscriptskipregion
+ \else
+% \end{macrocode}
+% Try without sub-language.
+% \begin{macrocode}
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedDialectScript}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIskipscriptskipregion
+ }%
+ \fi
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIIIskipscriptskipregion}
+%\changes{1.4}{2019-11-30}{new}
+%Test without script and without region.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIIIskipscriptskipregion#1#2#3{%
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+% \end{macrocode}
+% No other language codes. Try just the region.
+% \begin{macrocode}
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@region
+ \else
+% \end{macrocode}
+% Try just language code.
+% \begin{macrocode}
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+% \end{macrocode}
+% No other language codes. Try just the region.
+% \begin{macrocode}
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@region
+ }%
+ \fi
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langII}
+%\changes{1.4}{2019-11-30}{new}
+%No region or script.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langII#1#2#3{%
+ \IfTrackedLanguageHasIsoCode{639-2}{\CurrentTrackedLanguage}%
+ {%
+ \let\CurrentTrackedIsoCode\CurrentTrackedIsoCodeII
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedDialectSubLang}%
+ \fi
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIII
+ \else
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIII
+ }%
+ \fi
+ }%
+ {%
+ \fi
+ }%
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIII
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIII}
+%\changes{1.4}{2019-11-30}{new}
+%No region or script.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIII#1#2#3{%
+ \IfTrackedLanguageHasIsoCode{639-3}{\CurrentTrackedLanguage}%
+ {%
+ \let\CurrentTrackedIsoCode\CurrentTrackedIsoCodeIII
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedIsoCode-\CurrentTrackedDialectSubLang}%
+ \fi
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langvariant
+ \else
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langvariant
+ }%
+ \fi
+ }%
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langvariant
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@region}
+%\changes{1.4}{2019-11-30}{new}
+%Test just the region.
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@region#1#2#3{%
+ \let\CurrentTrackedTag\CurrentTrackedRegion
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langvariant
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langvariant}
+%\changes{1.4}{2019-11-30}{new}
+%Test language code and variant
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langvariant#1#2#3{%
+ \ifx\CurrentTrackedDialectVariant\empty
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@rootlang
+ \else
+ \IfTrackedLanguageHasIsoCode{639-1}{\CurrentTrackedLanguage}%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIvariant
+ }%
+ {%
+ \IfTrackedLanguageHasIsoCode{639-2}{\CurrentTrackedLanguage}%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIvariant
+ }%
+ {%
+ \IfTrackedLanguageHasIsoCode{639-3}{\CurrentTrackedLanguage}%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIvariant
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@rootlang
+ }%
+ }%
+ }%
+ \fi
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIvariant}
+%\changes{1.4}{2019-11-30}{new}
+%Test 639-1 code and variant
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIvariant#1#2#3{%
+ \let\CurrentTrackedIsoCode\CurrentTrackedIsoCodeI
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectVariant}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \IfTrackedLanguageHasIsoCode{639-2}{\CurrentTrackedLanguage}%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIvariant
+ }
+ {%
+ \IfTrackedLanguageHasIsoCode{639-3}{\CurrentTrackedLanguage}%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIvariant
+ }
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@rootlang
+ }%
+ }%
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIIvariant}
+%\changes{1.4}{2019-11-30}{new}
+%Test 639-2 code and variant
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIIvariant#1#2#3{%
+ \let\CurrentTrackedIsoCode\CurrentTrackedIsoCodeII
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectVariant}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \IfTrackedLanguageHasIsoCode{639-3}{\CurrentTrackedLanguage}%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@langIIIvariant
+ }
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@rootlang
+ }%
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@langIIIvariant}
+%\changes{1.4}{2019-11-30}{new}
+%Test 639-3 code and variant
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@langIIIvariant#1#2#3{%
+ \let\CurrentTrackedIsoCode\CurrentTrackedIsoCodeIII
+ \let\CurrentTrackedTag\CurrentTrackedIsoCode
+ \ifx\CurrentTrackedDialectSubLang\empty
+ \else
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectSubLang}%
+ \fi
+ \edef\CurrentTrackedTag{\CurrentTrackedTag-\CurrentTrackedDialectVariant}%
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@noop
+ }%
+ {%
+ \let\@tracklang@test@if@file@exists@next\@tracklang@test@if@file@exists@for@rootlang
+ }%
+ \@tracklang@test@if@file@exists@next{#1}{#2}{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@test@if@file@exists@for@rootlang}
+%\changes{1.4}{2019-11-30}{new}
+%Test the root language label. (Final test.)
+% \begin{macrocode}
+\def\@tracklang@test@if@file@exists@for@rootlang#1#2#3{%
+ \let\CurrentTrackedTag\CurrentTrackedLanguage
+ \@tracklang@verbose{Testing tag `\CurrentTrackedTag'}%
+ \@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
+ {%
+ \let\@tracklang@if@file@exists\@tracklang@firstoftwo
+ }%
+ {}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\IfTrackedLanguageFileExists@orig}
+%\changes{1.4}{2019-11-30}{new}
+%The new definition of \cs{IfTrackedLanguageFileExists} has a
+%different order of priority. If the original behaviour is
+%specifically required, this has the pre version 1.4 definition.
+% \begin{macrocode}
+\long\def\IfTrackedLanguageFileExists@orig#1#2#3#4#5{%
+ \def\CurrentTrackedTag{}%
+ \SetCurrentTrackedDialect{#1}%
+ \IfTrackedDialect{#1}%
+ {%
\edef\CurrentTrackedTag{#1}%
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
{#4}%
{%
-% \end{macrocode}
-% No file found for dialect label, try \meta{ISO 639-1}-\meta{ISO
-% 3166-1} next.
-% \begin{macrocode}
\IfTrackedLanguageHasIsoCode
{639-1}{\CurrentTrackedLanguage}
{%
@@ -9412,17 +11617,10 @@ and~\ref{tab:nonisoopts}}
\TrackedIsoCodeFromLanguage
{639-1}{\CurrentTrackedLanguage}}%
\ifx\CurrentTrackedRegion\empty
-% \end{macrocode}
-% No region, just try ISO 639-1 code
-% \begin{macrocode}
\let\CurrentTrackedTag\CurrentTrackedIsoCode
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
{#4}
{%
-% \end{macrocode}
-% No region and file for just \meta{ISO 639-1 code}. Try ISO 639-2 code.
-% (No check for 639-3 since it has 639-1 code.)
-% \begin{macrocode}
\IfTrackedLanguageHasIsoCode
{639-2}{\CurrentTrackedLanguage}
{%
@@ -9433,35 +11631,21 @@ and~\ref{tab:nonisoopts}}
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
{#4}%
{%
-% \end{macrocode}
-% Try root language.
-% \begin{macrocode}
\let\CurrentTrackedTag\CurrentTrackedLanguage
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}{#4}{#5}%
}%
}%
{%
-% \end{macrocode}
-% No region, no ISO 639-1 code and no ISO 639-2 code.
-% No file found for dialect label, try root language label next.
-% \begin{macrocode}
\let\CurrentTrackedTag\CurrentTrackedLanguage
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}{#4}{#5}%
}%
}%
\else
-% \end{macrocode}
-% Has a region so try \meta{ISO 639-1 code}\texttt{-}\meta{region}
-% \begin{macrocode}
\edef\CurrentTrackedTag{%
\CurrentTrackedIsoCode-\CurrentTrackedRegion}%
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
{#4}
{%
-% \end{macrocode}
-% Has a region but \meta{ISO 639-1 code}\texttt{-}\meta{region}
-% not found, so try \meta{ISO 639-2 code}\texttt{-}\meta{region}
-% \begin{macrocode}
\IfTrackedLanguageHasIsoCode
{639-2}{\CurrentTrackedLanguage}
{%
@@ -9474,35 +11658,21 @@ and~\ref{tab:nonisoopts}}
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
{#4}%
{%
-% \end{macrocode}
-% Has a region but \meta{ISO 639-1 code}\texttt{-}\meta{region} not
-% found and \meta{ISO 639-2 code}\texttt{-}\meta{region} not found,
-% so try just \meta{ISO 639-1 code}
-% \begin{macrocode}
\let\CurrentTrackedTag\org@currenttrackedisocode
\let\org@currenttrackedisocode\CurrentTrackedIsoCode
\let\CurrentTrackedIsoCode\CurrentTrackedTag
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
{#4}
{%
-% \end{macrocode}
-% Try just the ISO 639-2 code.
-% \begin{macrocode}
\let\CurrentTrackedIsoCode\org@currenttrackedisocode
\let\CurrentTrackedTag\CurrentTrackedIsoCode
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
{#4}%
{%
-% \end{macrocode}
-% Try just the region.
-% \begin{macrocode}
\let\CurrentTrackedTag\CurrentTrackedRegion
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
{#4}%
{%
-% \end{macrocode}
-% Try the root language.
-% \begin{macrocode}
\let\CurrentTrackedTag\CurrentTrackedLanguage
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}{#4}{#5}%
}%
@@ -9511,24 +11681,14 @@ and~\ref{tab:nonisoopts}}
}%
}%
{%
-% \end{macrocode}
-% Has a region but \meta{ISO 639-1 code}\texttt{-}\meta{region}
-% not found, and no ISO 639-2 code so just try \meta{ISO 639-1 code}
-% \begin{macrocode}
\let\CurrentTrackedTag\CurrentTrackedIsoCode
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
{#4}%
{%
-% \end{macrocode}
-% Just try the region
-% \begin{macrocode}
\let\CurrentTrackedTag\CurrentTrackedRegion
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
{#4}%
{%
-% \end{macrocode}
-% Try the root language.
-% \begin{macrocode}
\let\CurrentTrackedTag\CurrentTrackedLanguage
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}{#4}{#5}%
}%
@@ -9538,9 +11698,6 @@ and~\ref{tab:nonisoopts}}
\fi
}%
{%
-% \end{macrocode}
-% No ISO 639-1 code. Try ISO 639-2 code.
-% \begin{macrocode}
\IfTrackedLanguageHasIsoCode
{639-2}{\CurrentTrackedLanguage}
{%
@@ -9549,9 +11706,6 @@ and~\ref{tab:nonisoopts}}
{639-2}{\CurrentTrackedLanguage}}%
}%
{%
-% \end{macrocode}
-% No ISO 639-1 code or ISO 639-2 code. Try 639-3 code.
-% \begin{macrocode}
\IfTrackedLanguageHasIsoCode
{639-3}{\CurrentTrackedLanguage}
{%
@@ -9564,78 +11718,41 @@ and~\ref{tab:nonisoopts}}
}%
}%
\ifx\CurrentTrackedIsoCode\empty
-% \end{macrocode}
-% No ISO 639-1 code or ISO 639-2 code. Try just the region.
-% \begin{macrocode}
\ifx\CurrentTrackedRegion\empty
-% \end{macrocode}
-% No region. Try the root language.
-% \begin{macrocode}
\let\CurrentTrackedTag\CurrentTrackedLanguage
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}{#4}{#5}%
\else
-% \end{macrocode}
-% Try the region.
-% \begin{macrocode}
\let\CurrentTrackedTag\CurrentTrackedRegion
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
{#4}%
{%
-% \end{macrocode}
-% Try the root language.
-% \begin{macrocode}
\let\CurrentTrackedTag\CurrentTrackedLanguage
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}{#4}{#5}%
}%
\fi
\else
-% \end{macrocode}
-% Has ISO 639-2 or 639-3 code.
-% \begin{macrocode}
\ifx\CurrentTrackedRegion\empty
-% \end{macrocode}
-% Has ISO 639-2 or 639-3 code but no region.
-% \begin{macrocode}
\let\CurrentTrackedTag\CurrentTrackedIsoCode
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
{#4}%
{%
-% \end{macrocode}
-% Try the root language.
-% \begin{macrocode}
\let\CurrentTrackedTag\CurrentTrackedLanguage
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}{#4}{#5}%
}%
\else
-% \end{macrocode}
-% Has ISO 639-2 or 639-3 code and a region. Try \meta{ISO
-% 639-2 or 639-3}\texttt{-}\meta{region} first.
-% \begin{macrocode}
\edef\CurrentTrackedTag{%
\CurrentTrackedIsoCode-\CurrentTrackedRegion}%
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
{#4}%
{%
-% \end{macrocode}
-% Has ISO 639-2 or 639-3 code and a region but \meta{ISO
-% 639-2 or 639-3}\texttt{-}\meta{region} doesn't exist. Try just \meta{ISO
-% 639-2 or 639-3}
-% \begin{macrocode}
\let\CurrentTrackedTag\CurrentTrackedIsoCode
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
{#4}%
{%
-% \end{macrocode}
-% Has ISO 639-2 or 639-3 code and a region but \meta{ISO
-% 639-2 or 639-3} doesn't exist. Try just \meta{region}
-% \begin{macrocode}
\let\CurrentTrackedTag\CurrentTrackedRegion
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}%
{#4}%
{%
-% \end{macrocode}
-% Try the root language.
-% \begin{macrocode}
\let\CurrentTrackedTag\CurrentTrackedLanguage
\@tracklang@IfFileExists{#2\CurrentTrackedTag#3}{#4}{#5}%
}%
@@ -9838,6 +11955,102 @@ and~\ref{tab:nonisoopts}}
% \end{macrocode}
%\end{macro}
%
+%\begin{macro}{\TrackLangRedefHook}
+%\changes{1.4}{2019-11-30}{new}
+%\begin{definition}
+%\cs{TrackLangRedefHook}\marg{code}\marg{type}
+%\end{definition}
+% Similar to \cs{TrackLangAddToHook} but redefines the hook rather
+% than appending to it.
+% This command is not permitted outside resource files.
+% \begin{macrocode}
+\def\TrackLangRedefHook{\noop@TrackLangRedefHook}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\noop@TrackLangRedefHook}
+% \begin{macrocode}
+\def\noop@TrackLangRedefHook#1#2{%
+ \@tracklang@err{\string\TrackLangRedefHook\space
+ only permitted within resource files}
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@TrackLangRedefHook}
+% \begin{macrocode}
+\def\@TrackLangRedefHook#1#2{%
+% \end{macrocode}
+% \sty{babel} check first.
+% \begin{macrocode}
+ \@tracklang@ifundef{#2\CurrentTrackedDialect}%
+ {%
+% \end{macrocode}
+% Does the dialect label have a mapping?
+% \begin{macrocode}
+ \IfTrackedDialectHasMapping{\CurrentTrackedDialect}%
+ {%
+% \end{macrocode}
+% Try the mapping label next.
+% \begin{macrocode}
+ \edef\@tracklang@tmp{%
+ \csname @tracklang@dialectmap@tohook@\CurrentTrackedDialect\endcsname}%
+ \@tracklang@ifundef{#2\@tracklang@tmp}%
+ {%
+% \end{macrocode}
+% No captions hook. Try \sty{polyglossia}.
+% \begin{macrocode}
+ \@tracklang@ifundef{#2\CurrentTrackedLanguage}%
+ {%
+% \end{macrocode}
+% No captions hook. Do the code now.
+% \begin{macrocode}
+ #1%
+ }%
+ {%
+ \@tracklang@redefhook{#2}{\CurrentTrackedLanguage}{#1}%
+ }%
+ }%
+ {%
+ \@tracklang@redefhook{#2}{\@tracklang@tmp}{#1}%
+ }%
+ }%
+ {%
+% \end{macrocode}
+% \sty{polyglossia} check next.
+% \begin{macrocode}
+ \@tracklang@ifundef{#2\CurrentTrackedLanguage}%
+ {%
+% \end{macrocode}
+% No captions hook.
+% \begin{macrocode}
+ }%
+ {%
+ \@tracklang@redefhook{#2}{\CurrentTrackedLanguage}{#1}%
+ }%
+ }%
+ }%
+ {%
+ \@tracklang@redefhook{#2}{\CurrentTrackedDialect}{#1}%
+ }%
+% \end{macrocode}
+% Do the code now in case the hook has already been used.
+% \begin{macrocode}
+ #1%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@tracklang@redefhook}
+%\changes{1.4}{2019-11-30}{new}
+%\begin{definition}
+%\cs{@tracklang@redefhook}\marg{type}\marg{label}\marg{code}
+%\end{definition}
+% \begin{macrocode}
+\def\@tracklang@redefhook#1#2#3{%
+ \expandafter\gdef\csname#1#2\endcsname{#3}%
+}
+% \end{macrocode}
+%\end{macro}
+%
%\begin{macro}{\SetTrackedDialectLabelMap}
%\changes{1.3}{2016-10-07}{new}
%\begin{definition}
@@ -10193,7 +12406,7 @@ and~\ref{tab:nonisoopts}}
% Version info.
% \begin{macrocode}
\expandafter\def\csname ver@tracklang-region-codes.tex\endcsname{%
- 2019/11/11 v1.3.9 (NLCT) Track Languages Regions}%
+ 2019/11/30 v1.4 (NLCT) Track Languages Regions}%
% \end{macrocode}
%
%\begin{macro}{\TrackLangRegionMap}
@@ -10560,6 +12773,10 @@ and~\ref{tab:nonisoopts}}
\TrackLangRegionMap{894}{ZM}{ZMB}%
\TrackLangRegionMap{716}{ZW}{ZWE}%
% \end{macrocode}
+%\changes{1.4}{2019-11-30}{input extra regions if provided}
+% \begin{macrocode}
+\@tracklang@input@extra@region@files
+% \end{macrocode}
%
%Restore category code of \texttt{@}.
% \begin{macrocode}
@@ -10582,7 +12799,7 @@ and~\ref{tab:nonisoopts}}
%\changes{1.3}{2016-10-07}{added tracklang-scripts.sty}
% \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{tracklang-scripts}[2019/11/11 v1.3.9 (NLCT) Track
+\ProvidesPackage{tracklang-scripts}[2019/11/30 v1.4 (NLCT) Track
Language Scripts (LaTeX)]
\RequirePackage{tracklang}
\input{tracklang-scripts}
@@ -10624,7 +12841,7 @@ Language Scripts (LaTeX)]
% Version info.
% \begin{macrocode}
\expandafter\def\csname ver@tracklang-scripts.tex\endcsname{%
- 2019/11/11 v1.3.9 (NLCT) Track Languages Scripts (Generic)}%
+ 2019/11/30 v1.4 (NLCT) Track Languages Scripts (Generic)}%
% \end{macrocode}
%
%\begin{macro}{\TrackLangScriptsMap}
@@ -10785,202 +13002,197 @@ Language Scripts (LaTeX)]
%\end{macro}
%
%Define mappings. The parent information is currently missing.
-% \begin{macrocode}
-\TrackLangScriptMap{Adlm}{166}{Adlam}{RL}{}
-\TrackLangScriptMap{Afak}{439}{Afaka}{varies}{}
-\TrackLangScriptMap{Aghb}{239}{Caucasian Albanian}{LR}{}
-\TrackLangScriptMap{Ahom}{338}{Ahom, Tai Ahom}{LR}{}
-\TrackLangScriptMap{Arab}{160}{Arabic}{RL}{}
-\TrackLangScriptMap{Aran}{161}{Arabic (Nastaliq variant)}{RL}{}
-\TrackLangScriptMap{Armi}{124}{Imperial Aramaic}{RL}{}
-\TrackLangScriptMap{Armn}{230}{Armenian}{LR}{}
-\TrackLangScriptMap{Avst}{134}{Avestan}{RL}{}
-\TrackLangScriptMap{Bali}{360}{Balinese}{LR}{}
-\TrackLangScriptMap{Bamu}{435}{Bamum}{LR}{}
-\TrackLangScriptMap{Bass}{259}{Bassa Vah}{LR}{}
-\TrackLangScriptMap{Batk}{365}{Batak}{LR}{}
-\TrackLangScriptMap{Beng}{334}{Bhaiksuki}{LR}{}
-\TrackLangScriptMap{Blis}{550}{Blissymbols}{varies}{}
-\TrackLangScriptMap{Bopo}{285}{Bopomofo}{LR}{}
-\TrackLangScriptMap{Brah}{300}{Brahmi}{LR}{}
-\TrackLangScriptMap{Brai}{570}{Braille}{LR}{}
-\TrackLangScriptMap{Bugi}{367}{Buginese}{LR}{}
-\TrackLangScriptMap{Buhd}{372}{Buhid}{LR}{}
-\TrackLangScriptMap{Cakm}{349}{Chakma}{LR}{}
-\TrackLangScriptMap{Cans}{440}{Unified Canadian Aboriginal Syllabics}{LR}{}
-\TrackLangScriptMap{Cari}{201}{Carian}{LR}{}
-\TrackLangScriptMap{Cham}{358}{Cham}{LR}{}
-\TrackLangScriptMap{Cher}{445}{Cherokee}{LR}{}
-\TrackLangScriptMap{Cirt}{291}{Cirth}{varies}{}
-\TrackLangScriptMap{Copt}{204}{Coptic}{LR}{}
-\TrackLangScriptMap{Cprt}{403}{Cypriot}{RL}{}
-\TrackLangScriptMap{Cyrl}{220}{Cyrillic}{LR}{}
-\TrackLangScriptMap{Cyrs}{221}{Cyrillic (Old Church Slavonic{}
-variant)}{varies}{}
-\TrackLangScriptMap{Deva}{315}{Devanagari (Nagari)}{LR}{}
-\TrackLangScriptMap{Dsrt}{250}{Deseret (Mormon)}{LR}{}
-\TrackLangScriptMap{Dupl}{755}{Duployan shorthand, Duployan{}
-stenography}{LR}{}
-\TrackLangScriptMap{Egyd}{070}{Egyptian demotic}{RL}{}
-\TrackLangScriptMap{Egyh}{060}{Egyptian hieratic}{RL}{}
-\TrackLangScriptMap{Egyp}{050}{Egyptian hieroglyphs}{LR}{}
-\TrackLangScriptMap{Elba}{226}{Elbasan}{LR}{}
-\TrackLangScriptMap{Ethi}{430}{Ethiopic (Ge'ez)}{LR}{}
-\TrackLangScriptMap{Geok}{241}{Khutsuri (Asomtavruli and{}
-Nuskhuri)}{LR}{}
-\TrackLangScriptMap{Geor}{240}{Georgian (Mkhedruli)}{LR}{}
-\TrackLangScriptMap{Glag}{225}{Glagolitic}{LR}{}
-\TrackLangScriptMap{Goth}{206}{Gothic}{LR}{}
-\TrackLangScriptMap{Gran}{343}{Grantha}{LR}{}
-\TrackLangScriptMap{Grek}{200}{Greek}{LR}{}
-\TrackLangScriptMap{Gujr}{320}{Gujarati}{LR}{}
-\TrackLangScriptMap{Guru}{310}{Gurmukhi}{LR}{}
-\TrackLangScriptMap{Hanb}{503}{Han with Bopomofo (alias for Han +{}
-Bopomofo)}{LR}{}
-\TrackLangScriptMap{Hang}{286}{Hangul}{LR}{}
-\TrackLangScriptMap{Hani}{500}{Han (Hanzi, Kanji, Hanja)}{LR}{}
-\TrackLangScriptMap{Hano}{371}{Hanunoo}{LR}{}
-\TrackLangScriptMap{Hans}{501}{Han (Simplified variant)}{varies}{}
-\TrackLangScriptMap{Hant}{502}{Han (Traditional variant)}{varies}{}
-\TrackLangScriptMap{Hatr}{127}{Hatran}{RL}{}
-\TrackLangScriptMap{Hebr}{125}{Hebrew}{RL}{}
-\TrackLangScriptMap{Hira}{410}{Hiragana}{LR}{}
-\TrackLangScriptMap{Hluw}{080}{Anatolian Hieroglyphs (Luwian{}
-Hieroglyphs, Hittite Hieroglyphs)}{LR}{}
-\TrackLangScriptMap{Hmng}{450}{Pahawh Hmong}{LR}{}
-\TrackLangScriptMap{Hrkt}{412}{Japanese syllabaries (alias for{}
-Hiragana + Katakana)}{varies}{}
-\TrackLangScriptMap{Hung}{176}{Old Hungarian (Hungarian Runic)}{RL}{}
-\TrackLangScriptMap{Inds}{610}{Indus (Harappan)}{RL}{}
-\TrackLangScriptMap{Ital}{210}{Old Italic (Etruscan, Oscan, etc.)}{LR}{}
-\TrackLangScriptMap{Jamo}{284}{Jamo (alias for Jamo subset of{}
-Hangul)}{LR}{}
-\TrackLangScriptMap{Java}{361}{Javanese}{LR}{}
-\TrackLangScriptMap{Jpan}{413}{Japanese (alias for Han + Hiragana +{}
-Katakana)}{varies}{}
-\TrackLangScriptMap{Jurc}{510}{Jurchen}{LR}{}
-\TrackLangScriptMap{Kali}{357}{Kayah Li}{LR}{}
-\TrackLangScriptMap{Kana}{411}{Katakana}{LR}{}
-\TrackLangScriptMap{Khar}{305}{Kharoshthi}{RL}{}
-\TrackLangScriptMap{Khmr}{355}{Khmer}{LR}{}
-\TrackLangScriptMap{Khoj}{322}{Khojki}{LR}{}
-\TrackLangScriptMap{Kitl}{505}{Khitan large script}{LR}{}
-\TrackLangScriptMap{Kits}{288}{Khitan small script}{TB}{}
-\TrackLangScriptMap{Knda}{345}{Kannada}{LR}{}
-\TrackLangScriptMap{Kore}{287}{Korean (alias for Hangul + Han)}{LR}{}
-\TrackLangScriptMap{Kpel}{436}{Kpelle}{LR}{}
-\TrackLangScriptMap{Kthi}{317}{Kaithi}{LR}{}
-\TrackLangScriptMap{Lana}{351}{Tai Tham (Lanna)}{LR}{}
-\TrackLangScriptMap{Laoo}{356}{Lao}{LR}{}
-\TrackLangScriptMap{Latf}{217}{Latin (Fraktur variant)}{varies}{}
-\TrackLangScriptMap{Latg}{216}{Latin (Gaelic variant)}{LR}{}
-\TrackLangScriptMap{Latn}{215}{Latin}{LR}{}
-\TrackLangScriptMap{Leke}{364}{Leke}{LR}{}
-\TrackLangScriptMap{Lepc}{335}{Lepcha}{LR}{}
-\TrackLangScriptMap{Limb}{336}{Limbu}{LR}{}
-\TrackLangScriptMap{Lina}{400}{Linear A}{LR}{}
-\TrackLangScriptMap{Linb}{401}{Linear B}{LR}{}
-\TrackLangScriptMap{Lisu}{399}{Lisu (Fraser)}{LR}{}
-\TrackLangScriptMap{Loma}{437}{Loma}{LR}{}
-\TrackLangScriptMap{Lyci}{202}{Lycian}{LR}{}
-\TrackLangScriptMap{Lydi}{116}{Lydian}{RL}{}
-\TrackLangScriptMap{Mahj}{314}{Mahajani}{LR}{}
-\TrackLangScriptMap{Mand}{140}{Mandaic, Mandaean}{RL}{}
-\TrackLangScriptMap{Mani}{139}{Manichaean}{RL}{}
-\TrackLangScriptMap{Marc}{332}{Marchen}{LR}{}
-\TrackLangScriptMap{Maya}{090}{Mayan hieroglyphs}{varies}{}
-\TrackLangScriptMap{Mend}{438}{Mende Kikakui}{RL}{}
-\TrackLangScriptMap{Merc}{101}{Meroitic Cursive}{RL}{}
-\TrackLangScriptMap{Mero}{100}{Meroitic Hieroglyphs}{RL}{}
-\TrackLangScriptMap{Mlym}{347}{Malayalam}{LR}{}
-\TrackLangScriptMap{Modi}{324}{Modi}{LR}{}
-\TrackLangScriptMap{Mong}{145}{Mongolian}{TB}{}
-\TrackLangScriptMap{Moon}{218}{Moon (Moon code, Moon script, Moon{}
-type)}{varies}{}
-\TrackLangScriptMap{Mroo}{199}{Mro, Mru}{LR}{}
-\TrackLangScriptMap{Mtei}{337}{Meitei Mayek (Meithei, Meetei)}{LR}{}
-\TrackLangScriptMap{Mult}{323}{Multani}{LR}{}
-\TrackLangScriptMap{Mymr}{350}{Myanmar (Burmese)}{LR}{}
-\TrackLangScriptMap{Narb}{106}{Old North Arabian (Ancient North{}
-Arabian)}{RL}{}
-\TrackLangScriptMap{Nbat}{159}{Nabataean}{RL}{}
-\TrackLangScriptMap{Newa}{333}{Newa, Newar, Newari}{LR}{}
-\TrackLangScriptMap{Nkgb}{420}{Nakhi Geba}{LR}{}
-\TrackLangScriptMap{Nkoo}{165}{N'Ko}{RL}{}
-\TrackLangScriptMap{Nshu}{499}{Nushu}{LR}{}
-\TrackLangScriptMap{Ogam}{212}{Ogham}{varies}{}
-\TrackLangScriptMap{Olck}{261}{Ol Chiki}{LR}{}
-\TrackLangScriptMap{Orkh}{175}{Old Turkic, Orkhon Runic}{RL}{}
-\TrackLangScriptMap{Orya}{327}{Oriya}{LR}{}
-\TrackLangScriptMap{Osge}{219}{Osage}{LR}{}
-\TrackLangScriptMap{Osma}{260}{Osmanya}{LR}{}
-\TrackLangScriptMap{Palm}{126}{Palmyrene}{RL}{}
-\TrackLangScriptMap{Pauc}{263}{Pau Cin Hau}{LR}{}
-\TrackLangScriptMap{Perm}{227}{Old Permic}{LR}{}
-\TrackLangScriptMap{Phag}{331}{Phags-pa}{TB}{}
-\TrackLangScriptMap{Phli}{131}{Inscriptional Pahlavi}{RL}{}
-\TrackLangScriptMap{Phlp}{132}{Psalter Pahlavi}{RL}{}
-\TrackLangScriptMap{Phlv}{133}{Book Pahlavi}{RL}{}
-\TrackLangScriptMap{Phnx}{115}{Phoenician}{RL}{}
-\TrackLangScriptMap{Piqd}{293}{Klingon (KLI plqaD)}{LR}{}
-\TrackLangScriptMap{Plrd}{282}{Miao (Pollard)}{LR}{}
-\TrackLangScriptMap{Prti}{130}{Inscriptional Parthian}{RL}{}
-\TrackLangScriptMap{Qaaa}{900}{Reserved for private use{}
-(start)}{varies}{}
-\TrackLangScriptMap{Qaai}{908}{Private use}{varies}{}
-\TrackLangScriptMap{Qabx}{949}{Reserved for private use{}
-(end)}{varies}{}
-\TrackLangScriptMap{Rjng}{363}{Rejang (Redjang, Kaganga)}{LR}{}
-\TrackLangScriptMap{Roro}{620}{Rongorongo}{varies}{}
-\TrackLangScriptMap{Runr}{211}{Runic}{LR}{}
-\TrackLangScriptMap{Samr}{123}{Samaritan}{RL}{}
-\TrackLangScriptMap{Sara}{292}{Sarati}{varies}{}
-\TrackLangScriptMap{Sarb}{105}{Old South Arabian}{RL}{}
-\TrackLangScriptMap{Saur}{344}{Saurashtra}{LR}{}
-\TrackLangScriptMap{Sgnw}{095}{SignWriting}{TB}{}
-\TrackLangScriptMap{Shaw}{281}{Shavian (Shaw)}{LR}{}
-\TrackLangScriptMap{Shrd}{319}{Sharada}{LR}{}
-\TrackLangScriptMap{Sidd}{302}{Siddham}{LR}{}
-\TrackLangScriptMap{Sind}{318}{Khudawadi, Sindhi}{LR}{}
-\TrackLangScriptMap{Sinh}{348}{Sinhala}{LR}{}
-\TrackLangScriptMap{Sora}{398}{Sora Sompeng}{LR}{}
-\TrackLangScriptMap{Sund}{362}{Sundanese}{LR}{}
-\TrackLangScriptMap{Sylo}{316}{Syloti Nagri}{LR}{}
-\TrackLangScriptMap{Syrc}{135}{Syriac}{RL}{}
-\TrackLangScriptMap{Syre}{138}{Syriac (Estrangelo variant)}{RL}{}
-\TrackLangScriptMap{Syrj}{137}{Syriac (Western variant)}{RL}{}
-\TrackLangScriptMap{Syrn}{136}{Syriac (Eastern variant)}{RL}{}
-\TrackLangScriptMap{Tagb}{373}{Tagbanwa}{LR}{}
-\TrackLangScriptMap{Takr}{321}{Takri}{LR}{}
-\TrackLangScriptMap{Tale}{353}{Tai Le}{LR}{}
-\TrackLangScriptMap{Talu}{354}{New Tai Lue}{LR}{}
-\TrackLangScriptMap{Taml}{346}{Tamil}{LR}{}
-\TrackLangScriptMap{Taml}{346}{Tamil}{LR}{}
-\TrackLangScriptMap{Tang}{520}{Tangut}{LR}{}
-\TrackLangScriptMap{Tavt}{359}{Tai Viet}{LR}{}
-\TrackLangScriptMap{Telu}{340}{Telugu}{LR}{}
-\TrackLangScriptMap{Teng}{290}{Tengwar}{LR}{}
-\TrackLangScriptMap{Tfng}{120}{Tifinagh (Berber)}{LR}{}
-\TrackLangScriptMap{Tglg}{370}{Tagalog (Baybayin, Alibata)}{LR}{}
-\TrackLangScriptMap{Thaa}{170}{Thaana}{RL}{}
-\TrackLangScriptMap{Thai}{352}{Thai}{LR}{}
-\TrackLangScriptMap{Tibt}{330}{Tibetan}{LR}{}
-\TrackLangScriptMap{Tirh}{326}{Tirhuta}{LR}{}
-\TrackLangScriptMap{Ugar}{040}{Ugaritic}{LR}{}
-\TrackLangScriptMap{Vaii}{470}{Vai}{LR}{}
-\TrackLangScriptMap{Visp}{280}{Visible Speech}{LR}{}
-\TrackLangScriptMap{Wara}{262}{Warang Citi (Varang Kshiti)}{LR}{}
-\TrackLangScriptMap{Wole}{480}{Woleai}{RL}{}
-\TrackLangScriptMap{Xpeo}{030}{Old Persian}{LR}{}
-\TrackLangScriptMap{Xsux}{020}{Cuneiform, Sumero-Akkadian}{LR}{}
-\TrackLangScriptMap{Yiii}{460}{Yi}{LR}{}
-\TrackLangScriptMap{Zinh}{994}{Inherited script}{inherited}{}
-\TrackLangScriptMap{Zmth}{995}{Mathematical notation}{LR}{}
-\TrackLangScriptMap{Zsym}{996}{Symbols}{varies}{}
-\TrackLangScriptMap{Zsye}{993}{Symbols (emoji variant)}{varies}{}
-\TrackLangScriptMap{Zxxx}{997}{Unwritten documents}{varies}{}
-\TrackLangScriptMap{Zyyy}{998}{Undetermined script}{varies}{}
-\TrackLangScriptMap{Zzzz}{999}{Uncoded script}{varies}{}
+%\changes{1.4}{2019-11-30}{removed some spurious empty braces and commented
+%out EOL}
+% \begin{macrocode}
+\TrackLangScriptMap{Adlm}{166}{Adlam}{RL}{}%
+\TrackLangScriptMap{Afak}{439}{Afaka}{varies}{}%
+\TrackLangScriptMap{Aghb}{239}{Caucasian Albanian}{LR}{}%
+\TrackLangScriptMap{Ahom}{338}{Ahom, Tai Ahom}{LR}{}%
+\TrackLangScriptMap{Arab}{160}{Arabic}{RL}{}%
+\TrackLangScriptMap{Aran}{161}{Arabic (Nastaliq variant)}{RL}{}%
+\TrackLangScriptMap{Armi}{124}{Imperial Aramaic}{RL}{}%
+\TrackLangScriptMap{Armn}{230}{Armenian}{LR}{}%
+\TrackLangScriptMap{Avst}{134}{Avestan}{RL}{}%
+\TrackLangScriptMap{Bali}{360}{Balinese}{LR}{}%
+\TrackLangScriptMap{Bamu}{435}{Bamum}{LR}{}%
+\TrackLangScriptMap{Bass}{259}{Bassa Vah}{LR}{}%
+\TrackLangScriptMap{Batk}{365}{Batak}{LR}{}%
+\TrackLangScriptMap{Beng}{334}{Bhaiksuki}{LR}{}%
+\TrackLangScriptMap{Blis}{550}{Blissymbols}{varies}{}%
+\TrackLangScriptMap{Bopo}{285}{Bopomofo}{LR}{}%
+\TrackLangScriptMap{Brah}{300}{Brahmi}{LR}{}%
+\TrackLangScriptMap{Brai}{570}{Braille}{LR}{}%
+\TrackLangScriptMap{Bugi}{367}{Buginese}{LR}{}%
+\TrackLangScriptMap{Buhd}{372}{Buhid}{LR}{}%
+\TrackLangScriptMap{Cakm}{349}{Chakma}{LR}{}%
+\TrackLangScriptMap{Cans}{440}{Unified Canadian Aboriginal Syllabics}{LR}{}%
+\TrackLangScriptMap{Cari}{201}{Carian}{LR}{}%
+\TrackLangScriptMap{Cham}{358}{Cham}{LR}{}%
+\TrackLangScriptMap{Cher}{445}{Cherokee}{LR}{}%
+\TrackLangScriptMap{Cirt}{291}{Cirth}{varies}{}%
+\TrackLangScriptMap{Copt}{204}{Coptic}{LR}{}%
+\TrackLangScriptMap{Cprt}{403}{Cypriot}{RL}{}%
+\TrackLangScriptMap{Cyrl}{220}{Cyrillic}{LR}{}%
+\TrackLangScriptMap{Cyrs}{221}{Cyrillic (Old Church Slavonic variant)}{varies}{}%
+\TrackLangScriptMap{Deva}{315}{Devanagari (Nagari)}{LR}{}%
+\TrackLangScriptMap{Dsrt}{250}{Deseret (Mormon)}{LR}{}%
+\TrackLangScriptMap{Dupl}{755}{Duployan shorthand, Duployan stenography}{LR}{}%
+\TrackLangScriptMap{Egyd}{070}{Egyptian demotic}{RL}{}%
+\TrackLangScriptMap{Egyh}{060}{Egyptian hieratic}{RL}{}%
+\TrackLangScriptMap{Egyp}{050}{Egyptian hieroglyphs}{LR}{}%
+\TrackLangScriptMap{Elba}{226}{Elbasan}{LR}{}%
+\TrackLangScriptMap{Ethi}{430}{Ethiopic (Ge'ez)}{LR}{}%
+\TrackLangScriptMap{Geok}{241}{Khutsuri (Asomtavruli and Nuskhuri)}{LR}{}%
+\TrackLangScriptMap{Geor}{240}{Georgian (Mkhedruli)}{LR}{}%
+\TrackLangScriptMap{Glag}{225}{Glagolitic}{LR}{}%
+\TrackLangScriptMap{Goth}{206}{Gothic}{LR}{}%
+\TrackLangScriptMap{Gran}{343}{Grantha}{LR}{}%
+\TrackLangScriptMap{Grek}{200}{Greek}{LR}{}%
+\TrackLangScriptMap{Gujr}{320}{Gujarati}{LR}{}%
+\TrackLangScriptMap{Guru}{310}{Gurmukhi}{LR}{}%
+\TrackLangScriptMap{Hanb}{503}{Han with Bopomofo (alias for Han + Bopomofo)}{LR}{}%
+\TrackLangScriptMap{Hang}{286}{Hangul}{LR}{}%
+\TrackLangScriptMap{Hani}{500}{Han (Hanzi, Kanji, Hanja)}{LR}{}%
+\TrackLangScriptMap{Hano}{371}{Hanunoo}{LR}{}%
+\TrackLangScriptMap{Hans}{501}{Han (Simplified variant)}{varies}{}%
+\TrackLangScriptMap{Hant}{502}{Han (Traditional variant)}{varies}{}%
+\TrackLangScriptMap{Hatr}{127}{Hatran}{RL}{}%
+\TrackLangScriptMap{Hebr}{125}{Hebrew}{RL}{}%
+\TrackLangScriptMap{Hira}{410}{Hiragana}{LR}{}%
+\TrackLangScriptMap{Hluw}{080}{Anatolian Hieroglyphs (Luwian Hieroglyphs, Hittite Hieroglyphs)}{LR}{}%
+\TrackLangScriptMap{Hmng}{450}{Pahawh Hmong}{LR}{}%
+\TrackLangScriptMap{Hrkt}{412}{Japanese syllabaries (alias for Hiragana + Katakana)}{varies}{}%
+\TrackLangScriptMap{Hung}{176}{Old Hungarian (Hungarian Runic)}{RL}{}%
+\TrackLangScriptMap{Inds}{610}{Indus (Harappan)}{RL}{}%
+\TrackLangScriptMap{Ital}{210}{Old Italic (Etruscan, Oscan, etc.)}{LR}{}%
+\TrackLangScriptMap{Jamo}{284}{Jamo (alias for Jamo subset of Hangul)}{LR}{}%
+\TrackLangScriptMap{Java}{361}{Javanese}{LR}{}%
+\TrackLangScriptMap{Jpan}{413}{Japanese (alias for Han + Hiragana + Katakana)}{varies}{}%
+\TrackLangScriptMap{Jurc}{510}{Jurchen}{LR}{}%
+\TrackLangScriptMap{Kali}{357}{Kayah Li}{LR}{}%
+\TrackLangScriptMap{Kana}{411}{Katakana}{LR}{}%
+\TrackLangScriptMap{Khar}{305}{Kharoshthi}{RL}{}%
+\TrackLangScriptMap{Khmr}{355}{Khmer}{LR}{}%
+\TrackLangScriptMap{Khoj}{322}{Khojki}{LR}{}%
+\TrackLangScriptMap{Kitl}{505}{Khitan large script}{LR}{}%
+\TrackLangScriptMap{Kits}{288}{Khitan small script}{TB}{}%
+\TrackLangScriptMap{Knda}{345}{Kannada}{LR}{}%
+\TrackLangScriptMap{Kore}{287}{Korean (alias for Hangul + Han)}{LR}{}%
+\TrackLangScriptMap{Kpel}{436}{Kpelle}{LR}{}%
+\TrackLangScriptMap{Kthi}{317}{Kaithi}{LR}{}%
+\TrackLangScriptMap{Lana}{351}{Tai Tham (Lanna)}{LR}{}%
+\TrackLangScriptMap{Laoo}{356}{Lao}{LR}{}%
+\TrackLangScriptMap{Latf}{217}{Latin (Fraktur variant)}{varies}{}%
+\TrackLangScriptMap{Latg}{216}{Latin (Gaelic variant)}{LR}{}%
+\TrackLangScriptMap{Latn}{215}{Latin}{LR}{}%
+\TrackLangScriptMap{Leke}{364}{Leke}{LR}{}%
+\TrackLangScriptMap{Lepc}{335}{Lepcha}{LR}{}%
+\TrackLangScriptMap{Limb}{336}{Limbu}{LR}{}%
+\TrackLangScriptMap{Lina}{400}{Linear A}{LR}{}%
+\TrackLangScriptMap{Linb}{401}{Linear B}{LR}{}%
+\TrackLangScriptMap{Lisu}{399}{Lisu (Fraser)}{LR}{}%
+\TrackLangScriptMap{Loma}{437}{Loma}{LR}{}%
+\TrackLangScriptMap{Lyci}{202}{Lycian}{LR}{}%
+\TrackLangScriptMap{Lydi}{116}{Lydian}{RL}{}%
+\TrackLangScriptMap{Mahj}{314}{Mahajani}{LR}{}%
+\TrackLangScriptMap{Mand}{140}{Mandaic, Mandaean}{RL}{}%
+\TrackLangScriptMap{Mani}{139}{Manichaean}{RL}{}%
+\TrackLangScriptMap{Marc}{332}{Marchen}{LR}{}%
+\TrackLangScriptMap{Maya}{090}{Mayan hieroglyphs}{varies}{}%
+\TrackLangScriptMap{Mend}{438}{Mende Kikakui}{RL}{}%
+\TrackLangScriptMap{Merc}{101}{Meroitic Cursive}{RL}{}%
+\TrackLangScriptMap{Mero}{100}{Meroitic Hieroglyphs}{RL}{}%
+\TrackLangScriptMap{Mlym}{347}{Malayalam}{LR}{}%
+\TrackLangScriptMap{Modi}{324}{Modi}{LR}{}%
+\TrackLangScriptMap{Mong}{145}{Mongolian}{TB}{}%
+\TrackLangScriptMap{Moon}{218}{Moon (Moon code, Moon script, Moon type)}{varies}{}%
+\TrackLangScriptMap{Mroo}{199}{Mro, Mru}{LR}{}%
+\TrackLangScriptMap{Mtei}{337}{Meitei Mayek (Meithei, Meetei)}{LR}{}%
+\TrackLangScriptMap{Mult}{323}{Multani}{LR}{}%
+\TrackLangScriptMap{Mymr}{350}{Myanmar (Burmese)}{LR}{}%
+\TrackLangScriptMap{Narb}{106}{Old North Arabian (Ancient North Arabian)}{RL}{}%
+\TrackLangScriptMap{Nbat}{159}{Nabataean}{RL}{}%
+\TrackLangScriptMap{Newa}{333}{Newa, Newar, Newari}{LR}{}%
+\TrackLangScriptMap{Nkgb}{420}{Nakhi Geba}{LR}{}%
+\TrackLangScriptMap{Nkoo}{165}{N'Ko}{RL}{}%
+\TrackLangScriptMap{Nshu}{499}{Nushu}{LR}{}%
+\TrackLangScriptMap{Ogam}{212}{Ogham}{varies}{}%
+\TrackLangScriptMap{Olck}{261}{Ol Chiki}{LR}{}%
+\TrackLangScriptMap{Orkh}{175}{Old Turkic, Orkhon Runic}{RL}{}%
+\TrackLangScriptMap{Orya}{327}{Oriya}{LR}{}%
+\TrackLangScriptMap{Osge}{219}{Osage}{LR}{}%
+\TrackLangScriptMap{Osma}{260}{Osmanya}{LR}{}%
+\TrackLangScriptMap{Palm}{126}{Palmyrene}{RL}{}%
+\TrackLangScriptMap{Pauc}{263}{Pau Cin Hau}{LR}{}%
+\TrackLangScriptMap{Perm}{227}{Old Permic}{LR}{}%
+\TrackLangScriptMap{Phag}{331}{Phags-pa}{TB}{}%
+\TrackLangScriptMap{Phli}{131}{Inscriptional Pahlavi}{RL}{}%
+\TrackLangScriptMap{Phlp}{132}{Psalter Pahlavi}{RL}{}%
+\TrackLangScriptMap{Phlv}{133}{Book Pahlavi}{RL}{}%
+\TrackLangScriptMap{Phnx}{115}{Phoenician}{RL}{}%
+\TrackLangScriptMap{Piqd}{293}{Klingon (KLI plqaD)}{LR}{}%
+\TrackLangScriptMap{Plrd}{282}{Miao (Pollard)}{LR}{}%
+\TrackLangScriptMap{Prti}{130}{Inscriptional Parthian}{RL}{}%
+\TrackLangScriptMap{Qaaa}{900}{Reserved for private use (start)}{varies}{}%
+\TrackLangScriptMap{Qaai}{908}{Private use}{varies}{}%
+\TrackLangScriptMap{Qabx}{949}{Reserved for private use (end)}{varies}{}%
+\TrackLangScriptMap{Rjng}{363}{Rejang (Redjang, Kaganga)}{LR}{}%
+\TrackLangScriptMap{Roro}{620}{Rongorongo}{varies}{}%
+\TrackLangScriptMap{Runr}{211}{Runic}{LR}{}%
+\TrackLangScriptMap{Samr}{123}{Samaritan}{RL}{}%
+\TrackLangScriptMap{Sara}{292}{Sarati}{varies}{}%
+\TrackLangScriptMap{Sarb}{105}{Old South Arabian}{RL}{}%
+\TrackLangScriptMap{Saur}{344}{Saurashtra}{LR}{}%
+\TrackLangScriptMap{Sgnw}{095}{SignWriting}{TB}{}%
+\TrackLangScriptMap{Shaw}{281}{Shavian (Shaw)}{LR}{}%
+\TrackLangScriptMap{Shrd}{319}{Sharada}{LR}{}%
+\TrackLangScriptMap{Sidd}{302}{Siddham}{LR}{}%
+\TrackLangScriptMap{Sind}{318}{Khudawadi, Sindhi}{LR}{}%
+\TrackLangScriptMap{Sinh}{348}{Sinhala}{LR}{}%
+\TrackLangScriptMap{Sora}{398}{Sora Sompeng}{LR}{}%
+\TrackLangScriptMap{Sund}{362}{Sundanese}{LR}{}%
+\TrackLangScriptMap{Sylo}{316}{Syloti Nagri}{LR}{}%
+\TrackLangScriptMap{Syrc}{135}{Syriac}{RL}{}%
+\TrackLangScriptMap{Syre}{138}{Syriac (Estrangelo variant)}{RL}{}%
+\TrackLangScriptMap{Syrj}{137}{Syriac (Western variant)}{RL}{}%
+\TrackLangScriptMap{Syrn}{136}{Syriac (Eastern variant)}{RL}{}%
+\TrackLangScriptMap{Tagb}{373}{Tagbanwa}{LR}{}%
+\TrackLangScriptMap{Takr}{321}{Takri}{LR}{}%
+\TrackLangScriptMap{Tale}{353}{Tai Le}{LR}{}%
+\TrackLangScriptMap{Talu}{354}{New Tai Lue}{LR}{}%
+\TrackLangScriptMap{Taml}{346}{Tamil}{LR}{}%
+\TrackLangScriptMap{Taml}{346}{Tamil}{LR}{}%
+\TrackLangScriptMap{Tang}{520}{Tangut}{LR}{}%
+\TrackLangScriptMap{Tavt}{359}{Tai Viet}{LR}{}%
+\TrackLangScriptMap{Telu}{340}{Telugu}{LR}{}%
+\TrackLangScriptMap{Teng}{290}{Tengwar}{LR}{}%
+\TrackLangScriptMap{Tfng}{120}{Tifinagh (Berber)}{LR}{}%
+\TrackLangScriptMap{Tglg}{370}{Tagalog (Baybayin, Alibata)}{LR}{}%
+\TrackLangScriptMap{Thaa}{170}{Thaana}{RL}{}%
+\TrackLangScriptMap{Thai}{352}{Thai}{LR}{}%
+\TrackLangScriptMap{Tibt}{330}{Tibetan}{LR}{}%
+\TrackLangScriptMap{Tirh}{326}{Tirhuta}{LR}{}%
+\TrackLangScriptMap{Ugar}{040}{Ugaritic}{LR}{}%
+\TrackLangScriptMap{Vaii}{470}{Vai}{LR}{}%
+\TrackLangScriptMap{Visp}{280}{Visible Speech}{LR}{}%
+\TrackLangScriptMap{Wara}{262}{Warang Citi (Varang Kshiti)}{LR}{}%
+\TrackLangScriptMap{Wole}{480}{Woleai}{RL}{}%
+\TrackLangScriptMap{Xpeo}{030}{Old Persian}{LR}{}%
+\TrackLangScriptMap{Xsux}{020}{Cuneiform, Sumero-Akkadian}{LR}{}%
+\TrackLangScriptMap{Yiii}{460}{Yi}{LR}{}%
+\TrackLangScriptMap{Zinh}{994}{Inherited script}{inherited}{}%
+\TrackLangScriptMap{Zmth}{995}{Mathematical notation}{LR}{}%
+\TrackLangScriptMap{Zsym}{996}{Symbols}{varies}{}%
+\TrackLangScriptMap{Zsye}{993}{Symbols (emoji variant)}{varies}{}%
+\TrackLangScriptMap{Zxxx}{997}{Unwritten documents}{varies}{}%
+\TrackLangScriptMap{Zyyy}{998}{Undetermined script}{varies}{}%
+\TrackLangScriptMap{Zzzz}{999}{Uncoded script}{varies}{}%
+% \end{macrocode}
+%\changes{1.4}{2019-11-30}{new}
+%Load additional script files.
+% \begin{macrocode}
+\@tracklang@input@extra@script@files
% \end{macrocode}
%
%Restore category code of \texttt{@}.
diff --git a/macros/generic/tracklang/tracklang.ins b/macros/generic/tracklang/tracklang.ins
index 19adb1e4f4..019b391cd1 100644
--- a/macros/generic/tracklang/tracklang.ins
+++ b/macros/generic/tracklang/tracklang.ins
@@ -1,4 +1,4 @@
-% tracklang.ins generated using makedtx version 1.2 2019/11/11 16:00
+% tracklang.ins generated using makedtx version 1.2 2019/12/1 17:41
\input docstrip
\preamble
diff --git a/macros/generic/tracklang/tracklang.pdf b/macros/generic/tracklang/tracklang.pdf
index 5aef4affc3..8f0aeee5fc 100644
--- a/macros/generic/tracklang/tracklang.pdf
+++ b/macros/generic/tracklang/tracklang.pdf
Binary files differ
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/american-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/american-apa6.lbx
index c67da1f37c..03e5924d57 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/american-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/american-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{american-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{american-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{american}
% (APA 6.22) The example abbreviations
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/apa6.bbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/apa6.bbx
index 61f99fb3f6..8fff277b41 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/apa6.bbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/apa6.bbx
@@ -1,4 +1,4 @@
-%% Copyright 2019 Philip Kime
+p%% Copyright 2019 Philip Kime
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3
@@ -12,7 +12,7 @@
%%
%% The Current Maintainer of this work is Philip Kime.
-\ProvidesFile{apa6.bbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex references style]
+\ProvidesFile{apa6.bbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex references style]
\RequireBiber[3]
\RequireBibliographyStyle{standard}
\urlstyle{rm} % APA examples all have URLs in same font as text
@@ -251,7 +251,7 @@
\ExecuteBibliographyOptions{%
abbreviate=true,%
autocite=inline,%
- backref=true,%
+ backref=false,%
citetracker=true,%
date=apalong,%
dateabbrev=false,%
@@ -295,18 +295,6 @@
}
}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% It is not APA standard to have backrefs in the bib
-% Some users might like it though.
-
-\newbool{apa:backref}
-\DeclareBibliographyOption{apabackref}{%
- \ifstrequal{#1}{true}
- {\global\booltrue{apa:backref}}
- {\global\boolfalse{apa:backref}}}
-
-%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% (APA 6.29) Additional material sometimes goes in parens
@@ -1348,7 +1336,7 @@
\usebibmacro{related}}
{}%
\usebibmacro{apa:finpunct}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{finentry}}
\DeclareBibliographyDriver{newsarticle}{%
@@ -1375,7 +1363,7 @@
\usebibmacro{related}}
{}%
\usebibmacro{apa:finpunct}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{finentry}}
\DeclareBibliographyDriver{book}{%
@@ -1401,7 +1389,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -1428,7 +1416,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -1461,7 +1449,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -1486,7 +1474,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -1517,7 +1505,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -1548,7 +1536,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -1590,7 +1578,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -1621,7 +1609,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -1653,7 +1641,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -1681,7 +1669,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -1710,7 +1698,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -1736,7 +1724,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -1759,7 +1747,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -1786,7 +1774,7 @@
\usebibmacro{doi+eprint+url}%
\newunit\newblock
\printfield{addendum}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -1821,7 +1809,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -1850,7 +1838,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -1877,7 +1865,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -1904,7 +1892,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -1933,7 +1921,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -1962,7 +1950,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -1989,7 +1977,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -2009,7 +1997,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -2029,7 +2017,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}%
\usebibmacro{finentry}}
@@ -2059,7 +2047,7 @@
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
- \usebibmacro{apa:pageref}%
+ \usebibmacro{pageref}%
\usebibmacro{apa:finpunct}
\usebibmacro{finentry}}
@@ -2175,14 +2163,6 @@
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% Wrapper for backrefs
-
-\newbibmacro{apa:pageref}{%
- \ifbool{apa:backref}{\usebibmacro{pageref}}{}}
-
-%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/apa6.cbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/apa6.cbx
index 8284dff849..581f254693 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/apa6.cbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/apa6.cbx
@@ -9,10 +9,10 @@
%% version 2005/12/01 or later.
%%
%% This work has the LPPL maintenance status `maintained'.
-%%
+%%
%% The Current Maintainer of this work is Philip Kime.
-\ProvidesFile{apa6.cbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex citation style]
+\ProvidesFile{apa6.cbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex citation style]
\RequireBiber[3]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -242,7 +242,7 @@
% X and Y and Z (2009)
% X and W and V (2010)
%
-% which have the same namehash due to minnames visibility truncation to 1
+% which have the same namehash due to minnames visibility truncation to 1
% would be printed incorrectly as
% \cite{one, two} -> X, Y & Z 2009, 2010
\newbibmacro*{cite}{%
@@ -370,7 +370,6 @@
\DeclareDelimFormat[nptextcite]{finalnamedelim}
{\ifnum\value{liststop}>2 \finalandcomma\fi\addspace\&\space}
-\DeclareMultiCiteCommand{\nptextcites}{\nptextcite}{\multicitedelim}
\DeclareCiteCommand{\nptextcite}
{\usebibmacro{cite:init}%
\usebibmacro{prenote}}
@@ -390,7 +389,7 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% No shorthand
-%
+%
\newbibmacro*{citeyear}{%
\iffieldundef{labelyear}
{\usebibmacro{cite:init}}
@@ -515,8 +514,6 @@
{}
{\usebibmacro{postnote}}
-\DeclareMultiCiteCommand{\textcites}{\textcite}{\compcitedelim}
-
\DeclareCiteCommand{\textcite}
{\usebibmacro{cite:init}%
\usebibmacro{prenote}}
@@ -535,4 +532,17 @@
{}
{\usebibmacro{postnote}}
+
+\DeclareMultiCiteCommand{\cites}{\cite}{\setunit{\multicitedelim}}
+\DeclareMultiCiteCommand{\textcites}{\textcite}{\setunit{\compcitedelim}}
+\DeclareMultiCiteCommand{\nptextcites}{\nptextcite}{\setunit{\multicitedelim}}
+\DeclareMultiCiteCommand{\parencites}[\mkbibparens]{\parencite}
+ {\setunit{\multicitedelim}}
+\DeclareMultiCiteCommand{\footcites}[\mkbibfootnote]{\footcite}
+ {\setunit{\multicitedelim}}
+\DeclareMultiCiteCommand{\footcitetexts}[\mkbibfootnotetext]
+ {\footcitetext}{\setunit{\multicitedelim}}
+\DeclareMultiCiteCommand{\smartcites}[\iffootnote\mkbibparens\mkbibfootnote]
+ {\smartcite}{\setunit{\multicitedelim}}
+
\endinput
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/apa6.dbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/apa6.dbx
index 48f94999d7..2dbac52698 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/apa6.dbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/apa6.dbx
@@ -12,7 +12,7 @@
%%
%% The Current Maintainer of this work is Philip Kime.
-\ProvidesFile{apa6.dbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex style data model]
+\ProvidesFile{apa6.dbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex style data model]
\RequireBiber[3]
\DeclareDatamodelEntrytypes{
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/austrian-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/austrian-apa6.lbx
index 4ca5219127..73cc9eff56 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/austrian-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/austrian-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{austrian-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{austrian-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{austrian}
% Following DGPs guidlines for German/Austrian
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/biblatex-apa-test.pdf b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/biblatex-apa-test.pdf
deleted file mode 100644
index 92de9ef490..0000000000
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/biblatex-apa-test.pdf
+++ /dev/null
Binary files differ
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/biblatex-apa6-test.pdf b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/biblatex-apa6-test.pdf
index 3ae40818e7..08decb866a 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/biblatex-apa6-test.pdf
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/biblatex-apa6-test.pdf
Binary files differ
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/biblatex-apa6.pdf b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/biblatex-apa6.pdf
index ae85a92118..52bc6a548c 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/biblatex-apa6.pdf
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/biblatex-apa6.pdf
Binary files differ
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/biblatex-apa6.tex b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/biblatex-apa6.tex
index 221bb1c916..e2acfe3544 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/biblatex-apa6.tex
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/biblatex-apa6.tex
@@ -24,7 +24,7 @@
url={http://mirror.ctan.org/macros/latex/exptl/biblatex-contrib/biblatex-apa/},
author={Philip Kime},
email={Philip@kime.org.uk},
- revision={8.1},
+ revision={8.2},
date={\today}}
\hypersetup{%
@@ -251,16 +251,6 @@ The following options are set as usual in the options passed to
|biblatex|.
\begin{ltxcode}
-apabackref=true|false
-\end{ltxcode}% | stupid comment to stop emacs highlighting as verb due
- % to single pipe
-
-\noindent It is not APA style to include backreferences in the References to
-pages where citations of the entry occur. However, this is very
-useful, especially in proofing and so if you set the |apabackref|
-option to «true», these are enabled. The default is «false».
-
-\begin{ltxcode}
apamaxprtauth=<num>
\end{ltxcode}
@@ -467,6 +457,10 @@ applied to the data stream by |biber| and does not change your \file{.bib}.
\section{Revision history}\label{rev}
\begin{changelog}
+\begin{release}{8.2}{2019-12-01}
+\item Removed |apabackref| option, use the standard
+ |biblatex| |backref| option instead
+\end{release}
\begin{release}{8.1}{2019-11-27}
\item Corrected documentation for legacy 6th edition style
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/brazilian-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/brazilian-apa6.lbx
index ef292120b2..436ac9c87a 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/brazilian-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/brazilian-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{brazilian-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{brazilian-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{brazilian}
% (APA 6.22) The example abbreviations
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/british-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/british-apa6.lbx
index 6a31ce4945..fb681549b7 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/british-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/british-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{british-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{british-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{british}
% (APA 6.22) The example abbreviations
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/danish-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/danish-apa6.lbx
index 8e3f35c134..dccb0a4016 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/danish-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/danish-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{danish-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{danish-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{danish}
% (APA 6.22) The example abbreviations
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/dutch-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/dutch-apa6.lbx
index e6bd73bc8f..f49dd16eeb 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/dutch-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/dutch-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{dutch-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{dutch-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{dutch}
% (APA 6.22) The example abbreviations
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/english-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/english-apa6.lbx
index 2dbc0716e9..a2b4dcbe30 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/english-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/english-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{english-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{english-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{english}
% (APA 6.22) The example abbreviations
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/french-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/french-apa6.lbx
index 10a6b16dca..ced24ab438 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/french-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/french-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{french-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{french-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{french}
% (APA 6.22) The example abbreviations
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/galician-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/galician-apa6.lbx
index 7430bc6601..0bdac305b2 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/galician-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/galician-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{galician-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{galician-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{galician}
\setcounter{smartand}{0} % Turn off "smart and" or ampersands will all be replaced
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/german-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/german-apa6.lbx
index 74a58af809..6fa6a51be1 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/german-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/german-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{german-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{german-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{german}
% (APA 6.22) The example abbreviations
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/greek-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/greek-apa6.lbx
index 130a5ae1c8..c85fb78e9e 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/greek-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/greek-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{greek-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{greek-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{greek}
% (APA 6.22) The example abbreviations
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/italian-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/italian-apa6.lbx
index 10682b6242..deaf12a53d 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/italian-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/italian-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{italian-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{italian-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{italian}
% (APA 6.22) The example abbreviations
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/naustrian-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/naustrian-apa6.lbx
index 1885026e67..04633411ae 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/naustrian-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/naustrian-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{naustrian-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{naustrian-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{naustrian}
% (APA 6.22) The example abbreviations
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/ngerman-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/ngerman-apa6.lbx
index 8aa8892ddd..e4f82536e0 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/ngerman-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/ngerman-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{ngerman-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{ngerman-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{ngerman}
% (APA 6.22) The example abbreviations
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/norsk-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/norsk-apa6.lbx
index 25843dac49..82aede694c 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/norsk-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/norsk-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{norsk-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{norsk-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{norsk}
% (APA 6.22) The example abbreviations
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/norwegian-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/norwegian-apa6.lbx
index 58edd9310b..7607c475b5 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/norwegian-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/norwegian-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{norwegian-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{norwegian-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{norwegian}
% (APA 6.22) The example abbreviations
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/nswissgerman-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/nswissgerman-apa6.lbx
index a39910cad6..959144cbc0 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/nswissgerman-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/nswissgerman-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{nswissgerman-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{nswissgerman-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{nswissgerman}
% (APA 6.22) The example abbreviations
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/nynorsk-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/nynorsk-apa6.lbx
index 6354be0d65..9fa7a8627f 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/nynorsk-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/nynorsk-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{nynorsk-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{nynorsk-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{nynorsk}
% (APA 6.22) The example abbreviations
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/portuguese-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/portuguese-apa6.lbx
index 09e7c65896..33b8adf4ac 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/portuguese-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/portuguese-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{portuguese-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{portuguese-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{portuguese}
% (APA 6.22) The example abbreviations
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/russian-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/russian-apa6.lbx
index c1d91d306f..bf5c6864e5 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/russian-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/russian-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{russian-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{russian-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{russian}
% (APA 6.22) The example abbreviations
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/slovene-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/slovene-apa6.lbx
index 04d3ad581a..a572fa9ce0 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/slovene-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/slovene-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{slovene-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{slovene-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{slovene}
% (APA 6.22) The example abbreviations
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/spanish-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/spanish-apa6.lbx
index 431c4e56f1..1dab1f59bb 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/spanish-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/spanish-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{spanish-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{spanish-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{spanish}
\setcounter{smartand}{0} % Turn off "smart and" or ampersands will all be replaced
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/swedish-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/swedish-apa6.lbx
index bb8c0f8f4e..1e9e68a6bf 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/swedish-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/swedish-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{swedish-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{swedish-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{swedish}
% (APA 6.22) The example abbreviations
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/swissgerman-apa6.lbx b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/swissgerman-apa6.lbx
index b8d0f0a0ce..e85e399990 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-apa6/swissgerman-apa6.lbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-apa6/swissgerman-apa6.lbx
@@ -1,4 +1,4 @@
-\ProvidesFile{swissgerman-apa6.lbx}[2019/11/27\space v8.1\space APA 6th ed. biblatex localisation]
+\ProvidesFile{swissgerman-apa6.lbx}[2019/12/01\space v8.2\space APA 6th ed. biblatex localisation]
\InheritBibliographyExtras{swissgerman}
% Following DGPs guidlines for German/Austrian/Swiss German
diff --git a/macros/latex/contrib/hvqrurl/Changes b/macros/latex/contrib/hvqrurl/Changes
index dbf1c990f2..85dfdd189e 100644
--- a/macros/latex/contrib/hvqrurl/Changes
+++ b/macros/latex/contrib/hvqrurl/Changes
@@ -1,2 +1,3 @@
hvqrurl.sty:
-0.01 2019-11-27 - first CTAN version
+0.01a 2019-12-01 - fixes to the documentation
+0.01 2019-11-27 - first CTAN version
diff --git a/macros/latex/contrib/hvqrurl/README b/macros/latex/contrib/hvqrurl/README
index 12b48923cb..8de40ba379 100644
--- a/macros/latex/contrib/hvqrurl/README
+++ b/macros/latex/contrib/hvqrurl/README
@@ -3,8 +3,8 @@ Placing an URL as a QR code into the margin of the text.
The package loads by default url, qrcode, marginnote,
xcolor, and xkeyval
-%% This program can be redistributed and/or modified under the terms
-%% of the LaTeX Project Public License Distributed from CTAN archives
-%% in directory macros/latex/base/lppl.txt.
+This file is distributed under the terms of the LaTeX Project Public
+License from CTAN archives in directory macros/latex/base/lppl.txt.
+Either version 1.3 or, at your option, any later version.
hvoss@tug.org \ No newline at end of file
diff --git a/macros/latex/contrib/hvqrurl/doc/hvqrurl.pdf b/macros/latex/contrib/hvqrurl/doc/hvqrurl.pdf
index f1e8eb176c..7a0aa0aa49 100644
--- a/macros/latex/contrib/hvqrurl/doc/hvqrurl.pdf
+++ b/macros/latex/contrib/hvqrurl/doc/hvqrurl.pdf
Binary files differ
diff --git a/macros/latex/contrib/hvqrurl/doc/hvqrurl.tex b/macros/latex/contrib/hvqrurl/doc/hvqrurl.tex
index 23196651ec..7125c0d723 100644
--- a/macros/latex/contrib/hvqrurl/doc/hvqrurl.tex
+++ b/macros/latex/contrib/hvqrurl/doc/hvqrurl.tex
@@ -1,4 +1,4 @@
-%% $Id: hvqrurl.tex 1118 2019-11-29 07:56:18Z herbert $
+%% $Id: hvqrurl.tex 1119 2019-11-30 17:36:28Z herbert $
\listfiles
\errorcontextlines=100
\documentclass[twoside,usegeometry]{scrartcl}
@@ -37,7 +37,7 @@
\hypersetup{urlcolor=blue, linktocpage, colorlinks=true}%
\begin{document}
-\title{Package \texttt{hvqrurl}\\Creating a QR-code of an URL in the margin \\ver 0.01}
+\title{Package \texttt{hvqrurl}\\Creating a QR-code of an URL in the margin \\\small ver 0.01a}
\author{Herbert Voß\thanks{\protect\url{hvoss@tug.org}}}
\date{\today}
\maketitle
@@ -52,13 +52,13 @@ and
\end{abstract}
-\section{The macro}
+\section{The macros}
\begin{BDef}
-\Lcs{hvqrset}\Largb{key=value list}\\
-\Lcs{hvqrurl}\Largb{key=value list}\Largb{URL}\\
-\Lcs{hvqrurl*}\Largb{key=value list}\Largb{URL}
+\Lcs{hvqrset}\Largb{key=value, \ldots}\\
+\Lcs{hvqrurl}\OptArg{key=value, \ldots}\Largb{URL}\\
+\Lcs{hvqrurl*}\OptArg{key=value, \ldots}\Largb{URL}
\end{BDef}
With the default macro \Lcs{hvqrurl} the URL is printed as as QR code into the margin and
@@ -66,6 +66,13 @@ in the the text as usual with the macro \Lcs{url}, for example \hvqrurl{https://
With \LPack{hyperref} you'll get the the same color for the QR code as for the URL link and, of course,
is also a link. This example shows the default setting for a QR code.
+With \Lcs{hvqrset} one can set the optional arguments globally. For example if one do not want all
+QR codes not as a link when using \LPack{hyperref}:
+
+\begin{lstlisting}
+\hvqrset{qrlink=nolink}
+\end{lstlisting}
+
\section{Optional arguments}
@@ -75,7 +82,6 @@ is also a link. This example shows the default setting for a QR code.
With \Lkeyset{qrlink=nolink} the QR code is no link: \hvqrurl[qrlink=nolink]{https://mirror.ctan.org/pkg/hvqrurl}.
The default setting is \Lkeyset{qrlink=link}.
\end{lstlisting}
-
With \Lkeyset{qrlink=nolink} the QR code is no link: \hvqrurl[qrlink=nolink]{https://mirror.ctan.org/pkg/hvqrurl}.
The default setting is \Lkeyset{qrlink=link}. Without using \LPack{hyperref} this optional argument
has no meaning.
diff --git a/macros/latex/contrib/hvqrurl/latex/hvqrurl.sty b/macros/latex/contrib/hvqrurl/latex/hvqrurl.sty
index b8c657b82f..bf27b32006 100644
--- a/macros/latex/contrib/hvqrurl/latex/hvqrurl.sty
+++ b/macros/latex/contrib/hvqrurl/latex/hvqrurl.sty
@@ -7,7 +7,7 @@
% Copyright 2019 Herbert Voss hvoss@tug.org
%%
\ProvidesPackage{hvqrurl}[%
- 2019/11/27 v.0.01 (Herbert Voss) Supports qr images into the margin (hv)]
+ 2019/12/01 v.0.01a (Herbert Voss) Supports qr images into the margin (hv)]
%
\NeedsTeXFormat{LaTeX2e}
\RequirePackage{url}
diff --git a/macros/luatex/generic/barracuda/INSTALL.txt b/macros/luatex/generic/barracuda/INSTALL.txt
new file mode 100644
index 0000000000..55ce68da5c
--- /dev/null
+++ b/macros/luatex/generic/barracuda/INSTALL.txt
@@ -0,0 +1,30 @@
+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
+looking for `installed` key in the output of the command:
+
+$ tlmgr show barracuda
+
+If `barracuda` is not present, run the command:
+
+$ 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.
+
+Installing for Lua
+
+Manually copy `src` folder content to a suitable directory of your system that
+is reachable to Lua interpreter.
+
diff --git a/macros/luatex/generic/barracuda/LICENSE.txt b/macros/luatex/generic/barracuda/LICENSE.txt
new file mode 100644
index 0000000000..d1d6cd4ea1
--- /dev/null
+++ b/macros/luatex/generic/barracuda/LICENSE.txt
@@ -0,0 +1,339 @@
+GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ 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.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/macros/luatex/generic/barracuda/README.md b/macros/luatex/generic/barracuda/README.md
new file mode 100644
index 0000000000..e4ca271287
--- /dev/null
+++ b/macros/luatex/generic/barracuda/README.md
@@ -0,0 +1,77 @@
+# `barracuda` project
+
+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.
+
+![a SVG formatted Code39 symbol](/test/test-ga-svg/test-code39.svg)
+
+Internal modules is structured to ensure good performance and to allow a
+complete user control over barcode symbol parameters :thumbsup: .
+
+Although development is in beta stage, `barracuda` has a good level of
+stability.
+
+## Barcode symbologies
+
+So far, are supported
+
+- Code 39
+- Code 128
+- 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.
+
+## 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:
+
+```latex
+% !TeX program = LuaLaTeX
+\documentclass{article}
+\usepackage{barracuda}
+\begin{document}
+\barracuda{code39}{123ABC}
+\end{document}
+```
+
+## Documentation
+
+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.
+
+## Installation
+
+The `barracuda` package can be used with pure Lua interpreter or from within a
+TeX source file for Lua-powered typesetting engine like LuaTeX. In the first
+case you can manually copy `src` folder content to a suitable directory of
+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.
+
+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.
+
+## Contribute
+
+Contributes are welcome in any form and for any topics.
+
+## License
+
+Please, for more legal details refer to LICENSE.txt file.
+
+Copyright (C) 2019 Roberto Giacomelli
diff --git a/macros/luatex/generic/barracuda/barracuda.pdf b/macros/luatex/generic/barracuda/barracuda.pdf
new file mode 100644
index 0000000000..3554d40a4a
--- /dev/null
+++ b/macros/luatex/generic/barracuda/barracuda.pdf
Binary files differ
diff --git a/macros/luatex/generic/barracuda/barracuda.sty b/macros/luatex/generic/barracuda/barracuda.sty
new file mode 100644
index 0000000000..7ee6b02104
--- /dev/null
+++ b/macros/luatex/generic/barracuda/barracuda.sty
@@ -0,0 +1,21 @@
+%
+\NeedsTeXFormat{LaTeX2e}[2009/06/27]
+\ProvidesPackage{barracuda}[2018/12/30 v0.1 a barcode typesetting package]%
+
+\newbox\barracudabox
+\newcommand\barracuda[2]{\directlua{
+ local barracuda = require "barracuda"
+ local e = [[#1]]
+ local s = [[#2]]
+ local enc, err = barracuda:get_barcode_class():new_encoder(e)
+ assert(enc, err)
+ local symb, err = enc:from_string(s); assert(symb, err)
+ local canvas = barracuda:new_canvas()
+ symb:append_ga(canvas)
+ local drv = barracuda:get_driver()
+ drv:ga_to_hbox(canvas, "barracudabox")
+}%
+\box\barracudabox
+}
+
+\endinput
diff --git a/macros/luatex/generic/barracuda/example/001-13-ean-test.pdf b/macros/luatex/generic/barracuda/example/001-13-ean-test.pdf
new file mode 100644
index 0000000000..925a8ad8f0
--- /dev/null
+++ b/macros/luatex/generic/barracuda/example/001-13-ean-test.pdf
Binary files 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
new file mode 100644
index 0000000000..c0a4db3894
--- /dev/null
+++ b/macros/luatex/generic/barracuda/example/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/example/001-code128-test.lua b/macros/luatex/generic/barracuda/example/001-code128-test.lua
new file mode 100644
index 0000000000..78645612dc
--- /dev/null
+++ b/macros/luatex/generic/barracuda/example/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/example/001-i2of5-test.pdf b/macros/luatex/generic/barracuda/example/001-i2of5-test.pdf
new file mode 100644
index 0000000000..c46bb12d50
--- /dev/null
+++ b/macros/luatex/generic/barracuda/example/001-i2of5-test.pdf
Binary files differ
diff --git a/macros/luatex/generic/barracuda/example/001-i2of5-test.tex b/macros/luatex/generic/barracuda/example/001-i2of5-test.tex
new file mode 100644
index 0000000000..43c652d66a
--- /dev/null
+++ b/macros/luatex/generic/barracuda/example/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
+
+
diff --git a/macros/luatex/generic/barracuda/example/003-code39-test.pdf b/macros/luatex/generic/barracuda/example/003-code39-test.pdf
new file mode 100644
index 0000000000..4625a40010
--- /dev/null
+++ b/macros/luatex/generic/barracuda/example/003-code39-test.pdf
Binary files differ
diff --git a/macros/luatex/generic/barracuda/example/003-code39-test.tex b/macros/luatex/generic/barracuda/example/003-code39-test.tex
new file mode 100644
index 0000000000..a4ba3d6e81
--- /dev/null
+++ b/macros/luatex/generic/barracuda/example/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/example/003-ean-test.pdf b/macros/luatex/generic/barracuda/example/003-ean-test.pdf
new file mode 100644
index 0000000000..e03c2d48d7
--- /dev/null
+++ b/macros/luatex/generic/barracuda/example/003-ean-test.pdf
Binary files differ
diff --git a/macros/luatex/generic/barracuda/example/003-ean-test.tex b/macros/luatex/generic/barracuda/example/003-ean-test.tex
new file mode 100644
index 0000000000..59b17c4c07
--- /dev/null
+++ b/macros/luatex/generic/barracuda/example/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/example/004-ean-test.lua b/macros/luatex/generic/barracuda/example/004-ean-test.lua
new file mode 100644
index 0000000000..017e0725b8
--- /dev/null
+++ b/macros/luatex/generic/barracuda/example/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/example/006-code39-test.lua b/macros/luatex/generic/barracuda/example/006-code39-test.lua
new file mode 100644
index 0000000000..d33ad4ffaf
--- /dev/null
+++ b/macros/luatex/generic/barracuda/example/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/example/006-six.svg b/macros/luatex/generic/barracuda/example/006-six.svg
new file mode 100644
index 0000000000..25ce8bb34c
--- /dev/null
+++ b/macros/luatex/generic/barracuda/example/006-six.svg
@@ -0,0 +1,653 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Barracuda package (https://github.com/robitex/barracuda) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg"
+ version="1.1"
+ width="132.036779mm" height="33.746381mm"
+ viewBox="-2.539987 -10.873169 132.036779 33.746381"
+>
+ <g stroke="black">
+ <path d="M0.095249 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M0.666746 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M1.142994 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M1.714491 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M2.190738 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M2.666986 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M3.143233 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M3.524231 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M4.095728 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M4.571976 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M5.048223 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M5.524471 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M6.000718 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M6.572215 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M7.048463 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M7.619960 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M8.191457 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M8.667704 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M9.239201 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M9.620199 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M10.001197 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M10.382195 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M10.858443 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M11.525189 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M12.001437 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M12.572934 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M13.049181 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M13.525429 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M14.192175 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M14.573173 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M14.954171 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M15.430419 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M16.001916 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M16.668662 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M17.049660 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M17.525908 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M18.002155 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M18.573652 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M18.954650 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M19.430898 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M19.907145 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M20.383393 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M21.050139 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M21.431137 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M21.907385 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M22.383632 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M22.764630 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M23.145628 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M23.621876 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M24.383872 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M24.860119 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M25.241117 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M25.717365 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M26.479361 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M26.955608 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M27.431856 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M28.003353 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M28.670099 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M29.051097 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M29.432095 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M29.908343 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M30.384590 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M30.956087 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M31.337085 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M31.813333 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M32.289580 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M32.861077 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M33.242075 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M33.813572 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M34.385069 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M34.766067 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M35.337564 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M35.813812 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M36.385309 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M36.861556 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <text x="0.000000" y="-8.773169" font-family="Verdana" font-size="2.877000">
+ ABCDEF12QJ31+ </text>
+ <g stroke="black">
+ <path d="M45.095249 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M45.666746 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M46.142994 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M46.714491 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M47.190738 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M47.666986 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M48.143233 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M48.524231 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M49.095728 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M49.571976 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M50.048223 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M50.524471 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M51.000718 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M51.572215 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M52.048463 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M52.619960 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M53.191457 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M53.667704 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M54.239201 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M54.620199 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M55.001197 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M55.382195 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M55.858443 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M56.525189 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M57.001437 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M57.572934 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M58.049181 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M58.525429 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M59.192175 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M59.573173 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M59.954171 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M60.430419 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M61.001916 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M61.668662 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M62.049660 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M62.525908 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M63.002155 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M63.573652 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M63.954650 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M64.430898 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M64.907145 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M65.383393 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M66.050139 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M66.431137 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M66.907385 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M67.383632 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M67.764630 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M68.145628 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M68.621876 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M69.383872 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M69.860119 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M70.241117 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M70.717365 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M71.479361 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M71.955608 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M72.431856 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M73.003353 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M73.670099 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M74.051097 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M74.432095 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M74.908343 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M75.384590 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M75.956087 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M76.337085 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M76.813333 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M77.289580 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M77.861077 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M78.242075 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M78.813572 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M79.385069 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M79.766067 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M80.337564 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M80.813812 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M81.385309 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M81.861556 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <text x="63.478403" y="-8.773169" font-family="Verdana" font-size="2.877000" text-anchor="middle">
+ ABCDEF12QJ31+ </text>
+ <g stroke="black">
+ <path d="M90.095249 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M90.666746 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M91.142994 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M91.714491 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M92.190738 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M92.666986 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M93.143233 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M93.524231 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M94.095728 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M94.571976 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M95.048223 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M95.524471 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M96.000718 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M96.572215 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M97.048463 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M97.619960 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M98.191457 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M98.667704 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M99.239201 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M99.620199 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M100.001197 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M100.382195 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M100.858443 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M101.525189 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M102.001437 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M102.572934 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M103.049181 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M103.525429 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M104.192175 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M104.573173 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M104.954171 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M105.430419 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M106.001916 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M106.668662 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M107.049660 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M107.525908 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M108.002155 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M108.573652 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M108.954650 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M109.430898 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M109.907145 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M110.383393 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M111.050139 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M111.431137 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M111.907385 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M112.383632 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M112.764630 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M113.145628 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M113.621876 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M114.383872 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M114.860119 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M115.241117 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M115.717365 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M116.479361 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M116.955608 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M117.431856 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M118.003353 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M118.670099 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M119.051097 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M119.432095 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M119.908343 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M120.384590 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M120.956087 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M121.337085 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M121.813333 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M122.289580 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M122.861077 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M123.242075 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M123.813572 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M124.385069 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M124.766067 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M125.337564 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ <path d="M125.813812 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M126.385309 -7.999958V-0.000000" style="stroke-width:0.380998"/>
+ <path d="M126.861556 -7.999958V-0.000000" style="stroke-width:0.190499"/>
+ </g>
+ <text x="126.956806" y="-8.773169" font-family="Verdana" font-size="2.877000" text-anchor="end">
+ ABCDEF12QJ31+ </text>
+ <g stroke="black">
+ <path d="M0.095249 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M0.666746 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M1.142994 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M1.714491 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M2.190738 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M2.666986 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M3.143233 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M3.524231 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M4.095728 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M4.571976 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M5.048223 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M5.524471 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M6.000718 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M6.572215 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M7.048463 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M7.619960 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M8.191457 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M8.667704 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M9.239201 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M9.620199 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M10.001197 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M10.382195 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M10.858443 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M11.525189 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M12.001437 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M12.572934 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M13.049181 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M13.525429 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M14.192175 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M14.573173 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M14.954171 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M15.430419 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M16.001916 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M16.668662 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M17.049660 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M17.525908 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M18.002155 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M18.573652 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M18.954650 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M19.430898 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M19.907145 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M20.383393 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M21.050139 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M21.431137 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M21.907385 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M22.383632 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M22.764630 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M23.145628 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M23.621876 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M24.383872 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M24.860119 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M25.241117 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M25.717365 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M26.479361 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M26.955608 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M27.431856 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M28.003353 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M28.670099 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M29.051097 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M29.432095 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M29.908343 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M30.384590 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M30.956087 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M31.337085 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M31.813333 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M32.289580 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M32.861077 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M33.242075 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M33.813572 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M34.385069 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M34.766067 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M35.337564 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M35.813812 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M36.385309 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M36.861556 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <text x="0.000000" y="22.873212" font-family="Verdana" font-size="2.877000">
+ ABCDEF12QJ31+ </text>
+ <g stroke="black">
+ <path d="M45.095249 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M45.666746 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M46.142994 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M46.714491 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M47.190738 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M47.666986 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M48.143233 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M48.524231 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M49.095728 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M49.571976 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M50.048223 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M50.524471 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M51.000718 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M51.572215 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M52.048463 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M52.619960 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M53.191457 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M53.667704 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M54.239201 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M54.620199 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M55.001197 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M55.382195 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M55.858443 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M56.525189 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M57.001437 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M57.572934 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M58.049181 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M58.525429 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M59.192175 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M59.573173 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M59.954171 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M60.430419 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M61.001916 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M61.668662 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M62.049660 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M62.525908 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M63.002155 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M63.573652 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M63.954650 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M64.430898 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M64.907145 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M65.383393 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M66.050139 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M66.431137 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M66.907385 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M67.383632 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M67.764630 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M68.145628 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M68.621876 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M69.383872 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M69.860119 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M70.241117 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M70.717365 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M71.479361 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M71.955608 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M72.431856 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M73.003353 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M73.670099 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M74.051097 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M74.432095 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M74.908343 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M75.384590 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M75.956087 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M76.337085 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M76.813333 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M77.289580 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M77.861077 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M78.242075 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M78.813572 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M79.385069 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M79.766067 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M80.337564 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M80.813812 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M81.385309 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M81.861556 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <text x="63.478403" y="22.873212" font-family="Verdana" font-size="2.877000" text-anchor="middle">
+ ABCDEF12QJ31+ </text>
+ <g stroke="black">
+ <path d="M90.095249 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M90.666746 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M91.142994 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M91.714491 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M92.190738 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M92.666986 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M93.143233 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M93.524231 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M94.095728 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M94.571976 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M95.048223 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M95.524471 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M96.000718 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M96.572215 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M97.048463 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M97.619960 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M98.191457 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M98.667704 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M99.239201 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M99.620199 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M100.001197 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M100.382195 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M100.858443 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M101.525189 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M102.001437 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M102.572934 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M103.049181 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M103.525429 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M104.192175 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M104.573173 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M104.954171 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M105.430419 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M106.001916 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M106.668662 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M107.049660 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M107.525908 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M108.002155 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M108.573652 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M108.954650 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M109.430898 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M109.907145 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M110.383393 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M111.050139 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M111.431137 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M111.907385 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M112.383632 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M112.764630 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M113.145628 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M113.621876 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M114.383872 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M114.860119 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M115.241117 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M115.717365 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M116.479361 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M116.955608 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M117.431856 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M118.003353 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M118.670099 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M119.051097 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M119.432095 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M119.908343 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M120.384590 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M120.956087 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M121.337085 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M121.813333 12.000042V20.000000" style="stroke-width:0.380998"/>
+ </g>
+ <g stroke="black">
+ <path d="M122.289580 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M122.861077 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M123.242075 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M123.813572 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M124.385069 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <g stroke="black">
+ <path d="M124.766067 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M125.337564 12.000042V20.000000" style="stroke-width:0.190499"/>
+ <path d="M125.813812 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M126.385309 12.000042V20.000000" style="stroke-width:0.380998"/>
+ <path d="M126.861556 12.000042V20.000000" style="stroke-width:0.190499"/>
+ </g>
+ <text x="126.956806" y="22.873212" font-family="Verdana" font-size="2.877000" text-anchor="end">
+ ABCDEF12QJ31+ </text>
+</svg>
+
diff --git a/macros/luatex/generic/barracuda/example/01-latex-code39.pdf b/macros/luatex/generic/barracuda/example/01-latex-code39.pdf
new file mode 100644
index 0000000000..d40c55f46c
--- /dev/null
+++ b/macros/luatex/generic/barracuda/example/01-latex-code39.pdf
Binary files differ
diff --git a/macros/luatex/generic/barracuda/example/01-latex-code39.tex b/macros/luatex/generic/barracuda/example/01-latex-code39.tex
new file mode 100644
index 0000000000..c74935ed8d
--- /dev/null
+++ b/macros/luatex/generic/barracuda/example/01-latex-code39.tex
@@ -0,0 +1,14 @@
+% !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
new file mode 100644
index 0000000000..f7965e94d4
--- /dev/null
+++ b/macros/luatex/generic/barracuda/example/8006194056290.svg
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Barracuda package (https://github.com/robitex/barracuda) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg"
+ version="1.1"
+ width="37.289804mm" height="25.279878mm"
+ viewBox="-3.629981 -24.499871 37.289804 25.279878"
+>
+ <g stroke="black">
+ <path d="M0.164999 -24.499871V-0.000000" style="stroke-width:0.329998"/>
+ <path d="M0.824996 -24.499871V-0.000000" style="stroke-width:0.329998"/>
+ </g>
+ <g stroke="black">
+ <path d="M2.309988 -24.499871V-1.649991" style="stroke-width:0.659997"/>
+ <path d="M3.134984 -24.499871V-1.649991" style="stroke-width:0.329998"/>
+ </g>
+ <g stroke="black">
+ <path d="M3.794980 -24.499871V-1.649991" style="stroke-width:0.329998"/>
+ <path d="M5.114973 -24.499871V-1.649991" style="stroke-width:0.989995"/>
+ </g>
+ <g stroke="black">
+ <path d="M6.104968 -24.499871V-1.649991" style="stroke-width:0.329998"/>
+ <path d="M7.259962 -24.499871V-1.649991" style="stroke-width:1.319993"/>
+ </g>
+ <g stroke="black">
+ <path d="M8.579955 -24.499871V-1.649991" style="stroke-width:0.659997"/>
+ <path d="M9.899948 -24.499871V-1.649991" style="stroke-width:0.659997"/>
+ </g>
+ <g stroke="black">
+ <path d="M11.054942 -24.499871V-1.649991" style="stroke-width:0.329998"/>
+ <path d="M12.044937 -24.499871V-1.649991" style="stroke-width:0.989995"/>
+ </g>
+ <g stroke="black">
+ <path d="M13.034931 -24.499871V-1.649991" style="stroke-width:0.329998"/>
+ <path d="M14.519924 -24.499871V-1.649991" style="stroke-width:0.659997"/>
+ </g>
+ <g stroke="black">
+ <path d="M15.344919 -24.499871V-0.000000" style="stroke-width:0.329998"/>
+ <path d="M16.004916 -24.499871V-0.000000" style="stroke-width:0.329998"/>
+ </g>
+ <g stroke="black">
+ <path d="M16.994911 -24.499871V-1.649991" style="stroke-width:0.989995"/>
+ <path d="M18.314904 -24.499871V-1.649991" style="stroke-width:0.329998"/>
+ </g>
+ <g stroke="black">
+ <path d="M18.974900 -24.499871V-1.649991" style="stroke-width:0.329998"/>
+ <path d="M20.294893 -24.499871V-1.649991" style="stroke-width:0.989995"/>
+ </g>
+ <g stroke="black">
+ <path d="M21.284888 -24.499871V-1.649991" style="stroke-width:0.329998"/>
+ <path d="M21.944885 -24.499871V-1.649991" style="stroke-width:0.329998"/>
+ </g>
+ <g stroke="black">
+ <path d="M23.759875 -24.499871V-1.649991" style="stroke-width:0.659997"/>
+ <path d="M24.749870 -24.499871V-1.649991" style="stroke-width:0.659997"/>
+ </g>
+ <g stroke="black">
+ <path d="M26.234862 -24.499871V-1.649991" style="stroke-width:0.989995"/>
+ <path d="M27.224857 -24.499871V-1.649991" style="stroke-width:0.329998"/>
+ </g>
+ <g stroke="black">
+ <path d="M28.544850 -24.499871V-1.649991" style="stroke-width:0.989995"/>
+ <path d="M29.864843 -24.499871V-1.649991" style="stroke-width:0.329998"/>
+ </g>
+ <g stroke="black">
+ <path d="M30.524839 -24.499871V-0.000000" style="stroke-width:0.329998"/>
+ <path d="M31.184836 -24.499871V-0.000000" style="stroke-width:0.329998"/>
+ </g>
+ <text x="-3.629981" y="0.780007" font-family="Verdana" font-size="2.877000">
+ 8 </text>
+ <text y="0.780007" font-family="Verdana" font-size="2.877000" text-anchor="middle">
+ <tspan x="2.043326">0</tspan>
+ <tspan x="4.459979">0</tspan>
+ <tspan x="6.876631">6</tspan>
+ <tspan x="9.293284">1</tspan>
+ <tspan x="11.709936">9</tspan>
+ <tspan x="14.126589">4</tspan>
+ </text>
+ <text y="0.780007" font-family="Verdana" font-size="2.877000" text-anchor="middle">
+ <tspan x="17.223246">0</tspan>
+ <tspan x="19.639899">5</tspan>
+ <tspan x="22.056551">6</tspan>
+ <tspan x="24.473204">2</tspan>
+ <tspan x="26.889856">9</tspan>
+ <tspan x="29.306509">0</tspan>
+ </text>
+</svg>
+
diff --git a/macros/luatex/generic/barracuda/example/c128-123.svg b/macros/luatex/generic/barracuda/example/c128-123.svg
new file mode 100644
index 0000000000..9f5b5847aa
--- /dev/null
+++ b/macros/luatex/generic/barracuda/example/c128-123.svg
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Barracuda package (https://github.com/robitex/barracuda) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg"
+ version="1.1"
+ width="18.479903mm" height="9.999947mm"
+ viewBox="-2.099989 -9.999947 18.479903 9.999947"
+>
+ <g stroke="black">
+ <path d="M0.209999 -9.999947V-0.000000" style="stroke-width:0.419998"/>
+ <path d="M0.734996 -9.999947V-0.000000" style="stroke-width:0.209999"/>
+ <path d="M1.364993 -9.999947V-0.000000" style="stroke-width:0.209999"/>
+ </g>
+ <g stroke="black">
+ <path d="M2.414987 -9.999947V-0.000000" style="stroke-width:0.209999"/>
+ <path d="M3.254983 -9.999947V-0.000000" style="stroke-width:0.629997"/>
+ <path d="M4.199978 -9.999947V-0.000000" style="stroke-width:0.419998"/>
+ </g>
+ <g stroke="black">
+ <path d="M4.829975 -9.999947V-0.000000" style="stroke-width:0.419998"/>
+ <path d="M5.774970 -9.999947V-0.000000" style="stroke-width:0.629997"/>
+ <path d="M6.614965 -9.999947V-0.000000" style="stroke-width:0.209999"/>
+ </g>
+ <g stroke="black">
+ <path d="M7.139962 -9.999947V-0.000000" style="stroke-width:0.419998"/>
+ <path d="M7.874959 -9.999947V-0.000000" style="stroke-width:0.209999"/>
+ <path d="M8.504955 -9.999947V-0.000000" style="stroke-width:0.629997"/>
+ </g>
+ <g stroke="black">
+ <path d="M9.344951 -9.999947V-0.000000" style="stroke-width:0.209999"/>
+ <path d="M10.289946 -9.999947V-0.000000" style="stroke-width:0.419998"/>
+ <path d="M11.024942 -9.999947V-0.000000" style="stroke-width:0.209999"/>
+ </g>
+ <g stroke="black">
+ <path d="M11.759938 -9.999947V-0.000000" style="stroke-width:0.419998"/>
+ <path d="M12.914932 -9.999947V-0.000000" style="stroke-width:0.629997"/>
+ <path d="M13.544929 -9.999947V-0.000000" style="stroke-width:0.209999"/>
+ <path d="M14.069926 -9.999947V-0.000000" style="stroke-width:0.419998"/>
+ </g>
+</svg>
+
diff --git a/macros/luatex/generic/barracuda/lib/barracuda.lua b/macros/luatex/generic/barracuda/lib/barracuda.lua
new file mode 100644
index 0000000000..33e81be24f
--- /dev/null
+++ b/macros/luatex/generic/barracuda/lib/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",
+ _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
new file mode 100644
index 0000000000..ed6204528a
--- /dev/null
+++ b/macros/luatex/generic/barracuda/lib/lib-barcode/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.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 <family>-<variant>.
+-- in more details:
+-- <family id><dash char><variant id> if there are variants
+-- <encoder id> 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 <pname>
+ 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) --> <encoder object>, <err>
+ 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 <pname>
+ 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
new file mode 100644
index 0000000000..317b3de8f8
--- /dev/null
+++ b/macros/luatex/generic/barracuda/lib/lib-barcode/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/lib/lib-barcode/code39.lua b/macros/luatex/generic/barracuda/lib/lib-barcode/code39.lua
new file mode 100644
index 0000000000..a639619c63
--- /dev/null
+++ b/macros/luatex/generic/barracuda/lib/lib-barcode/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/lib/lib-barcode/ean.lua b/macros/luatex/generic/barracuda/lib/lib-barcode/ean.lua
new file mode 100644
index 0000000000..6893550a5c
--- /dev/null
+++ b/macros/luatex/generic/barracuda/lib/lib-barcode/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/lib/lib-barcode/i2of5.lua b/macros/luatex/generic/barracuda/lib/lib-barcode/i2of5.lua
new file mode 100644
index 0000000000..8097b855f7
--- /dev/null
+++ b/macros/luatex/generic/barracuda/lib/lib-barcode/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/lib/lib-driver/driver.lua b/macros/luatex/generic/barracuda/lib/lib-driver/driver.lua
new file mode 100644
index 0000000000..956c1f1e9d
--- /dev/null
+++ b/macros/luatex/generic/barracuda/lib/lib-driver/driver.lua
@@ -0,0 +1,400 @@
+--
+-- 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 <W: dim>; 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 <e: u8>; 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 <e: u8>; 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 <x1: DIM> <x2: DIM> <y: DIM>
+ [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 <y1: DIM> <y2: DIM> <x: DIM>
+ 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 <y1: DIM> <y2: DIM> <b: UINT> <x1: DIM> <t1: DIM>
+ [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 <x axis> <width>
+ 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 <x1: DIM> <y1: DIM> <x2: DIM> <y2: DIM>
+ [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
+ -- <ay: FLOAT> <x1: DIM> <x2: DIM> <y: DIM> <c: CHARS>
+ [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
new file mode 100644
index 0000000000..50baea1472
--- /dev/null
+++ b/macros/luatex/generic/barracuda/lib/lib-driver/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 <W: dim>; 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 <enum: u8>; set line cap style
+function PDFnative.append_002(st, bf, xt, cap)
+ bf[#bf + 1] = string.format("%d J", cap)
+end
+
+-- 3 <enum: u8>; 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 <x1: DIM> <x2: DIM> <y: DIM>
+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 <y1: DIM> <y2: DIM> <x: DIM>
+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 <y1: DIM> <y2: DIM> <b: UINT> <x1: DIM> <t1: DIM> ...
+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 <x y w h re>
+ 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 <x1: DIM> <y1: DIM> <x2: DIM> <y2: DIM>
+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 <x y w h re>
+ bf[#bf + 1] = string.format(fmt, x1/bp, y1/bp, w/bp, h/bp)
+end
+
+-- 130 <text> Text with several glyphs
+-- 130 <ax: FLOAT> <ay: FLOAT> <xpos: DIM> <ypos: DIM> <c: CHARS>
+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_xspaced>, Text with glyphs equally spaced on its vertical axis
+-- 131 <x1: DIM> <xgap: DIM> <ay: FLOAT> <ypos: DIM> <c: CHARS>
+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 <text_xwidth> Glyphs equally spaced on vertical axis between two x coordinates
+-- 132 <ay: FLOAT> <x1: DIM> <x2: DIM> <y: DIM> <c: CHARS>
+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
new file mode 100644
index 0000000000..7a2c5ab112
--- /dev/null
+++ b/macros/luatex/generic/barracuda/lib/lib-driver/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 = {
+ '<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n',
+ '<!-- Created with Barracuda package (https://github.com/robitex/barracuda) -->\n',
+ '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"\n',
+ ' "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n',
+ '<svg xmlns="http://www.w3.org/2000/svg"\n',
+ ' version="1.1"\n',
+ ' width="%0.6fmm" height="%0.6fmm"\n', -- line 7
+ ' viewBox="%0.6f %0.6f %0.6f %0.6f"\n', -- line 8
+ '>\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] = '</svg>\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 <W: dim>; set line width
+function SVG.append_001(st, bf, xt, w)
+ -- nothing to do
+end
+
+-- draw an horizontal line
+-- 33 <x1: DIM> <x2: DIM> <y: DIM>
+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( -- <path> element
+ '%s<path d="M%0.6f %0.6fH%0.6f"\n',
+ ident, x1/mm, -y/mm, x2/mm
+ )
+ local lw = st.line_width
+ bf[#bf + 1] = string.format(
+ '%s style="stroke:#000000;stroke-width:%0.6f"\n',
+ ident, lw/mm
+ )
+ bf[#bf + 1] = ident..'/>\n'
+end
+
+-- Vertical line: 34 <y1: DIM> <y2: DIM> <x: DIM>
+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( -- <path> element
+ '%s<path d="M%0.6f %0.6fV%0.6f"\n',
+ ident, x/mm, -y2/mm, -y1/mm
+ )
+ local lw = st.line_width
+ bf[#bf + 1] = string.format(
+ '%s style="stroke:#000000;stroke-width:%0.6f"\n',
+ ident, lw/mm
+ )
+ bf[#bf + 1] = ident..'/>\n'
+end
+
+-- Vbar
+-- draw a group of vertical lines
+-- 36 <y1: DIM> <y2: DIM> <b: UINT> <x1: DIM> <t1: DIM> ...
+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..'<g stroke="black">\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<path d="M%0.6f %0.6fV%0.6f" style="stroke-width:%0.6f"/>\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..'</g>\n' -- end group
+end
+
+-- Text
+-- 130 <text> Text with several glyphs
+-- 130 <ax: FLOAT> <ay: FLOAT> <xpos: DIM> <ypos: DIM> <c: CHARS>
+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<text x="%0.6f" y="%0.6f" font-family="Verdana" font-size="%0.6f"%s>\n',
+ ident, x1/mm, -y1/mm, fs/mm, anchor
+ )
+ bf[#bf + 1] = ident..txt
+ bf[#bf + 1] = ident..'</text>\n'
+ return bx1, y1, bx1 + w, y1 + h
+end
+
+-- 131 <text_xspaced>, Text with glyphs equally spaced on its vertical axis
+-- 131 <x1: DIM> <xgap: DIM> <ay: FLOAT> <ypos: DIM> <c: CHARS>
+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<text y="%0.6f" font-family="Verdana" font-size="%0.6f" text-anchor="middle">\n',
+ ident, -y1/mm, fs/mm
+ )
+ local x = x1
+ for _, c in ipairs(chars) do
+ bf[#bf + 1] = string.format('%s<tspan x="%0.6f">%s</tspan>\n',
+ ident, x/mm, c
+ )
+ x = x + xgap
+ end
+ bf[#bf + 1] = ident..'</text>\n'
+ local x2 = x1 + (n - 1)*xgap -- sp
+ return x1 - hw, y1, x2 + hw, y1 + h -- text group bounding box
+end
+
+-- 132 <text_xwidth> Glyphs equally spaced on vertical axis between two x coordinates
+-- 132 <ay: FLOAT> <x1: DIM> <x2: DIM> <y: DIM> <c: CHARS>
+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<text y="%0.6f" font-family="Verdana" font-size="%0.6f" text-anchor="middle">\n',
+ ident, -y1/mm, fs/mm
+ )
+ local x = x1 + cw/2
+ for _, c in ipairs(chars) do
+ bf[#bf + 1] = string.format('%s<tspan x="%0.6f">%s</tspan>\n',
+ ident, x/mm, c
+ )
+ x = x + xgap
+ end
+ bf[#bf + 1] = ident..'</text>\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
new file mode 100644
index 0000000000..cccc68f447
--- /dev/null
+++ b/macros/luatex/generic/barracuda/lib/lib-geo/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> <w: DIM>
+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> <cap: u8>
+-- 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> <join: u8>
+-- 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> <x1: DIM> <y1: DIM> <x2: DIM> <y2: DIM>
+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 <x_i t_i>
+ 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> <ay: FLOAT> <x1: DIM> <x2: DIM> <y: DIM> <c: CHARS>
+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
new file mode 100644
index 0000000000..fd53ca6509
--- /dev/null
+++ b/macros/luatex/generic/barracuda/lib/lib-geo/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) --> <vbar object>
+ 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, -- [<xcenter>, <width>, ...] 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) --> <vbar object>
+ 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, -- [<xcenter>, <width>, ...] 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) --> <vbar object>
+ 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, -- [<xcenter>, <width>, ...] 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) --> <vbar object>
+ 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, -- [<xcenter>, <width>, ...] 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) --> <vbar object>
+ 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, -- [<xcenter>, <width>, ...] 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