summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xBuild/source/texk/texlive/linked_scripts/luaotfload/luaotfload-tool.lua42
-rw-r--r--Master/texmf-dist/doc/luatex/luaotfload/NEWS8
-rw-r--r--Master/texmf-dist/doc/luatex/luaotfload/README2
-rw-r--r--Master/texmf-dist/doc/luatex/luaotfload/filegraph.pdfbin59830 -> 59899 bytes
-rw-r--r--Master/texmf-dist/doc/luatex/luaotfload/luaotfload.pdfbin201145 -> 224533 bytes
-rw-r--r--Master/texmf-dist/doc/man/man1/luaotfload-tool.12
-rw-r--r--Master/texmf-dist/doc/man/man1/luaotfload-tool.man1.pdfbin43596 -> 20805 bytes
-rw-r--r--Master/texmf-dist/doc/man/man5/luaotfload.conf.525
-rw-r--r--Master/texmf-dist/doc/man/man5/luaotfload.conf.man5.pdfbin45506 -> 24386 bytes
-rwxr-xr-xMaster/texmf-dist/scripts/luaotfload/luaotfload-tool.lua42
-rwxr-xr-xMaster/texmf-dist/scripts/luaotfload/mkglyphlist21
-rwxr-xr-xMaster/texmf-dist/scripts/luaotfload/mkimport25
-rwxr-xr-xMaster/texmf-dist/scripts/luaotfload/mkstatus2
-rw-r--r--Master/texmf-dist/source/luatex/luaotfload/Makefile18
-rw-r--r--Master/texmf-dist/source/luatex/luaotfload/luaotfload-main.tex17
-rw-r--r--Master/texmf-dist/source/luatex/luaotfload/luaotfload-tool.rst4
-rw-r--r--Master/texmf-dist/source/luatex/luaotfload/luaotfload.conf.rst49
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-2017-01-29.lua (renamed from Master/texmf-dist/tex/luatex/luaotfload/fontloader-2016-06-16.lua)4043
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-basics-gen.lua102
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-basics-nod.lua10
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-data-con.lua2
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-cff.lua231
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-con.lua594
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-def.lua5
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-dsp.lua125
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-gbn.lua4
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-map.lua112
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ocl.lua210
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-one.lua122
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-onr.lua206
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-osd.lua168
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ota.lua54
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otc.lua952
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otd.lua268
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oti.lua6
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otj.lua99
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otl.lua244
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oto.lua14
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otr.lua319
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ots.lua481
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oup.lua37
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-tfm.lua552
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-demo-vf-1.lua8
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-enc.lua59
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-ext.lua15
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts.lua7
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-file.lua11
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-io.lua95
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-lua.lua1
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-string.lua13
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-table.lua77
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-mplib.lua22
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-plain.tex8
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua4219
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-swiglib-test.lua750
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-swiglib.lua5
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-test.tex12
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-util-fil.lua126
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/fontloader-util-str.lua97
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-auxiliary.lua17
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-characters.lua5586
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-colors.lua2
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-configuration.lua56
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-database.lua162
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-features.lua684
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-glyphlist.lua2
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-init.lua5
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua10
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-loaders.lua26
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-log.lua32
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-main.lua26
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-parsers.lua4
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-resolvers.lua1
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload-status.lua124
-rw-r--r--Master/texmf-dist/tex/luatex/luaotfload/luaotfload.sty4
75 files changed, 16409 insertions, 5074 deletions
diff --git a/Build/source/texk/texlive/linked_scripts/luaotfload/luaotfload-tool.lua b/Build/source/texk/texlive/linked_scripts/luaotfload/luaotfload-tool.lua
index bc9e425cb5d..e7df3ce4482 100755
--- a/Build/source/texk/texlive/linked_scripts/luaotfload/luaotfload-tool.lua
+++ b/Build/source/texk/texlive/linked_scripts/luaotfload/luaotfload-tool.lua
@@ -2,15 +2,15 @@
-----------------------------------------------------------------------
-- FILE: luaotfload-tool.lua
-- DESCRIPTION: database functionality
--- REQUIREMENTS: luaotfload 2.7
+-- REQUIREMENTS: luaotfload 2.8
-- AUTHOR: Khaled Hosny, Élie Roux, Philipp Gesang
-- LICENSE: GPL v2.0
-----------------------------------------------------------------------
luaotfload = luaotfload or { }
-local version = "2.7"
+local version = "2.8"
luaotfload.version = version
-luaotfload.min_luatex_version = { 0, 95, 0 } --- i. e. 0.95.0
+luaotfload.min_luatex_version = { 0, 95, 0 }
luaotfload.self = "luaotfload-tool"
--[[doc--
@@ -64,8 +64,9 @@ do
actual = { major, minor, revno or 0 }
end
- if actual [1] < minimum [1] or actual [2] < minimum [2]
- or actual [3] < minimum [3]
+ if actual [1] < minimum [1]
+ or actual == minimum and actual [2] < minimum [2]
+ or actual == minimum and actual [2] == minimum [2] and actual [3] < minimum [3]
then
texio.write_nl ("term and log",
string.format ("\tFATAL ERROR\n\z
@@ -138,32 +139,22 @@ require "fontloader-basics-gen.lua"
texio.write, texio.write_nl = backup.write, backup.write_nl
utilities = backup.utilities
+pdf = pdf or { } --- for font-tfm
+
require "fontloader-data-con"
require "fontloader-font-ini"
require "fontloader-font-con"
require "fontloader-fonts-enc"
require "fontloader-font-cid"
require "fontloader-font-map"
-require "fontloader-font-tfm"
require "fontloader-font-oti"
require "fontloader-font-otr"
require "fontloader-font-cff"
require "fontloader-font-ttf"
require "fontloader-font-dsp"
require "fontloader-font-oup"
-require "fontloader-font-otl"
-require "fontloader-font-oto"
-------- "fontloader-font-otj"
-------- "fontloader-font-ota"
-------- "fontloader-font-ots"
-------- "fontloader-font-osd"
require "fontloader-font-onr"
-require "fontloader-font-one"
-require "fontloader-font-afk"
-require "fontloader-font-lua"
require "fontloader-font-def"
-require "fontloader-fonts-ext"
-------- "fontloader-font-gbn"
fonts = fonts or { }
local fontsnames = fonts.names or { }
@@ -190,7 +181,7 @@ end
require "alt_getopt"
-loadmodule "log.lua" --- this populates the luaotfload.log.* namespace
+loadmodule "log" --- this populates the luaotfload.log.* namespace
loadmodule "parsers" --- fonts.conf, configuration, and request syntax
loadmodule "configuration" --- configuration file handling
loadmodule "database"
@@ -664,7 +655,7 @@ subfont_by_name = function (lst, askedname, n)
if fonts.names.sanitize_fontname (font.fullname) == askedname then
return font
end
- return subfont_by_name (lst, askedname, n)
+ return subfont_by_name (lst, askedname, n + 1)
end
return false
end
@@ -677,7 +668,7 @@ The font info knows two levels of detail:
returned by readers.loadfont().
--doc]]--
-local show_font_info = function (basename, askedname, detail)
+local show_font_info = function (basename, askedname, detail, subfont)
local filenames = fonts.names.data().files
local index = filenames.base[basename]
local fullname = filenames.full[index]
@@ -687,7 +678,7 @@ local show_font_info = function (basename, askedname, detail)
end
if fullname then
local shortinfo = fonts.handlers.otf.readers.getinfo (fullname, {
- subfont = nil,
+ subfont = subfont,
platformnames = true,
rawfamilynames = true,
})
@@ -710,7 +701,8 @@ local show_font_info = function (basename, askedname, detail)
[[%s is a font collection]], basename)
for subfont = 1, nfonts do
logreport (true, 1, "resolve",
- [[Showing info for font no. %d]], n)
+ [[Showing info for font no. %d]],
+ subfont)
show_info_items(shortinfo[subfont])
if detail == true then
show_full_info(fullname, subfont)
@@ -1182,7 +1174,8 @@ actions.query = function (job)
needle = tmpspec.resolved or tmpspec.name
end
elseif tmpspec.lookup == "file" then
- needle = tmpspec.name
+ needle = tmpspec.name
+ subfont = tmpspec.sub
end
if needle then
@@ -1200,7 +1193,8 @@ actions.query = function (job)
"Resolved file name %q", foundname)
end
if job.show_info then
- show_font_info (foundname, query, job.full_info)
+ logreport (false, 3, "resolve", "Dump extra info.")
+ show_font_info (foundname, query, job.full_info, subfont)
iowrite "\n"
end
else
diff --git a/Master/texmf-dist/doc/luatex/luaotfload/NEWS b/Master/texmf-dist/doc/luatex/luaotfload/NEWS
index f558e3b54f3..83ac5c20d73 100644
--- a/Master/texmf-dist/doc/luatex/luaotfload/NEWS
+++ b/Master/texmf-dist/doc/luatex/luaotfload/NEWS
@@ -1,5 +1,13 @@
Change History
--------------
+2017-01-29, luaotfload v2.8:
+ * Latest fontloader code.
+ * Support for Luatex 1.0.
+ * Integration of the extended AFM handler.
+ * Fixes to font family assignment.
+ * Skip initialization if Luaotfload is already loaded.
+ * Optical sizes advertised by fonts treated as big points.
+
2016/04/21, luaotfload v2.7:
* Rework lookup chaining.
* Combining glyphs from different fonts (``combo: ...`` requests).
diff --git a/Master/texmf-dist/doc/luatex/luaotfload/README b/Master/texmf-dist/doc/luatex/luaotfload/README
index 01e1fc6025e..77b286479bf 100644
--- a/Master/texmf-dist/doc/luatex/luaotfload/README
+++ b/Master/texmf-dist/doc/luatex/luaotfload/README
@@ -56,7 +56,7 @@ Here are the recommended installation methods (preferred first).
distribution's manual for details.
3. a. Grab the sources from CTAN or github.
- b. Run 'make install TEXMFROOT=/path/to/texmf'.
+ b. Run 'make install DESTDIR=/path/to/texmf'.
c. See 2c.
4. Try to figure it out by looking at the Makefile and comments in the sources.
diff --git a/Master/texmf-dist/doc/luatex/luaotfload/filegraph.pdf b/Master/texmf-dist/doc/luatex/luaotfload/filegraph.pdf
index fa880a2f82c..15a752213ee 100644
--- a/Master/texmf-dist/doc/luatex/luaotfload/filegraph.pdf
+++ b/Master/texmf-dist/doc/luatex/luaotfload/filegraph.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/luatex/luaotfload/luaotfload.pdf b/Master/texmf-dist/doc/luatex/luaotfload/luaotfload.pdf
index 597a4e3a160..de6a6ef5f7e 100644
--- a/Master/texmf-dist/doc/luatex/luaotfload/luaotfload.pdf
+++ b/Master/texmf-dist/doc/luatex/luaotfload/luaotfload.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/man/man1/luaotfload-tool.1 b/Master/texmf-dist/doc/man/man1/luaotfload-tool.1
index ffbe2f94938..c3205140117 100644
--- a/Master/texmf-dist/doc/man/man1/luaotfload-tool.1
+++ b/Master/texmf-dist/doc/man/man1/luaotfload-tool.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH LUAOTFLOAD-TOOL 1 "2016-06-16" "2.7" "text processing"
+.TH LUAOTFLOAD-TOOL 1 "2017-01-28" "2.8" "text processing"
.SH NAME
luaotfload-tool \- generate and query the Luaotfload font names database
.
diff --git a/Master/texmf-dist/doc/man/man1/luaotfload-tool.man1.pdf b/Master/texmf-dist/doc/man/man1/luaotfload-tool.man1.pdf
index 19f4e3d49a6..551c39e5c06 100644
--- a/Master/texmf-dist/doc/man/man1/luaotfload-tool.man1.pdf
+++ b/Master/texmf-dist/doc/man/man1/luaotfload-tool.man1.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/man/man5/luaotfload.conf.5 b/Master/texmf-dist/doc/man/man5/luaotfload.conf.5
index c7276a5f66d..fda621c6439 100644
--- a/Master/texmf-dist/doc/man/man5/luaotfload.conf.5
+++ b/Master/texmf-dist/doc/man/man5/luaotfload.conf.5
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH LUAOTFLOAD.CONF 5 "2016-06-16" "2.7" "text processing"
+.TH LUAOTFLOAD.CONF 5 "2017-01-29" "2.8" "text processing"
.SH NAME
luaotfload.conf \- Luaotfload configuration file
.
@@ -200,6 +200,14 @@ T} T{
T}
_
T{
+designsize\-dimen
+T} T{
+b
+T} T{
+\fBbp\fP
+T}
+_
+T{
formats
T} T{
s
@@ -247,14 +255,6 @@ T} T{
\fBtrue\fP
T}
_
-T{
-use\-fontforge
-T} T{
-b
-T} T{
-\fBfalse\fP
-T}
-_
.TE
.sp
The flag \fBcompress\fP determines whether the font index (usually
@@ -264,6 +264,10 @@ If unset it is equivalent of passing \fB\-\-no\-compress\fP to
and has no effect on the runtime behavior of Luaotfload, the flag
should remain set. Most editors come with zlib support anyways.
.sp
+The setting \fBdesignsize\-dimen\fP applies when looking up fonts from
+families with design sizes. The default of DTP\-style “big points”
+can be changed for \fBpt\fP or even \fBdd\fP\&.
+.sp
The list of \fBformats\fP must be a comma separated sequence of strings
containing one or more of these elements:
.INDENT 0.0
@@ -304,9 +308,6 @@ If \fBupdate\-live\fP is set, Luaotfload will reload the database if it
cannot find a requested font. Those who prefer to update manually using
\fBluaotfload\-tool\fP should unset this flag. This option does not affect
rebuilds due to version mismatch.
-.sp
-The option \fBuse\-fontforge\fP had a meaning during the transition to the
-Lua\-only Opentype reader. At present it is ignored.
.SS Section \fBdefault\-features\fP
.sp
By default Luaotfload enables \fBnode\fP mode and picks the default font
diff --git a/Master/texmf-dist/doc/man/man5/luaotfload.conf.man5.pdf b/Master/texmf-dist/doc/man/man5/luaotfload.conf.man5.pdf
index acaf2bd88fb..b09cd792113 100644
--- a/Master/texmf-dist/doc/man/man5/luaotfload.conf.man5.pdf
+++ b/Master/texmf-dist/doc/man/man5/luaotfload.conf.man5.pdf
Binary files differ
diff --git a/Master/texmf-dist/scripts/luaotfload/luaotfload-tool.lua b/Master/texmf-dist/scripts/luaotfload/luaotfload-tool.lua
index bc9e425cb5d..e7df3ce4482 100755
--- a/Master/texmf-dist/scripts/luaotfload/luaotfload-tool.lua
+++ b/Master/texmf-dist/scripts/luaotfload/luaotfload-tool.lua
@@ -2,15 +2,15 @@
-----------------------------------------------------------------------
-- FILE: luaotfload-tool.lua
-- DESCRIPTION: database functionality
--- REQUIREMENTS: luaotfload 2.7
+-- REQUIREMENTS: luaotfload 2.8
-- AUTHOR: Khaled Hosny, Élie Roux, Philipp Gesang
-- LICENSE: GPL v2.0
-----------------------------------------------------------------------
luaotfload = luaotfload or { }
-local version = "2.7"
+local version = "2.8"
luaotfload.version = version
-luaotfload.min_luatex_version = { 0, 95, 0 } --- i. e. 0.95.0
+luaotfload.min_luatex_version = { 0, 95, 0 }
luaotfload.self = "luaotfload-tool"
--[[doc--
@@ -64,8 +64,9 @@ do
actual = { major, minor, revno or 0 }
end
- if actual [1] < minimum [1] or actual [2] < minimum [2]
- or actual [3] < minimum [3]
+ if actual [1] < minimum [1]
+ or actual == minimum and actual [2] < minimum [2]
+ or actual == minimum and actual [2] == minimum [2] and actual [3] < minimum [3]
then
texio.write_nl ("term and log",
string.format ("\tFATAL ERROR\n\z
@@ -138,32 +139,22 @@ require "fontloader-basics-gen.lua"
texio.write, texio.write_nl = backup.write, backup.write_nl
utilities = backup.utilities
+pdf = pdf or { } --- for font-tfm
+
require "fontloader-data-con"
require "fontloader-font-ini"
require "fontloader-font-con"
require "fontloader-fonts-enc"
require "fontloader-font-cid"
require "fontloader-font-map"
-require "fontloader-font-tfm"
require "fontloader-font-oti"
require "fontloader-font-otr"
require "fontloader-font-cff"
require "fontloader-font-ttf"
require "fontloader-font-dsp"
require "fontloader-font-oup"
-require "fontloader-font-otl"
-require "fontloader-font-oto"
-------- "fontloader-font-otj"
-------- "fontloader-font-ota"
-------- "fontloader-font-ots"
-------- "fontloader-font-osd"
require "fontloader-font-onr"
-require "fontloader-font-one"
-require "fontloader-font-afk"
-require "fontloader-font-lua"
require "fontloader-font-def"
-require "fontloader-fonts-ext"
-------- "fontloader-font-gbn"
fonts = fonts or { }
local fontsnames = fonts.names or { }
@@ -190,7 +181,7 @@ end
require "alt_getopt"
-loadmodule "log.lua" --- this populates the luaotfload.log.* namespace
+loadmodule "log" --- this populates the luaotfload.log.* namespace
loadmodule "parsers" --- fonts.conf, configuration, and request syntax
loadmodule "configuration" --- configuration file handling
loadmodule "database"
@@ -664,7 +655,7 @@ subfont_by_name = function (lst, askedname, n)
if fonts.names.sanitize_fontname (font.fullname) == askedname then
return font
end
- return subfont_by_name (lst, askedname, n)
+ return subfont_by_name (lst, askedname, n + 1)
end
return false
end
@@ -677,7 +668,7 @@ The font info knows two levels of detail:
returned by readers.loadfont().
--doc]]--
-local show_font_info = function (basename, askedname, detail)
+local show_font_info = function (basename, askedname, detail, subfont)
local filenames = fonts.names.data().files
local index = filenames.base[basename]
local fullname = filenames.full[index]
@@ -687,7 +678,7 @@ local show_font_info = function (basename, askedname, detail)
end
if fullname then
local shortinfo = fonts.handlers.otf.readers.getinfo (fullname, {
- subfont = nil,
+ subfont = subfont,
platformnames = true,
rawfamilynames = true,
})
@@ -710,7 +701,8 @@ local show_font_info = function (basename, askedname, detail)
[[%s is a font collection]], basename)
for subfont = 1, nfonts do
logreport (true, 1, "resolve",
- [[Showing info for font no. %d]], n)
+ [[Showing info for font no. %d]],
+ subfont)
show_info_items(shortinfo[subfont])
if detail == true then
show_full_info(fullname, subfont)
@@ -1182,7 +1174,8 @@ actions.query = function (job)
needle = tmpspec.resolved or tmpspec.name
end
elseif tmpspec.lookup == "file" then
- needle = tmpspec.name
+ needle = tmpspec.name
+ subfont = tmpspec.sub
end
if needle then
@@ -1200,7 +1193,8 @@ actions.query = function (job)
"Resolved file name %q", foundname)
end
if job.show_info then
- show_font_info (foundname, query, job.full_info)
+ logreport (false, 3, "resolve", "Dump extra info.")
+ show_font_info (foundname, query, job.full_info, subfont)
iowrite "\n"
end
else
diff --git a/Master/texmf-dist/scripts/luaotfload/mkglyphlist b/Master/texmf-dist/scripts/luaotfload/mkglyphlist
index f66a686322b..b9d5309d529 100755
--- a/Master/texmf-dist/scripts/luaotfload/mkglyphlist
+++ b/Master/texmf-dist/scripts/luaotfload/mkglyphlist
@@ -18,7 +18,7 @@
-----------------------------------------------------------------------
local glyphfile = "./build/glyphlist.txt"
local font_age = "./build/luaotfload-glyphlist.lua"
-local glyph_source = "http://partners.adobe.com/public/developer/en/opentype/glyphlist.txt"
+local glyph_source = "https://raw.githubusercontent.com/adobe-type-tools/agl-aglfn/master/glyphlist.txt"
-----------------------------------------------------------------------
-- fallbacks
@@ -67,7 +67,7 @@ local eol = P"\n\r" + P"\r\n" + P"\r" + P"\n"
local space = P" "
local alphanum = R("az", "AZ", "09")
local hexdigit = R("af", "AF", "09")
-local eof_tag = gartenzaun * P"--end"
+local eof_tag = gartenzaun * P"END"
local header_line = gartenzaun * (1-eol)^0 * eol
local codepoint = hexdigit^1
local glyphname = alphanum^1
@@ -140,19 +140,12 @@ local get_raw get_raw = function (retry)
elseif not retry then --- attempt download
print"info: retrieving glyph list from"
print(glyph_source)
- local glyphdata = http.request(glyph_source)
- if glyphdata then
- local fh = io.open(glyphfile, "wb")
- if not fh then
- print (string.format ("error: glyph file (%s) not writable", glyphfile))
- os.exit(-1)
- end
- fh:write(glyphdata)
- fh:close()
- return get_raw(true)
+ local cmd = string.format("wget '%s' -o '%s'", glyph_source, glyphfile)
+ local st = os.execute(string.format("wget '%s' -O '%s'", glyph_source, glyphfile))
+ if st ~= 0 then
+ print(string.format("error: download failed; status: %d, command: %q", st, cmd))
+ os.exit(-1)
end
- print"error: download failed"
- os.exit(-1)
end
print("error: could not obtain glyph data from "..glyphfile)
os.exit(-1)
diff --git a/Master/texmf-dist/scripts/luaotfload/mkimport b/Master/texmf-dist/scripts/luaotfload/mkimport
index 1dc0a291ecb..94e1f0bc5b2 100755
--- a/Master/texmf-dist/scripts/luaotfload/mkimport
+++ b/Master/texmf-dist/scripts/luaotfload/mkimport
@@ -238,11 +238,11 @@ local imports = {
{ name = "font-lua" , ours = "font-lua" , kind = kind_merged },
{ name = "font-map" , ours = "font-map" , kind = kind_merged },
{ name = "font-ocl" , ours = "font-ocl" , kind = kind_merged },
+ { name = "font-otc" , ours = "font-otc" , kind = kind_merged },
{ name = "font-onr" , ours = "font-onr" , kind = kind_merged },
{ name = "font-one" , ours = "font-one" , kind = kind_merged },
{ name = "font-osd" , ours = "font-osd" , kind = kind_merged },
{ name = "font-ota" , ours = "font-ota" , kind = kind_merged },
- { name = "font-otd" , ours = "font-otd" , kind = kind_merged },
{ name = "font-oti" , ours = "font-oti" , kind = kind_merged },
{ name = "font-otj" , ours = "font-otj" , kind = kind_merged },
{ name = "font-otl" , ours = "font-otl" , kind = kind_merged },
@@ -295,7 +295,6 @@ local package = {
--- [19] font-cid.lua
--- [20] font-map.lua
--- [21] luatex-fonts-syn.lua
---- [22] font-tfm.lua
--- [23] font-oti.lua
--- [24] font-otr.lua
--- [25] font-cff.lua
@@ -309,14 +308,16 @@ local package = {
--- [33] font-ots.lua
--- [34] font-osd.lua
--- [35] font-ocl.lua
---- [36] font-onr.lua
---- [37] font-one.lua
---- [38] font-afk.lua
---- [39] font-lua.lua
---- [40] font-def.lua
---- [41] font-xtx.lua
---- [42] luatex-fonts-ext.lua
---- [43] font-gbn.lua
+--- [36] font-otc.lua
+--- [37] font-onr.lua
+--- [38] font-one.lua
+--- [39] font-afk.lua
+--- [40] font-tfm.lua
+--- [41] font-lua.lua
+--- [42] font-def.lua
+--- [43] font-xtx.lua
+--- [44] luatex-fonts-ext.lua
+--- [45] font-gbn.lua
---
--- Of these, nos. 01--11 are provided by the Lualibs. Keeping them
--- around in the Luaotfload fontloader is therefore unnecessary.
@@ -360,8 +361,6 @@ local package = {
"fonts-enc",
"font-cid",
"font-map",
- "fonts-syn",
- "font-tfm",
"font-oti",
"font-otr",
"font-cff",
@@ -375,9 +374,11 @@ local package = {
"font-ots",
"font-osd",
"font-ocl",
+ "font-otc",
"font-onr",
"font-one",
"font-afk",
+ "font-tfm",
"font-lua",
"font-def",
"fonts-ext",
diff --git a/Master/texmf-dist/scripts/luaotfload/mkstatus b/Master/texmf-dist/scripts/luaotfload/mkstatus
index 10f66802003..4fda6a7ff95 100755
--- a/Master/texmf-dist/scripts/luaotfload/mkstatus
+++ b/Master/texmf-dist/scripts/luaotfload/mkstatus
@@ -101,7 +101,6 @@ local names = {
{ miscdir, "fontloader-font-lua.lua", },
{ miscdir, "fontloader-fonts-syn.lua", },
{ miscdir, "fontloader-font-tfm.lua", },
- { miscdir, "fontloader-font-tfm.lua", },
{ miscdir, "fontloader-font-otr.lua", },
{ miscdir, "fontloader-font-cff.lua", },
{ miscdir, "fontloader-font-ttf.lua", },
@@ -114,6 +113,7 @@ local names = {
{ miscdir, "fontloader-font-ots.lua", },
{ miscdir, "fontloader-font-osd.lua", },
{ miscdir, "fontloader-font-ocl.lua", },
+ { miscdir, "fontloader-font-otc.lua", },
--- lua libraries
{ miscdir, "fontloader-languages.lua", },
diff --git a/Master/texmf-dist/source/luatex/luaotfload/Makefile b/Master/texmf-dist/source/luatex/luaotfload/Makefile
index a131f3ace05..e59b43e290c 100644
--- a/Master/texmf-dist/source/luatex/luaotfload/Makefile
+++ b/Master/texmf-dist/source/luatex/luaotfload/Makefile
@@ -198,16 +198,18 @@ $(TDS_ZIP): $(DOCS) $(ALL_STATUS) check
sign: $(CTAN_ZIPSIG)
-.PHONY: package install manifest clean mrproper show showtargets check import news
+.PHONY: package install manifest clean mrproper show showtargets
+.PHONY: check import news tds ctan sign package loader
+ifndef DESTDIR
install:
- @echo " ××××××××××××××××××××××××××××××××"
- @echo " There is no “install” target."
- @echo " ××××××××××××××××××××××××××××××××"
- @echo " Compile a TDS zipball (make tds)"
- @echo " and extract that into your local"
- @echo " TEXMF instead."
- @echo " ××××××××××××××××××××××××××××××××"
+ $(error "in order to install you need to provide $$DESTDIR")
+else
+install: $(TDS_ZIP)
+ $(info installing to destination “$(DESTDIR)”)
+ install -dm755 "$(DESTDIR)"
+ unzip "$(TDS_ZIP)" -d "$(DESTDIR)"
+endif
manifest:
@echo "Source files:"
diff --git a/Master/texmf-dist/source/luatex/luaotfload/luaotfload-main.tex b/Master/texmf-dist/source/luatex/luaotfload/luaotfload-main.tex
index f6c7301a4a4..c26235e479d 100644
--- a/Master/texmf-dist/source/luatex/luaotfload/luaotfload-main.tex
+++ b/Master/texmf-dist/source/luatex/luaotfload/luaotfload-main.tex
@@ -1,4 +1,4 @@
-%% Copyright (C) 2009-2016
+%% Copyright (C) 2009-2017
%%
%% by Elie Roux <elie.roux@telecom-bretagne.eu>
%% and Khaled Hosny <khaledhosny@eglug.org>
@@ -32,7 +32,7 @@
\beginfrontmatter
\setdocumenttitle {The \identifier{luaotfload} package}
- \setdocumentdate {2016/06/16 v2.7}
+ \setdocumentdate {2017/01/29 v2.8}
\setdocumentauthor {Elie Roux · Khaled Hosny · Philipp Gesang\\
Home: \hyperlink {https://github.com/lualatex/luaotfload}\\
Support: \email {lualatex-dev@tug.org}}
@@ -424,6 +424,19 @@ non-standard directory:
\font \gfsporson = "[/tmp/GFSPorson.otf]" at 12pt
\endlisting
+\identifier{TrueType} collection files (the extension is usually
+\inlinecode{.ttc}) contain more than a single font. In order to refer to these
+subfonts, the respective index may be added in parentheses after the file
+name.\footnote{%
+ Incidentally, this syntactical detail also prevents one from loading files
+ that end in balanced parentheses.
+}
+
+\beginlisting
+ \font \cambriamain = "file:cambria.ttc(0)" at 10pt
+ \font \cambriamath = "file:cambria.ttc(1)" at 10pt
+\endlisting
+
\endsubsubsection
\beginsubsubsection{Loading by Font Name}
diff --git a/Master/texmf-dist/source/luatex/luaotfload/luaotfload-tool.rst b/Master/texmf-dist/source/luatex/luaotfload/luaotfload-tool.rst
index 28f8e0099c6..1eeba11aaed 100644
--- a/Master/texmf-dist/source/luatex/luaotfload/luaotfload-tool.rst
+++ b/Master/texmf-dist/source/luatex/luaotfload/luaotfload-tool.rst
@@ -6,9 +6,9 @@
generate and query the Luaotfload font names database
-----------------------------------------------------------------------
-:Date: 2016-06-16
+:Date: 2017-01-28
:Copyright: GPL v2.0
-:Version: 2.7
+:Version: 2.8
:Manual section: 1
:Manual group: text processing
diff --git a/Master/texmf-dist/source/luatex/luaotfload/luaotfload.conf.rst b/Master/texmf-dist/source/luatex/luaotfload/luaotfload.conf.rst
index 051ec7fb981..fbef8ec70a2 100644
--- a/Master/texmf-dist/source/luatex/luaotfload/luaotfload.conf.rst
+++ b/Master/texmf-dist/source/luatex/luaotfload/luaotfload.conf.rst
@@ -6,9 +6,9 @@
Luaotfload configuration file
-----------------------------------------------------------------------
-:Date: 2016-06-16
+:Date: 2017-01-29
:Copyright: GPL v2.0
-:Version: 2.7
+:Version: 2.8
:Manual section: 5
:Manual group: text processing
@@ -125,25 +125,25 @@ the variable is unset.
Section ``db``
-----------------------------------------------------------------------
-+-----------------+--------+---------------------------+
-| variable | type | default |
-+-----------------+--------+---------------------------+
-| compress | b | ``true`` |
-+-----------------+--------+---------------------------+
-| formats | s | ``"otf,ttf,ttc"`` |
-+-----------------+--------+---------------------------+
-| max-fonts | n | ``2^51`` |
-+-----------------+--------+---------------------------+
-| scan-local | b | ``false`` |
-+-----------------+--------+---------------------------+
-| skip-read | b | ``false`` |
-+-----------------+--------+---------------------------+
-| strip | b | ``true`` |
-+-----------------+--------+---------------------------+
-| update-live | b | ``true`` |
-+-----------------+--------+---------------------------+
-| use-fontforge | b | ``false`` |
-+-----------------+--------+---------------------------+
++--------------------+--------+---------------------------+
+| variable | type | default |
++--------------------+--------+---------------------------+
+| compress | b | ``true`` |
++--------------------+--------+---------------------------+
+| designsize-dimen | b | ``bp`` |
++--------------------+--------+---------------------------+
+| formats | s | ``"otf,ttf,ttc"`` |
++--------------------+--------+---------------------------+
+| max-fonts | n | ``2^51`` |
++--------------------+--------+---------------------------+
+| scan-local | b | ``false`` |
++--------------------+--------+---------------------------+
+| skip-read | b | ``false`` |
++--------------------+--------+---------------------------+
+| strip | b | ``true`` |
++--------------------+--------+---------------------------+
+| update-live | b | ``true`` |
++--------------------+--------+---------------------------+
The flag ``compress`` determines whether the font index (usually
``luaotfload-names.lua[.gz]`` will be stored in compressed forms.
@@ -152,6 +152,10 @@ If unset it is equivalent of passing ``--no-compress`` to
and has no effect on the runtime behavior of Luaotfload, the flag
should remain set. Most editors come with zlib support anyways.
+The setting ``designsize-dimen`` applies when looking up fonts from
+families with design sizes. The default of DTP-style “big points”
+can be changed for ``pt`` or even ``dd``.
+
The list of ``formats`` must be a comma separated sequence of strings
containing one or more of these elements:
@@ -189,9 +193,6 @@ cannot find a requested font. Those who prefer to update manually using
**luaotfload-tool** should unset this flag. This option does not affect
rebuilds due to version mismatch.
-The option ``use-fontforge`` had a meaning during the transition to the
-Lua-only Opentype reader. At present it is ignored.
-
Section ``default-features``
-----------------------------------------------------------------------
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2016-06-16.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2017-01-29.lua
index b0dcc629c98..1b3df22da02 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2016-06-16.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2017-01-29.lua
@@ -1,9 +1,9 @@
--[[info-----------------------------------------------------------------------
Luaotfload fontloader package
- build 2016-06-16 22:10:46 by phg@phlegethon
+ build 2017-01-29 21:08:57 by phg@phlegethon
-------------------------------------------------------------------------------
- © 2016 PRAGMA ADE / ConTeXt Development Team
+ © 2017 PRAGMA ADE / ConTeXt Development Team
The code in this file is provided under the GPL v2.0 license. See the
file COPYING in the Luaotfload repository for details.
@@ -26,8 +26,6 @@
· fontloader-fonts-enc.lua
· fontloader-font-cid.lua
· fontloader-font-map.lua
- · fontloader-fonts-syn.lua
- · fontloader-font-tfm.lua
· fontloader-font-oti.lua
· fontloader-font-otr.lua
· fontloader-font-cff.lua
@@ -41,9 +39,11 @@
· fontloader-font-ots.lua
· fontloader-font-osd.lua
· fontloader-font-ocl.lua
+ · fontloader-font-otc.lua
· fontloader-font-onr.lua
· fontloader-font-one.lua
· fontloader-font-afk.lua
+ · fontloader-font-tfm.lua
· fontloader-font-lua.lua
· fontloader-font-def.lua
· fontloader-fonts-ext.lua
@@ -52,7 +52,7 @@
--info]]-----------------------------------------------------------------------
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “data-con” 675f5a0af45ffb3e0d2e2ab5d6c2e47b] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “data-con” d8982c834ed9acc6193eee23067b9d5d] ---
if not modules then modules={} end modules ['data-con']={
version=1.100,
@@ -122,7 +122,7 @@ function containers.read(container,name)
local storage=container.storage
local stored=storage[name]
if not stored and container.enabled and caches and containers.usecache then
- stored=caches.loaddata(container.readables,name)
+ stored=caches.loaddata(container.readables,name,container.writable)
if stored and stored.cache_version==container.version then
if trace_cache or trace_containers then
report_containers("action %a, category %a, name %a","load",container.subcategory,name)
@@ -164,10 +164,10 @@ function containers.cleanname(name)
return (gsub(lower(name),"[^%w\128-\255]+","-"))
end
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “data-con”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “data-con”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “basics-nod” ecd4eb8a91ac539824a9a72c5b97ded4] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “basics-nod” 9288471b8395bfb683aba0ff3964d950] ---
if not modules then modules={} end modules ['luatex-fonts-nod']={
version=1.001,
@@ -222,7 +222,7 @@ end
nodes.nodecodes=nodecodes
nodes.glyphcodes=glyphcodes
nodes.disccodes=disccodes
-local free_node=node.free
+local flush_node=node.flush_node
local remove_node=node.remove
local new_node=node.new
local traverse_id=node.traverse_id
@@ -242,7 +242,7 @@ function nodes.remove(head,current,free_too)
head,current=remove_node(head,current)
if t then
if free_too then
- free_node(t)
+ flush_node(t)
t=nil
else
t.next,t.prev=nil,nil
@@ -266,12 +266,14 @@ nodes.getattr=getfield
nodes.setattr=setfield
nodes.tostring=node.tostring or tostring
nodes.copy=node.copy
+nodes.copy_node=node.copy
nodes.copy_list=node.copy_list
nodes.delete=node.delete
nodes.dimensions=node.dimensions
nodes.end_of_math=node.end_of_math
nodes.flush_list=node.flush_list
nodes.flush_node=node.flush_node
+nodes.flush=node.flush_node
nodes.free=node.free
nodes.insert_after=node.insert_after
nodes.insert_before=node.insert_before
@@ -285,7 +287,6 @@ nodes.vpack=node.vpack
nodes.first_glyph=node.first_glyph
nodes.has_glyph=node.has_glyph or node.first_glyph
nodes.current_attr=node.current_attr
-nodes.do_ligature_n=node.do_ligature_n
nodes.has_field=node.has_field
nodes.last_node=node.last_node
nodes.usedlist=node.usedlist
@@ -372,9 +373,12 @@ nuts.insert_before=direct.insert_before
nuts.insert_after=direct.insert_after
nuts.delete=direct.delete
nuts.copy=direct.copy
+nuts.copy_node=direct.copy
nuts.copy_list=direct.copy_list
nuts.tail=direct.tail
nuts.flush_list=direct.flush_list
+nuts.flush_node=direct.flush_node
+nuts.flush=direct.flush
nuts.free=direct.free
nuts.remove=direct.remove
nuts.is_node=direct.is_node
@@ -417,10 +421,10 @@ end
nodes.setprop=nodes.setproperty
nodes.getprop=nodes.getproperty
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “basics-nod”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “basics-nod”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-ini” 10cb9a563a98e06ff79c35a8751e13dc] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-ini” 10cb9a563a98e06ff79c35a8751e13dc] ---
if not modules then modules={} end modules ['font-ini']={
version=1.001,
@@ -443,10 +447,10 @@ fonts.definers={ methods={} }
fonts.loggers={ register=function() end }
fontloader.totable=fontloader.to_table
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-ini”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-ini”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-con” a8eafab28257eac082b1a8d184bb93f1] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-con” 7575a7b4e6d04816072945e27d7d0b33] ---
if not modules then modules={} end modules ['font-con']={
version=1.001,
@@ -456,9 +460,10 @@ if not modules then modules={} end modules ['font-con']={
license="see context related readme files"
}
local next,tostring,rawget=next,tostring,rawget
-local format,match,lower,gsub=string.format,string.match,string.lower,string.gsub
+local format,match,lower,gsub,find=string.format,string.match,string.lower,string.gsub,string.find
local sort,insert,concat,sortedkeys,serialize,fastcopy=table.sort,table.insert,table.concat,table.sortedkeys,table.serialize,table.fastcopy
local derivetable=table.derive
+local ioflush=io.flush
local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
local trace_scaling=false trackers.register("fonts.scaling",function(v) trace_scaling=v end)
local report_defining=logs.reporter("fonts","defining")
@@ -476,89 +481,6 @@ constructors.version=1.01
constructors.cache=containers.define("fonts","constructors",constructors.version,false)
constructors.privateoffset=0xF0000
constructors.cacheintex=true
-constructors.keys={
- properties={
- encodingbytes="number",
- embedding="number",
- cidinfo={},
- format="string",
- fontname="string",
- fullname="string",
- filename="filename",
- psname="string",
- name="string",
- virtualized="boolean",
- hasitalics="boolean",
- autoitalicamount="basepoints",
- nostackmath="boolean",
- noglyphnames="boolean",
- mode="string",
- hasmath="boolean",
- mathitalics="boolean",
- textitalics="boolean",
- finalized="boolean",
- },
- parameters={
- mathsize="number",
- scriptpercentage="float",
- scriptscriptpercentage="float",
- units="cardinal",
- designsize="scaledpoints",
- expansion={
- stretch="integerscale",
- shrink="integerscale",
- step="integerscale",
- auto="boolean",
- },
- protrusion={
- auto="boolean",
- },
- slantfactor="float",
- extendfactor="float",
- factor="float",
- hfactor="float",
- vfactor="float",
- size="scaledpoints",
- units="scaledpoints",
- scaledpoints="scaledpoints",
- slantperpoint="scaledpoints",
- spacing={
- width="scaledpoints",
- stretch="scaledpoints",
- shrink="scaledpoints",
- extra="scaledpoints",
- },
- xheight="scaledpoints",
- quad="scaledpoints",
- ascender="scaledpoints",
- descender="scaledpoints",
- synonyms={
- space="spacing.width",
- spacestretch="spacing.stretch",
- spaceshrink="spacing.shrink",
- extraspace="spacing.extra",
- x_height="xheight",
- space_stretch="spacing.stretch",
- space_shrink="spacing.shrink",
- extra_space="spacing.extra",
- em="quad",
- ex="xheight",
- slant="slantperpoint",
- },
- },
- description={
- width="basepoints",
- height="basepoints",
- depth="basepoints",
- boundingbox={},
- },
- character={
- width="scaledpoints",
- height="scaledpoints",
- depth="scaledpoints",
- italic="scaledpoints",
- },
-}
local designsizes=allocate()
constructors.designsizes=designsizes
local loadedfonts=allocate()
@@ -604,7 +526,9 @@ end
local unscaled={
ScriptPercentScaleDown=true,
ScriptScriptPercentScaleDown=true,
- RadicalDegreeBottomRaisePercent=true
+ RadicalDegreeBottomRaisePercent=true,
+ NoLimitSupFactor=true,
+ NoLimitSubFactor=true,
}
function constructors.assignmathparameters(target,original)
local mathparameters=original.mathparameters
@@ -696,6 +620,23 @@ local function mathkerns(v,vdelta)
end
return k
end
+local psfake=0
+local function fixedpsname(psname,fallback)
+ local usedname=psname
+ if psname and psname~="" then
+ if find(psname," ") then
+ usedname=gsub(psname,"[%s]+","-")
+ else
+ end
+ elseif not fallback or fallback=="" then
+ psfake=psfake+1
+ psname="fakename-"..psfake
+ else
+ psname=fallback
+ usedname=gsub(psname,"[^a-zA-Z0-9]+","-")
+ end
+ return usedname,psname~=usedname
+end
function constructors.scale(tfmdata,specification)
local target={}
if tonumber(specification) then
@@ -769,14 +710,12 @@ function constructors.scale(tfmdata,specification)
target.cidinfo=properties.cidinfo
target.format=properties.format
target.cache=constructors.cacheintex and "yes" or "renew"
- local fontname=properties.fontname or tfmdata.fontname
- local fullname=properties.fullname or tfmdata.fullname
- local filename=properties.filename or tfmdata.filename
- local psname=properties.psname or tfmdata.psname
+ local fontname=properties.fontname or tfmdata.fontname
+ local fullname=properties.fullname or tfmdata.fullname
+ local filename=properties.filename or tfmdata.filename
+ local psname=properties.psname or tfmdata.psname
local name=properties.name or tfmdata.name
- if not psname or psname=="" then
- psname=fontname or (fullname and fonts.names.cleanname(fullname))
- end
+ local psname,psfixed=fixedpsname(psname,fontname or fullname or file.nameonly(filename))
target.fontname=fontname
target.fullname=fullname
target.filename=filename
@@ -826,10 +765,14 @@ function constructors.scale(tfmdata,specification)
local haskerns=properties.haskerns or properties.mode=="base"
local hasligatures=properties.hasligatures or properties.mode=="base"
local realdimensions=properties.realdimensions
+ local writingmode=properties.writingmode or "horizontal"
+ local identity=properties.identity or "horizontal"
if changed and not next(changed) then
changed=false
end
target.type=isvirtual and "virtual" or "real"
+ target.writingmode=writingmode=="vertical" and "vertical" or "horizontal"
+ target.identity=identity=="vertical" and "vertical" or "horizontal"
target.postprocessors=tfmdata.postprocessors
local targetslant=(parameters.slant or parameters[1] or 0)*factors.pt
local targetspace=(parameters.space or parameters[2] or 0)*hdelta
@@ -889,8 +832,9 @@ function constructors.scale(tfmdata,specification)
end
end
if trace_defining then
- report_defining("defining tfm, name %a, fullname %a, filename %a, hscale %a, vscale %a, math %a, italics %a",
- name,fullname,filename,hdelta,vdelta,hasmath and "enabled" or "disabled",hasitalics and "enabled" or "disabled")
+ report_defining("defining tfm, name %a, fullname %a, filename %a, %spsname %a, hscale %a, vscale %a, math %a, italics %a",
+ name,fullname,filename,psfixed and "(fixed) " or "",psname,hdelta,vdelta,
+ hasmath and "enabled" or "disabled",hasitalics and "enabled" or "disabled")
end
constructors.beforecopyingcharacters(target,tfmdata)
local sharedkerns={}
@@ -1214,6 +1158,8 @@ function constructors.finalize(tfmdata)
cidinfo=tfmdata.cidinfo or nil,
format=tfmdata.format or "type1",
direction=tfmdata.direction or 0,
+ writingmode=tfmdata.writingmode or "horizontal",
+ identity=tfmdata.identity or "horizontal",
}
end
if not tfmdata.resources then
@@ -1351,134 +1297,232 @@ setmetatableindex(formats,function(t,k)
end
return rawget(t,file.suffix(l))
end)
-local locations={}
-local function setindeed(mode,target,group,name,action,position)
- local t=target[mode]
- if not t then
- report_defining("fatal error in setting feature %a, group %a, mode %a",name,group,mode)
- os.exit()
- elseif position then
- insert(t,position,{ name=name,action=action })
- else
- for i=1,#t do
- local ti=t[i]
- if ti.name==name then
- ti.action=action
- return
+do
+ local function setindeed(mode,source,target,group,name,position)
+ local action=source[mode]
+ if not action then
+ return
+ end
+ local t=target[mode]
+ if not t then
+ report_defining("fatal error in setting feature %a, group %a, mode %a",name,group,mode)
+ os.exit()
+ elseif position then
+ insert(t,position,{ name=name,action=action })
+ else
+ for i=1,#t do
+ local ti=t[i]
+ if ti.name==name then
+ ti.action=action
+ return
+ end
end
+ insert(t,{ name=name,action=action })
end
- insert(t,{ name=name,action=action })
end
-end
-local function set(group,name,target,source)
- target=target[group]
- if not target then
- report_defining("fatal target error in setting feature %a, group %a",name,group)
- os.exit()
+ local function set(group,name,target,source)
+ target=target[group]
+ if not target then
+ report_defining("fatal target error in setting feature %a, group %a",name,group)
+ os.exit()
+ end
+ local source=source[group]
+ if not source then
+ report_defining("fatal source error in setting feature %a, group %a",name,group)
+ os.exit()
+ end
+ local position=source.position
+ setindeed("node",source,target,group,name,position)
+ setindeed("base",source,target,group,name,position)
+ setindeed("plug",source,target,group,name,position)
end
- local source=source[group]
- if not source then
- report_defining("fatal source error in setting feature %a, group %a",name,group)
- os.exit()
+ local function register(where,specification)
+ local name=specification.name
+ if name and name~="" then
+ local default=specification.default
+ local description=specification.description
+ local initializers=specification.initializers
+ local processors=specification.processors
+ local manipulators=specification.manipulators
+ local modechecker=specification.modechecker
+ if default then
+ where.defaults[name]=default
+ end
+ if description and description~="" then
+ where.descriptions[name]=description
+ end
+ if initializers then
+ set('initializers',name,where,specification)
+ end
+ if processors then
+ set('processors',name,where,specification)
+ end
+ if manipulators then
+ set('manipulators',name,where,specification)
+ end
+ if modechecker then
+ where.modechecker=modechecker
+ end
+ end
end
- local node=source.node
- local base=source.base
- local position=source.position
- if node then
- setindeed("node",target,group,name,node,position)
+ constructors.registerfeature=register
+ function constructors.getfeatureaction(what,where,mode,name)
+ what=handlers[what].features
+ if what then
+ where=what[where]
+ if where then
+ mode=where[mode]
+ if mode then
+ for i=1,#mode do
+ local m=mode[i]
+ if m.name==name then
+ return m.action
+ end
+ end
+ end
+ end
+ end
end
- if base then
- setindeed("base",target,group,name,base,position)
+ local newfeatures={}
+ constructors.newfeatures=newfeatures
+ constructors.features=newfeatures
+ local function setnewfeatures(what)
+ local handler=handlers[what]
+ local features=handler.features
+ if not features then
+ local tables=handler.tables
+ local statistics=handler.statistics
+ features=allocate {
+ defaults={},
+ descriptions=tables and tables.features or {},
+ used=statistics and statistics.usedfeatures or {},
+ initializers={ base={},node={},plug={} },
+ processors={ base={},node={},plug={} },
+ manipulators={ base={},node={},plug={} },
+ }
+ features.register=function(specification) return register(features,specification) end
+ handler.features=features
+ end
+ return features
end
+ setmetatable(newfeatures,{
+ __call=function(t,k) local v=t[k] return v end,
+ __index=function(t,k) local v=setnewfeatures(k) t[k]=v return v end,
+ })
end
-local function register(where,specification)
- local name=specification.name
- if name and name~="" then
- local default=specification.default
- local description=specification.description
- local initializers=specification.initializers
- local processors=specification.processors
- local manipulators=specification.manipulators
- local modechecker=specification.modechecker
- if default then
- where.defaults[name]=default
- end
- if description and description~="" then
- where.descriptions[name]=description
- end
- if initializers then
- set('initializers',name,where,specification)
- end
- if processors then
- set('processors',name,where,specification)
+do
+ local newhandler={}
+ constructors.handlers=newhandler
+ constructors.newhandler=newhandler
+ local function setnewhandler(what)
+ local handler=handlers[what]
+ if not handler then
+ handler={}
+ handlers[what]=handler
+ end
+ return handler
+ end
+ setmetatable(newhandler,{
+ __call=function(t,k) local v=t[k] return v end,
+ __index=function(t,k) local v=setnewhandler(k) t[k]=v return v end,
+ })
+end
+do
+ local newenhancer={}
+ constructors.enhancers=newenhancer
+ constructors.newenhancer=newenhancer
+ local function setnewenhancer(format)
+ local handler=handlers[format]
+ local enhancers=handler.enhancers
+ if not enhancers then
+ local actions=allocate()
+ local before=allocate()
+ local after=allocate()
+ local order=allocate()
+ local patches={ before=before,after=after }
+ local trace=false
+ local report=logs.reporter("fonts",format.." enhancing")
+ trackers.register(format..".loading",function(v) trace=v end)
+ local function enhance(name,data,filename,raw)
+ local enhancer=actions[name]
+ if enhancer then
+ if trace then
+ report("apply enhancement %a to file %a",name,filename)
+ ioflush()
+ end
+ enhancer(data,filename,raw)
+ else
+ end
+ end
+ local function apply(data,filename,raw)
+ local basename=file.basename(lower(filename))
+ if trace then
+ report("%s enhancing file %a","start",filename)
+ end
+ ioflush()
+ for e=1,#order do
+ local enhancer=order[e]
+ local b=before[enhancer]
+ if b then
+ for pattern,action in next,b do
+ if find(basename,pattern) then
+ action(data,filename,raw)
+ end
+ end
+ end
+ enhance(enhancer,data,filename,raw)
+ local a=after[enhancer]
+ if a then
+ for pattern,action in next,a do
+ if find(basename,pattern) then
+ action(data,filename,raw)
+ end
+ end
+ end
+ ioflush()
+ end
+ if trace then
+ report("%s enhancing file %a","stop",filename)
+ end
+ ioflush()
+ end
+ local function register(what,action)
+ if action then
+ if actions[what] then
+ else
+ order[#order+1]=what
+ end
+ actions[what]=action
+ else
+ report("bad enhancer %a",what)
+ end
+ end
+ local function patch(what,where,pattern,action)
+ local pw=patches[what]
+ if pw then
+ local ww=pw[where]
+ if ww then
+ ww[pattern]=action
+ else
+ pw[where]={ [pattern]=action}
+ end
+ end
+ end
+ enhancers={
+ register=register,
+ apply=apply,
+ patch=patch,
+ patches={ register=patch },
+ }
+ handler.enhancers=enhancers
end
- if manipulators then
- set('manipulators',name,where,specification)
- end
- if modechecker then
- where.modechecker=modechecker
- end
- end
-end
-constructors.registerfeature=register
-function constructors.getfeatureaction(what,where,mode,name)
- what=handlers[what].features
- if what then
- where=what[where]
- if where then
- mode=where[mode]
- if mode then
- for i=1,#mode do
- local m=mode[i]
- if m.name==name then
- return m.action
- end
- end
- end
- end
- end
-end
-local newhandler={}
-constructors.handlers=newhandler
-constructors.newhandler=newhandler
-local function setnewhandler(what)
- local handler=handlers[what]
- if not handler then
- handler={}
- handlers[what]=handler
- end
- return handler
-end
-setmetatable(newhandler,{
- __call=function(t,k) local v=t[k] return v end,
- __index=function(t,k) local v=setnewhandler(k) t[k]=v return v end,
-})
-local newfeatures={}
-constructors.newfeatures=newfeatures
-constructors.features=newfeatures
-local function setnewfeatures(what)
- local handler=handlers[what]
- local features=handler.features
- if not features then
- local tables=handler.tables
- local statistics=handler.statistics
- features=allocate {
- defaults={},
- descriptions=tables and tables.features or {},
- used=statistics and statistics.usedfeatures or {},
- initializers={ base={},node={} },
- processors={ base={},node={} },
- manipulators={ base={},node={} },
- }
- features.register=function(specification) return register(features,specification) end
- handler.features=features
+ return enhancers
end
- return features
+ setmetatable(newenhancer,{
+ __call=function(t,k) local v=t[k] return v end,
+ __index=function(t,k) local v=setnewenhancer(k) t[k]=v return v end,
+ })
end
-setmetatable(newfeatures,{
- __call=function(t,k) local v=t[k] return v end,
- __index=function(t,k) local v=setnewfeatures(k) t[k]=v return v end,
-})
function constructors.checkedfeatures(what,features)
local defaults=handlers[what].features.defaults
if features and next(features) then
@@ -1616,10 +1660,10 @@ function constructors.addcoreunicodes(unicodes)
return unicodes
end
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-con”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-con”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “fonts-enc” b224fe179312d924ffaf8334cf5ef15b] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “fonts-enc” a7ace7c1969cd64a5ca9888838f3edb6] ---
if not modules then modules={} end modules ['luatex-font-enc']={
version=1.001,
@@ -1633,24 +1677,66 @@ if context then
os.exit()
end
local fonts=fonts
-fonts.encodings={}
-fonts.encodings.agl={}
-fonts.encodings.known={}
-setmetatable(fonts.encodings.agl,{ __index=function(t,k)
+local encodings={}
+fonts.encodings=encodings
+encodings.agl={}
+encodings.known={}
+setmetatable(encodings.agl,{ __index=function(t,k)
if k=="unicodes" then
texio.write(" <loading (extended) adobe glyph list>")
local unicodes=dofile(resolvers.findfile("font-age.lua"))
- fonts.encodings.agl={ unicodes=unicodes }
+ encodings.agl={ unicodes=unicodes }
return unicodes
else
return nil
end
end })
+encodings.cache=containers.define("fonts","enc",encodings.version,true)
+function encodings.load(filename)
+ local name=file.removesuffix(filename)
+ local data=containers.read(encodings.cache,name)
+ if data then
+ return data
+ end
+ local vector,tag,hash,unicodes={},"",{},{}
+ local foundname=resolvers.findfile(filename,'enc')
+ if foundname and foundname~="" then
+ local ok,encoding,size=resolvers.loadbinfile(foundname)
+ if ok and encoding then
+ encoding=string.gsub(encoding,"%%(.-)\n","")
+ local unicoding=encodings.agl.unicodes
+ local tag,vec=string.match(encoding,"/(%w+)%s*%[(.*)%]%s*def")
+ local i=0
+ for ch in string.gmatch(vec,"/([%a%d%.]+)") do
+ if ch~=".notdef" then
+ vector[i]=ch
+ if not hash[ch] then
+ hash[ch]=i
+ else
+ end
+ local u=unicoding[ch]
+ if u then
+ unicodes[u]=i
+ end
+ end
+ i=i+1
+ end
+ end
+ end
+ local data={
+ name=name,
+ tag=tag,
+ vector=vector,
+ hash=hash,
+ unicodes=unicodes
+ }
+ return containers.write(encodings.cache,name,data)
+end
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “fonts-enc”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “fonts-enc”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-cid” 52421d1fdaa07ec4b1d936c6ff5079be] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-cid” 52421d1fdaa07ec4b1d936c6ff5079be] ---
if not modules then modules={} end modules ['font-cid']={
version=1.001,
@@ -1801,10 +1887,10 @@ function cid.getmap(specification)
return found
end
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-cid”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-cid”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-map” 692066163d78ed09e7659eae72587b9a] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-map” 8708bde7467785c4d3b7afdaf2f9333a] ---
if not modules then modules={} end modules ['font-map']={
version=1.001,
@@ -1818,8 +1904,9 @@ local match,format,find,concat,gsub,lower=string.match,string.format,string.find
local P,R,S,C,Ct,Cc,lpegmatch=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.match
local floor=math.floor
local formatters=string.formatters
+local sortedhash,sortedkeys=table.sortedhash,table.sortedkeys
local trace_loading=false trackers.register("fonts.loading",function(v) trace_loading=v end)
-local trace_mapping=false trackers.register("fonts.mapping",function(v) trace_unimapping=v end)
+local trace_mapping=false trackers.register("fonts.mapping",function(v) trace_mapping=v end)
local report_fonts=logs.reporter("fonts","loading")
local force_ligatures=false directives.register("fonts.mapping.forceligatures",function(v) force_ligatures=v end)
local fonts=fonts or {}
@@ -1909,36 +1996,44 @@ mappings.fromunicode16=fromunicode16
local ligseparator=P("_")
local varseparator=P(".")
local namesplitter=Ct(C((1-ligseparator-varseparator)^1)*(ligseparator*C((1-ligseparator-varseparator)^1))^0)
-local overloads=allocate {
- IJ={ name="I_J",unicode={ 0x49,0x4A },mess=0x0132 },
- ij={ name="i_j",unicode={ 0x69,0x6A },mess=0x0133 },
- ff={ name="f_f",unicode={ 0x66,0x66 },mess=0xFB00 },
- fi={ name="f_i",unicode={ 0x66,0x69 },mess=0xFB01 },
- fl={ name="f_l",unicode={ 0x66,0x6C },mess=0xFB02 },
- ffi={ name="f_f_i",unicode={ 0x66,0x66,0x69 },mess=0xFB03 },
- ffl={ name="f_f_l",unicode={ 0x66,0x66,0x6C },mess=0xFB04 },
- fj={ name="f_j",unicode={ 0x66,0x6A } },
- fk={ name="f_k",unicode={ 0x66,0x6B } },
-}
-for k,v in next,overloads do
- local name=v.name
- local mess=v.mess
- if name then
- overloads[name]=v
- end
- if mess then
- overloads[mess]=v
+do
+ local overloads=allocate {
+ IJ={ name="I_J",unicode={ 0x49,0x4A },mess=0x0132 },
+ ij={ name="i_j",unicode={ 0x69,0x6A },mess=0x0133 },
+ ff={ name="f_f",unicode={ 0x66,0x66 },mess=0xFB00 },
+ fi={ name="f_i",unicode={ 0x66,0x69 },mess=0xFB01 },
+ fl={ name="f_l",unicode={ 0x66,0x6C },mess=0xFB02 },
+ ffi={ name="f_f_i",unicode={ 0x66,0x66,0x69 },mess=0xFB03 },
+ ffl={ name="f_f_l",unicode={ 0x66,0x66,0x6C },mess=0xFB04 },
+ fj={ name="f_j",unicode={ 0x66,0x6A } },
+ fk={ name="f_k",unicode={ 0x66,0x6B } },
+ }
+ local o={}
+ for k,v in next,overloads do
+ local name=v.name
+ local mess=v.mess
+ if name then
+ o[name]=v
+ end
+ if mess then
+ o[mess]=v
+ end
+ o[k]=v
end
+ mappings.overloads=o
end
-mappings.overloads=overloads
function mappings.addtounicode(data,filename,checklookups)
local resources=data.resources
local unicodes=resources.unicodes
if not unicodes then
+ if trace_mapping then
+ report_fonts("no unicode list, quitting tounicode for %a",filename)
+ end
return
end
local properties=data.properties
local descriptions=data.descriptions
+ local overloads=mappings.overloads
unicodes['space']=unicodes['space'] or 32
unicodes['hyphen']=unicodes['hyphen'] or 45
unicodes['zwj']=unicodes['zwj'] or 0x200D
@@ -1961,10 +2056,13 @@ function mappings.addtounicode(data,filename,checklookups)
end
local ns=0
local nl=0
- for du,glyph in next,descriptions do
+ local dlist=sortedkeys(descriptions)
+ for i=1,#dlist do
+ local du=dlist[i]
+ local glyph=descriptions[du]
local name=glyph.name
if name then
- local overload=overloads[name]
+ local overload=overloads[name] or overloads[du]
if overload then
glyph.unicode=overload.unicode
else
@@ -2083,6 +2181,11 @@ function mappings.addtounicode(data,filename,checklookups)
end
end
end
+ else
+ local overload=overloads[du]
+ if overload then
+ glyph.unicode=overload.unicode
+ end
end
end
if type(checklookups)=="function" then
@@ -2090,7 +2193,9 @@ function mappings.addtounicode(data,filename,checklookups)
end
local collected=false
local unicoded=0
- for unicode,glyph in next,descriptions do
+ for i=1,#dlist do
+ local du=dlist[i]
+ local glyph=descriptions[du]
if glyph.class=="ligature" and (force_ligatures or not glyph.unicode) then
if not collected then
collected=fonts.handlers.otf.readers.getcomponents(data)
@@ -2098,7 +2203,7 @@ function mappings.addtounicode(data,filename,checklookups)
break
end
end
- local u=collected[unicode]
+ local u=collected[du]
if u then
local n=#u
for i=1,n do
@@ -2122,9 +2227,11 @@ function mappings.addtounicode(data,filename,checklookups)
report_fonts("%n ligature tounicode mappings deduced from gsub ligature features",unicoded)
end
if trace_mapping then
- for unic,glyph in table.sortedhash(descriptions) do
- local name=glyph.name
- local index=glyph.index
+ for i=1,#dlist do
+ local du=dlist[i]
+ local glyph=descriptions[du]
+ local name=glyph.name or "-"
+ local index=glyph.index or 0
local unicode=glyph.unicode
if unicode then
if type(unicode)=="table" then
@@ -2132,12 +2239,12 @@ function mappings.addtounicode(data,filename,checklookups)
for i=1,#unicode do
unicodes[i]=formatters("%U",unicode[i])
end
- report_fonts("internal slot %U, name %a, unicode %U, tounicode % t",index,name,unic,unicodes)
+ report_fonts("internal slot %U, name %a, unicode %U, tounicode % t",index,name,du,unicodes)
else
- report_fonts("internal slot %U, name %a, unicode %U, tounicode %U",index,name,unic,unicode)
+ report_fonts("internal slot %U, name %a, unicode %U, tounicode %U",index,name,du,unicode)
end
else
- report_fonts("internal slot %U, name %a, unicode %U",index,name,unic)
+ report_fonts("internal slot %U, name %a, unicode %U",index,name,du)
end
end
end
@@ -2146,247 +2253,10 @@ function mappings.addtounicode(data,filename,checklookups)
end
end
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-map”] ---
-
-
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “fonts-syn” 6753dfb9a28aad35266284bb00072dca] ---
-
-if not modules then modules={} end modules ['luatex-fonts-syn']={
- version=1.001,
- comment="companion to luatex-*.tex",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-if context then
- texio.write_nl("fatal error: this module is not for context")
- os.exit()
-end
-local fonts=fonts
-fonts.names=fonts.names or {}
-fonts.names.version=1.001
-fonts.names.basename="luatex-fonts-names"
-fonts.names.cache=containers.define("fonts","data",fonts.names.version,true)
-local data=nil
-local loaded=false
-local fileformats={ "lua","tex","other text files" }
-function fonts.names.reportmissingbase()
- texio.write("<missing font database, run: mtxrun --script fonts --reload --simple>")
- fonts.names.reportmissingbase=nil
-end
-function fonts.names.reportmissingname()
- texio.write("<unknown font in database, run: mtxrun --script fonts --reload --simple>")
- fonts.names.reportmissingname=nil
-end
-function fonts.names.resolve(name,sub)
- if not loaded then
- local basename=fonts.names.basename
- if basename and basename~="" then
- data=containers.read(fonts.names.cache,basename)
- if not data then
- basename=file.addsuffix(basename,"lua")
- for i=1,#fileformats do
- local format=fileformats[i]
- local foundname=resolvers.findfile(basename,format) or ""
- if foundname~="" then
- data=dofile(foundname)
- texio.write("<font database loaded: ",foundname,">")
- break
- end
- end
- end
- end
- loaded=true
- end
- if type(data)=="table" and data.version==fonts.names.version then
- local condensed=string.gsub(string.lower(name),"[^%a%d]","")
- local found=data.mappings and data.mappings[condensed]
- if found then
- local fontname,filename,subfont=found[1],found[2],found[3]
- if subfont then
- return filename,fontname
- else
- return filename,false
- end
- elseif fonts.names.reportmissingname then
- fonts.names.reportmissingname()
- return name,false
- end
- elseif fonts.names.reportmissingbase then
- fonts.names.reportmissingbase()
- end
-end
-fonts.names.resolvespec=fonts.names.resolve
-function fonts.names.getfilename(askedname,suffix)
- return ""
-end
-function fonts.names.ignoredfile(filename)
- return false
-end
-
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “fonts-syn”] ---
-
-
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-tfm” 5f60184464be0655620709c332065706] ---
-
-if not modules then modules={} end modules ['font-tfm']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local next=next
-local match=string.match
-local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
-local trace_features=false trackers.register("tfm.features",function(v) trace_features=v end)
-local report_defining=logs.reporter("fonts","defining")
-local report_tfm=logs.reporter("fonts","tfm loading")
-local findbinfile=resolvers.findbinfile
-local fonts=fonts
-local handlers=fonts.handlers
-local readers=fonts.readers
-local constructors=fonts.constructors
-local encodings=fonts.encodings
-local tfm=constructors.handlers.tfm
-tfm.version=1.000
-tfm.maxnestingdepth=5
-tfm.maxnestingsize=65536*1024
-local tfmfeatures=constructors.features.tfm
-constructors.resolvevirtualtoo=false
-fonts.formats.tfm="type1"
-fonts.formats.ofm="type1"
-function tfm.setfeatures(tfmdata,features)
- local okay=constructors.initializefeatures("tfm",tfmdata,features,trace_features,report_tfm)
- if okay then
- return constructors.collectprocessors("tfm",tfmdata,features,trace_features,report_tfm)
- else
- return {}
- end
-end
-local depth={}
-local function read_from_tfm(specification)
- local filename=specification.filename
- local size=specification.size
- depth[filename]=(depth[filename] or 0)+1
- if trace_defining then
- report_defining("loading tfm file %a at size %s",filename,size)
- end
- local tfmdata=font.read_tfm(filename,size)
- if tfmdata then
- local features=specification.features and specification.features.normal or {}
- local resources=tfmdata.resources or {}
- local properties=tfmdata.properties or {}
- local parameters=tfmdata.parameters or {}
- local shared=tfmdata.shared or {}
- properties.name=tfmdata.name
- properties.fontname=tfmdata.fontname
- properties.psname=tfmdata.psname
- properties.filename=specification.filename
- properties.format=fonts.formats.tfm
- parameters.size=size
- tfmdata.properties=properties
- tfmdata.resources=resources
- tfmdata.parameters=parameters
- tfmdata.shared=shared
- shared.rawdata={}
- shared.features=features
- shared.processes=next(features) and tfm.setfeatures(tfmdata,features) or nil
- parameters.slant=parameters.slant or parameters[1] or 0
- parameters.space=parameters.space or parameters[2] or 0
- parameters.space_stretch=parameters.space_stretch or parameters[3] or 0
- parameters.space_shrink=parameters.space_shrink or parameters[4] or 0
- parameters.x_height=parameters.x_height or parameters[5] or 0
- parameters.quad=parameters.quad or parameters[6] or 0
- parameters.extra_space=parameters.extra_space or parameters[7] or 0
- constructors.enhanceparameters(parameters)
- if constructors.resolvevirtualtoo then
- fonts.loggers.register(tfmdata,file.suffix(filename),specification)
- local vfname=findbinfile(specification.name,'ovf')
- if vfname and vfname~="" then
- local vfdata=font.read_vf(vfname,size)
- if vfdata then
- local chars=tfmdata.characters
- for k,v in next,vfdata.characters do
- chars[k].commands=v.commands
- end
- properties.virtualized=true
- tfmdata.fonts=vfdata.fonts
- tfmdata.type="virtual"
- local fontlist=vfdata.fonts
- local name=file.nameonly(filename)
- for i=1,#fontlist do
- local n=fontlist[i].name
- local s=fontlist[i].size
- local d=depth[filename]
- s=constructors.scaled(s,vfdata.designsize)
- if d>tfm.maxnestingdepth then
- report_defining("too deeply nested virtual font %a with size %a, max nesting depth %s",n,s,tfm.maxnestingdepth)
- fontlist[i]={ id=0 }
- elseif (d>1) and (s>tfm.maxnestingsize) then
- report_defining("virtual font %a exceeds size %s",n,s)
- fontlist[i]={ id=0 }
- else
- local t,id=fonts.constructors.readanddefine(n,s)
- fontlist[i]={ id=id }
- end
- end
- end
- end
- end
- local allfeatures=tfmdata.shared.features or specification.features.normal
- constructors.applymanipulators("tfm",tfmdata,allfeatures.normal,trace_features,report_tfm)
- if not features.encoding then
- local encoding,filename=match(properties.filename,"^(.-)%-(.*)$")
- if filename and encoding and encodings.known and encodings.known[encoding] then
- features.encoding=encoding
- end
- end
- properties.haskerns=true
- properties.hasligatures=true
- resources.unicodes={}
- resources.lookuptags={}
- depth[filename]=depth[filename]-1
- return tfmdata
- else
- depth[filename]=depth[filename]-1
- end
-end
-local function check_tfm(specification,fullname)
- local foundname=findbinfile(fullname,'tfm') or ""
- if foundname=="" then
- foundname=findbinfile(fullname,'ofm') or ""
- end
- if foundname=="" then
- foundname=fonts.names.getfilename(fullname,"tfm") or ""
- end
- if foundname~="" then
- specification.filename=foundname
- specification.format="ofm"
- return read_from_tfm(specification)
- elseif trace_defining then
- report_defining("loading tfm with name %a fails",specification.name)
- end
-end
-readers.check_tfm=check_tfm
-function readers.tfm(specification)
- local fullname=specification.filename or ""
- if fullname=="" then
- local forced=specification.forced or ""
- if forced~="" then
- fullname=specification.name.."."..forced
- else
- fullname=specification.name
- end
- end
- return check_tfm(specification,fullname)
-end
-readers.ofm=readers.tfm
-
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-tfm”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-map”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-oti” 7e7e749e6cb1c802a06397e8bed33b98] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-oti” 8f48c06a1d632febd7231ad5dfadfc53] ---
if not modules then modules={} end modules ['font-oti']={
version=1.001,
@@ -2414,6 +2284,7 @@ local function setmode(tfmdata,value)
tfmdata.properties.mode=lower(value)
end
end
+otf.modeinitializer=setmode
local function setlanguage(tfmdata,value)
if value then
local cleanvalue=lower(value)
@@ -2448,6 +2319,7 @@ registerotffeature {
initializers={
base=setmode,
node=setmode,
+ plug=setmode,
}
}
registerotffeature {
@@ -2456,6 +2328,7 @@ registerotffeature {
initializers={
base=setlanguage,
node=setlanguage,
+ plug=setlanguage,
}
}
registerotffeature {
@@ -2464,6 +2337,7 @@ registerotffeature {
initializers={
base=setscript,
node=setscript,
+ plug=setscript,
}
}
otftables.featuretypes=allocate {
@@ -2525,10 +2399,10 @@ function otffeatures.checkeddefaultlanguage(featuretype,autolanguage,languages)
end
end
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-oti”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-oti”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-otr” aaf9545b2a5d425489ebbcd3e398c1a0] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-otr” 2bd0085b78027f261218d63034f43474] ---
if not modules then modules={} end modules ['font-otr']={
version=1.001,
@@ -2560,7 +2434,9 @@ handlers.otf=otf
local readers=otf.readers or {}
otf.readers=readers
local streamreader=utilities.files
+local streamwriter=utilities.files
readers.streamreader=streamreader
+readers.streamwriter=streamwriter
local openfile=streamreader.open
local closefile=streamreader.close
local setposition=streamreader.setposition
@@ -3032,11 +2908,43 @@ readers.hhea=function(f,fontdata,specification)
reserved_3=readshort(f),
reserved_4=readshort(f),
metricdataformat=readshort(f),
- nofhmetrics=readushort(f),
+ nofmetrics=readushort(f),
}
else
fontdata.horizontalheader={
- nofhmetrics=0,
+ nofmetrics=0,
+ }
+ end
+ end
+end
+readers.vhea=function(f,fontdata,specification)
+ if specification.details then
+ local datatable=fontdata.tables.vhea
+ if datatable then
+ setposition(f,datatable.offset)
+ local version=readfixed(f)
+ fontdata.verticalheader={
+ version=version,
+ ascender=readfword(f),
+ descender=readfword(f),
+ linegap=readfword(f),
+ maxadvanceheight=readufword(f),
+ mintopsidebearing=readfword(f),
+ minbottomsidebearing=readfword(f),
+ maxextent=readfword(f),
+ caretsloperise=readshort(f),
+ caretsloperun=readshort(f),
+ caretoffset=readshort(f),
+ reserved_1=readshort(f),
+ reserved_2=readshort(f),
+ reserved_3=readshort(f),
+ reserved_4=readshort(f),
+ metricdataformat=readshort(f),
+ nofmetrics=readushort(f),
+ }
+ else
+ fontdata.verticalheader={
+ nofmetrics=0,
}
end
end
@@ -3087,7 +2995,8 @@ readers.hmtx=function(f,fontdata,specification)
local datatable=fontdata.tables.hmtx
if datatable then
setposition(f,datatable.offset)
- local nofmetrics=fontdata.horizontalheader.nofhmetrics
+ local horizontalheader=fontdata.horizontalheader
+ local nofmetrics=horizontalheader.nofmetrics
local glyphs=fontdata.glyphs
local nofglyphs=fontdata.nofglyphs
local width=0
@@ -3109,6 +3018,43 @@ readers.hmtx=function(f,fontdata,specification)
end
end
end
+readers.vmtx=function(f,fontdata,specification)
+ if specification.glyphs then
+ local datatable=fontdata.tables.vmtx
+ if datatable then
+ setposition(f,datatable.offset)
+ local verticalheader=fontdata.verticalheader
+ local nofmetrics=verticalheader.nofmetrics
+ local glyphs=fontdata.glyphs
+ local nofglyphs=fontdata.nofglyphs
+ local vheight=0
+ local vdefault=verticalheader.ascender+verticalheader.descender
+ local topsidebearing=0
+ for i=0,nofmetrics-1 do
+ local glyph=glyphs[i]
+ vheight=readshort(f)
+ topsidebearing=readshort(f)
+ if vheight~=0 and vheight~=vdefault then
+ glyph.vheight=vheight
+ end
+ end
+ for i=nofmetrics,nofglyphs-1 do
+ local glyph=glyphs[i]
+ if vheight~=0 and vheight~=vdefault then
+ glyph.vheight=vheight
+ end
+ end
+ end
+ end
+end
+readers.vorg=function(f,fontdata,specification)
+ if specification.glyphs then
+ local datatable=fontdata.tables.vorg
+ if datatable then
+ report("todo: %s","vorg")
+ end
+ end
+end
readers.post=function(f,fontdata,specification)
local datatable=fontdata.tables.post
if datatable then
@@ -3666,113 +3612,7 @@ function readers.math(f,fontdata,specification)
reportskippedtable("math")
end
end
-local function packoutlines(data,makesequence)
- local subfonts=data.subfonts
- if subfonts then
- for i=1,#subfonts do
- packoutlines(subfonts[i],makesequence)
- end
- return
- end
- local common=data.segments
- if common then
- return
- end
- local glyphs=data.glyphs
- if not glyphs then
- return
- end
- if makesequence then
- for index=1,#glyphs do
- local glyph=glyphs[index]
- local segments=glyph.segments
- if segments then
- local sequence={}
- local nofsequence=0
- for i=1,#segments do
- local segment=segments[i]
- local nofsegment=#segment
- nofsequence=nofsequence+1
- sequence[nofsequence]=segment[nofsegment]
- for i=1,nofsegment-1 do
- nofsequence=nofsequence+1
- sequence[nofsequence]=segment[i]
- end
- end
- glyph.sequence=sequence
- glyph.segments=nil
- end
- end
- else
- local hash={}
- local common={}
- local reverse={}
- local last=0
- for index=1,#glyphs do
- local segments=glyphs[index].segments
- if segments then
- for i=1,#segments do
- local h=concat(segments[i]," ")
- hash[h]=(hash[h] or 0)+1
- end
- end
- end
- for index=1,#glyphs do
- local segments=glyphs[index].segments
- if segments then
- for i=1,#segments do
- local segment=segments[i]
- local h=concat(segment," ")
- if hash[h]>1 then
- local idx=reverse[h]
- if not idx then
- last=last+1
- reverse[h]=last
- common[last]=segment
- idx=last
- end
- segments[i]=idx
- end
- end
- end
- end
- if last>0 then
- data.segments=common
- end
- end
-end
-local function unpackoutlines(data)
- local subfonts=data.subfonts
- if subfonts then
- for i=1,#subfonts do
- unpackoutlines(subfonts[i])
- end
- return
- end
- local common=data.segments
- if not common then
- return
- end
- local glyphs=data.glyphs
- if not glyphs then
- return
- end
- for index=1,#glyphs do
- local segments=glyphs[index].segments
- if segments then
- for i=1,#segments do
- local c=common[segments[i]]
- if c then
- segments[i]=c
- end
- end
- end
- end
- data.segments=nil
-end
-otf.packoutlines=packoutlines
-otf.unpackoutlines=unpackoutlines
-local function getinfo(maindata,sub,platformnames,rawfamilynames)
+local function getinfo(maindata,sub,platformnames,rawfamilynames,metricstoo)
local fontdata=sub and maindata.subfonts and maindata.subfonts[sub] or maindata
local names=fontdata.names
local info=nil
@@ -3782,8 +3622,8 @@ local function getinfo(maindata,sub,platformnames,rawfamilynames)
local fontheader=fontdata.fontheader or {}
local cffinfo=fontdata.cffinfo or {}
local filename=fontdata.filename
- local weight=getname(fontdata,"weight") or cffinfo.weight or metrics.weight
- local width=getname(fontdata,"width") or cffinfo.width or metrics.width
+ local weight=getname(fontdata,"weight") or (cffinfo and cffinfo.weight) or (metrics and metrics.weight)
+ local width=getname(fontdata,"width") or (cffinfo and cffinfo.width ) or (metrics and metrics.width )
local fontname=getname(fontdata,"postscriptname")
local fullname=getname(fontdata,"fullname")
local family=getname(fontdata,"family")
@@ -3825,6 +3665,27 @@ local function getinfo(maindata,sub,platformnames,rawfamilynames)
descender=metrics.typodescender,
platformnames=platformnames and fontdata.platformnames or nil,
}
+ if metricstoo then
+ local keys={
+ "version",
+ "ascender","descender","linegap",
+ "maxadvancewidth","maxadvanceheight","maxextent",
+ "minbottomsidebearing","mintopsidebearing",
+ }
+ local h=fontdata.horizontalheader or {}
+ local v=fontdata.verticalheader or {}
+ if h then
+ local th={}
+ local tv={}
+ for i=1,#keys do
+ local key=keys[i]
+ th[key]=h[key] or 0
+ tv[key]=v[key] or 0
+ end
+ info.horizontalmetrics=th
+ info.verticalmetrics=tv
+ end
+ end
elseif n then
info={
filename=fontdata.filename,
@@ -3908,7 +3769,10 @@ local function readdata(f,offset,specification)
readers["head"](f,fontdata,specification)
readers["maxp"](f,fontdata,specification)
readers["hhea"](f,fontdata,specification)
+ readers["vhea"](f,fontdata,specification)
readers["hmtx"](f,fontdata,specification)
+ readers["vmtx"](f,fontdata,specification)
+ readers["vorg"](f,fontdata,specification)
readers["post"](f,fontdata,specification)
readers["cff" ](f,fontdata,specification)
readers["cmap"](f,fontdata,specification)
@@ -4039,6 +3903,13 @@ function readers.loadshapes(filename,n)
shapes=true,
subfont=n,
}
+ if fontdata then
+ for k,v in next,fontdata.glyphs do
+ v.class=nil
+ v.index=nil
+ v.math=nil
+ end
+ end
return fontdata and {
filename=filename,
format=fontdata.format,
@@ -4069,7 +3940,7 @@ function readers.loadfont(filename,n)
descriptions=fontdata.descriptions,
format=fontdata.format,
goodies={},
- metadata=getinfo(fontdata,n),
+ metadata=getinfo(fontdata,n,false,false,true),
properties={
hasitalics=fontdata.hasitalics or false,
maxcolorclass=fontdata.maxcolorclass,
@@ -4168,61 +4039,11 @@ function readers.extend(fontdata)
end
end
end
-if fonts.hashes then
- local identifiers=fonts.hashes.identifiers
- local loadshapes=readers.loadshapes
- readers.version=0.006
- readers.cache=containers.define("fonts","shapes",readers.version,true)
- local function load(filename,sub)
- local base=file.basename(filename)
- local name=file.removesuffix(base)
- local kind=file.suffix(filename)
- local attr=lfs.attributes(filename)
- local size=attr and attr.size or 0
- local time=attr and attr.modification or 0
- local sub=tonumber(sub)
- if size>0 and (kind=="otf" or kind=="ttf" or kind=="tcc") then
- local hash=containers.cleanname(base)
- if sub then
- hash=hash.."-"..sub
- end
- data=containers.read(readers.cache,hash)
- if not data or data.time~=time or data.size~=size then
- data=loadshapes(filename,sub)
- if data then
- data.size=size
- data.format=data.format or (kind=="otf" and "opentype") or "truetype"
- data.time=time
- packoutlines(data)
- containers.write(readers.cache,hash,data)
- data=containers.read(readers.cache,hash)
- end
- end
- unpackoutlines(data)
- else
- data={
- filename=filename,
- size=0,
- time=time,
- format="unknown",
- units=1000,
- glyphs={}
- }
- end
- return data
- end
- fonts.hashes.shapes=table.setmetatableindex(function(t,k)
- local d=identifiers[k]
- local v=load(d.properties.filename,d.subindex)
- t[k]=v
- return v
- end)
-end
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-otr”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-otr”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-cff” 84590de32a9d3bcd1e3fee0bb667e9c2] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-cff” f3fc74e8629f7a2825c34a34550c790d] ---
if not modules then modules={} end modules ['font-cff']={
version=1.001,
@@ -4237,6 +4058,7 @@ local concat,remove=table.concat,table.remove
local floor,abs,round,ceil=math.floor,math.abs,math.round,math.ceil
local P,C,R,S,C,Cs,Ct=lpeg.P,lpeg.C,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Ct
local lpegmatch=lpeg.match
+local formatters=string.formatters
local readers=fonts.handlers.otf.readers
local streamreader=readers.streamreader
local readbytes=streamreader.readbytes
@@ -4637,6 +4459,7 @@ do
local ymax=0
local checked=false
local keepcurve=false
+ local version=2
local function showstate(where)
report("%w%-10s : [%s] n=%i",depth*2,where,concat(stack," ",1,top),top)
end
@@ -5059,9 +4882,91 @@ do
return floor((stems+7)/8)
end
end
- local function unsupported()
+ local function unsupported(t)
+ if trace_charstrings then
+ showstate("unsupported "..t)
+ end
+ top=0
+ end
+ local function unsupportedsub(t)
if trace_charstrings then
- showstate("unsupported")
+ showstate("unsupported sub "..t)
+ end
+ top=0
+ end
+ local function getstem3()
+ if trace_charstrings then
+ showstate("stem3")
+ end
+ top=0
+ end
+ local function divide()
+ if version==1 then
+ local d=stack[top]
+ top=top-1
+ stack[top]=stack[top]/d
+ end
+ end
+ local function closepath()
+ if version==1 then
+ if trace_charstrings then
+ showstate("closepath")
+ end
+ end
+ top=0
+ end
+ local function hsbw()
+ if version==1 then
+ if trace_charstrings then
+ showstate("dotsection")
+ end
+ width=stack[top]
+ end
+ top=0
+ end
+ local function seac()
+ if version==1 then
+ if trace_charstrings then
+ showstate("seac")
+ end
+ end
+ top=0
+ end
+ local function sbw()
+ if version==1 then
+ if trace_charstrings then
+ showstate("sbw")
+ end
+ width=stack[top-1]
+ end
+ top=0
+ end
+ local function callothersubr()
+ if version==1 then
+ if trace_charstrings then
+ showstate("callothersubr (unsupported)")
+ end
+ end
+ top=0
+ end
+ local function pop()
+ if version==1 then
+ if trace_charstrings then
+ showstate("pop (unsupported)")
+ end
+ top=top+1
+ stack[top]=0
+ else
+ top=0
+ end
+ end
+ local function setcurrentpoint()
+ if version==1 then
+ if trace_charstrings then
+ showstate("pop (unsupported)")
+ end
+ x=x+stack[top-1]
+ y=y+stack[top]
end
top=0
end
@@ -5078,7 +4983,7 @@ do
unsupported,
unsupported,
unsupported,
- unsupported,
+ hsbw,
unsupported,
unsupported,
unsupported,
@@ -5099,6 +5004,15 @@ do
hvcurveto,
}
local subactions={
+ [000]=dotsection,
+ [001]=getstem3,
+ [002]=getstem3,
+ [006]=seac,
+ [007]=sbw,
+ [012]=divide,
+ [016]=callothersubr,
+ [017]=pop,
+ [033]=setcurrentpoint,
[034]=hflex,
[035]=flex,
[036]=hflex1,
@@ -5106,23 +5020,29 @@ do
}
local p_bytes=Ct((P(1)/byte)^0)
local function call(scope,list,bias,process)
- local index=stack[top]+bias
- top=top-1
- if trace_charstrings then
- showvalue(scope,index,true)
- end
- local str=list[index]
- if str then
- if type(str)=="string" then
- str=lpegmatch(p_bytes,str)
- list[index]=str
- end
- depth=depth+1
- process(str)
- depth=depth-1
+ depth=depth+1
+ if top==0 then
+ showstate(formatters["unknown %s call"](scope))
+ top=0
else
- report("unknown %s %i",scope,index)
+ local index=stack[top]+bias
+ top=top-1
+ if trace_charstrings then
+ showvalue(scope,index,true)
+ end
+ local tab=list[index]
+ if tab then
+ if type(tab)=="string" then
+ tab=lpegmatch(p_bytes,tab)
+ list[index]=tab
+ end
+ process(tab)
+ else
+ showstate(formatters["unknown %s call %i"](scope,index))
+ top=0
+ end
end
+ depth=depth-1
end
local function process(tab)
local i=1
@@ -5189,7 +5109,7 @@ do
local t=tab[i]
local a=subactions[t]
if a then
- a()
+ a(t)
else
if trace_charstrings then
showvalue("<subaction>",t)
@@ -5200,7 +5120,7 @@ do
else
local a=actions[t]
if a then
- local s=a()
+ local s=a(t)
if s then
i=i+s
end
@@ -5214,25 +5134,38 @@ do
end
end
end
- parsecharstrings=function(data,glyphs,doshapes)
+ local function setbias(globals,locals)
+ if version==1 then
+ return
+ false,
+ false
+ else
+ local g,l=#globals,#locals
+ return
+ ((g<1240 and 107) or (g<33900 and 1131) or 32768)+1,
+ ((l<1240 and 107) or (l<33900 and 1131) or 32768)+1
+ end
+ end
+ parsecharstrings=function(data,glyphs,doshapes,tversion)
local dictionary=data.dictionaries[1]
local charstrings=dictionary.charstrings
local charset=dictionary.charset
+ local private=dictionary.private or { data={} }
keepcurve=doshapes
+ version=tversion
stack={}
glyphs=glyphs or {}
strings=data.strings
- locals=dictionary.subroutines
- globals=data.routines
- globalbias=#globals
- localbias=#locals
- globalbias=((globalbias<1240 and 107) or (globalbias<33900 and 1131) or 32768)+1
- localbias=((localbias<1240 and 107) or (localbias<33900 and 1131) or 32768)+1
- local nominalwidth=dictionary.private.data.nominalwidthx or 0
- local defaultwidth=dictionary.private.data.defaultwidthx or 0
+ globals=data.routines or {}
+ locals=dictionary.subroutines or {}
+ globalbias,localbias=setbias(globals,locals)
+ local nominalwidth=private.data.nominalwidthx or 0
+ local defaultwidth=private.data.defaultwidthx or 0
for i=1,#charstrings do
- local str=charstrings[i]
- local tab=lpegmatch(p_bytes,str)
+ local tab=charstrings[i]
+ if type(tab)=="string" then
+ tab=lpegmatch(p_bytes,tab)
+ end
local index=i-1
x=0
y=0
@@ -5283,19 +5216,19 @@ do
end
return glyphs
end
- parsecharstring=function(data,dictionary,charstring,glyphs,index,doshapes)
+ parsecharstring=function(data,dictionary,tab,glyphs,index,doshapes,tversion)
local private=dictionary.private
keepcurve=doshapes
+ version=tversion
strings=data.strings
locals=dictionary.subroutines or {}
globals=data.routines or {}
- globalbias=#globals
- localbias=#locals
- globalbias=((globalbias<1240 and 107) or (globalbias<33900 and 1131) or 32768)+1
- localbias=((localbias<1240 and 107) or (localbias<33900 and 1131) or 32768)+1
+ globalbias,localbias=setbias(globals,locals)
local nominalwidth=private and private.data.nominalwidthx or 0
local defaultwidth=private and private.data.defaultwidthx or 0
- local tab=lpegmatch(p_bytes,charstring)
+ if type(tab)=="string" then
+ tab=lpegmatch(p_bytes,tab)
+ end
x=0
y=0
width=false
@@ -5319,7 +5252,7 @@ do
else
width=nominalwidth+width
end
-index=index-1
+ index=index-1
local glyph=glyphs[index]
if not glyph then
glyphs[index]={
@@ -5342,7 +5275,6 @@ index=index-1
report("width: %s",tostring(width))
report("boundingbox: % t",boundingbox)
end
- return charstring
end
resetcharstrings=function()
result={}
@@ -5456,7 +5388,7 @@ local function readcidprivates(f,data)
end
parseprivates(data,dictionaries)
end
-local function readnoselect(f,data,glyphs,doshapes)
+local function readnoselect(f,data,glyphs,doshapes,version)
local dictionaries=data.dictionaries
local dictionary=dictionaries[1]
readglobals(f,data)
@@ -5466,10 +5398,11 @@ local function readnoselect(f,data,glyphs,doshapes)
readprivates(f,data)
parseprivates(data,data.dictionaries)
readlocals(f,data,dictionary)
- parsecharstrings(data,glyphs,doshapes)
+ parsecharstrings(data,glyphs,doshapes,version)
resetcharstrings()
end
-local function readfdselect(f,data,glyphs,doshapes)
+readers.parsecharstrings=parsecharstrings
+local function readfdselect(f,data,glyphs,doshapes,version)
local header=data.header
local dictionaries=data.dictionaries
local dictionary=dictionaries[1]
@@ -5527,7 +5460,7 @@ local function readfdselect(f,data,glyphs,doshapes)
readlocals(f,data,dictionaries[i])
end
for i=1,#charstrings do
- parsecharstring(data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes)
+ parsecharstring(data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes,version)
end
resetcharstrings()
end
@@ -5591,10 +5524,10 @@ function readers.cff(f,fontdata,specification)
end
end
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-cff”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-cff”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-ttf” e0893de6d0f3f421ee4386fa90429db8] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-ttf” e0893de6d0f3f421ee4386fa90429db8] ---
if not modules then modules={} end modules ['font-ttf']={
version=1.001,
@@ -6006,10 +5939,10 @@ function readers.glyf(f,fontdata,specification)
end
end
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-ttf”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-ttf”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-dsp” f9dc5739b0d203d3ed9db87269c13647] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-dsp” 7eda319c53a28de9d91de4a0cfba79c3] ---
if not modules then modules={} end modules ['font-dsp']={
version=1.001,
@@ -6023,6 +5956,7 @@ local bittest=bit32.btest
local rshift=bit32.rshift
local concat=table.concat
local lower=string.lower
+local copy=table.copy
local sub=string.sub
local strip=string.strip
local tohash=table.tohash
@@ -6035,6 +5969,7 @@ local report=logs.reporter("otf reader")
local readers=fonts.handlers.otf.readers
local streamreader=readers.streamreader
local setposition=streamreader.setposition
+local getposition=streamreader.getposition
local skipshort=streamreader.skipshort
local readushort=streamreader.readcardinal2
local readulong=streamreader.readcardinal4
@@ -6148,10 +6083,15 @@ local function readcoverage(f,offset,simple)
end
return coverage
end
-local function readclassdef(f,offset)
+local function readclassdef(f,offset,preset)
setposition(f,offset)
local classdefformat=readushort(f)
local classdef={}
+ if type(preset)=="number" then
+ for k=0,preset-1 do
+ classdef[k]=1
+ end
+ end
if classdefformat==1 then
local index=readushort(f)
local nofclassdef=readushort(f)
@@ -6173,6 +6113,13 @@ local function readclassdef(f,offset)
else
report("unknown classdef format %a ",classdefformat)
end
+ if type(preset)=="table" then
+ for k in next,preset do
+ if not classdef[k] then
+ classdef[k]=1
+ end
+ end
+ end
return classdef
end
local function classtocoverage(defs)
@@ -6272,7 +6219,7 @@ local function covered(subset,all)
end
return used
end
-local function readlookuparray(f,noflookups)
+local function readlookuparray(f,noflookups,nofcurrent)
local lookups={}
if noflookups>0 then
local length=0
@@ -6315,7 +6262,7 @@ local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,n
for i=2,nofcurrent do
current[i]={ readushort(f) }
end
- local lookups=readlookuparray(f,noflookups)
+ local lookups=readlookuparray(f,noflookups,nofcurrent)
rules[#rules+1]={
current=current,
lookups=lookups
@@ -6337,7 +6284,7 @@ local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,n
local rules={}
if subclasssets then
coverage=readcoverage(f,tableoffset+coverage)
- currentclassdef=readclassdef(f,tableoffset+currentclassdef)
+ currentclassdef=readclassdef(f,tableoffset+currentclassdef,coverage)
local currentclasses=classtocoverage(currentclassdef,fontdata.glyphs)
for class=1,#subclasssets do
local offset=subclasssets[class]
@@ -6356,7 +6303,7 @@ local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,n
for i=2,nofcurrent do
current[i]=currentclasses[readushort(f)+1]
end
- local lookups=readlookuparray(f,noflookups)
+ local lookups=readlookuparray(f,noflookups,nofcurrent)
rules[#rules+1]={
current=current,
lookups=lookups
@@ -6380,7 +6327,7 @@ local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,n
elseif subtype==3 then
local current=readarray(f)
local noflookups=readushort(f)
- local lookups=readlookuparray(f,noflookups)
+ local lookups=readlookuparray(f,noflookups,#current)
current=readcoveragearray(f,tableoffset,current,true)
return {
format="coverage",
@@ -6435,7 +6382,7 @@ local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nof
end
end
local noflookups=readushort(f)
- local lookups=readlookuparray(f,noflookups)
+ local lookups=readlookuparray(f,noflookups,nofcurrent)
rules[#rules+1]={
before=before,
current=current,
@@ -6461,9 +6408,9 @@ local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nof
local rules={}
if subclasssets then
local coverage=readcoverage(f,tableoffset+coverage)
- local beforeclassdef=readclassdef(f,tableoffset+beforeclassdef)
- local currentclassdef=readclassdef(f,tableoffset+currentclassdef)
- local afterclassdef=readclassdef(f,tableoffset+afterclassdef)
+ local beforeclassdef=readclassdef(f,tableoffset+beforeclassdef,nofglyphs)
+ local currentclassdef=readclassdef(f,tableoffset+currentclassdef,coverage)
+ local afterclassdef=readclassdef(f,tableoffset+afterclassdef,nofglyphs)
local beforeclasses=classtocoverage(beforeclassdef,fontdata.glyphs)
local currentclasses=classtocoverage(currentclassdef,fontdata.glyphs)
local afterclasses=classtocoverage(afterclassdef,fontdata.glyphs)
@@ -6500,7 +6447,7 @@ local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nof
end
end
local noflookups=readushort(f)
- local lookups=readlookuparray(f,noflookups)
+ local lookups=readlookuparray(f,noflookups,nofcurrent)
rules[#rules+1]={
before=before,
current=current,
@@ -6528,7 +6475,7 @@ local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nof
local current=readarray(f)
local after=readarray(f)
local noflookups=readushort(f)
- local lookups=readlookuparray(f,noflookups)
+ local lookups=readlookuparray(f,noflookups,#current)
before=readcoveragearray(f,tableoffset,before,true)
current=readcoveragearray(f,tableoffset,current,true)
after=readcoveragearray(f,tableoffset,after,true)
@@ -6854,8 +6801,8 @@ function gposhandlers.pair(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofgly
local nofclasses2=readushort(f)
local classlist=readpairclasssets(f,nofclasses1,nofclasses2,format1,format2)
coverage=readcoverage(f,tableoffset+coverage)
- classdef1=readclassdef(f,tableoffset+classdef1)
- classdef2=readclassdef(f,tableoffset+classdef2)
+ classdef1=readclassdef(f,tableoffset+classdef1,coverage)
+ classdef2=readclassdef(f,tableoffset+classdef2,nofglyphs)
local usedcoverage={}
for g1,c1 in next,classdef1 do
if coverage[g1] then
@@ -7078,15 +7025,39 @@ function gposhandlers.extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,n
end
do
local plugins={}
- function plugins.size(f,fontdata,tableoffset,parameters)
- if not fontdata.designsize then
- setposition(f,tableoffset+parameters)
- local designsize=readushort(f)
- if designsize>0 then
+ function plugins.size(f,fontdata,tableoffset,feature)
+ if fontdata.designsize then
+ else
+ local function check(offset)
+ setposition(f,offset)
+ local designsize=readushort(f)
+ if designsize>0 then
+ local fontstyle=readushort(f)
+ local guimenuid=readushort(f)
+ local minsize=readushort(f)
+ local maxsize=readushort(f)
+ if minsize==0 and maxsize==0 and fontstyleid==0 and guimenuid==0 then
+ minsize=designsize
+ maxsize=designsize
+ end
+ if designsize>=minsize and designsize<=maxsize then
+ return minsize,maxsize,designsize
+ end
+ end
+ end
+ local minsize,maxsize,designsize=check(tableoffset+feature.offset+feature.parameters)
+ if not designsize then
+ minsize,maxsize,designsize=check(tableoffset+feature.parameters)
+ if designsize then
+ report("bad size feature in %a, falling back to wrong offset",fontdata.filename or "?")
+ else
+ report("bad size feature in %a,",fontdata.filename or "?")
+ end
+ end
+ if designsize then
+ fontdata.minsize=minsize
+ fontdata.maxsize=maxsize
fontdata.designsize=designsize
- skipshort(f,2)
- fontdata.minsize=readushort(f)
- fontdata.maxsize=readushort(f)
end
end
end
@@ -7223,7 +7194,7 @@ do
feature.parameters=parameters
local plugin=plugins[feature.tag]
if plugin then
- plugin(f,fontdata,offset,parameters)
+ plugin(f,fontdata,featureoffset,feature)
end
end
end
@@ -7444,7 +7415,7 @@ do
markclass=d.markclass or nil,
flags=d.flags,
}
- sublookuplist[nofsublookups]=h
+ sublookuplist[nofsublookups]=copy(h)
sublookuphash[lookupid]=nofsublookups
sublookupcheck[lookupid]=1
else
@@ -7656,7 +7627,7 @@ function readers.gdef(f,fontdata,specification)
end
end
end
- if marksetsoffset then
+ if marksetsoffset and marksetsoffset>tableoffset then
setposition(f,marksetsoffset)
local format=readushort(f)
if format==1 then
@@ -8106,10 +8077,10 @@ function readers.svg(f,fontdata,specification)
end
end
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-dsp”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-dsp”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-oup” 6f089eaae576d1dbaa46e134cfeba9c7] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-oup” f7237130b648a4c2b477dabedc7f90e8] ---
if not modules then modules={} end modules ['font-oup']={
version=1.001,
@@ -8135,7 +8106,11 @@ local f_unicode=formatters["U%05X"]
local f_index=formatters["I%05X"]
local f_character_y=formatters["%C"]
local f_character_n=formatters["[ %C ]"]
-local doduplicates=true
+local check_duplicates=true
+local check_soft_hyphen=false
+directives.register("otf.checksofthyphen",function(v)
+ check_soft_hyphen=v
+end)
local function replaced(list,index,replacement)
if type(list)=="number" then
return replacement
@@ -8203,7 +8178,7 @@ local function unifyresources(fontdata,indices)
end
end
local done={}
- local duplicates=doduplicates and resources.duplicates
+ local duplicates=check_duplicates and resources.duplicates
if duplicates and not next(duplicates) then
duplicates=false
end
@@ -8440,10 +8415,31 @@ local function unifyresources(fontdata,indices)
unifythem(resources.sublookups)
end
local function copyduplicates(fontdata)
- if doduplicates then
+ if check_duplicates then
local descriptions=fontdata.descriptions
local resources=fontdata.resources
local duplicates=resources.duplicates
+ if check_soft_hyphen then
+ local ds=descriptions[0xAD]
+ if not ds or ds.width==0 then
+ if ds then
+ descriptions[0xAD]=nil
+ report("patching soft hyphen")
+ else
+ report("adding soft hyphen")
+ end
+ if not duplicates then
+ duplicates={}
+ resources.duplicates=duplicates
+ end
+ local dh=duplicates[0x2D]
+ if dh then
+ dh[#dh+1]={ [0xAD]=true }
+ else
+ duplicates[0x2D]={ [0xAD]=true }
+ end
+ end
+ end
if duplicates then
for u,d in next,duplicates do
local du=descriptions[u]
@@ -8884,6 +8880,7 @@ function readers.getcomponents(fontdata)
end
end
end
+readers.unifymissing=unifymissing
function readers.rehash(fontdata,hashmethod)
if not (fontdata and fontdata.glyphs) then
return
@@ -10126,10 +10123,10 @@ function readers.expand(data)
expandlookups(sublookups)
end
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-oup”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-oup”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-otl” eaab42986842ff8963114575dca6a6c6] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-otl” 2e7c8d9a331c46826211bd507f8e488a] ---
if not modules then modules={} end modules ['font-otl']={
version=1.001,
@@ -10141,7 +10138,6 @@ if not modules then modules={} end modules ['font-otl']={
local gmatch,find,match,lower,strip=string.gmatch,string.find,string.match,string.lower,string.strip
local type,next,tonumber,tostring,unpack=type,next,tonumber,tostring,unpack
local abs=math.abs
-local ioflush=io.flush
local derivetable=table.derive
local formatters=string.formatters
local setmetatableindex=table.setmetatableindex
@@ -10158,7 +10154,7 @@ local trace_defining=false registertracker("fonts.defining",function(v) trace_de
local report_otf=logs.reporter("fonts","otf loading")
local fonts=fonts
local otf=fonts.handlers.otf
-otf.version=3.023
+otf.version=3.027
otf.cache=containers.define("fonts","otl",otf.version,true)
otf.svgcache=containers.define("fonts","svg",otf.version,true)
otf.pdfcache=containers.define("fonts","pdf",otf.version,true)
@@ -10170,10 +10166,8 @@ local readers=fonts.readers
local constructors=fonts.constructors
local otffeatures=constructors.features.otf
local registerotffeature=otffeatures.register
-local enhancers=allocate()
-otf.enhancers=enhancers
-local patches={}
-enhancers.patches=patches
+local otfenhancers=constructors.enhancers.otf
+local registerotfenhancer=otfenhancers.register
local forceload=false
local cleanup=0
local syncspace=true
@@ -10189,76 +10183,7 @@ registerdirective("fonts.otf.loader.cleanup",function(v) cleanup=tonumber(v) or
registerdirective("fonts.otf.loader.force",function(v) forceload=v end)
registerdirective("fonts.otf.loader.syncspace",function(v) syncspace=v end)
registerdirective("fonts.otf.loader.forcenotdef",function(v) forcenotdef=v end)
-local ordered_enhancers={
- "check extra features",
-}
-local actions=allocate()
-local before=allocate()
-local after=allocate()
-patches.before=before
-patches.after=after
-local function enhance(name,data,filename,raw)
- local enhancer=actions[name]
- if enhancer then
- if trace_loading then
- report_otf("apply enhancement %a to file %a",name,filename)
- ioflush()
- end
- enhancer(data,filename,raw)
- else
- end
-end
-function enhancers.apply(data,filename,raw)
- local basename=file.basename(lower(filename))
- if trace_loading then
- report_otf("%s enhancing file %a","start",filename)
- end
- ioflush()
- for e=1,#ordered_enhancers do
- local enhancer=ordered_enhancers[e]
- local b=before[enhancer]
- if b then
- for pattern,action in next,b do
- if find(basename,pattern) then
- action(data,filename,raw)
- end
- end
- end
- enhance(enhancer,data,filename,raw)
- local a=after[enhancer]
- if a then
- for pattern,action in next,a do
- if find(basename,pattern) then
- action(data,filename,raw)
- end
- end
- end
- ioflush()
- end
- if trace_loading then
- report_otf("%s enhancing file %a","stop",filename)
- end
- ioflush()
-end
-function patches.register(what,where,pattern,action)
- local pw=patches[what]
- if pw then
- local ww=pw[where]
- if ww then
- ww[pattern]=action
- else
- pw[where]={ [pattern]=action}
- end
- end
-end
-function patches.report(fmt,...)
- if trace_loading then
- report_otf("patching: %s",formatters[fmt](...))
- end
-end
-function enhancers.register(what,action)
- actions[what]=action
-end
+registerotfenhancer("check extra features",function() end)
function otf.load(filename,sub,featurefile)
local featurefile=nil
local base=file.basename(file.removesuffix(filename))
@@ -10336,7 +10261,7 @@ function otf.load(filename,sub,featurefile)
collectgarbage("collect")
end
stoptiming(otfreaders)
- if elapsedtime then
+ if elapsedtime then
report_otf("loading, optimizing, packing and caching time %s",elapsedtime(otfreaders))
end
if cleanup>3 then
@@ -10358,7 +10283,7 @@ function otf.load(filename,sub,featurefile)
otfreaders.unpack(data)
otfreaders.expand(data)
otfreaders.addunicodetable(data)
- enhancers.apply(data,filename,data)
+ otfenhancers.apply(data,filename,data)
if applyruntimefixes then
applyruntimefixes(filename,data)
end
@@ -10498,13 +10423,13 @@ local function copytotfm(data,cache_id)
spaceunits,spacer=charwidth,"charwidth"
end
end
- spaceunits=tonumber(spaceunits) or 500
+ spaceunits=tonumber(spaceunits) or units/2
parameters.slant=0
- parameters.space=spaceunits
+ parameters.space=spaceunits
parameters.space_stretch=1*units/2
- parameters.space_shrink=1*units/3
- parameters.x_height=2*units/5
- parameters.quad=units
+ parameters.space_shrink=1*units/3
+ parameters.x_height=2*units/5
+ parameters.quad=units
if spaceunits<2*units/5 then
end
if italicangle and italicangle~=0 then
@@ -10557,10 +10482,38 @@ local function copytotfm(data,cache_id)
}
end
end
+local converters={
+ woff={
+ cachename="webfonts",
+ action=otf.readers.woff2otf,
+ }
+}
+local function checkconversion(specification)
+ local filename=specification.filename
+ local converter=converters[lower(file.suffix(filename))]
+ if converter then
+ local base=file.basename(filename)
+ local name=file.removesuffix(base)
+ local attr=lfs.attributes(filename)
+ local size=attr and attr.size or 0
+ local time=attr and attr.modification or 0
+ if size>0 then
+ local cleanname=containers.cleanname(name)
+ local cachename=caches.setfirstwritablefile(cleanname,converter.cachename)
+ if not io.exists(cachename) or (time~=lfs.attributes(cachename).modification) then
+ report_otf("caching font %a in %a",filename,cachename)
+ converter.action(filename,cachename)
+ lfs.touch(cachename,time,time)
+ end
+ specification.filename=cachename
+ end
+ end
+end
local function otftotfm(specification)
local cache_id=specification.hash
local tfmdata=containers.read(constructors.cache,cache_id)
if not tfmdata then
+ checkconversion(specification)
local name=specification.name
local sub=specification.sub
local subindex=specification.subindex
@@ -10690,7 +10643,6 @@ local function getgsub(tfmdata,k,kind,value)
local properties=tfmdata.properties
local validlookups,lookuplist=otf.collectlookups(rawdata,kind,properties.script,properties.language)
if validlookups then
- local choice=tonumber(value) or 1
for i=1,#lookuplist do
local lookup=lookuplist[i]
local steps=lookup.steps
@@ -10768,9 +10720,13 @@ local function opentypereader(specification,suffix)
end
end
readers.opentype=opentypereader
-function readers.otf (specification) return opentypereader(specification,"otf") end
-function readers.ttf (specification) return opentypereader(specification,"ttf") end
-function readers.ttc (specification) return opentypereader(specification,"ttf") end
+function readers.otf(specification) return opentypereader(specification,"otf") end
+function readers.ttf(specification) return opentypereader(specification,"ttf") end
+function readers.ttc(specification) return opentypereader(specification,"ttf") end
+function readers.woff(specification)
+ checkconversion(specification)
+ opentypereader(specification,"")
+end
function otf.scriptandlanguage(tfmdata,attr)
local properties=tfmdata.properties
return properties.script or "dflt",properties.language or "dflt"
@@ -10815,10 +10771,10 @@ otf.coverup={
end
}
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-otl”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-otl”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-oto” ea9826b209beb09e82a16ec81404fb86] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-oto” 5fbdd899624d4eef639f81b580afe9aa] ---
if not modules then modules={} end modules ['font-oto']={
version=1.001,
@@ -10915,7 +10871,7 @@ local function registerbasehash(tfmdata)
basehash[hash]=base
end
properties.basehash=base
- properties.fullname=properties.fullname.."-"..base
+ properties.fullname=(properties.fullname or properties.name).."-"..base
applied={}
end
local function registerbasefeature(feature,value)
@@ -10983,6 +10939,10 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
local trace_singles=trace_baseinit and trace_singles
local trace_alternatives=trace_baseinit and trace_alternatives
local trace_ligatures=trace_baseinit and trace_ligatures
+ if not changed then
+ changed={}
+ tfmdata.changed=changed
+ end
for i=1,#lookuplist do
local sequence=lookuplist[i]
local steps=sequence.steps
@@ -10990,12 +10950,10 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
if kind=="gsub_single" then
for i=1,#steps do
for unicode,data in next,steps[i].coverage do
- if not changed[unicode] then
if trace_singles then
report_substitution(feature,sequence,descriptions,unicode,data)
end
changed[unicode]=data
- end
end
end
elseif kind=="gsub_alternate" then
@@ -11136,7 +11094,8 @@ local function featuresinitializer(tfmdata,value)
local properties=tfmdata.properties
local script=properties.script
local language=properties.language
- local rawfeatures=rawdata.resources.features
+ local rawresources=rawdata.resources
+ local rawfeatures=rawresources and rawresources.features
local basesubstitutions=rawfeatures and rawfeatures.gsub
local basepositionings=rawfeatures and rawfeatures.gpos
if basesubstitutions or basepositionings then
@@ -11189,10 +11148,10 @@ registerotffeature {
}
otf.basemodeinitializer=featuresinitializer
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-oto”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-oto”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-otj” eb5afafa4d57c53e2918a8dfcb442a0c] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-otj” 5ea70db9f1990dc1459425853c79f663] ---
if not modules then modules={} end modules ['font-otj']={
version=1.001,
@@ -11208,7 +11167,7 @@ local registertracker=trackers.register
local trace_injections=false registertracker("fonts.injections",function(v) trace_injections=v end)
local trace_marks=false registertracker("fonts.injections.marks",function(v) trace_marks=v end)
local trace_cursive=false registertracker("fonts.injections.cursive",function(v) trace_cursive=v end)
-local trace_spaces=false registertracker("otf.spaces",function(v) trace_spaces=v end)
+local trace_spaces=false registertracker("fonts.injections.spaces",function(v) trace_spaces=v end)
local use_advance=false directives.register("fonts.injections.advance",function(v) use_advance=v end)
local report_injections=logs.reporter("fonts","injections")
local report_spaces=logs.reporter("fonts","spaces")
@@ -11474,7 +11433,7 @@ function injections.setkern(current,factor,rlmode,x,injection)
return 0,0
end
end
-function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk)
+function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk,checkmark)
local dx,dy=factor*(ba[1]-ma[1]),factor*(ba[2]-ma[2])
nofregisteredmarks=nofregisteredmarks+1
if rlmode>=0 then
@@ -11492,6 +11451,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk)
i.markbase=nofregisteredmarks
i.markbasenode=base
i.markmark=mkmk
+ i.checkmark=checkmark
end
else
p.injections={
@@ -11501,6 +11461,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk)
markbase=nofregisteredmarks,
markbasenode=base,
markmark=mkmk,
+ checkmark=checkmark,
}
end
else
@@ -11512,6 +11473,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk)
markbase=nofregisteredmarks,
markbasenode=base,
markmark=mkmk,
+ checkmark=checkmark,
},
}
end
@@ -12063,10 +12025,16 @@ local function inject_everything(head,where)
end
else
ox=px-pn.markx
- local wn=getfield(n,"width")
- if wn~=0 then
- pn.leftkern=-wn/2
- pn.rightkern=-wn/2
+ if pn.checkmark then
+ local wn=getfield(n,"width")
+ if wn~=0 then
+ wn=wn/2
+ if trace_injections then
+ report_injections("correcting non zero width mark %C",getchar(n))
+ end
+ insert_node_before(n,n,newkern(-wn))
+ insert_node_after(n,n,newkern(-wn))
+ end
end
end
local oy=getfield(n,"yoffset")+getfield(p,"yoffset")+pn.marky
@@ -12090,6 +12058,10 @@ local function inject_everything(head,where)
nofmarks=nofmarks+1
marks[nofmarks]=current
else
+ local yoffset=i.yoffset
+ if yoffset and yoffset~=0 then
+ setfield(current,"yoffset",yoffset)
+ end
if hascursives then
local cursivex=i.cursivex
if cursivex then
@@ -12141,10 +12113,6 @@ local function inject_everything(head,where)
cursiveanchor=nil
end
end
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(current,"yoffset",yoffset)
- end
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
insert_node_before(head,current,newkern(leftkern))
@@ -12391,6 +12359,37 @@ function nodes.injections.setspacekerns(font,sequence)
triggers={ [font]=sequence }
end
end
+local getthreshold
+if context then
+ local threshold=1
+ local parameters=fonts.hashes.parameters
+ directives.register("otf.threshold",function(v) threshold=tonumber(v) or 1 end)
+ getthreshold=function(font)
+ local p=parameters[font]
+ local f=p.factor
+ local s=p.spacing
+ local t=threshold*(s and s.width or p.space or 0)-2
+ return t>0 and t or 0,f
+ end
+else
+ injections.threshold=0
+ getthreshold=function(font)
+ local p=fontdata[font].parameters
+ local f=p.factor
+ local s=p.spacing
+ local t=injections.threshold*(s and s.width or p.space or 0)-2
+ return t>0 and t or 0,f
+ end
+end
+injections.getthreshold=getthreshold
+function injections.isspace(n,threshold)
+ if getid(n)==glue_code then
+ local w=getfield(n,"width")
+ if threshold and w>threshold then
+ return 32
+ end
+ end
+end
local function injectspaces(head)
if not triggers then
return head,false
@@ -12406,10 +12405,9 @@ local function injectspaces(head)
local function updatefont(font,trig)
leftkerns=trig.left
rightkerns=trig.right
- local par=fontdata[font].parameters
- factor=par.factor
- threshold=par.spacing.width-1
lastfont=font
+ threshold,
+ factor=getthreshold(font)
end
for n in traverse_id(glue_code,tonut(head)) do
local prev,next=getboth(n)
@@ -12428,7 +12426,7 @@ local function injectspaces(head)
end
end
if prevchar then
- local font=getfont(next)
+ local font=getfont(prev)
local trig=triggers[font]
if trig then
if lastfont~=font then
@@ -12441,7 +12439,7 @@ local function injectspaces(head)
end
if leftkern then
local old=getfield(n,"width")
- if old>=threshold then
+ if old>threshold then
if rightkern then
local new=old+(leftkern+rightkern)*factor
if trace_spaces then
@@ -12460,7 +12458,7 @@ local function injectspaces(head)
leftkern=false
elseif rightkern then
local old=getfield(n,"width")
- if old>=threshold then
+ if old>threshold then
local new=old+rightkern*factor
if trace_spaces then
report_spaces("[%p -> %p] %C",nextchar,old,new)
@@ -12497,10 +12495,10 @@ function injections.handler(head,where)
end
end
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-otj”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-otj”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-ota” 9d8f76acfcfad35684429d0bb9006bc0] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-ota” c281d18dfc89a8ca18af64f55e9fa92b] ---
if not modules then modules={} end modules ['font-ota']={
version=1.001,
@@ -12705,33 +12703,40 @@ local mappers={
}
local classifiers=characters.classifiers
if not classifiers then
- local first_arabic,last_arabic=characters.blockrange("arabic")
- local first_syriac,last_syriac=characters.blockrange("syriac")
- local first_mandiac,last_mandiac=characters.blockrange("mandiac")
- local first_nko,last_nko=characters.blockrange("nko")
+ local f_arabic,l_arabic=characters.blockrange("arabic")
+ local f_syriac,l_syriac=characters.blockrange("syriac")
+ local f_mandiac,l_mandiac=characters.blockrange("mandiac")
+ local f_nko,l_nko=characters.blockrange("nko")
+ local f_ext_a,l_ext_a=characters.blockrange("arabicextendeda")
classifiers=table.setmetatableindex(function(t,k)
- local c=chardata[k]
- local v=false
- if c then
- local arabic=c.arabic
- if arabic then
- v=mappers[arabic]
- if not v then
- log.report("analyze","error in mapping arabic %C",k)
- v=false
- end
- elseif k>=first_arabic and k<=last_arabic or k>=first_syriac and k<=last_syriac or
- k>=first_mandiac and k<=last_mandiac or k>=first_nko and k<=last_nko then
- if categories[k]=="mn" then
- v=s_mark
- else
- v=s_rest
+ if type(k)=="number" then
+ local c=chardata[k]
+ local v=false
+ if c then
+ local arabic=c.arabic
+ if arabic then
+ v=mappers[arabic]
+ if not v then
+ log.report("analyze","error in mapping arabic %C",k)
+ v=false
+ end
+ elseif (k>=f_arabic and k<=l_arabic) or
+ (k>=f_syriac and k<=l_syriac) or
+ (k>=f_mandiac and k<=l_mandiac) or
+ (k>=f_nko and k<=l_nko) or
+ (k>=f_ext_a and k<=l_ext_a) then
+ if categories[k]=="mn" then
+ v=s_mark
+ else
+ v=s_rest
+ end
end
end
+ t[k]=v
+ return v
end
- t[k]=v
- return v
end)
+ characters.classifiers=classifiers
end
function methods.arab(head,font,attr)
local first,last=nil,nil
@@ -12873,10 +12878,10 @@ directives.register("otf.analyze.useunicodemarks",function(v)
analyzers.useunicodemarks=v
end)
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-ota”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-ota”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-ots” e792a7e57659ced225ba311177709463] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-ots” 7e1e55f9f728474372665e4a64a43f5a] ---
if not modules then modules={} end modules ['font-ots']={
version=1.001,
@@ -12909,15 +12914,13 @@ local trace_details=false registertracker("otf.details",function(v) trace_detail
local trace_steps=false registertracker("otf.steps",function(v) trace_steps=v end)
local trace_skips=false registertracker("otf.skips",function(v) trace_skips=v end)
local trace_directions=false registertracker("otf.directions",function(v) trace_directions=v end)
+local trace_plugins=false registertracker("otf.plugins",function(v) trace_plugins=v end)
local trace_kernruns=false registertracker("otf.kernruns",function(v) trace_kernruns=v end)
local trace_discruns=false registertracker("otf.discruns",function(v) trace_discruns=v end)
local trace_compruns=false registertracker("otf.compruns",function(v) trace_compruns=v end)
local trace_testruns=false registertracker("otf.testruns",function(v) trace_testruns=v end)
-local quit_on_no_replacement=true
-local zwnjruns=true
local optimizekerns=true
-registerdirective("otf.zwnjruns",function(v) zwnjruns=v end)
-registerdirective("otf.chain.quitonnoreplacement",function(value) quit_on_no_replacement=value end)
+local alwaysdisc=true registerdirective("otf.alwaysdisc",function(v) alwaysdisc=v end)
local report_direct=logs.reporter("fonts","otf direct")
local report_subchain=logs.reporter("fonts","otf subchain")
local report_chain=logs.reporter("fonts","otf chain")
@@ -12959,7 +12962,7 @@ local copy_node=nuts.copy
local copy_node_list=nuts.copy_list
local find_node_tail=nuts.tail
local flush_node_list=nuts.flush_list
-local free_node=nuts.free
+local flush_node=nuts.flush_node
local end_of_math=nuts.end_of_math
local traverse_nodes=nuts.traverse
local traverse_id=nuts.traverse_id
@@ -12994,9 +12997,11 @@ local getligaindex=injections.getligaindex
local cursonce=true
local fonthashes=fonts.hashes
local fontdata=fonthashes.identifiers
+local fontfeatures=fonthashes.features
local otffeatures=fonts.constructors.features.otf
local registerotffeature=otffeatures.register
local onetimemessage=fonts.loggers.onetimemessage or function() end
+local getrandom=utilities and utilities.randomizer and utilities.randomizer.get
otf.defaultnodealternate="none"
local tfmdata=false
local characters=false
@@ -13005,6 +13010,7 @@ local marks=false
local currentfont=false
local factor=0
local threshold=0
+local checkmarks=false
local sweepnode=nil
local sweepprev=nil
local sweepnext=nil
@@ -13013,17 +13019,17 @@ local notmatchpre={}
local notmatchpost={}
local notmatchreplace={}
local handlers={}
-local function isspace(n)
- if getid(n)==glue_code then
- local w=getfield(n,"width")
- if w>=threshold then
- return 32
- end
- end
-end
+local isspace=injections.isspace
+local getthreshold=injections.getthreshold
local checkstep=(nodes and nodes.tracers and nodes.tracers.steppers.check) or function() end
local registerstep=(nodes and nodes.tracers and nodes.tracers.steppers.register) or function() end
local registermessage=(nodes and nodes.tracers and nodes.tracers.steppers.message) or function() end
+local function checkdisccontent(d)
+ local pre,post,replace=getdisc(d)
+ if pre then for n in traverse_id(glue_code,pre) do print("pre",nodes.idstostring(pre)) break end end
+ if post then for n in traverse_id(glue_code,post) do print("pos",nodes.idstostring(post)) break end end
+ if replace then for n in traverse_id(glue_code,replace) do print("rep",nodes.idstostring(replace)) break end end
+end
local function logprocess(...)
if trace_steps then
registermessage(...)
@@ -13084,7 +13090,7 @@ end
local function copy_glyph(g)
local components=getfield(g,"components")
if components then
- setfield(g,"components",nil)
+ setfield(g,"components")
local n=copy_node(g)
copyinjection(n,g)
setfield(g,"components",components)
@@ -13096,11 +13102,18 @@ local function copy_glyph(g)
end
end
local function flattendisk(head,disc)
- local _,_,replace,_,_,replacetail=getdisc(disc,true)
- setfield(disc,"replace",nil)
- free_node(disc)
- if head==disc then
- local next=getnext(disc)
+ local pre,post,replace,pretail,posttail,replacetail=getdisc(disc,true)
+ local prev,next=getboth(disc)
+ local ishead=head==disc
+ setdisc(disc)
+ flush_node(disc)
+ if pre then
+ flush_node_list(pre)
+ end
+ if post then
+ flush_node_list(post)
+ end
+ if ishead then
if replace then
if next then
setlink(replacetail,next)
@@ -13112,7 +13125,6 @@ local function flattendisk(head,disc)
return
end
else
- local prev,next=getboth(disc)
if replace then
if next then
setlink(replacetail,next)
@@ -13147,8 +13159,8 @@ local function markstoligature(head,start,stop,char)
else
local prev=getprev(start)
local next=getnext(stop)
- setprev(start,nil)
- setnext(stop,nil)
+ setprev(start)
+ setnext(stop)
local base=copy_glyph(start)
if head==start then
head=base
@@ -13195,8 +13207,8 @@ local function toligature(head,start,stop,char,dataset,sequence,markflag,discfou
local prev=getprev(start)
local next=getnext(stop)
local comp=start
- setprev(start,nil)
- setnext(stop,nil)
+ setprev(start)
+ setnext(stop)
local base=copy_glyph(start)
if start==head then
head=base
@@ -13260,45 +13272,45 @@ local function toligature(head,start,stop,char,dataset,sequence,markflag,discfou
local pre,post,replace,pretail,posttail,replacetail=getdisc(discfound,true)
if not replace then
local prev=getprev(base)
-local current=comp
-local previous=nil
-local copied=nil
-while current do
- if getid(current)==glyph_code then
- local n=copy_node(current)
- if copied then
- setlink(previous,n)
- else
- copied=n
- end
- previous=n
- end
- current=getnext(current)
-end
- setprev(discnext,nil)
- setnext(discprev,nil)
+ local current=comp
+ local previous=nil
+ local copied=nil
+ while current do
+ if getid(current)==glyph_code then
+ local n=copy_node(current)
+ if copied then
+ setlink(previous,n)
+ else
+ copied=n
+ end
+ previous=n
+ end
+ current=getnext(current)
+ end
+ setprev(discnext)
+ setnext(discprev)
if pre then
setlink(discprev,pre)
end
pre=comp
if post then
setlink(posttail,discnext)
- setprev(post,nil)
+ setprev(post)
else
post=discnext
end
setlink(prev,discfound)
setlink(discfound,next)
- setboth(base,nil,nil)
+ setboth(base)
setfield(base,"components",copied)
- setdisc(discfound,pre,post,base,discretionary_code)
+ setdisc(discfound,pre,post,base)
base=prev
end
end
end
return head,base
end
-local function multiple_glyphs(head,start,multiple,ignoremarks)
+local function multiple_glyphs(head,start,multiple,ignoremarks,what)
local nofmultiples=#multiple
if nofmultiples>0 then
resetinjection(start)
@@ -13312,6 +13324,17 @@ local function multiple_glyphs(head,start,multiple,ignoremarks)
insert_node_after(head,start,n)
start=n
end
+ if what==true then
+ elseif what>1 then
+ local m=multiple[nofmultiples]
+ for i=2,what do
+ local n=copy_node(start)
+ resetinjection(n)
+ setchar(n,m)
+ insert_node_after(head,start,n)
+ start=n
+ end
+ end
end
return head,start,true
else
@@ -13324,7 +13347,7 @@ end
local function get_alternative_glyph(start,alternatives,value)
local n=#alternatives
if value=="random" then
- local r=random(1,n)
+ local r=getrandom and getrandom("glyph",1,n) or random(1,n)
return alternatives[r],trace_alternatives and formatters["value %a, taking %a"](value,r)
elseif value=="first" then
return alternatives[1],trace_alternatives and formatters["value %a, taking %a"](value,1)
@@ -13382,7 +13405,7 @@ function handlers.gsub_multiple(head,start,dataset,sequence,multiple)
if trace_multiples then
logprocess("%s: replacing %s by multiple %s",pref(dataset,sequence),gref(getchar(start)),gref(multiple))
end
- return multiple_glyphs(head,start,multiple,sequence.flags[1])
+ return multiple_glyphs(head,start,multiple,sequence.flags[1],dataset[1])
end
function handlers.gsub_ligature(head,start,dataset,sequence,ligature)
local current=getnext(start)
@@ -13603,7 +13626,7 @@ function handlers.gpos_mark2base(head,start,dataset,sequence,markanchors,rlmode)
local ba=markanchors[1][basechar]
if ba then
local ma=markanchors[2]
- local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
+ local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -13658,7 +13681,7 @@ function handlers.gpos_mark2ligature(head,start,dataset,sequence,markanchors,rlm
local index=getligaindex(start)
ba=ba[index]
if ba then
- local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
+ local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks)
if trace_marks then
logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
pref(dataset,sequence),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy)
@@ -13705,7 +13728,7 @@ function handlers.gpos_mark2mark(head,start,dataset,sequence,markanchors,rlmode)
local ba=markanchors[1][basechar]
if ba then
local ma=markanchors[2]
- local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true)
+ local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true,checkmarks)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -13837,7 +13860,7 @@ function chainprocs.gsub_multiple(head,start,stop,dataset,sequence,currentlookup
if trace_multiples then
logprocess("%s: replacing %s by multiple characters %s",cref(dataset,sequence),gref(startchar),gref(replacement))
end
- return multiple_glyphs(head,start,replacement,sequence.flags[1])
+ return multiple_glyphs(head,start,replacement,sequence.flags[1],dataset[1])
end
return head,start,false
end
@@ -13849,7 +13872,7 @@ function chainprocs.gsub_alternate(head,start,stop,dataset,sequence,currentlooku
end
local kind=dataset[4]
local what=dataset[1]
- local value=what==true and tfmdata.shared.features[kind] or what
+ local value=what==true and tfmdata.shared.features[kind] or what
local current=start
while current do
local currentchar=ischar(current)
@@ -14087,7 +14110,7 @@ function chainprocs.gpos_mark2base(head,start,stop,dataset,sequence,currentlooku
if ba then
local ma=markanchors[2]
if ma then
- local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
+ local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -14153,7 +14176,7 @@ function chainprocs.gpos_mark2ligature(head,start,stop,dataset,sequence,currentl
local index=getligaindex(start)
ba=ba[index]
if ba then
- local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
+ local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
cref(dataset,sequence),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy)
@@ -14205,7 +14228,7 @@ function chainprocs.gpos_mark2mark(head,start,stop,dataset,sequence,currentlooku
if ba then
local ma=markanchors[2]
if ma then
- local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true)
+ local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true,checkmarks)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -14282,6 +14305,39 @@ end
local function show_skip(dataset,sequence,char,ck,class)
logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(dataset,sequence),gref(char),class,ck[1],ck[8] or ck[2])
end
+local new_kern=nuts.pool.kern
+local function checked(head)
+ local current=head
+ while current do
+ if getid(current)==glue_code then
+ local kern=new_kern(getfield(current,"width"))
+ if head==current then
+ local next=getnext(current)
+ if next then
+ setlink(kern,next)
+ end
+ flush_node(current)
+ head=kern
+ current=next
+ else
+ local prev,next=getboth(current)
+ setlink(prev,kern)
+ setlink(kern,next)
+ flush_node(current)
+ current=next
+ end
+ else
+ current=getnext(current)
+ end
+ end
+ return head
+end
+local function setdiscchecked(d,pre,post,replace)
+ if pre then pre=checked(pre) end
+ if post then post=checked(post) end
+ if replace then replace=checked(replace) end
+ setdisc(d,pre,post,replace)
+end
local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,ck,chainproc)
if not start then
return head,start,false
@@ -14302,6 +14358,7 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
local current=start
local last=start
local prev=getprev(start)
+ local hasglue=false
local i=f
while i<=l do
local id=getid(current)
@@ -14309,6 +14366,11 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
i=i+1
last=current
current=getnext(current)
+ elseif id==glue_code then
+ i=i+1
+ last=current
+ current=getnext(current)
+ hasglue=true
elseif id==disc_code then
if keepdisc then
keepdisc=false
@@ -14358,8 +14420,8 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
tail=find_node_tail(head)
end
setnext(sweepnode,current)
- setprev(head,nil)
- setnext(tail,nil)
+ setprev(head)
+ setnext(tail)
appenddisc(sweepnode,head)
end
end
@@ -14371,6 +14433,10 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
if id==glyph_code then
i=i+1
current=getnext(current)
+ elseif id==glue_code then
+ i=i+1
+ current=getnext(current)
+ hasglue=true
elseif id==disc_code then
if keepdisc then
keepdisc=false
@@ -14412,6 +14478,9 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
local id=getid(current)
if id==glyph_code then
i=i-1
+ elseif id==glue_code then
+ i=i-1
+ hasglue=true
elseif id==disc_code then
if keepdisc then
keepdisc=false
@@ -14456,8 +14525,8 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
if cprev then
setnext(cprev,lookaheaddisc)
end
- setprev(cf,nil)
- setnext(cl,nil)
+ setprev(cf)
+ setnext(cl)
if startishead then
head=lookaheaddisc
end
@@ -14484,7 +14553,11 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
local tail=find_node_tail(new)
setlink(tail,replace)
end
- setdisc(lookaheaddisc,cf,post,new)
+ if hasglue then
+ setdiscchecked(lookaheaddisc,cf,post,new)
+ else
+ setdisc(lookaheaddisc,cf,post,new)
+ end
start=getprev(lookaheaddisc)
sweephead[cf]=getnext(clast)
sweephead[new]=getnext(last)
@@ -14507,8 +14580,8 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
setprev(cnext,backtrackdisc)
end
setnext(backtrackdisc,cnext)
- setprev(cf,nil)
- setnext(cl,nil)
+ setprev(cf)
+ setnext(cl)
local pre,post,replace,pretail,posttail,replacetail=getdisc(backtrackdisc,true)
local new=copy_node_list(cf)
local cnew=find_node_tail(new)
@@ -14535,7 +14608,11 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
else
replace=new
end
- setdisc(backtrackdisc,pre,post,replace)
+ if hasglue then
+ setdiscchecked(backtrackdisc,pre,post,replace)
+ else
+ setdisc(backtrackdisc,pre,post,replace)
+ end
start=getprev(backtrackdisc)
sweephead[post]=getnext(clast)
sweephead[replace]=getnext(last)
@@ -14790,16 +14867,13 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
end
prev=getprev(prev)
- elseif seq[n][32] then
+ elseif seq[n][32] and isspace(prev,threshold) then
n=n-1
prev=getprev(prev)
else
match=false
break
end
- elseif seq[n][32] then
- n=n-1
- prev=getprev(prev)
else
match=false
break
@@ -14913,15 +14987,13 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
else
end
current=getnext(current)
- elseif seq[n][32] then
+ elseif seq[n][32] and isspace(current,threshold) then
n=n+1
+ current=getnext(current)
else
match=false
break
end
- elseif seq[n][32] then
- n=n+1
- current=getnext(current)
else
match=false
break
@@ -15016,7 +15088,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if replacements then
head,start,done=reversesub(head,start,last,dataset,sequence,replacements,rlmode)
else
- done=quit_on_no_replacement
+ done=true
if trace_contexts then
logprocess("%s: skipping match",cref(dataset,sequence))
end
@@ -15136,10 +15208,12 @@ function otf.dataset(tfmdata,font)
}
rs[language]=rl
local sequences=tfmdata.resources.sequences
- for s=1,#sequences do
- local v=enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
- if v then
- rl[#rl+1]=v
+ if sequences then
+ for s=1,#sequences do
+ local v=enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
+ if v then
+ rl[#rl+1]=v
+ end
end
end
end
@@ -15165,10 +15239,10 @@ local function kernrun(disc,k_run,font,attr,...)
break
end
end
- if prev and (pre or replace) and not ischar(prev,font) then
+ if prev and not ischar(prev,font) then
prev=false
end
- if next and (post or replace) and not ischar(next,font) then
+ if next and not ischar(next,font) then
next=false
end
if pre then
@@ -15194,7 +15268,7 @@ local function kernrun(disc,k_run,font,attr,...)
if k_run(posttail,"postinjections",next,font,attr,...) then
done=true
end
- setnext(posttail,nil)
+ setnext(posttail)
setprev(next,disc)
end
end
@@ -15216,7 +15290,7 @@ local function kernrun(disc,k_run,font,attr,...)
if k_run(replacetail,"replaceinjections",next,font,attr,...) then
done=true
end
- setnext(replacetail,nil)
+ setnext(replacetail)
setprev(next,disc)
end
elseif prev and next then
@@ -15283,7 +15357,7 @@ local function testrun(disc,t_run,c_run,...)
setlink(replacetail,next)
local ok,overflow=t_run(replace,next,...)
if ok and overflow then
- setfield(disc,"replace",nil)
+ setfield(disc,"replace")
setlink(prev,replace)
setboth(disc)
flush_node_list(disc)
@@ -15398,6 +15472,7 @@ local function t_run_single(start,stop,font,attr,lookupcache)
return true,d>1
end
end
+ else
end
start=getnext(start)
else
@@ -15511,6 +15586,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
report_missing_coverage(dataset,sequence)
end
end
+ else
end
start=getnext(start)
else
@@ -15582,6 +15658,9 @@ local function pardirstate(start)
end
return getnext(start),new,new
end
+otf.helpers=otf.helpers or {}
+otf.helpers.txtdirstate=txtdirstate
+otf.helpers.pardirstate=pardirstate
local function featuresprocessor(head,font,attr)
local sequences=sequencelists[font]
if not sequencelists then
@@ -15594,8 +15673,9 @@ local function featuresprocessor(head,font,attr)
descriptions=tfmdata.descriptions
characters=tfmdata.characters
marks=tfmdata.resources.marks
- factor=tfmdata.parameters.factor
- threshold=tfmdata.parameters.spacing.width or 65536*10
+ threshold,
+ factor=getthreshold(font)
+ checkmarks=tfmdata.properties.checkmarks
elseif currentfont~=font then
report_warning("nested call with a different font, level %s, quitting",nesting)
nesting=nesting-1
@@ -15608,6 +15688,7 @@ local function featuresprocessor(head,font,attr)
local rlmode=0
local done=false
local datasets=otf.dataset(tfmdata,font,attr)
+ local forcedisc=alwaysdisc or not attr
local dirstack={}
sweephead={}
for s=1,#datasets do
@@ -15623,15 +15704,12 @@ local function featuresprocessor(head,font,attr)
local steps=sequence.steps
local nofsteps=sequence.nofsteps
if not steps then
- local h,d,ok=handler(head,start,dataset,sequence,nil,nil,nil,0,font,attr)
+ local h,d,ok=handler(head,head,dataset,sequence,nil,nil,nil,0,font,attr)
if ok then
success=true
if h then
head=h
end
- if d then
- start=d
- end
end
elseif typ=="gsub_reversecontextchain" then
local start=find_node_tail(head)
@@ -15703,16 +15781,21 @@ local function featuresprocessor(head,font,attr)
elseif char==false then
start=getnext(start)
elseif id==disc_code then
- local ok
- if gpossing then
- start,ok=kernrun(start,k_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- elseif typ=="gsub_ligature" then
- start,ok=testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ local a=forcedisc or getsubtype(start)==discretionary_code or getattr(start,0)==attr
+ if a then
+ local ok
+ if gpossing then
+ start,ok=kernrun(start,k_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ elseif typ=="gsub_ligature" then
+ start,ok=testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ else
+ start,ok=comprun(start,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ end
+ if ok then
+ success=true
+ end
else
- start,ok=comprun(start,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- end
- if ok then
- success=true
+ start=getnext(start)
end
elseif id==math_code then
start=getnext(end_of_math(start))
@@ -15764,16 +15847,21 @@ local function featuresprocessor(head,font,attr)
elseif char==false then
start=getnext(start)
elseif id==disc_code then
- local ok
- if gpossing then
- start,ok=kernrun(start,k_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- elseif typ=="gsub_ligature" then
- start,ok=testrun(start,t_run_multiple,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ local a=forcedisc or getsubtype(start)==discretionary_code or getattr(start,0)==attr
+ if a then
+ local ok
+ if gpossing then
+ start,ok=kernrun(start,k_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ elseif typ=="gsub_ligature" then
+ start,ok=testrun(start,t_run_multiple,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ else
+ start,ok=comprun(start,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ end
+ if ok then
+ success=true
+ end
else
- start,ok=comprun(start,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- end
- if ok then
- success=true
+ start=getnext(start)
end
elseif id==math_code then
start=getnext(end_of_math(start))
@@ -15798,6 +15886,30 @@ local function featuresprocessor(head,font,attr)
head=tonode(head)
return head,done
end
+local plugins={}
+otf.plugins=plugins
+function otf.registerplugin(name,f)
+ if type(name)=="string" and type(f)=="function" then
+ plugins[name]={ name,f }
+ end
+end
+local function plugininitializer(tfmdata,value)
+ if type(value)=="string" then
+ tfmdata.shared.plugin=plugins[value]
+ end
+end
+local function pluginprocessor(head,font)
+ local s=fontdata[font].shared
+ local p=s and s.plugin
+ if p then
+ if trace_plugins then
+ report_process("applying plugin %a",p[1])
+ end
+ return p[2](head,font)
+ else
+ return head,false
+ end
+end
local function featuresinitializer(tfmdata,value)
end
registerotffeature {
@@ -15807,18 +15919,36 @@ registerotffeature {
initializers={
position=1,
node=featuresinitializer,
+ plug=plugininitializer,
},
processors={
node=featuresprocessor,
+ plug=pluginprocessor,
}
}
otf.nodemodeinitializer=featuresinitializer
otf.featuresprocessor=featuresprocessor
otf.handlers=handlers
local setspacekerns=nodes.injections.setspacekerns if not setspacekerns then os.exit() end
-function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr)
- setspacekerns(font,sequence)
- return head,start,true
+if fontfeatures then
+ function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr)
+ local features=fontfeatures[font]
+ local enabled=features and features.spacekern and features.kern
+ if enabled then
+ setspacekerns(font,sequence)
+ end
+ return head,start,enabled
+ end
+else
+ function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr)
+ local shared=fontdata[font].shared
+ local features=shared and shared.features
+ local enabled=features and features.spacekern and features.kern
+ if enabled then
+ setspacekerns(font,sequence)
+ end
+ return head,start,enabled
+ end
end
local function hasspacekerns(data)
local sequences=data.resources.sequences
@@ -15852,8 +15982,8 @@ otf.readers.registerextender {
local function spaceinitializer(tfmdata,value)
local resources=tfmdata.resources
local spacekerns=resources and resources.spacekerns
- if spacekerns==nil then
- local properties=tfmdata.properties
+ local properties=tfmdata.properties
+ if value and spacekerns==nil then
if properties and properties.hasspacekerns then
local sequences=resources.sequences
local left={}
@@ -15866,28 +15996,55 @@ local function spaceinitializer(tfmdata,value)
if steps then
local kern=sequence.features.kern
if kern then
- feat=feat or kern
+ if feat then
+ for script,languages in next,kern do
+ local f=feat[script]
+ if f then
+ for l in next,languages do
+ f[l]=true
+ end
+ else
+ feat[script]=languages
+ end
+ end
+ else
+ feat=kern
+ end
for i=1,#steps do
local step=steps[i]
local coverage=step.coverage
- if coverage then
+ local rules=step.rules
+ local format=step.format
+ if rules then
+ elseif coverage then
+ local single=format==gpos_single
local kerns=coverage[32]
if kerns then
for k,v in next,kerns do
- if type(v)=="table" then
- right[k]=v[3]
- else
+ if type(v)~="table" then
right[k]=v
+ elseif single then
+ right[k]=v[3]
+ else
+ local one=v[1]
+ if one then
+ right[k]=one[3]
+ end
end
end
end
for k,v in next,coverage do
local kern=v[32]
if kern then
- if type(kern)=="table" then
- left[k]=kern[3]
- else
+ if type(kern)~="table" then
left[k]=kern
+ elseif single then
+ left[k]=v[3]
+ else
+ local one=v[1]
+ if one then
+ left[k]=one[3]
+ end
end
end
end
@@ -15935,11 +16092,23 @@ registerotffeature {
node=spaceinitializer,
},
}
+local function markinitializer(tfmdata,value)
+ local properties=tfmdata.properties
+ properties.checkmarks=value
+end
+registerotffeature {
+ name="checkmarks",
+ description="check mark widths",
+ default=true,
+ initializers={
+ node=markinitializer,
+ },
+}
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-ots”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-ots”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-osd” 5599b76874f4987032a207e1413ab98b] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-osd” 10ecd4b375680b011e7c6a25e5ad74f7] ---
if not modules then modules={} end modules ['font-osd']={
version=1.001,
@@ -15978,9 +16147,9 @@ local setprop=nuts.setprop
local ischar=nuts.is_char
local insert_node_after=nuts.insert_after
local copy_node=nuts.copy
-local free_node=nuts.free
local remove_node=nuts.remove
local flush_list=nuts.flush_list
+local flush_node=nuts.flush_node
local copyinjection=nodes.injections.copy
local unsetvalue=attributes.unsetvalue
local fontdata=fonts.hashes.identifiers
@@ -16339,9 +16508,11 @@ local function initializedevanagi(tfmdata)
local steps=sequence.steps
local nofsteps=sequence.nofsteps
local features=sequence.features
- if features["rphf"] then
+ local has_rphf=features.rphf
+ local has_blwf=features.blwf
+ if has_rphf and has_rphf.deva then
devanagari.reph=true
- elseif features["blwf"] then
+ elseif has_blwf and has_blwf.deva then
devanagari.vattu=true
for i=1,nofsteps do
local step=steps[i]
@@ -16355,57 +16526,60 @@ local function initializedevanagi(tfmdata)
end
end
end
- if valid[kind] then
- for i=1,nofsteps do
- local step=steps[i]
- local coverage=step.coverage
- if coverage then
- local reph=false
- if step.osdstep then
- for k,v in next,ra do
- local r=coverage[k]
- if r then
- local h=false
- for k,v in next,halant do
- local h=r[k]
- if h then
- reph=h.ligature or false
- break
+ for kind,spec in next,features do
+ if spec.dev2 and valid[kind] then
+ for i=1,nofsteps do
+ local step=steps[i]
+ local coverage=step.coverage
+ if coverage then
+ local reph=false
+ if kind=="rphf" then
+ if true then
+ for k,v in next,ra do
+ local r=coverage[k]
+ if r then
+ local h=false
+ for k,v in next,halant do
+ local h=r[k]
+ if h then
+ reph=h.ligature or false
+ break
+ end
+ end
+ if reph then
+ break
+ end
end
end
- if reph then
- break
- end
+ else
end
end
- else
+ seqsubset[#seqsubset+1]={ kind,coverage,reph }
end
- seqsubset[#seqsubset+1]={ kind,coverage,reph }
end
end
- end
- if kind=="pref" then
- local sequence=dataset[3]
- local steps=sequence.steps
- local nofsteps=sequence.nofsteps
- for i=1,nofsteps do
- local step=steps[i]
- local coverage=step.coverage
- if coverage then
- for k,v in next,halant do
- local h=coverage[k]
- if h then
- local found=false
- for k,v in next,h do
- found=v and v.ligature
+ if kind=="pref" then
+ local steps=sequence.steps
+ local nofsteps=sequence.nofsteps
+ for i=1,nofsteps do
+ local step=steps[i]
+ local coverage=step.coverage
+ if coverage then
+ for k,v in next,halant do
+ local h=coverage[k]
+ if h then
+ local found=false
+ for k,v in next,h do
+ found=v and v.ligature
+ if found then
+ pre_base_reordering_consonants[k]=found
+ break
+ end
+ end
if found then
- pre_base_reordering_consonants[k]=found
break
end
end
- if found then
- break
- end
end
end
end
@@ -16490,7 +16664,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
if current==stop then
stop=getprev(stop)
head=remove_node(head,current)
- free_node(current)
+ flush_node(current)
return head,stop,nbspaces
else
nbspaces=nbspaces+1
@@ -16528,7 +16702,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
setchar(current,getchar(tempcurrent))
local freenode=getnext(current)
setlink(current,tmp)
- free_node(freenode)
+ flush_node(freenode)
flush_list(tempcurrent)
if changestop then
stop=current
@@ -16765,7 +16939,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
if getchar(base)==c_nbsp then
nbspaces=nbspaces-1
head=remove_node(head,base)
- free_node(base)
+ flush_node(base)
end
return head,stop,nbspaces
end
@@ -16792,6 +16966,8 @@ function handlers.devanagari_reorder_matras(head,start)
start=startnext
break
end
+ else
+ break
end
current=next
end
@@ -16804,12 +16980,12 @@ function handlers.devanagari_reorder_reph(head,start)
local startfont=getfont(start)
local startattr=getprop(start,a_syllabe)
while current do
- local char=ischar(current,font)
+ local char=ischar(current,startfont)
if char and getprop(current,a_syllabe)==startattr then
if halant[char] and not getprop(current,a_state) then
local next=getnext(current)
if next then
- local nextchar=ischar(next,font)
+ local nextchar=ischar(next,startfont)
if nextchar and zw_char[nextchar] and getprop(next,a_syllabe)==startattr then
current=next
next=getnext(current)
@@ -16831,7 +17007,7 @@ function handlers.devanagari_reorder_reph(head,start)
if not startnext then
current=getnext(start)
while current do
- local char=ischar(current,font)
+ local char=ischar(current,startfont)
if char and getprop(current,a_syllabe)==startattr then
if getprop(current,a_state)==s_pstf then
startnext=getnext(start)
@@ -16853,7 +17029,7 @@ function handlers.devanagari_reorder_reph(head,start)
current=getnext(start)
local c=nil
while current do
- local char=ischar(current,font)
+ local char=ischar(current,startfont)
if char and getprop(current,a_syllabe)==startattr then
if not c and mark_above_below_post[char] and reorder_class[char]~="after subscript" then
c=current
@@ -16877,7 +17053,7 @@ function handlers.devanagari_reorder_reph(head,start)
current=start
local next=getnext(current)
while next do
- local nextchar=ischar(next,font)
+ local nextchar=ischar(next,startfont)
if nextchar and getprop(next,a_syllabe)==startattr then
current=next
next=getnext(current)
@@ -16890,7 +17066,7 @@ function handlers.devanagari_reorder_reph(head,start)
head=remove_node(head,start)
local next=getnext(current)
setlink(start,next)
- setlink(current,"next",start)
+ setlink(current,start)
start=startnext
end
end
@@ -16903,12 +17079,12 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
local startfont=getfont(start)
local startattr=getprop(start,a_syllabe)
while current do
- local char=ischar(current,font)
+ local char=ischar(current,startfont)
if char and getprop(current,a_syllabe)==startattr then
local next=getnext(current)
if halant[char] and not getprop(current,a_state) then
if next then
- local nextchar=ischar(next,font)
+ local nextchar=ischar(next,startfont)
if nextchar and getprop(next,a_syllabe)==startattr then
if nextchar==c_zwnj or nextchar==c_zwj then
current=next
@@ -16932,13 +17108,13 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
current=getnext(start)
startattr=getprop(start,a_syllabe)
while current do
- local char=ischar(current,font)
+ local char=ischar(current,startfont)
if char and getprop(current,a_syllabe)==startattr then
if not consonant[char] and getprop(current,a_state) then
startnext=getnext(start)
removenode(start,start)
local prev=getprev(current)
- setlink(start,prev)
+ setlink(prev,start)
setlink(start,current)
start=startnext
break
@@ -16998,21 +17174,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces)
local kind=subset[1]
local lookupcache=subset[2]
if kind=="rphf" then
- for k,v in next,ra do
- local r=lookupcache[k]
- if r then
- for k,v in next,halant do
- local h=r[k]
- if h then
- reph=h.ligature or false
- break
- end
- end
- if reph then
- break
- end
- end
- end
+ reph=subset[3]
local current=start
local last=getnext(stop)
while current~=last do
@@ -17045,7 +17207,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces)
if current~=stop then
local c=locl[current] or getchar(current)
local found=lookupcache[c]
- if found then
+ if found then
local next=getnext(current)
local n=locl[next] or getchar(next)
if found[n] then
@@ -17133,7 +17295,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces)
if current==stop then
stop=getprev(stop)
head=remove_node(head,current)
- free_node(current)
+ flush_node(current)
return head,stop,nbspaces
else
nbspaces=nbspaces+1
@@ -17272,7 +17434,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces)
local prev=getprev(current)
if prev~=target then
local next=getnext(current)
- setlink(next,prev)
+ setlink(prev,next)
if current==stop then
stop=prev
end
@@ -17303,7 +17465,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces)
stop=current
end
local prev=getprev(c)
- setlink(next,prev)
+ setlink(prev,next)
local nextnext=getnext(next)
setnext(current,nextnext)
local nextnextnext=getnext(nextnext)
@@ -17316,9 +17478,12 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces)
current=getnext(current)
end
if getchar(base)==c_nbsp then
+ if base==stop then
+ stop=getprev(stop)
+ end
nbspaces=nbspaces-1
head=remove_node(head,base)
- free_node(base)
+ flush_node(base)
end
return head,stop,nbspaces
end
@@ -17357,7 +17522,7 @@ local function analyze_next_chars_one(c,font,variant)
elseif (vv==c_zwnj or vv==c_zwj) and halant[vvv] then
local nnnn=getnext(nnn)
if nnnn then
- local vvvv=ischar(nnnn)
+ local vvvv=ischar(nnnn,font)
if vvvv and consonant[vvvv] then
c=nnnn
end
@@ -17380,7 +17545,7 @@ local function analyze_next_chars_one(c,font,variant)
local nn=getnext(n)
if nn then
local vv=ischar(nn,font)
- if vv and zw_char[vv] then
+ if vv and zw_char[v] then
n=nn
v=vv
nn=getnext(nn)
@@ -17906,10 +18071,10 @@ end
methods.mlym=methods.deva
methods.mlm2=methods.dev2
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-osd”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-osd”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-ocl” 21d4db431ea76de6ca180d89f952616a] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-ocl” fbc00782e4efb24a7569f99cd1574ffb] ---
if not modules then modules={} end modules ['font-ocl']={
version=1.001,
@@ -17918,32 +18083,77 @@ if not modules then modules={} end modules ['font-ocl']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local tostring,next=tostring,next
+local tostring,next,format=tostring,next,string.format
+local round,max=math.round,math.round
local formatters=string.formatters
+local tounicode=fonts.mappings.tounicode
local otf=fonts.handlers.otf
-local f_color_start=formatters["pdf:direct: %f %f %f rg"]
-local s_color_stop="pdf:direct:"
+local f_color=formatters["pdf:direct:%f %f %f rg"]
+local f_gray=formatters["pdf:direct:%f g"]
+local s_black="pdf:direct:0 g"
if context then
local startactualtext=nil
local stopactualtext=nil
- function otf.getactualtext(n)
+ function otf.getactualtext(s)
if not startactualtext then
- startactualtext=backends.codeinjections.startunicodetoactualtext
- stopactualtext=backends.codeinjections.stopunicodetoactualtext
+ startactualtext=backends.codeinjections.startunicodetoactualtextdirect
+ stopactualtext=backends.codeinjections.stopunicodetoactualtextdirect
end
- return startactualtext(n),stopactualtext()
+ return startactualtext(s),stopactualtext()
end
else
local tounicode=fonts.mappings.tounicode16
- function otf.getactualtext(n)
- return "/Span << /ActualText <feff"..tounicode(n).."> >> BDC","EMC"
+ function otf.getactualtext(s)
+ return
+ "/Span << /ActualText <feff"..n.."> >> BDC",
+ "EMC"
+ end
+end
+local sharedpalettes={}
+if context then
+ local graytorgb=attributes.colors.graytorgb
+ local cmyktorgb=attributes.colors.cmyktorgb
+ function otf.registerpalette(name,values)
+ sharedpalettes[name]=values
+ for i=1,#values do
+ local v=values[i]
+ local r,g,b
+ local s=v.s
+ if s then
+ r,g,b=graytorgb(s)
+ else
+ local c,m,y,k=v.c,v.m,v.y,v.k
+ if c or m or y or k then
+ r,g,b=cmyktorgb(c or 0,m or 0,y or 0,k or 0)
+ else
+ r,g,b=v.r,v.g,v.b
+ end
+ end
+ values[i]={
+ max(r and round(r*255) or 0,255),
+ max(g and round(g*255) or 0,255),
+ max(b and round(b*255) or 0,255)
+ }
+ end
+ end
+else
+ function otf.registerpalette(name,values)
+ sharedpalettes[name]=values
+ for i=1,#values do
+ local v=values[i]
+ values[i]={
+ max(round((v.r or 0)*255),255),
+ max(round((v.g or 0)*255),255),
+ max(round((v.b or 0)*255),255)
+ }
+ end
end
end
local function initializecolr(tfmdata,kind,value)
if value then
local palettes=tfmdata.resources.colorpalettes
if palettes then
- local palette=palettes[tonumber(value) or 1] or palettes[1] or {}
+ local palette=sharedpalettes[value] or palettes[tonumber(value) or 1] or palettes[1] or {}
local classes=#palette
if classes==0 then
return
@@ -17958,7 +18168,12 @@ local function initializecolr(tfmdata,kind,value)
}
for i=1,classes do
local p=palette[i]
- colorvalues[i]={ "special",f_color_start(p[1]/255,p[2]/255,p[3]/255) }
+ local r,g,b=p[1],p[2],p[3]
+ if r==g and g==b then
+ colorvalues[i]={ "special",f_gray(r/255) }
+ else
+ colorvalues[i]={ "special",f_color(r/255,g/255,b/255) }
+ end
end
local getactualtext=otf.getactualtext
for unicode,character in next,characters do
@@ -17966,22 +18181,24 @@ local function initializecolr(tfmdata,kind,value)
if description then
local colorlist=description.colors
if colorlist then
- local b,e=getactualtext(unicode)
+ local b,e=getactualtext(tounicode(characters[unicode].unicode or 0xFFFD))
local w=character.width or 0
local s=#colorlist
- local n=1
local t={
- { "special","pdf:direct: q "..b }
+ { "special","pdf:page:q" },
+ { "special","pdf:raw:"..b }
}
+ local n=#t
for i=1,s do
local entry=colorlist[i]
- n=n+1 t[n]=colorvalues[entry.class]
+ n=n+1 t[n]=colorvalues[entry.class] or s_black
n=n+1 t[n]={ "char",entry.slot }
if s>1 and i<s and w~=0 then
n=n+1 t[n]={ "right",-w }
end
end
- n=n+1 t[n]={ "special","pdf:direct:"..e.." Q" }
+ n=n+1 t[n]={ "special","pdf:page:"..e }
+ n=n+1 t[n]={ "special","pdf:raw:Q" }
character.commands=t
end
end
@@ -18035,70 +18252,62 @@ do
end
end
end
-if context and xml.convert then
+do
local report_svg=logs.reporter("fonts","svg conversion")
- local xmlconvert=xml.convert
- local xmlfirst=xml.first
local loaddata=io.loaddata
local savedata=io.savedata
local remove=os.remove
+ if context and xml.convert then
+ local xmlconvert=xml.convert
+ local xmlfirst=xml.first
+ function otfsvg.filterglyph(entry,index)
+ local svg=xmlconvert(entry.data)
+ local root=svg and xmlfirst(svg,"/svg[@id='glyph"..index.."']")
+ local data=root and tostring(root)
+ return data
+ end
+ else
+ function otfsvg.filterglyph(entry,index)
+ return entry.data
+ end
+ end
function otfsvg.topdf(svgshapes)
- local inkscape=io.popen("inkscape --shell 2>&1","w")
+ local inkscape=io.popen("inkscape --shell > temp-otf-svg-shape.log","w")
local pdfshapes={}
local nofshapes=#svgshapes
local f_svgfile=formatters["temp-otf-svg-shape-%i.svg"]
local f_pdffile=formatters["temp-otf-svg-shape-%i.pdf"]
local f_convert=formatters["%s --export-pdf=%s\n"]
+ local filterglyph=otfsvg.filterglyph
report_svg("processing %i svg containers",nofshapes)
statistics.starttiming()
for i=1,nofshapes do
local entry=svgshapes[i]
- for j=entry.first,entry.last do
- local svg=xmlconvert(entry.data)
- local root=svg and xmlfirst(svg,"/svg[@id='glyph"..j.."']")
- local data=root and tostring(root)
+ for index=entry.first,entry.last do
+ local data=filterglyph(entry,index)
if data and data~="" then
- local svgfile=f_svgfile(j)
- local pdffile=f_pdffile(j)
+ local svgfile=f_svgfile(index)
+ local pdffile=f_pdffile(index)
savedata(svgfile,data)
inkscape:write(f_convert(svgfile,pdffile))
- pdfshapes[j]=true
+ pdfshapes[index]=true
end
end
end
inkscape:write("quit\n")
inkscape:close()
report_svg("processing %i pdf results",nofshapes)
- for i in next,pdfshapes do
- local svgfile=f_svgfile(i)
- local pdffile=f_pdffile(i)
- pdfshapes[i]=loaddata(pdffile)
+ for index in next,pdfshapes do
+ local svgfile=f_svgfile(index)
+ local pdffile=f_pdffile(index)
+ pdfshapes[index]=loaddata(pdffile)
remove(svgfile)
remove(pdffile)
end
statistics.stoptiming()
- report_svg("conversion time: %0.3f",statistics.elapsedtime())
- return pdfshapes
- end
-else
- function otfsvg.topdf(svgshapes)
- local svgfile="temp-otf-svg-shape.svg"
- local pdffile="temp-otf-svg-shape.pdf"
- local command="inkscape "..svgfile.." --export-pdf="..pdffile
- local pdfshapes={}
- local nofshapes=#svgshapes
- texio.write(formatters["[converting %i svg glyphs to pdf using command %q : "](nofshapes,command))
- for i=1,nofshapes do
- local entry=svgshapes[i]
- for j=entry.first,entry.last do
- texio.write(formatters["%i "](j))
- io.savedata(svgfile,tostring(entry.data))
- os.execute(command)
- pdfshapes[j]=io.loaddata(pdffile)
- end
+ if statistics.elapsedseconds then
+ report_svg("svg conversion time %s",statistics.elapsedseconds())
end
- os.remove(svgfile)
- texio.write("done]")
return pdfshapes
end
end
@@ -18169,10 +18378,782 @@ fonts.handlers.otf.features.register {
}
}
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-ocl”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-ocl”] ---
+
+
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-otc” 85d63e257c748c624768aa7c8ec7f0bc] ---
+
+if not modules then modules={} end modules ['font-otc']={
+ version=1.001,
+ comment="companion to font-otf.lua (context)",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local format,insert,sortedkeys,tohash=string.format,table.insert,table.sortedkeys,table.tohash
+local type,next=type,next
+local lpegmatch=lpeg.match
+local utfbyte,utflen=utf.byte,utf.len
+local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end)
+local report_otf=logs.reporter("fonts","otf loading")
+local fonts=fonts
+local otf=fonts.handlers.otf
+local registerotffeature=otf.features.register
+local setmetatableindex=table.setmetatableindex
+local normalized={
+ substitution="substitution",
+ single="substitution",
+ ligature="ligature",
+ alternate="alternate",
+ multiple="multiple",
+ kern="kern",
+ pair="pair",
+ chainsubstitution="chainsubstitution",
+ chainposition="chainposition",
+}
+local types={
+ substitution="gsub_single",
+ ligature="gsub_ligature",
+ alternate="gsub_alternate",
+ multiple="gsub_multiple",
+ kern="gpos_pair",
+ pair="gpos_pair",
+ chainsubstitution="gsub_contextchain",
+ chainposition="gpos_contextchain",
+}
+local names={
+ gsub_single="gsub",
+ gsub_multiple="gsub",
+ gsub_alternate="gsub",
+ gsub_ligature="gsub",
+ gsub_context="gsub",
+ gsub_contextchain="gsub",
+ gsub_reversecontextchain="gsub",
+ gpos_single="gpos",
+ gpos_pair="gpos",
+ gpos_cursive="gpos",
+ gpos_mark2base="gpos",
+ gpos_mark2ligature="gpos",
+ gpos_mark2mark="gpos",
+ gpos_context="gpos",
+ gpos_contextchain="gpos",
+}
+setmetatableindex(types,function(t,k) t[k]=k return k end)
+local everywhere={ ["*"]={ ["*"]=true } }
+local noflags={ false,false,false,false }
+local function getrange(sequences,category)
+ local count=#sequences
+ local first=nil
+ local last=nil
+ for i=1,count do
+ local t=sequences[i].type
+ if t and names[t]==category then
+ if not first then
+ first=i
+ end
+ last=i
+ end
+ end
+ return first or 1,last or count
+end
+local function validspecification(specification,name)
+ local dataset=specification.dataset
+ if dataset then
+ elseif specification[1] then
+ dataset=specification
+ specification={ dataset=dataset }
+ else
+ dataset={ { data=specification.data } }
+ specification.data=nil
+ specification.dataset=dataset
+ end
+ local first=dataset[1]
+ if first then
+ first=first.data
+ end
+ if not first then
+ report_otf("invalid feature specification, no dataset")
+ return
+ end
+ if type(name)~="string" then
+ name=specification.name or first.name
+ end
+ if type(name)~="string" then
+ report_otf("invalid feature specification, no name")
+ return
+ end
+ local n=#dataset
+ if n>0 then
+ for i=1,n do
+ setmetatableindex(dataset[i],specification)
+ end
+ return specification,name
+ end
+end
+local function addfeature(data,feature,specifications)
+ if not specifications then
+ report_otf("missing specification")
+ return
+ end
+ local descriptions=data.descriptions
+ local resources=data.resources
+ local features=resources.features
+ local sequences=resources.sequences
+ if not features or not sequences then
+ report_otf("missing specification")
+ return
+ end
+ local alreadydone=resources.alreadydone
+ if not alreadydone then
+ alreadydone={}
+ resources.alreadydone=alreadydone
+ end
+ if alreadydone[specifications] then
+ return
+ else
+ alreadydone[specifications]=true
+ end
+ local fontfeatures=resources.features or everywhere
+ local unicodes=resources.unicodes
+ local splitter=lpeg.splitter(" ",unicodes)
+ local done=0
+ local skip=0
+ local aglunicodes=false
+ local specifications=validspecification(specifications,feature)
+ if not specifications then
+ return
+ end
+ local function tounicode(code)
+ if not code then
+ return
+ end
+ if type(code)=="number" then
+ return code
+ end
+ local u=unicodes[code]
+ if u then
+ return u
+ end
+ if utflen(code)==1 then
+ u=utfbyte(code)
+ if u then
+ return u
+ end
+ end
+ if not aglunicodes then
+ aglunicodes=fonts.encodings.agl.unicodes
+ end
+ return aglunicodes[code]
+ end
+ local coverup=otf.coverup
+ local coveractions=coverup.actions
+ local stepkey=coverup.stepkey
+ local register=coverup.register
+ local function prepare_substitution(list,featuretype)
+ local coverage={}
+ local cover=coveractions[featuretype]
+ for code,replacement in next,list do
+ local unicode=tounicode(code)
+ local description=descriptions[unicode]
+ if description then
+ if type(replacement)=="table" then
+ replacement=replacement[1]
+ end
+ replacement=tounicode(replacement)
+ if replacement and descriptions[replacement] then
+ cover(coverage,unicode,replacement)
+ done=done+1
+ else
+ skip=skip+1
+ end
+ else
+ skip=skip+1
+ end
+ end
+ return coverage
+ end
+ local function prepare_alternate(list,featuretype)
+ local coverage={}
+ local cover=coveractions[featuretype]
+ for code,replacement in next,list do
+ local unicode=tounicode(code)
+ local description=descriptions[unicode]
+ if not description then
+ skip=skip+1
+ elseif type(replacement)=="table" then
+ local r={}
+ for i=1,#replacement do
+ local u=tounicode(replacement[i])
+ r[i]=descriptions[u] and u or unicode
+ end
+ cover(coverage,unicode,r)
+ done=done+1
+ else
+ local u=tounicode(replacement)
+ if u then
+ cover(coverage,unicode,{ u })
+ done=done+1
+ else
+ skip=skip+1
+ end
+ end
+ end
+ return coverage
+ end
+ local function prepare_multiple(list,featuretype)
+ local coverage={}
+ local cover=coveractions[featuretype]
+ for code,replacement in next,list do
+ local unicode=tounicode(code)
+ local description=descriptions[unicode]
+ if not description then
+ skip=skip+1
+ elseif type(replacement)=="table" then
+ local r,n={},0
+ for i=1,#replacement do
+ local u=tounicode(replacement[i])
+ if descriptions[u] then
+ n=n+1
+ r[n]=u
+ end
+ end
+ if n>0 then
+ cover(coverage,unicode,r)
+ done=done+1
+ else
+ skip=skip+1
+ end
+ else
+ local u=tounicode(replacement)
+ if u then
+ cover(coverage,unicode,{ u })
+ done=done+1
+ else
+ skip=skip+1
+ end
+ end
+ end
+ return coverage
+ end
+ local function prepare_ligature(list,featuretype)
+ local coverage={}
+ local cover=coveractions[featuretype]
+ for code,ligature in next,list do
+ local unicode=tounicode(code)
+ local description=descriptions[unicode]
+ if description then
+ if type(ligature)=="string" then
+ ligature={ lpegmatch(splitter,ligature) }
+ end
+ local present=true
+ for i=1,#ligature do
+ local l=ligature[i]
+ local u=tounicode(l)
+ if descriptions[u] then
+ ligature[i]=u
+ else
+ present=false
+ break
+ end
+ end
+ if present then
+ cover(coverage,unicode,ligature)
+ done=done+1
+ else
+ skip=skip+1
+ end
+ else
+ skip=skip+1
+ end
+ end
+ return coverage
+ end
+ local function prepare_kern(list,featuretype)
+ local coverage={}
+ local cover=coveractions[featuretype]
+ for code,replacement in next,list do
+ local unicode=tounicode(code)
+ local description=descriptions[unicode]
+ if description and type(replacement)=="table" then
+ local r={}
+ for k,v in next,replacement do
+ local u=tounicode(k)
+ if u then
+ r[u]=v
+ end
+ end
+ if next(r) then
+ cover(coverage,unicode,r)
+ done=done+1
+ else
+ skip=skip+1
+ end
+ else
+ skip=skip+1
+ end
+ end
+ return coverage
+ end
+ local function prepare_pair(list,featuretype)
+ local coverage={}
+ local cover=coveractions[featuretype]
+ if cover then
+ for code,replacement in next,list do
+ local unicode=tounicode(code)
+ local description=descriptions[unicode]
+ if description and type(replacement)=="table" then
+ local r={}
+ for k,v in next,replacement do
+ local u=tounicode(k)
+ if u then
+ r[u]=v
+ end
+ end
+ if next(r) then
+ cover(coverage,unicode,r)
+ done=done+1
+ else
+ skip=skip+1
+ end
+ else
+ skip=skip+1
+ end
+ end
+ else
+ report_otf("unknown cover type %a",featuretype)
+ end
+ return coverage
+ end
+ local function prepare_chain(list,featuretype,sublookups)
+ local rules=list.rules
+ local coverage={}
+ if rules then
+ local rulehash={}
+ local rulesize=0
+ local sequence={}
+ local nofsequences=0
+ local lookuptype=types[featuretype]
+ for nofrules=1,#rules do
+ local rule=rules[nofrules]
+ local current=rule.current
+ local before=rule.before
+ local after=rule.after
+ local replacements=rule.replacements or false
+ local sequence={}
+ local nofsequences=0
+ if before then
+ for n=1,#before do
+ nofsequences=nofsequences+1
+ sequence[nofsequences]=before[n]
+ end
+ end
+ local start=nofsequences+1
+ for n=1,#current do
+ nofsequences=nofsequences+1
+ sequence[nofsequences]=current[n]
+ end
+ local stop=nofsequences
+ if after then
+ for n=1,#after do
+ nofsequences=nofsequences+1
+ sequence[nofsequences]=after[n]
+ end
+ end
+ local lookups=rule.lookups or false
+ local subtype=nil
+ if lookups and sublookups then
+ for k,v in next,lookups do
+ local lookup=sublookups[v]
+ if lookup then
+ lookups[k]=lookup
+ if not subtype then
+ subtype=lookup.type
+ end
+ else
+ end
+ end
+ end
+ if nofsequences>0 then
+ local hashed={}
+ for i=1,nofsequences do
+ local t={}
+ local s=sequence[i]
+ for i=1,#s do
+ local u=tounicode(s[i])
+ if u then
+ t[u]=true
+ end
+ end
+ hashed[i]=t
+ end
+ sequence=hashed
+ rulesize=rulesize+1
+ rulehash[rulesize]={
+ nofrules,
+ lookuptype,
+ sequence,
+ start,
+ stop,
+ lookups,
+ replacements,
+ subtype,
+ }
+ for unic in next,sequence[start] do
+ local cu=coverage[unic]
+ if not cu then
+ coverage[unic]=rulehash
+ end
+ end
+ end
+ end
+ end
+ return coverage
+ end
+ local dataset=specifications.dataset
+ local function report(name,category,position,first,last,sequences)
+ report_otf("injecting name %a of category %a at position %i in [%i,%i] of [%i,%i]",
+ name,category,position,first,last,1,#sequences)
+ end
+ local function inject(specification,sequences,sequence,first,last,category,name)
+ local position=specification.position or false
+ if not position then
+ position=specification.prepend
+ if position==true then
+ if trace_loading then
+ report(name,category,first,first,last,sequences)
+ end
+ insert(sequences,first,sequence)
+ return
+ end
+ end
+ if not position then
+ position=specification.append
+ if position==true then
+ if trace_loading then
+ report(name,category,last+1,first,last,sequences)
+ end
+ insert(sequences,last+1,sequence)
+ return
+ end
+ end
+ local kind=type(position)
+ if kind=="string" then
+ local index=false
+ for i=first,last do
+ local s=sequences[i]
+ local f=s.features
+ if f then
+ for k in next,f do
+ if k==position then
+ index=i
+ break
+ end
+ end
+ if index then
+ break
+ end
+ end
+ end
+ if index then
+ position=index
+ else
+ position=last+1
+ end
+ elseif kind=="number" then
+ if position<0 then
+ position=last-position+1
+ end
+ if position>last then
+ position=last+1
+ elseif position<first then
+ position=first
+ end
+ else
+ position=last+1
+ end
+ if trace_loading then
+ report(name,category,position,first,last,sequences)
+ end
+ insert(sequences,position,sequence)
+ end
+ for s=1,#dataset do
+ local specification=dataset[s]
+ local valid=specification.valid
+ local feature=specification.name or feature
+ if not feature or feature=="" then
+ report_otf("no valid name given for extra feature")
+ elseif not valid or valid(data,specification,feature) then
+ local initialize=specification.initialize
+ if initialize then
+ specification.initialize=initialize(specification,data) and initialize or nil
+ end
+ local askedfeatures=specification.features or everywhere
+ local askedsteps=specification.steps or specification.subtables or { specification.data } or {}
+ local featuretype=normalized[specification.type or "substitution"] or "substitution"
+ local featureflags=specification.flags or noflags
+ local featureorder=specification.order or { feature }
+ local featurechain=(featuretype=="chainsubstitution" or featuretype=="chainposition") and 1 or 0
+ local nofsteps=0
+ local steps={}
+ local sublookups=specification.lookups
+ local category=nil
+ if sublookups then
+ local s={}
+ for i=1,#sublookups do
+ local specification=sublookups[i]
+ local askedsteps=specification.steps or specification.subtables or { specification.data } or {}
+ local featuretype=normalized[specification.type or "substitution"] or "substitution"
+ local featureflags=specification.flags or noflags
+ local nofsteps=0
+ local steps={}
+ for i=1,#askedsteps do
+ local list=askedsteps[i]
+ local coverage=nil
+ local format=nil
+ if featuretype=="substitution" then
+ coverage=prepare_substitution(list,featuretype)
+ elseif featuretype=="ligature" then
+ coverage=prepare_ligature(list,featuretype)
+ elseif featuretype=="alternate" then
+ coverage=prepare_alternate(list,featuretype)
+ elseif featuretype=="multiple" then
+ coverage=prepare_multiple(list,featuretype)
+ elseif featuretype=="kern" then
+ format="kern"
+ coverage=prepare_kern(list,featuretype)
+ elseif featuretype=="pair" then
+ format="pair"
+ coverage=prepare_pair(list,featuretype)
+ end
+ if coverage and next(coverage) then
+ nofsteps=nofsteps+1
+ steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
+ end
+ end
+ s[i]={
+ [stepkey]=steps,
+ nofsteps=nofsteps,
+ type=types[featuretype],
+ }
+ end
+ sublookups=s
+ end
+ for i=1,#askedsteps do
+ local list=askedsteps[i]
+ local coverage=nil
+ local format=nil
+ if featuretype=="substitution" then
+ category="gsub"
+ coverage=prepare_substitution(list,featuretype)
+ elseif featuretype=="ligature" then
+ category="gsub"
+ coverage=prepare_ligature(list,featuretype)
+ elseif featuretype=="alternate" then
+ category="gsub"
+ coverage=prepare_alternate(list,featuretype)
+ elseif featuretype=="multiple" then
+ category="gsub"
+ coverage=prepare_multiple(list,featuretype)
+ elseif featuretype=="kern" then
+ category="gpos"
+ format="kern"
+ coverage=prepare_kern(list,featuretype)
+ elseif featuretype=="pair" then
+ category="gpos"
+ format="pair"
+ coverage=prepare_pair(list,featuretype)
+ elseif featuretype=="chainsubstitution" then
+ category="gsub"
+ coverage=prepare_chain(list,featuretype,sublookups)
+ elseif featuretype=="chainposition" then
+ category="gpos"
+ coverage=prepare_chain(list,featuretype,sublookups)
+ else
+ report_otf("not registering feature %a, unknown category",feature)
+ return
+ end
+ if coverage and next(coverage) then
+ nofsteps=nofsteps+1
+ steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
+ end
+ end
+ if nofsteps>0 then
+ for k,v in next,askedfeatures do
+ if v[1] then
+ askedfeatures[k]=tohash(v)
+ end
+ end
+ if featureflags[1] then featureflags[1]="mark" end
+ if featureflags[2] then featureflags[2]="ligature" end
+ if featureflags[3] then featureflags[3]="base" end
+ local steptype=types[featuretype]
+ local sequence={
+ chain=featurechain,
+ features={ [feature]=askedfeatures },
+ flags=featureflags,
+ name=feature,
+ order=featureorder,
+ [stepkey]=steps,
+ nofsteps=nofsteps,
+ type=steptype,
+ }
+ local first,last=getrange(sequences,category)
+ inject(specification,sequences,sequence,first,last,category,feature)
+ local features=fontfeatures[category]
+ if not features then
+ features={}
+ fontfeatures[category]=features
+ end
+ local k=features[feature]
+ if not k then
+ k={}
+ features[feature]=k
+ end
+ for script,languages in next,askedfeatures do
+ local kk=k[script]
+ if not kk then
+ kk={}
+ k[script]=kk
+ end
+ for language,value in next,languages do
+ kk[language]=value
+ end
+ end
+ end
+ end
+ end
+ if trace_loading then
+ report_otf("registering feature %a, affected glyphs %a, skipped glyphs %a",feature,done,skip)
+ end
+end
+otf.enhancers.addfeature=addfeature
+local extrafeatures={}
+local knownfeatures={}
+function otf.addfeature(name,specification)
+ if type(name)=="table" then
+ specification=name
+ end
+ if type(specification)~="table" then
+ report_otf("invalid feature specification, no valid table")
+ return
+ end
+ specification,name=validspecification(specification,name)
+ if name and specification then
+ local slot=knownfeatures[name]
+ if slot then
+ else
+ slot=#extrafeatures+1
+ knownfeatures[name]=slot
+ end
+ specification.name=name
+ extrafeatures[slot]=specification
+ end
+end
+local function enhance(data,filename,raw)
+ for slot=1,#extrafeatures do
+ local specification=extrafeatures[slot]
+ addfeature(data,specification.name,specification)
+ end
+end
+otf.enhancers.enhance=enhance
+otf.enhancers.register("check extra features",enhance)
+local tlig={
+ [0x2013]={ 0x002D,0x002D },
+ [0x2014]={ 0x002D,0x002D,0x002D },
+}
+local tlig_specification={
+ type="ligature",
+ features=everywhere,
+ data=tlig,
+ order={ "tlig" },
+ flags=noflags,
+ prepend=true,
+}
+otf.addfeature("tlig",tlig_specification)
+registerotffeature {
+ name='tlig',
+ description='tex ligatures',
+}
+local trep={
+ [0x0027]=0x2019,
+}
+local trep_specification={
+ type="substitution",
+ features=everywhere,
+ data=trep,
+ order={ "trep" },
+ flags=noflags,
+ prepend=true,
+}
+otf.addfeature("trep",trep_specification)
+registerotffeature {
+ name='trep',
+ description='tex replacements',
+}
+local anum_arabic={
+ [0x0030]=0x0660,
+ [0x0031]=0x0661,
+ [0x0032]=0x0662,
+ [0x0033]=0x0663,
+ [0x0034]=0x0664,
+ [0x0035]=0x0665,
+ [0x0036]=0x0666,
+ [0x0037]=0x0667,
+ [0x0038]=0x0668,
+ [0x0039]=0x0669,
+}
+local anum_persian={
+ [0x0030]=0x06F0,
+ [0x0031]=0x06F1,
+ [0x0032]=0x06F2,
+ [0x0033]=0x06F3,
+ [0x0034]=0x06F4,
+ [0x0035]=0x06F5,
+ [0x0036]=0x06F6,
+ [0x0037]=0x06F7,
+ [0x0038]=0x06F8,
+ [0x0039]=0x06F9,
+}
+local function valid(data)
+ local features=data.resources.features
+ if features then
+ for k,v in next,features do
+ for k,v in next,v do
+ if v.arab then
+ return true
+ end
+ end
+ end
+ end
+end
+local anum_specification={
+ {
+ type="substitution",
+ features={ arab={ urd=true,dflt=true } },
+ order={ "anum" },
+ data=anum_arabic,
+ flags=noflags,
+ valid=valid,
+ },
+ {
+ type="substitution",
+ features={ arab={ urd=true } },
+ order={ "anum" },
+ data=anum_persian,
+ flags=noflags,
+ valid=valid,
+ },
+}
+otf.addfeature("anum",anum_specification)
+registerotffeature {
+ name='anum',
+ description='arabic digits',
+}
+
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-otc”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-onr” a802cb0b7c5152d7f7f99927131118e9] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-onr” 205c8bc640715aecf3538a33b842f450] ---
if not modules then modules={} end modules ['font-onr']={
version=1.001,
@@ -18182,51 +19163,25 @@ if not modules then modules={} end modules ['font-onr']={
license="see context related readme files"
}
local fonts,logs,trackers,resolvers=fonts,logs,trackers,resolvers
-local next,type,tonumber,rawget=next,type,tonumber,rawget
+local next,type,tonumber,rawget,rawset=next,type,tonumber,rawget,rawset
local match,lower,gsub,strip,find=string.match,string.lower,string.gsub,string.strip,string.find
local char,byte,sub=string.char,string.byte,string.sub
local abs=math.abs
local bxor,rshift=bit32.bxor,bit32.rshift
-local P,S,R,Cmt,C,Ct,Cs,Carg=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg
+local P,S,R,Cmt,C,Ct,Cs,Carg,Cf,Cg=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg,lpeg.Cf,lpeg.Cg
local lpegmatch,patterns=lpeg.match,lpeg.patterns
local trace_indexing=false trackers.register("afm.indexing",function(v) trace_indexing=v end)
local trace_loading=false trackers.register("afm.loading",function(v) trace_loading=v end)
local report_afm=logs.reporter("fonts","afm loading")
-local report_afm=logs.reporter("fonts","pfb loading")
-fonts=fonts or {}
-local handlers=fonts.handlers or {}
-fonts.handlers=handlers
+local report_pfb=logs.reporter("fonts","pfb loading")
+local handlers=fonts.handlers
local afm=handlers.afm or {}
handlers.afm=afm
local readers=afm.readers or {}
afm.readers=readers
afm.version=1.512
-local get_indexes
+local get_indexes,get_shapes
do
- local n,m
- local progress=function(str,position,name,size)
- local forward=position+tonumber(size)+3+2
- n=n+1
- if n>=m then
- return #str,name
- elseif forward<#str then
- return forward,name
- else
- return #str,name
- end
- end
- local initialize=function(str,position,size)
- n=0
- m=tonumber(size)
- return position+1
- end
- local charstrings=P("/CharStrings")
- local name=P("/")*C((R("az")+R("AZ")+R("09")+S("-_."))^1)
- local size=C(R("09")^1)
- local spaces=P(" ")^1
- local p_filternames=Ct (
- (1-charstrings)^0*charstrings*spaces*Cmt(size,initialize)*(Cmt(name*P(" ")^1*C(R("09")^1),progress)+P(1))^1
- )
local decrypt
do
local r,c1,c2,n=0,0,0,0
@@ -18236,13 +19191,75 @@ do
r=((cipher+r)*c1+c2)%65536
return char(plain)
end
- decrypt=function(binary)
- r,c1,c2,n=55665,52845,22719,4
+ decrypt=function(binary,initial,seed)
+ r,c1,c2,n=initial,52845,22719,seed
binary=gsub(binary,".",step)
return sub(binary,n+1)
end
end
- local function loadpfbvector(filename)
+ local charstrings=P("/CharStrings")
+ local subroutines=P("/Subrs")
+ local encoding=P("/Encoding")
+ local dup=P("dup")
+ local put=P("put")
+ local array=P("array")
+ local name=P("/")*C((R("az")+R("AZ")+R("09")+S("-_."))^1)
+ local digits=R("09")^1
+ local cardinal=digits/tonumber
+ local spaces=P(" ")^1
+ local spacing=patterns.whitespace^0
+ local routines,vector,chars,n,m
+ local initialize=function(str,position,size)
+ n=0
+ m=size
+ return position+1
+ end
+ local setroutine=function(str,position,index,size)
+ local forward=position+tonumber(size)
+ local stream=sub(str,position+1,forward)
+ routines[index]=decrypt(stream,4330,4)
+ return forward
+ end
+ local setvector=function(str,position,name,size)
+ local forward=position+tonumber(size)
+ if n>=m then
+ return #str
+ elseif forward<#str then
+ vector[n]=name
+ n=n+1
+ return forward
+ else
+ return #str
+ end
+ end
+ local setshapes=function(str,position,name,size)
+ local forward=position+tonumber(size)
+ local stream=sub(str,position+1,forward)
+ if n>m then
+ return #str
+ elseif forward<#str then
+ vector[n]=name
+ n=n+1
+ chars [n]=decrypt(stream,4330,4)
+ return forward
+ else
+ return #str
+ end
+ end
+ local p_rd=spacing*(P("RD")+P("-|"))
+ local p_np=spacing*(P("NP")+P("|"))
+ local p_nd=spacing*(P("ND")+P("|"))
+ local p_filterroutines=
+ (1-subroutines)^0*subroutines*spaces*Cmt(cardinal,initialize)*(Cmt(cardinal*spaces*cardinal*p_rd,setroutine)*p_np+P(1))^1
+ local p_filtershapes=
+ (1-charstrings)^0*charstrings*spaces*Cmt(cardinal,initialize)*(Cmt(name*spaces*cardinal*p_rd,setshapes)*p_nd+P(1))^1
+ local p_filternames=Ct (
+ (1-charstrings)^0*charstrings*spaces*Cmt(cardinal,initialize)*(Cmt(name*spaces*cardinal,setvector)+P(1))^1
+ )
+ local p_filterencoding=(1-encoding)^0*encoding*spaces*digits*spaces*array*(1-dup)^0*Cf(
+ Ct("")*Cg(spacing*dup*spaces*cardinal*spaces*name*spaces*put)^1
+,rawset)
+ local function loadpfbvector(filename,shapestoo)
local data=io.loaddata(resolvers.findfile(filename))
if not data then
report_pfb("no data in %a",filename)
@@ -18257,17 +19274,34 @@ do
report_pfb("no binary data in %a",filename)
return
end
- binary=decrypt(binary,4)
- local vector=lpegmatch(p_filternames,binary)
- if vector[1]==".notdef" then
- vector[0]=table.remove(vector,1)
- end
- if not vector then
- report_pfb("no vector in %a",filename)
- return
+ binary=decrypt(binary,55665,4)
+ local names={}
+ local encoding=lpegmatch(p_filterencoding,ascii)
+ local glyphs={}
+ routines,vector,chars={},{},{}
+ if shapestoo then
+ lpegmatch(p_filterroutines,binary)
+ lpegmatch(p_filtershapes,binary)
+ local data={
+ dictionaries={
+ {
+ charstrings=chars,
+ charset=vector,
+ subroutines=routines,
+ }
+ },
+ }
+ fonts.handlers.otf.readers.parsecharstrings(data,glyphs,true,true)
+ else
+ lpegmatch(p_filternames,binary)
end
- return vector
+ names=vector
+ routines,vector,chars=nil,nil,nil
+ return names,encoding,glyphs
end
+ local pfb=handlers.pfb or {}
+ handlers.pfb=pfb
+ pfb.loadvector=loadpfbvector
get_indexes=function(data,pfbname)
local vector=loadpfbvector(pfbname)
if vector then
@@ -18287,6 +19321,10 @@ do
end
end
end
+ get_shapes=function(pfbname)
+ local vector,encoding,glyphs=loadpfbvector(pfbname,true)
+ return glyphs
+ end
end
local spacer=patterns.spacer
local whitespace=patterns.whitespace
@@ -18435,6 +19473,22 @@ function readers.loadfont(afmname,pfbname)
return data
end
end
+function readers.loadshapes(filename)
+ local fullname=resolvers.findfile(filename) or ""
+ if fullname=="" then
+ return {
+ filename="not found: "..filename,
+ glyphs={}
+ }
+ else
+ return {
+ filename=fullname,
+ format="opentype",
+ glyphs=get_shapes(fullname) or {},
+ units=1000,
+ }
+ end
+end
function readers.getinfo(filename)
local data=read(resolvers.findfile(filename),infoparser)
if data then
@@ -18442,10 +19496,10 @@ function readers.getinfo(filename)
end
end
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-onr”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-onr”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-one” 199a7b4720b9931180f289703c4fcb97] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-one” 6fbf6b9e219a944cd1ad5933d77cc488] ---
if not modules then modules={} end modules ['font-one']={
version=1.001,
@@ -18480,36 +19534,15 @@ local otfreaders=otf.readers
local otfenhancers=otf.enhancers
local afmfeatures=constructors.features.afm
local registerafmfeature=afmfeatures.register
+local afmenhancers=constructors.enhancers.afm
+local registerafmenhancer=afmenhancers.register
afm.version=1.512
-afm.cache=containers.define("fonts","afm",afm.version,true)
+afm.cache=containers.define("fonts","one",afm.version,true)
afm.autoprefixed=true
afm.helpdata={}
afm.syncspace=true
local overloads=fonts.mappings.overloads
local applyruntimefixes=fonts.treatments and fonts.treatments.applyfixes
-local enhancers={
-}
-local steps={
- "unify names",
- "add ligatures",
- "add extra kerns",
- "normalize features",
- "fix names",
-}
-local function applyenhancers(data,filename)
- for i=1,#steps do
- local step=steps[i]
- local enhancer=enhancers[step]
- if enhancer then
- if trace_loading then
- report_afm("applying enhancer %a",step)
- end
- enhancer(data,filename)
- else
- report_afm("invalid enhancer %a",step)
- end
- end
-end
function afm.load(filename)
filename=resolvers.findfile(filename,'afm') or ""
if filename~="" and not fonts.names.ignoredfile(filename) then
@@ -18532,7 +19565,7 @@ function afm.load(filename)
report_afm("reading %a",filename)
data=afm.readers.loadfont(filename,pfbname)
if data then
- applyenhancers(data,filename)
+ afmenhancers.apply(data,filename)
fonts.mappings.addtounicode(data,filename)
otfreaders.pack(data)
data.size=size
@@ -18557,7 +19590,7 @@ function afm.load(filename)
end
end
local uparser=fonts.mappings.makenameparser()
-enhancers["unify names"]=function(data,filename)
+local function enhance_unify_names(data,filename)
local unicodevector=fonts.encodings.agl.unicodes
local unicodes={}
local names={}
@@ -18609,7 +19642,7 @@ enhancers["unify names"]=function(data,filename)
end
local everywhere={ ["*"]={ ["*"]=true } }
local noflags={ false,false,false,false }
-enhancers["normalize features"]=function(data)
+local function enhance_normalize_features(data)
local ligatures=setmetatableindex("table")
local kerns=setmetatableindex("table")
local extrakerns=setmetatableindex("table")
@@ -18707,7 +19740,7 @@ enhancers["normalize features"]=function(data)
data.resources.features=features
data.resources.sequences=sequences
end
-enhancers["fix names"]=function(data)
+local function enhance_fix_names(data)
for k,v in next,data.descriptions do
local n=v.name
local r=overloads[n]
@@ -18746,10 +19779,10 @@ local addthem=function(rawdata,ligatures)
end
end
end
-enhancers["add ligatures"]=function(rawdata)
+local function enhance_add_ligatures(rawdata)
addthem(rawdata,afm.helpdata.ligatures)
end
-enhancers["add extra kerns"]=function(rawdata)
+local function enhance_add_extra_kerns(rawdata)
local descriptions=rawdata.descriptions
local resources=rawdata.resources
local unicodes=resources.unicodes
@@ -19068,17 +20101,12 @@ local function read_from_afm(specification)
end
return tfmdata
end
-local function setmode(tfmdata,value)
- if value then
- tfmdata.properties.mode=lower(value)
- end
-end
registerafmfeature {
name="mode",
description="mode",
initializers={
- base=setmode,
- node=setmode,
+ base=otf.modeinitializer,
+ node=otf.modeinitializer,
}
}
registerafmfeature {
@@ -19093,7 +20121,6 @@ registerafmfeature {
node=otf.featuresprocessor,
}
}
-local check_tfm=readers.check_tfm
fonts.formats.afm="type1"
fonts.formats.pfb="type1"
local function check_afm(specification,fullname)
@@ -19128,7 +20155,8 @@ function readers.afm(specification,method)
tfmdata=check_afm(specification,specification.name.."."..forced)
end
if not tfmdata then
- method=method or definers.method or "afm or tfm"
+ local check_tfm=readers.check_tfm
+ method=(check_tfm and (method or definers.method or "afm or tfm")) or "afm"
if method=="tfm" then
tfmdata=check_tfm(specification,specification.name)
elseif method=="afm" then
@@ -19162,11 +20190,17 @@ function readers.pfb(specification,method)
swap("specification")
return readers.afm(specification,method)
end
+registerafmenhancer("unify names",enhance_unify_names)
+registerafmenhancer("add ligatures",enhance_add_ligatures)
+registerafmenhancer("add extra kerns",enhance_add_extra_kerns)
+registerafmenhancer("normalize features",enhance_normalize_features)
+registerafmenhancer("check extra features",otfenhancers.enhance)
+registerafmenhancer("fix names",enhance_fix_names)
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-one”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-one”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-afk” b36a76ceb835f41f8c05b471000ddc14] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-afk” b36a76ceb835f41f8c05b471000ddc14] ---
if not modules then modules={} end modules ['font-afk']={
version=1.001,
@@ -19333,10 +20367,519 @@ fonts.handlers.afm.helpdata={
}
}
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-afk”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-afk”] ---
+
+
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-tfm” 3d813578dbf6c447e4b859c2bf0618f7] ---
+
+if not modules then modules={} end modules ['font-tfm']={
+ version=1.001,
+ comment="companion to font-ini.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local next,type=next,type
+local match,format=string.match,string.format
+local concat,sortedhash=table.concat,table.sortedhash
+local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
+local trace_features=false trackers.register("tfm.features",function(v) trace_features=v end)
+local report_defining=logs.reporter("fonts","defining")
+local report_tfm=logs.reporter("fonts","tfm loading")
+local findbinfile=resolvers.findbinfile
+local setmetatableindex=table.setmetatableindex
+local fonts=fonts
+local handlers=fonts.handlers
+local readers=fonts.readers
+local constructors=fonts.constructors
+local encodings=fonts.encodings
+local tfm=constructors.handlers.tfm
+tfm.version=1.000
+tfm.maxnestingdepth=5
+tfm.maxnestingsize=65536*1024
+local otf=fonts.handlers.otf
+local otfenhancers=otf.enhancers
+local tfmfeatures=constructors.features.tfm
+local registertfmfeature=tfmfeatures.register
+local tfmenhancers=constructors.enhancers.tfm
+local registertfmenhancer=tfmenhancers.register
+constructors.resolvevirtualtoo=false
+fonts.formats.tfm="type1"
+fonts.formats.ofm="type1"
+function tfm.setfeatures(tfmdata,features)
+ local okay=constructors.initializefeatures("tfm",tfmdata,features,trace_features,report_tfm)
+ if okay then
+ return constructors.collectprocessors("tfm",tfmdata,features,trace_features,report_tfm)
+ else
+ return {}
+ end
+end
+local depth={}
+local function read_from_tfm(specification)
+ local filename=specification.filename
+ local size=specification.size
+ depth[filename]=(depth[filename] or 0)+1
+ if trace_defining then
+ report_defining("loading tfm file %a at size %s",filename,size)
+ end
+ local tfmdata=font.read_tfm(filename,size)
+ if tfmdata then
+ local features=specification.features and specification.features.normal or {}
+ local features=constructors.checkedfeatures("tfm",features)
+ specification.features.normal=features
+ local newtfmdata=(depth[filename]==1) and tfm.reencode(tfmdata,specification)
+ if newtfmdata then
+ tfmdata=newtfmdata
+ end
+ local resources=tfmdata.resources or {}
+ local properties=tfmdata.properties or {}
+ local parameters=tfmdata.parameters or {}
+ local shared=tfmdata.shared or {}
+ shared.features=features
+ shared.resources=resources
+ properties.name=tfmdata.name
+ properties.fontname=tfmdata.fontname
+ properties.psname=tfmdata.psname
+ properties.fullname=tfmdata.fullname
+ properties.filename=specification.filename
+ properties.format=fonts.formats.tfm
+ tfmdata.properties=properties
+ tfmdata.resources=resources
+ tfmdata.parameters=parameters
+ tfmdata.shared=shared
+ shared.rawdata={ resources=resources }
+ shared.features=features
+ if newtfmdata then
+ if not resources.marks then
+ resources.marks={}
+ end
+ if not resources.sequences then
+ resources.sequences={}
+ end
+ if not resources.features then
+ resources.features={
+ gsub={},
+ gpos={},
+ }
+ end
+ if not tfmdata.changed then
+ tfmdata.changed={}
+ end
+ if not tfmdata.descriptions then
+ tfmdata.descriptions=tfmdata.characters
+ end
+ otf.readers.addunicodetable(tfmdata)
+ tfmenhancers.apply(tfmdata,filename)
+ constructors.applymanipulators("tfm",tfmdata,features,trace_features,report_tfm)
+ otf.readers.unifymissing(tfmdata)
+ fonts.mappings.addtounicode(tfmdata,filename)
+ tfmdata.tounicode=1
+ local tounicode=fonts.mappings.tounicode
+ for unicode,v in next,tfmdata.characters do
+ local u=v.unicode
+ if u then
+ v.tounicode=tounicode(u)
+ end
+ end
+ if tfmdata.usedbitmap then
+ tfm.addtounicode(tfmdata)
+ end
+ end
+ shared.processes=next(features) and tfm.setfeatures(tfmdata,features) or nil
+ parameters.factor=1
+ parameters.size=size
+ parameters.slant=parameters.slant or parameters[1] or 0
+ parameters.space=parameters.space or parameters[2] or 0
+ parameters.space_stretch=parameters.space_stretch or parameters[3] or 0
+ parameters.space_shrink=parameters.space_shrink or parameters[4] or 0
+ parameters.x_height=parameters.x_height or parameters[5] or 0
+ parameters.quad=parameters.quad or parameters[6] or 0
+ parameters.extra_space=parameters.extra_space or parameters[7] or 0
+ constructors.enhanceparameters(parameters)
+ if newtfmdata then
+ elseif constructors.resolvevirtualtoo then
+ fonts.loggers.register(tfmdata,file.suffix(filename),specification)
+ local vfname=findbinfile(specification.name,'ovf')
+ if vfname and vfname~="" then
+ local vfdata=font.read_vf(vfname,size)
+ if vfdata then
+ local chars=tfmdata.characters
+ for k,v in next,vfdata.characters do
+ chars[k].commands=v.commands
+ end
+ properties.virtualized=true
+ tfmdata.fonts=vfdata.fonts
+ tfmdata.type="virtual"
+ local fontlist=vfdata.fonts
+ local name=file.nameonly(filename)
+ for i=1,#fontlist do
+ local n=fontlist[i].name
+ local s=fontlist[i].size
+ local d=depth[filename]
+ s=constructors.scaled(s,vfdata.designsize)
+ if d>tfm.maxnestingdepth then
+ report_defining("too deeply nested virtual font %a with size %a, max nesting depth %s",n,s,tfm.maxnestingdepth)
+ fontlist[i]={ id=0 }
+ elseif (d>1) and (s>tfm.maxnestingsize) then
+ report_defining("virtual font %a exceeds size %s",n,s)
+ fontlist[i]={ id=0 }
+ else
+ local t,id=fonts.constructors.readanddefine(n,s)
+ fontlist[i]={ id=id }
+ end
+ end
+ end
+ end
+ end
+ properties.haskerns=true
+ properties.hasligatures=true
+ resources.unicodes={}
+ resources.lookuptags={}
+ depth[filename]=depth[filename]-1
+ return tfmdata
+ else
+ depth[filename]=depth[filename]-1
+ end
+end
+local function check_tfm(specification,fullname)
+ local foundname=findbinfile(fullname,'tfm') or ""
+ if foundname=="" then
+ foundname=findbinfile(fullname,'ofm') or ""
+ end
+ if foundname=="" then
+ foundname=fonts.names.getfilename(fullname,"tfm") or ""
+ end
+ if foundname~="" then
+ specification.filename=foundname
+ specification.format="ofm"
+ return read_from_tfm(specification)
+ elseif trace_defining then
+ report_defining("loading tfm with name %a fails",specification.name)
+ end
+end
+readers.check_tfm=check_tfm
+function readers.tfm(specification)
+ local fullname=specification.filename or ""
+ if fullname=="" then
+ local forced=specification.forced or ""
+ if forced~="" then
+ fullname=specification.name.."."..forced
+ else
+ fullname=specification.name
+ end
+ end
+ return check_tfm(specification,fullname)
+end
+readers.ofm=readers.tfm
+do
+ local outfiles={}
+ local tfmcache=table.setmetatableindex(function(t,tfmdata)
+ local id=font.define(tfmdata)
+ t[tfmdata]=id
+ return id
+ end)
+ local encdone=table.setmetatableindex("table")
+ function tfm.reencode(tfmdata,specification)
+ local features=specification.features
+ if not features then
+ return
+ end
+ local features=features.normal
+ if not features then
+ return
+ end
+ local tfmfile=file.basename(tfmdata.name)
+ local encfile=features.reencode
+ local pfbfile=features.pfbfile
+ local bitmap=features.bitmap
+ if not encfile then
+ return
+ end
+ local pfbfile=outfiles[tfmfile]
+ if pfbfile==nil then
+ if bitmap then
+ pfbfile=false
+ elseif type(pfbfile)~="string" then
+ pfbfile=tfmfile
+ end
+ if type(pfbfile)=="string" then
+ pfbfile=file.addsuffix(pfbfile,"pfb")
+ report_tfm("using type1 shapes from %a for %a",pfbfile,tfmfile)
+ else
+ report_tfm("using bitmap shapes for %a",tfmfile)
+ pfbfile=false
+ end
+ outfiles[tfmfile]=pfbfile
+ end
+ local encoding=false
+ local vector=false
+ if type(pfbfile)=="string" then
+ local pfb=fonts.constructors.handlers.pfb
+ if pfb and pfb.loadvector then
+ local v,e=pfb.loadvector(pfbfile)
+ if v then
+ vector=v
+ end
+ if e then
+ encoding=e
+ end
+ end
+ end
+ if type(encfile)=="string" and encfile~="auto" then
+ encoding=fonts.encodings.load(file.addsuffix(encfile,"enc"))
+ if encoding then
+ encoding=encoding.vector
+ end
+ end
+ if not encoding then
+ report_tfm("bad encoding for %a, quitting",tfmfile)
+ return
+ end
+ local unicoding=fonts.encodings.agl and fonts.encodings.agl.unicodes
+ local virtualid=tfmcache[tfmdata]
+ local tfmdata=table.copy(tfmdata)
+ local characters={}
+ local originals=tfmdata.characters
+ local indices={}
+ local parentfont={ "font",1 }
+ local private=fonts.constructors.privateoffset
+ local reported=encdone[tfmfile][encfile]
+ local backmap=vector and table.swapped(vector)
+ local done={}
+ for index,name in sortedhash(encoding) do
+ local unicode=unicoding[name]
+ local original=originals[index]
+ if original then
+ if unicode then
+ original.unicode=unicode
+ else
+ unicode=private
+ private=private+1
+ if not reported then
+ report_tfm("glyph %a in font %a with encoding %a gets unicode %U",name,tfmfile,encfile,unicode)
+ end
+ end
+ characters[unicode]=original
+ indices[index]=unicode
+ original.name=name
+ if backmap then
+ original.index=backmap[name]
+ else
+ original.commands={ parentfont,{ "char",index } }
+ original.oindex=index
+ end
+ done[name]=true
+ elseif not done[name] then
+ report_tfm("bad index %a in font %a with name %a",index,tfmfile,name)
+ end
+ end
+ encdone[tfmfile][encfile]=true
+ for k,v in next,characters do
+ local kerns=v.kerns
+ if kerns then
+ local t={}
+ for k,v in next,kerns do
+ local i=indices[k]
+ if i then
+ t[i]=v
+ end
+ end
+ v.kerns=next(t) and t or nil
+ end
+ local ligatures=v.ligatures
+ if ligatures then
+ local t={}
+ for k,v in next,ligatures do
+ local i=indices[k]
+ if i then
+ t[i]=v
+ v.char=indices[v.char]
+ end
+ end
+ v.ligatures=next(t) and t or nil
+ end
+ end
+ tfmdata.fonts={ { id=virtualid } }
+ tfmdata.characters=characters
+ tfmdata.fullname=tfmdata.fullname or tfmdata.name
+ tfmdata.psname=file.nameonly(pfbfile or tfmdata.name)
+ tfmdata.filename=pfbfile
+ tfmdata.encodingbytes=2
+ tfmdata.format="type1"
+ tfmdata.tounicode=1
+ tfmdata.embedding="subset"
+ tfmdata.usedbitmap=bitmap and virtualid
+ return tfmdata
+ end
+end
+do
+ local template=[[
+/CIDInit /ProcSet findresource begin
+ 12 dict begin
+ begincmap
+ /CIDSystemInfo << /Registry (TeX) /Ordering (bitmap-%s) /Supplement 0 >> def
+ /CMapName /TeX-bitmap-%s def
+ /CMapType 2 def
+ 1 begincodespacerange
+ <00> <FF>
+ endcodespacerange
+ %s beginbfchar
+%s
+ endbfchar
+ endcmap
+CMapName currentdict /CMap defineresource pop end
+end
+end
+]]
+ local flushstreamobject=lpdf and lpdf.flushstreamobject
+ local setfontattributes=pdf.setfontattributes
+ if not flushstreamobject then
+ flushstreamobject=function(data)
+ return pdf.obj {
+ immediate=true,
+ type="stream",
+ string=data,
+ }
+ end
+ end
+ if not setfontattributes then
+ setfontattributes=function(id,data)
+ print(format("your luatex is too old so no tounicode bitmap font%i",id))
+ end
+ end
+ function tfm.addtounicode(tfmdata)
+ local id=tfmdata.usedbitmap
+ local map={}
+ local char={}
+ for k,v in next,tfmdata.characters do
+ local index=v.oindex
+ local tounicode=v.tounicode
+ if index and tounicode then
+ map[index]=tounicode
+ end
+ end
+ for k,v in sortedhash(map) do
+ char[#char+1]=format("<%02X> <%s>",k,v)
+ end
+ char=concat(char,"\n")
+ local stream=format(template,id,id,#char,char)
+ local reference=flushstreamobject(stream,nil,true)
+ setfontattributes(id,format("/ToUnicode %i 0 R",reference))
+ end
+end
+do
+ local everywhere={ ["*"]={ ["*"]=true } }
+ local noflags={ false,false,false,false }
+ local function enhance_normalize_features(data)
+ local ligatures=setmetatableindex("table")
+ local kerns=setmetatableindex("table")
+ local characters=data.characters
+ for u,c in next,characters do
+ local l=c.ligatures
+ local k=c.kerns
+ if l then
+ ligatures[u]=l
+ for u,v in next,l do
+ l[u]={ ligature=v.char }
+ end
+ c.ligatures=nil
+ end
+ if k then
+ kerns[u]=k
+ for u,v in next,k do
+ k[u]=v
+ end
+ c.kerns=nil
+ end
+ end
+ for u,l in next,ligatures do
+ for k,v in next,l do
+ local vl=v.ligature
+ local dl=ligatures[vl]
+ if dl then
+ for kk,vv in next,dl do
+ v[kk]=vv
+ end
+ end
+ end
+ end
+ local features={
+ gpos={},
+ gsub={},
+ }
+ local sequences={
+ }
+ if next(ligatures) then
+ features.gsub.liga=everywhere
+ data.properties.hasligatures=true
+ sequences[#sequences+1]={
+ features={
+ liga=everywhere,
+ },
+ flags=noflags,
+ name="s_s_0",
+ nofsteps=1,
+ order={ "liga" },
+ type="gsub_ligature",
+ steps={
+ {
+ coverage=ligatures,
+ },
+ },
+ }
+ end
+ if next(kerns) then
+ features.gpos.kern=everywhere
+ data.properties.haskerns=true
+ sequences[#sequences+1]={
+ features={
+ kern=everywhere,
+ },
+ flags=noflags,
+ name="p_s_0",
+ nofsteps=1,
+ order={ "kern" },
+ type="gpos_pair",
+ steps={
+ {
+ format="kern",
+ coverage=kerns,
+ },
+ },
+ }
+ end
+ data.resources.features=features
+ data.resources.sequences=sequences
+ data.shared.resources=data.shared.resources or resources
+ end
+ registertfmenhancer("normalize features",enhance_normalize_features)
+ registertfmenhancer("check extra features",otfenhancers.enhance)
+end
+registertfmfeature {
+ name="mode",
+ description="mode",
+ initializers={
+ base=otf.modeinitializer,
+ node=otf.modeinitializer,
+ }
+}
+registertfmfeature {
+ name="features",
+ description="features",
+ default=true,
+ initializers={
+ base=otf.basemodeinitializer,
+ node=otf.nodemodeinitializer,
+ },
+ processors={
+ node=otf.featuresprocessor,
+ }
+}
+
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-tfm”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-lua” 1fbfdf7b689b2bdfd0e3bb9bf74ce136] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-lua” 1fbfdf7b689b2bdfd0e3bb9bf74ce136] ---
if not modules then modules={} end modules ['font-lua']={
version=1.001,
@@ -19376,10 +20919,10 @@ function readers.lua(specification)
return check_lua(specification,fullname)
end
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-lua”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-lua”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-def” 3c71c27300a8cb5c29f5d278d2049fb6] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-def” 49fa2b50d8d2a1bb70b08b72f858ecd0] ---
if not modules then modules={} end modules ['font-def']={
version=1.001,
@@ -19388,10 +20931,11 @@ if not modules then modules={} end modules ['font-def']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local format,gmatch,match,find,lower,gsub=string.format,string.gmatch,string.match,string.find,string.lower,string.gsub
+local lower,gsub=string.lower,string.gsub
local tostring,next=tostring,next
local lpegmatch=lpeg.match
local suffixonly,removesuffix=file.suffix,file.removesuffix
+local formatters=string.formatters
local allocate=utilities.storage.allocate
local trace_defining=false trackers .register("fonts.defining",function(v) trace_defining=v end)
local directive_embedall=false directives.register("fonts.embedall",function(v) directive_embedall=v end)
@@ -19552,7 +21096,7 @@ function definers.applypostprocessors(tfmdata)
local extrahash=postprocessors[i](tfmdata)
if type(extrahash)=="string" and extrahash~="" then
extrahash=gsub(lower(extrahash),"[^a-z]","-")
- properties.fullname=format("%s-%s",properties.fullname,extrahash)
+ properties.fullname=formatters["%s-%s"](properties.fullname,extrahash)
end
end
end
@@ -19710,10 +21254,10 @@ function font.getfont(id)
end
callbacks.register('define_font',definers.read,"definition of fonts (tfmdata preparation)")
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-def”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-def”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “fonts-ext” 52e620241ee991a687cf1ca8b8ee8de2] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “fonts-ext” aff3846f4c1f15de0a9f4fd7081e0c68] ---
if not modules then modules={} end modules ['luatex-fonts-ext']={
version=1.001,
@@ -19929,11 +21473,24 @@ otffeatures.register {
node=reencode,
}
}
+local function ignore(tfmdata,key,value)
+ if value then
+ tfmdata.mathparameters=nil
+ end
+end
+otffeatures.register {
+ name="ignoremathconstants",
+ description="ignore math constants table",
+ initializers={
+ base=ignore,
+ node=ignore,
+ }
+}
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “fonts-ext”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “fonts-ext”] ---
-do --- [luaotfload, fontloader-2016-06-16.lua scope for “font-gbn” f7bc5e7bbc3b6e4f58fc6b0ab61bf77e] ---
+do --- [luaotfload, fontloader-2017-01-29.lua scope for “font-gbn” b65b8a0b19cc1b870e4c0569a94d8825] ---
if not modules then modules={} end modules ['font-gbn']={
version=1.001,
@@ -19950,7 +21507,7 @@ local fonts=fonts
local nodes=nodes
local nuts=nodes.nuts
local traverse_id=nuts.traverse_id
-local free_node=nuts.free
+local flush_node=nuts.flush_node
local glyph_code=nodes.nodecodes.glyph
local disc_code=nodes.nodecodes.disc
local tonode=nuts.tonode
@@ -20074,7 +21631,7 @@ function nodes.handlers.nodepass(head)
end
end
end
- free_node(r)
+ flush_node(r)
end
end
for d in traverse_id(disc_code,nuthead) do
@@ -20167,7 +21724,7 @@ function nodes.simple_font_handler(head)
end
end
-end --- [luaotfload, fontloader-2016-06-16.lua scope for “font-gbn”] ---
+end --- [luaotfload, fontloader-2017-01-29.lua scope for “font-gbn”] ---
--- vim:ft=lua:sw=2:ts=8:et:tw=79
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-basics-gen.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-basics-gen.lua
index 2a68b1c180d..2be55cceabc 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-basics-gen.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-basics-gen.lua
@@ -97,6 +97,7 @@ local remapper = {
-- fea = "font feature files", -- no longer supported
pfb = "type1 fonts", -- needed for vector loading
afm = "afm",
+ enc = "enc files",
}
function resolvers.findfile(name,fileformat)
@@ -257,45 +258,84 @@ function caches.is_writable(path,name)
return fullname and file.is_writable(fullname)
end
-function caches.loaddata(paths,name)
- for i=1,#paths do
- local data = false
- local luaname, lucname = makefullname(paths[i],name)
- if lucname and not lfs.isfile(lucname) and type(caches.compile) == "function" then
- -- in case we used luatex and luajittex mixed ... lub or luc file
- texio.write(string.format("(compiling luc: %s)",lucname))
- data = loadfile(luaname)
- if data then
- data = data()
- end
- if data then
- caches.compile(data,luaname,lucname)
- return data
- end
- end
- if lucname and lfs.isfile(lucname) then -- maybe also check for size
+-- function caches.loaddata(paths,name)
+-- for i=1,#paths do
+-- local data = false
+-- local luaname, lucname = makefullname(paths[i],name)
+-- if lucname and not lfs.isfile(lucname) and type(caches.compile) == "function" then
+-- -- in case we used luatex and luajittex mixed ... lub or luc file
+-- texio.write(string.format("(compiling luc: %s)",lucname))
+-- data = loadfile(luaname)
+-- if data then
+-- data = data()
+-- end
+-- if data then
+-- caches.compile(data,luaname,lucname)
+-- return data
+-- end
+-- end
+-- if lucname and lfs.isfile(lucname) then -- maybe also check for size
+-- texio.write(string.format("(load luc: %s)",lucname))
+-- data = loadfile(lucname)
+-- if data then
+-- data = data()
+-- end
+-- if data then
+-- return data
+-- else
+-- texio.write(string.format("(loading failed: %s)",lucname))
+-- end
+-- end
+-- if luaname and lfs.isfile(luaname) then
+-- texio.write(string.format("(load lua: %s)",luaname))
+-- data = loadfile(luaname)
+-- if data then
+-- data = data()
+-- end
+-- if data then
+-- return data
+-- end
+-- end
+-- end
+-- end
+
+function caches.loaddata(readables,name,writable)
+ for i=1,#readables do
+ local path = readables[i]
+ local loader = false
+ local luaname, lucname = makefullname(path,name)
+ if lfs.isfile(lucname) then
texio.write(string.format("(load luc: %s)",lucname))
- data = loadfile(lucname)
- if data then
- data = data()
+ loader = loadfile(lucname)
+ end
+ if not loader and lfs.isfile(luaname) then
+ -- can be different paths when we read a file database from disk
+ local luacrap, lucname = makefullname(writable,name)
+ texio.write(string.format("(compiling luc: %s)",lucname))
+ if lfs.isfile(lucname) then
+ loader = loadfile(lucname)
end
- if data then
- return data
+ caches.compile(data,luaname,lucname)
+ if lfs.isfile(lucname) then
+ texio.write(string.format("(load luc: %s)",lucname))
+ loader = loadfile(lucname)
else
texio.write(string.format("(loading failed: %s)",lucname))
end
- end
- if luaname and lfs.isfile(luaname) then
- texio.write(string.format("(load lua: %s)",luaname))
- data = loadfile(luaname)
- if data then
- data = data()
- end
- if data then
- return data
+ if not loader then
+ texio.write(string.format("(load lua: %s)",luaname))
+ loader = loadfile(luaname)
+ else
+ texio.write(string.format("(loading failed: %s)",luaname))
end
end
+ if loader then
+ loader = loader()
+ collectgarbage("step")
+ return loader
+ end
end
+ return false
end
function caches.savedata(path,name,data)
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-basics-nod.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-basics-nod.lua
index e7b5ab24fc8..42a7a2e29eb 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-basics-nod.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-basics-nod.lua
@@ -71,7 +71,7 @@ nodes.nodecodes = nodecodes
nodes.glyphcodes = glyphcodes
nodes.disccodes = disccodes
-local free_node = node.free
+local flush_node = node.flush_node
local remove_node = node.remove
local new_node = node.new
local traverse_id = node.traverse_id
@@ -95,7 +95,7 @@ function nodes.remove(head, current, free_too)
head, current = remove_node(head,current)
if t then
if free_too then
- free_node(t)
+ flush_node(t)
t = nil
else
t.next, t.prev = nil, nil
@@ -128,12 +128,14 @@ nodes.setattr = setfield
nodes.tostring = node.tostring or tostring
nodes.copy = node.copy
+nodes.copy_node = node.copy
nodes.copy_list = node.copy_list
nodes.delete = node.delete
nodes.dimensions = node.dimensions
nodes.end_of_math = node.end_of_math
nodes.flush_list = node.flush_list
nodes.flush_node = node.flush_node
+nodes.flush = node.flush_node
nodes.free = node.free
nodes.insert_after = node.insert_after
nodes.insert_before = node.insert_before
@@ -149,7 +151,6 @@ nodes.first_glyph = node.first_glyph
nodes.has_glyph = node.has_glyph or node.first_glyph
nodes.current_attr = node.current_attr
-nodes.do_ligature_n = node.do_ligature_n
nodes.has_field = node.has_field
nodes.last_node = node.last_node
nodes.usedlist = node.usedlist
@@ -253,9 +254,12 @@ nuts.insert_before = direct.insert_before
nuts.insert_after = direct.insert_after
nuts.delete = direct.delete
nuts.copy = direct.copy
+nuts.copy_node = direct.copy
nuts.copy_list = direct.copy_list
nuts.tail = direct.tail
nuts.flush_list = direct.flush_list
+nuts.flush_node = direct.flush_node
+nuts.flush = direct.flush
nuts.free = direct.free
nuts.remove = direct.remove
nuts.is_node = direct.is_node
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-data-con.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-data-con.lua
index 240538df2db..c79fca7c5c1 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-data-con.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-data-con.lua
@@ -91,7 +91,7 @@ function containers.read(container,name)
local storage = container.storage
local stored = storage[name]
if not stored and container.enabled and caches and containers.usecache then
- stored = caches.loaddata(container.readables,name)
+ stored = caches.loaddata(container.readables,name,container.writable)
if stored and stored.cache_version == container.version then
if trace_cache or trace_containers then
report_containers("action %a, category %a, name %a","load",container.subcategory,name)
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-cff.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-cff.lua
index 8c57b473ef8..1c6bd56fd3d 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-cff.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-cff.lua
@@ -26,6 +26,7 @@ local concat, remove = table.concat, table.remove
local floor, abs, round, ceil = math.floor, math.abs, math.round, math.ceil
local P, C, R, S, C, Cs, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Ct
local lpegmatch = lpeg.match
+local formatters = string.formatters
local readers = fonts.handlers.otf.readers
local streamreader = readers.streamreader
@@ -594,6 +595,7 @@ do
local ymax = 0
local checked = false
local keepcurve = false
+ local version = 2
local function showstate(where)
report("%w%-10s : [%s] n=%i",depth*2,where,concat(stack," ",1,top),top)
@@ -1052,13 +1054,114 @@ do
end
end
- local function unsupported()
+ local function unsupported(t)
if trace_charstrings then
- showstate("unsupported")
+ showstate("unsupported " .. t)
end
top = 0
end
+ local function unsupportedsub(t)
+ if trace_charstrings then
+ showstate("unsupported sub " .. t)
+ end
+ top = 0
+ end
+
+ -- type 1 (not used in type 2)
+
+ local function getstem3()
+ if trace_charstrings then
+ showstate("stem3")
+ end
+ top = 0
+ end
+
+ local function divide()
+ if version == 1 then
+ local d = stack[top]
+ top = top - 1
+ stack[top] = stack[top] / d
+ end
+ end
+
+ local function closepath()
+ if version == 1 then
+ if trace_charstrings then
+ showstate("closepath")
+ end
+ end
+ top = 0
+ end
+
+ local function hsbw()
+ if version == 1 then
+ if trace_charstrings then
+ showstate("dotsection")
+ end
+ width = stack[top]
+ end
+ top = 0
+ end
+
+ local function seac()
+ if version == 1 then
+ if trace_charstrings then
+ showstate("seac")
+ end
+ end
+ top = 0
+ end
+
+ local function sbw()
+ if version == 1 then
+ if trace_charstrings then
+ showstate("sbw")
+ end
+ width = stack[top-1]
+ end
+ top = 0
+ end
+
+ -- these are probably used for special cases i.e. call out to postscript
+
+ local function callothersubr()
+ if version == 1 then
+ -- we don't support this (ok, we could mimick these othersubs)
+ if trace_charstrings then
+ showstate("callothersubr (unsupported)")
+ end
+ end
+ top = 0
+ end
+
+ local function pop()
+ if version == 1 then
+ -- we don't support this
+ if trace_charstrings then
+ showstate("pop (unsupported)")
+ end
+ top = top + 1
+ stack[top] = 0 -- a dummy
+ else
+ top = 0
+ end
+ end
+
+ local function setcurrentpoint()
+ if version == 1 then
+ -- we don't support this
+ if trace_charstrings then
+ showstate("pop (unsupported)")
+ end
+ x = x + stack[top-1]
+ y = y + stack[top]
+ end
+ top = 0
+ end
+
+ -- so far for unsupported postscript
+
-- Bah, we cannot use a fast lpeg because a hint has an unknown size and a
-- runtime capture cannot handle that well.
@@ -1076,7 +1179,7 @@ do
unsupported, -- 10 -- calllocal,
unsupported, -- 11 -- callreturn,
unsupported, -- 12 -- elsewhere
- unsupported, -- 13 -- hsbw
+ hsbw, -- 13 -- hsbw (type 1 cff)
unsupported, -- 14 -- endchar,
unsupported, -- 15
unsupported, -- 16
@@ -1098,6 +1201,17 @@ do
}
local subactions = {
+ -- cff 1
+ [000] = dotsection,
+ [001] = getstem3,
+ [002] = getstem3,
+ [006] = seac,
+ [007] = sbw,
+ [012] = divide,
+ [016] = callothersubr,
+ [017] = pop,
+ [033] = setcurrentpoint,
+ -- cff 2
[034] = hflex,
[035] = flex,
[036] = hflex1,
@@ -1107,23 +1221,29 @@ do
local p_bytes = Ct((P(1)/byte)^0)
local function call(scope,list,bias,process)
- local index = stack[top] + bias
- top = top - 1
- if trace_charstrings then
- showvalue(scope,index,true)
- end
- local str = list[index]
- if str then
- if type(str) == "string" then
- str = lpegmatch(p_bytes,str)
- list[index] = str
- end
- depth = depth + 1
- process(str)
- depth = depth - 1
+ depth = depth + 1
+ if top == 0 then
+ showstate(formatters["unknown %s call"](scope))
+ top = 0
else
- report("unknown %s %i",scope,index)
+ local index = stack[top] + bias
+ top = top - 1
+ if trace_charstrings then
+ showvalue(scope,index,true)
+ end
+ local tab = list[index]
+ if tab then
+ if type(tab) == "string" then
+ tab = lpegmatch(p_bytes,tab)
+ list[index] = tab
+ end
+ process(tab)
+ else
+ showstate(formatters["unknown %s call %i"](scope,index))
+ top = 0
+ end
end
+ depth = depth - 1
end
local function process(tab)
@@ -1131,7 +1251,7 @@ do
local n = #tab
while i <= n do
local t = tab[i]
- if t >= 32 and t<=246 then
+ if t >= 32 and t <= 246 then
-- -107 .. +107
top = top + 1
stack[top] = t - 139
@@ -1196,7 +1316,7 @@ do
local t = tab[i]
local a = subactions[t]
if a then
- a()
+ a(t)
else
if trace_charstrings then
showvalue("<subaction>",t)
@@ -1207,7 +1327,7 @@ do
else
local a = actions[t]
if a then
- local s = a()
+ local s = a(t)
if s then
i = i + s
end
@@ -1260,27 +1380,44 @@ do
-- end
-- end
- parsecharstrings = function(data,glyphs,doshapes)
+ local function setbias(globals,locals)
+ if version == 1 then
+ return
+ false,
+ false
+ else
+ local g, l = #globals, #locals
+ return
+ ((g < 1240 and 107) or (g < 33900 and 1131) or 32768) + 1,
+ ((l < 1240 and 107) or (l < 33900 and 1131) or 32768) + 1
+ end
+ end
+
+ parsecharstrings = function(data,glyphs,doshapes,tversion)
-- for all charstrings
local dictionary = data.dictionaries[1]
local charstrings = dictionary.charstrings
local charset = dictionary.charset
+ local private = dictionary.private or { data = { } }
+
keepcurve = doshapes
+ version = tversion
stack = { }
glyphs = glyphs or { }
strings = data.strings
- locals = dictionary.subroutines
- globals = data.routines
- globalbias = #globals
- localbias = #locals
- globalbias = ((globalbias < 1240 and 107) or (globalbias < 33900 and 1131) or 32768) + 1
- localbias = ((localbias < 1240 and 107) or (localbias < 33900 and 1131) or 32768) + 1
- local nominalwidth = dictionary.private.data.nominalwidthx or 0
- local defaultwidth = dictionary.private.data.defaultwidthx or 0
+ globals = data.routines or { }
+ locals = dictionary.subroutines or { }
+
+ globalbias, localbias = setbias(globals,locals)
+
+ local nominalwidth = private.data.nominalwidthx or 0
+ local defaultwidth = private.data.defaultwidthx or 0
for i=1,#charstrings do
- local str = charstrings[i]
- local tab = lpegmatch(p_bytes,str)
+ local tab = charstrings[i]
+ if type(tab) == "string" then
+ tab = lpegmatch(p_bytes,tab)
+ end
local index = i - 1
x = 0
y = 0
@@ -1341,20 +1478,23 @@ do
return glyphs
end
- parsecharstring = function(data,dictionary,charstring,glyphs,index,doshapes)
+ parsecharstring = function(data,dictionary,tab,glyphs,index,doshapes,tversion)
local private = dictionary.private
keepcurve = doshapes
+ version = tversion
strings = data.strings -- or in dict?
locals = dictionary.subroutines or { }
globals = data.routines or { }
- globalbias = #globals
- localbias = #locals
- globalbias = ((globalbias < 1240 and 107) or (globalbias < 33900 and 1131) or 32768) + 1
- localbias = ((localbias < 1240 and 107) or (localbias < 33900 and 1131) or 32768) + 1
+
+ globalbias, localbias = setbias(globals,locals)
+
local nominalwidth = private and private.data.nominalwidthx or 0
local defaultwidth = private and private.data.defaultwidthx or 0
--
- local tab = lpegmatch(p_bytes,charstring)
+ if type(tab) == "string" then
+ tab = lpegmatch(p_bytes,tab)
+ end
+ --
x = 0
y = 0
width = false
@@ -1384,7 +1524,8 @@ do
width = nominalwidth + width
end
--
-index = index - 1
+ index = index - 1
+ --
local glyph = glyphs[index] -- can be autodefined in otr
if not glyph then
glyphs[index] = {
@@ -1410,8 +1551,6 @@ index = index - 1
report("width: %s",tostring(width))
report("boundingbox: % t",boundingbox)
end
- --
- return charstring
end
resetcharstrings = function()
@@ -1542,7 +1681,7 @@ local function readcidprivates(f,data)
parseprivates(data,dictionaries)
end
-local function readnoselect(f,data,glyphs,doshapes)
+local function readnoselect(f,data,glyphs,doshapes,version)
local dictionaries = data.dictionaries
local dictionary = dictionaries[1]
readglobals(f,data)
@@ -1552,11 +1691,13 @@ local function readnoselect(f,data,glyphs,doshapes)
readprivates(f,data)
parseprivates(data,data.dictionaries)
readlocals(f,data,dictionary)
- parsecharstrings(data,glyphs,doshapes)
+ parsecharstrings(data,glyphs,doshapes,version)
resetcharstrings()
end
-local function readfdselect(f,data,glyphs,doshapes)
+readers.parsecharstrings = parsecharstrings
+
+local function readfdselect(f,data,glyphs,doshapes,version)
local header = data.header
local dictionaries = data.dictionaries
local dictionary = dictionaries[1]
@@ -1615,7 +1756,7 @@ local function readfdselect(f,data,glyphs,doshapes)
readlocals(f,data,dictionaries[i])
end
for i=1,#charstrings do
- parsecharstring(data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes)
+ parsecharstring(data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes,version)
end
resetcharstrings()
end
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-con.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-con.lua
index 1a0daff632e..18f2217108a 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-con.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-con.lua
@@ -9,12 +9,13 @@ if not modules then modules = { } end modules ['font-con'] = {
-- some names of table entries will be changed (no _)
local next, tostring, rawget = next, tostring, rawget
-local format, match, lower, gsub = string.format, string.match, string.lower, string.gsub
+local format, match, lower, gsub, find = string.format, string.match, string.lower, string.gsub, string.find
local sort, insert, concat, sortedkeys, serialize, fastcopy = table.sort, table.insert, table.concat, table.sortedkeys, table.serialize, table.fastcopy
local derivetable = table.derive
+local ioflush = io.flush
-local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
-local trace_scaling = false trackers.register("fonts.scaling" , function(v) trace_scaling = v end)
+local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
+local trace_scaling = false trackers.register("fonts.scaling", function(v) trace_scaling = v end)
local report_defining = logs.reporter("fonts","defining")
@@ -46,102 +47,6 @@ constructors.privateoffset = 0xF0000 -- 0x10FFFF
constructors.cacheintex = true -- so we see the original table in fonts.font
--- Some experimental helpers (handy for tracing):
---
--- todo: extra:
---
--- extra_space => space.extra
--- space => space.width
--- space_stretch => space.stretch
--- space_shrink => space.shrink
-
--- We do keep the x-height, extra_space, space_shrink and space_stretch
--- around as these are low level official names.
-
-constructors.keys = {
- properties = {
- encodingbytes = "number",
- embedding = "number",
- cidinfo = { },
- format = "string",
- fontname = "string",
- fullname = "string",
- filename = "filename",
- psname = "string",
- name = "string",
- virtualized = "boolean",
- hasitalics = "boolean",
- autoitalicamount = "basepoints",
- nostackmath = "boolean",
- noglyphnames = "boolean",
- mode = "string",
- hasmath = "boolean",
- mathitalics = "boolean",
- textitalics = "boolean",
- finalized = "boolean",
- },
- parameters = {
- mathsize = "number",
- scriptpercentage = "float",
- scriptscriptpercentage = "float",
- units = "cardinal",
- designsize = "scaledpoints",
- expansion = {
- stretch = "integerscale", -- might become float
- shrink = "integerscale", -- might become float
- step = "integerscale", -- might become float
- auto = "boolean",
- },
- protrusion = {
- auto = "boolean",
- },
- slantfactor = "float",
- extendfactor = "float",
- factor = "float",
- hfactor = "float",
- vfactor = "float",
- size = "scaledpoints",
- units = "scaledpoints",
- scaledpoints = "scaledpoints",
- slantperpoint = "scaledpoints",
- spacing = {
- width = "scaledpoints",
- stretch = "scaledpoints",
- shrink = "scaledpoints",
- extra = "scaledpoints",
- },
- xheight = "scaledpoints",
- quad = "scaledpoints",
- ascender = "scaledpoints",
- descender = "scaledpoints",
- synonyms = {
- space = "spacing.width",
- spacestretch = "spacing.stretch",
- spaceshrink = "spacing.shrink",
- extraspace = "spacing.extra",
- x_height = "xheight",
- space_stretch = "spacing.stretch",
- space_shrink = "spacing.shrink",
- extra_space = "spacing.extra",
- em = "quad",
- ex = "xheight",
- slant = "slantperpoint",
- },
- },
- description = {
- width = "basepoints",
- height = "basepoints",
- depth = "basepoints",
- boundingbox = { },
- },
- character = {
- width = "scaledpoints",
- height = "scaledpoints",
- depth = "scaledpoints",
- italic = "scaledpoints",
- },
-}
-
-- This might become an interface:
local designsizes = allocate()
@@ -239,7 +144,9 @@ end
local unscaled = {
ScriptPercentScaleDown = true,
ScriptScriptPercentScaleDown = true,
- RadicalDegreeBottomRaisePercent = true
+ RadicalDegreeBottomRaisePercent = true,
+ NoLimitSupFactor = true,
+ NoLimitSubFactor = true,
}
function constructors.assignmathparameters(target,original) -- simple variant, not used in context
@@ -351,6 +258,27 @@ local function mathkerns(v,vdelta)
return k
end
+local psfake = 0
+
+local function fixedpsname(psname,fallback)
+ local usedname = psname
+ if psname and psname ~= "" then
+ if find(psname," ") then
+ usedname = gsub(psname,"[%s]+","-")
+ else
+ -- we assume that the name is sane enough (we might sanitize completely some day)
+ end
+ elseif not fallback or fallback == "" then
+ psfake = psfake + 1
+ psname = "fakename-" .. psfake
+ else
+ -- filenames can be a mess so we do a drastic cleanup
+ psname = fallback
+ usedname = gsub(psname,"[^a-zA-Z0-9]+","-")
+ end
+ return usedname, psname ~= usedname
+end
+
function constructors.scale(tfmdata,specification)
local target = { } -- the new table
--
@@ -453,23 +381,22 @@ function constructors.scale(tfmdata,specification)
target.format = properties.format
target.cache = constructors.cacheintex and "yes" or "renew"
--
- local fontname = properties.fontname or tfmdata.fontname -- for the moment we fall back on
- local fullname = properties.fullname or tfmdata.fullname -- names in the tfmdata although
- local filename = properties.filename or tfmdata.filename -- that is not the right place to
- local psname = properties.psname or tfmdata.psname -- pass them
+ local fontname = properties.fontname or tfmdata.fontname
+ local fullname = properties.fullname or tfmdata.fullname
+ local filename = properties.filename or tfmdata.filename
+ local psname = properties.psname or tfmdata.psname
local name = properties.name or tfmdata.name
--
- if not psname or psname == "" then
- -- name used in pdf file as well as for selecting subfont in ttc/dfont
- psname = fontname or (fullname and fonts.names.cleanname(fullname))
- end
+ -- the psname used in pdf file as well as for selecting subfont in ttc
+ --
+ local psname, psfixed = fixedpsname(psname,fontname or fullname or file.nameonly(filename))
+ --
target.fontname = fontname
target.fullname = fullname
target.filename = filename
target.psname = psname
target.name = name
--
- --
properties.fontname = fontname
properties.fullname = fullname
properties.filename = filename
@@ -520,12 +447,16 @@ function constructors.scale(tfmdata,specification)
local haskerns = properties.haskerns or properties.mode == "base" -- we can have afm in node mode
local hasligatures = properties.hasligatures or properties.mode == "base" -- we can have afm in node mode
local realdimensions = properties.realdimensions
+ local writingmode = properties.writingmode or "horizontal"
+ local identity = properties.identity or "horizontal"
--
if changed and not next(changed) then
changed = false
end
--
- target.type = isvirtual and "virtual" or "real"
+ target.type = isvirtual and "virtual" or "real"
+ target.writingmode = writingmode == "vertical" and "vertical" or "horizontal"
+ target.identity = identity == "vertical" and "vertical" or "horizontal"
--
target.postprocessors = tfmdata.postprocessors
--
@@ -565,13 +496,13 @@ function constructors.scale(tfmdata,specification)
--
if hasmath then
constructors.assignmathparameters(target,tfmdata) -- does scaling and whatever is needed
- properties.hasmath = true
- target.nomath = false
- target.MathConstants = target.mathparameters
+ properties.hasmath = true
+ target.nomath = false
+ target.MathConstants = target.mathparameters
else
- properties.hasmath = false
- target.nomath = true
- target.mathparameters = nil -- nop
+ properties.hasmath = false
+ target.nomath = true
+ target.mathparameters = nil -- nop
end
--
-- Here we support some context specific trickery (this might move to a plugin). During the
@@ -602,8 +533,9 @@ function constructors.scale(tfmdata,specification)
-- end of context specific trickery
--
if trace_defining then
- report_defining("defining tfm, name %a, fullname %a, filename %a, hscale %a, vscale %a, math %a, italics %a",
- name,fullname,filename,hdelta,vdelta,hasmath and "enabled" or "disabled",hasitalics and "enabled" or "disabled")
+ report_defining("defining tfm, name %a, fullname %a, filename %a, %spsname %a, hscale %a, vscale %a, math %a, italics %a",
+ name,fullname,filename,psfixed and "(fixed) " or "",psname,hdelta,vdelta,
+ hasmath and "enabled" or "disabled",hasitalics and "enabled" or "disabled")
end
--
constructors.beforecopyingcharacters(target,tfmdata)
@@ -966,6 +898,8 @@ function constructors.finalize(tfmdata)
cidinfo = tfmdata.cidinfo or nil,
format = tfmdata.format or "type1",
direction = tfmdata.direction or 0,
+ writingmode = tfmdata.writingmode or "horizontal",
+ identity = tfmdata.identity or "horizontal",
}
end
if not tfmdata.resources then
@@ -979,42 +913,42 @@ function constructors.finalize(tfmdata)
-- tfmdata.unscaled
--
if not properties.hasmath then
- properties.hasmath = not tfmdata.nomath
+ properties.hasmath = not tfmdata.nomath
end
--
- tfmdata.MathConstants = nil
- tfmdata.postprocessors = nil
- --
- tfmdata.fontname = nil
- tfmdata.filename = nil
- tfmdata.fullname = nil
- tfmdata.name = nil -- most tricky part
- tfmdata.psname = nil
- --
- tfmdata.encodingbytes = nil
- tfmdata.embedding = nil
- tfmdata.tounicode = nil
- tfmdata.cidinfo = nil
- tfmdata.format = nil
- tfmdata.direction = nil
- tfmdata.type = nil
- tfmdata.nomath = nil
- tfmdata.designsize = nil
- --
- tfmdata.size = nil
- tfmdata.stretch = nil
- tfmdata.shrink = nil
- tfmdata.step = nil
- tfmdata.auto_expand = nil
- tfmdata.auto_protrude = nil
- tfmdata.extend = nil
- tfmdata.slant = nil
- tfmdata.units = nil
- tfmdata.units_per_em = nil
- --
- tfmdata.cache = nil
- --
- properties.finalized = true
+ tfmdata.MathConstants = nil
+ tfmdata.postprocessors = nil
+ --
+ tfmdata.fontname = nil
+ tfmdata.filename = nil
+ tfmdata.fullname = nil
+ tfmdata.name = nil -- most tricky part
+ tfmdata.psname = nil
+ --
+ tfmdata.encodingbytes = nil
+ tfmdata.embedding = nil
+ tfmdata.tounicode = nil
+ tfmdata.cidinfo = nil
+ tfmdata.format = nil
+ tfmdata.direction = nil
+ tfmdata.type = nil
+ tfmdata.nomath = nil
+ tfmdata.designsize = nil
+ --
+ tfmdata.size = nil
+ tfmdata.stretch = nil
+ tfmdata.shrink = nil
+ tfmdata.step = nil
+ tfmdata.auto_expand = nil
+ tfmdata.auto_protrude = nil
+ tfmdata.extend = nil
+ tfmdata.slant = nil
+ tfmdata.units = nil
+ tfmdata.units_per_em = nil
+ --
+ tfmdata.cache = nil
+ --
+ properties.finalized = true
--
return tfmdata
end
@@ -1161,146 +1095,268 @@ setmetatableindex(formats, function(t,k)
return rawget(t,file.suffix(l))
end)
-local locations = { }
+do
-local function setindeed(mode,target,group,name,action,position)
- local t = target[mode]
- if not t then
- report_defining("fatal error in setting feature %a, group %a, mode %a",name,group,mode)
- os.exit()
- elseif position then
- -- todo: remove existing
- insert(t, position, { name = name, action = action })
- else
- for i=1,#t do
- local ti = t[i]
- if ti.name == name then
- ti.action = action
- return
+ local function setindeed(mode,source,target,group,name,position)
+ local action = source[mode]
+ if not action then
+ return
+ end
+ local t = target[mode]
+ if not t then
+ report_defining("fatal error in setting feature %a, group %a, mode %a",name,group,mode)
+ os.exit()
+ elseif position then
+ -- todo: remove existing
+ insert(t, position, { name = name, action = action })
+ else
+ for i=1,#t do
+ local ti = t[i]
+ if ti.name == name then
+ ti.action = action
+ return
+ end
end
+ insert(t, { name = name, action = action })
end
- insert(t, { name = name, action = action })
- end
-end
-
-local function set(group,name,target,source)
- target = target[group]
- if not target then
- report_defining("fatal target error in setting feature %a, group %a",name,group)
- os.exit()
- end
- local source = source[group]
- if not source then
- report_defining("fatal source error in setting feature %a, group %a",name,group)
- os.exit()
- end
- local node = source.node
- local base = source.base
- local position = source.position
- if node then
- setindeed("node",target,group,name,node,position)
end
- if base then
- setindeed("base",target,group,name,base,position)
- end
-end
-local function register(where,specification)
- local name = specification.name
- if name and name ~= "" then
- local default = specification.default
- local description = specification.description
- local initializers = specification.initializers
- local processors = specification.processors
- local manipulators = specification.manipulators
- local modechecker = specification.modechecker
- if default then
- where.defaults[name] = default
- end
- if description and description ~= "" then
- where.descriptions[name] = description
- end
- if initializers then
- set('initializers',name,where,specification)
- end
- if processors then
- set('processors', name,where,specification)
+ local function set(group,name,target,source)
+ target = target[group]
+ if not target then
+ report_defining("fatal target error in setting feature %a, group %a",name,group)
+ os.exit()
end
- if manipulators then
- set('manipulators',name,where,specification)
+ local source = source[group]
+ if not source then
+ report_defining("fatal source error in setting feature %a, group %a",name,group)
+ os.exit()
end
- if modechecker then
- where.modechecker = modechecker
+ local position = source.position
+ setindeed("node",source,target,group,name,position)
+ setindeed("base",source,target,group,name,position)
+ setindeed("plug",source,target,group,name,position)
+ end
+
+ local function register(where,specification)
+ local name = specification.name
+ if name and name ~= "" then
+ local default = specification.default
+ local description = specification.description
+ local initializers = specification.initializers
+ local processors = specification.processors
+ local manipulators = specification.manipulators
+ local modechecker = specification.modechecker
+ if default then
+ where.defaults[name] = default
+ end
+ if description and description ~= "" then
+ where.descriptions[name] = description
+ end
+ if initializers then
+ set('initializers',name,where,specification)
+ end
+ if processors then
+ set('processors', name,where,specification)
+ end
+ if manipulators then
+ set('manipulators',name,where,specification)
+ end
+ if modechecker then
+ where.modechecker = modechecker
+ end
end
end
-end
-constructors.registerfeature = register
-
-function constructors.getfeatureaction(what,where,mode,name)
- what = handlers[what].features
- if what then
- where = what[where]
- if where then
- mode = where[mode]
- if mode then
- for i=1,#mode do
- local m = mode[i]
- if m.name == name then
- return m.action
+ constructors.registerfeature = register
+
+ function constructors.getfeatureaction(what,where,mode,name)
+ what = handlers[what].features
+ if what then
+ where = what[where]
+ if where then
+ mode = where[mode]
+ if mode then
+ for i=1,#mode do
+ local m = mode[i]
+ if m.name == name then
+ return m.action
+ end
end
end
end
end
end
+
+ local newfeatures = { }
+ constructors.newfeatures = newfeatures -- downward compatible
+ constructors.features = newfeatures
+
+ local function setnewfeatures(what)
+ local handler = handlers[what]
+ local features = handler.features
+ if not features then
+ local tables = handler.tables -- can be preloaded
+ local statistics = handler.statistics -- can be preloaded
+ features = allocate {
+ defaults = { },
+ descriptions = tables and tables.features or { },
+ used = statistics and statistics.usedfeatures or { },
+ initializers = { base = { }, node = { }, plug = { } },
+ processors = { base = { }, node = { }, plug = { } },
+ manipulators = { base = { }, node = { }, plug = { } },
+ }
+ features.register = function(specification) return register(features,specification) end
+ handler.features = features -- will also become hidden
+ end
+ return features
+ end
+
+ setmetatable(newfeatures, {
+ __call = function(t,k) local v = t[k] return v end,
+ __index = function(t,k) local v = setnewfeatures(k) t[k] = v return v end,
+ })
+
end
-local newhandler = { }
-constructors.handlers = newhandler -- downward compatible
-constructors.newhandler = newhandler
+do
-local function setnewhandler(what) -- could be a metatable newindex
- local handler = handlers[what]
- if not handler then
- handler = { }
- handlers[what] = handler
+ local newhandler = { }
+ constructors.handlers = newhandler -- downward compatible
+ constructors.newhandler = newhandler
+
+ local function setnewhandler(what) -- could be a metatable newindex
+ local handler = handlers[what]
+ if not handler then
+ handler = { }
+ handlers[what] = handler
+ end
+ return handler
end
- return handler
+
+ setmetatable(newhandler, {
+ __call = function(t,k) local v = t[k] return v end,
+ __index = function(t,k) local v = setnewhandler(k) t[k] = v return v end,
+ })
+
end
-setmetatable(newhandler, {
- __call = function(t,k) local v = t[k] return v end,
- __index = function(t,k) local v = setnewhandler(k) t[k] = v return v end,
-})
-
-local newfeatures = { }
-constructors.newfeatures = newfeatures -- downward compatible
-constructors.features = newfeatures
-
-local function setnewfeatures(what)
- local handler = handlers[what]
- local features = handler.features
- if not features then
- local tables = handler.tables -- can be preloaded
- local statistics = handler.statistics -- can be preloaded
- features = allocate {
- defaults = { },
- descriptions = tables and tables.features or { },
- used = statistics and statistics.usedfeatures or { },
- initializers = { base = { }, node = { } },
- processors = { base = { }, node = { } },
- manipulators = { base = { }, node = { } },
- }
- features.register = function(specification) return register(features,specification) end
- handler.features = features -- will also become hidden
+do
+ -- a pitty that we need to be generic as we have nicer mechanisms for this ...
+
+ local newenhancer = { }
+ constructors.enhancers = newenhancer
+ constructors.newenhancer = newenhancer
+
+ local function setnewenhancer(format)
+
+ local handler = handlers[format]
+ local enhancers = handler.enhancers
+
+ if not enhancers then
+
+ local actions = allocate()
+ local before = allocate()
+ local after = allocate()
+ local order = allocate()
+ local patches = { before = before, after = after }
+
+ local trace = false
+ local report = logs.reporter("fonts",format .. " enhancing")
+
+ trackers.register(format .. ".loading", function(v) trace = v end)
+
+ local function enhance(name,data,filename,raw)
+ local enhancer = actions[name]
+ if enhancer then
+ if trace then
+ report("apply enhancement %a to file %a",name,filename)
+ ioflush()
+ end
+ enhancer(data,filename,raw)
+ else
+ -- no message as we can have private ones
+ end
+ end
+
+ local function apply(data,filename,raw)
+ local basename = file.basename(lower(filename))
+ if trace then
+ report("%s enhancing file %a","start",filename)
+ end
+ ioflush() -- we want instant messages
+ for e=1,#order do
+ local enhancer = order[e]
+ local b = before[enhancer]
+ if b then
+ for pattern, action in next, b do
+ if find(basename,pattern) then
+ action(data,filename,raw)
+ end
+ end
+ end
+ enhance(enhancer,data,filename,raw)
+ local a = after[enhancer]
+ if a then
+ for pattern, action in next, a do
+ if find(basename,pattern) then
+ action(data,filename,raw)
+ end
+ end
+ end
+ ioflush() -- we want instant messages
+ end
+ if trace then
+ report("%s enhancing file %a","stop",filename)
+ end
+ ioflush() -- we want instant messages
+ end
+
+ local function register(what,action)
+ if action then
+ if actions[what] then
+ -- overloading, e.g."check extra features"
+ else
+ order[#order+1] = what
+ end
+ actions[what] = action
+ else
+ report("bad enhancer %a",what)
+ end
+ end
+
+ -- fonts.constructors.otf.enhancers.patch("before","migrate metadata","cambria",function() end)
+
+ local function patch(what,where,pattern,action)
+ local pw = patches[what]
+ if pw then
+ local ww = pw[where]
+ if ww then
+ ww[pattern] = action
+ else
+ pw[where] = { [pattern] = action}
+ end
+ end
+ end
+
+ enhancers = {
+ register = register,
+ apply = apply,
+ patch = patch,
+ patches = { register = patch }, -- for old times sake
+ }
+
+ handler.enhancers = enhancers
+ end
+ return enhancers
end
- return features
-end
-setmetatable(newfeatures, {
- __call = function(t,k) local v = t[k] return v end,
- __index = function(t,k) local v = setnewfeatures(k) t[k] = v return v end,
-})
+ setmetatable(newenhancer, {
+ __call = function(t,k) local v = t[k] return v end,
+ __index = function(t,k) local v = setnewenhancer(k) t[k] = v return v end,
+ })
+
+end
--[[ldx--
<p>We need to check for default features. For this we provide
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-def.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-def.lua
index add42ee3828..88d6145665b 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-def.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-def.lua
@@ -8,10 +8,11 @@ if not modules then modules = { } end modules ['font-def'] = {
-- We can overload some of the definers.functions so we don't local them.
-local format, gmatch, match, find, lower, gsub = string.format, string.gmatch, string.match, string.find, string.lower, string.gsub
+local lower, gsub = string.lower, string.gsub
local tostring, next = tostring, next
local lpegmatch = lpeg.match
local suffixonly, removesuffix = file.suffix, file.removesuffix
+local formatters = string.formatters
local allocate = utilities.storage.allocate
@@ -264,7 +265,7 @@ function definers.applypostprocessors(tfmdata)
if type(extrahash) == "string" and extrahash ~= "" then
-- e.g. a reencoding needs this
extrahash = gsub(lower(extrahash),"[^a-z]","-")
- properties.fullname = format("%s-%s",properties.fullname,extrahash)
+ properties.fullname = formatters["%s-%s"](properties.fullname,extrahash)
end
end
end
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-dsp.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-dsp.lua
index 1e8b3bd0c7a..14e3a1d623b 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-dsp.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-dsp.lua
@@ -53,6 +53,7 @@ local bittest = bit32.btest
local rshift = bit32.rshift
local concat = table.concat
local lower = string.lower
+local copy = table.copy
local sub = string.sub
local strip = string.strip
local tohash = table.tohash
@@ -69,6 +70,7 @@ local readers = fonts.handlers.otf.readers
local streamreader = readers.streamreader
local setposition = streamreader.setposition
+local getposition = streamreader.getposition
local skipshort = streamreader.skipshort
local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer
local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer
@@ -224,10 +226,15 @@ local function readcoverage(f,offset,simple)
return coverage
end
-local function readclassdef(f,offset)
+local function readclassdef(f,offset,preset)
setposition(f,offset)
local classdefformat = readushort(f)
local classdef = { }
+ if type(preset) == "number" then
+ for k=0,preset-1 do
+ classdef[k] = 1
+ end
+ end
if classdefformat == 1 then
local index = readushort(f)
local nofclassdef = readushort(f)
@@ -249,6 +256,13 @@ local function readclassdef(f,offset)
else
report("unknown classdef format %a ",classdefformat)
end
+ if type(preset) == "table" then
+ for k in next, preset do
+ if not classdef[k] then
+ classdef[k] = 1
+ end
+ end
+ end
return classdef
end
@@ -365,7 +379,9 @@ end
-- We generalize the chained lookups so that we can do with only one handler
-- when processing them.
-local function readlookuparray(f,noflookups)
+-- pruned
+
+local function readlookuparray(f,noflookups,nofcurrent)
local lookups = { }
if noflookups > 0 then
local length = 0
@@ -381,10 +397,34 @@ local function readlookuparray(f,noflookups)
lookups[index] = false
end
end
+ -- if length > nofcurrent then
+ -- report("more lookups than currently matched characters")
+ -- end
end
return lookups
end
+-- not pruned
+--
+-- local function readlookuparray(f,noflookups,nofcurrent)
+-- local lookups = { }
+-- for i=1,nofcurrent do
+-- lookups[i] = false
+-- end
+-- for i=1,noflookups do
+-- local index = readushort(f) + 1
+-- if index > nofcurrent then
+-- report("more lookups than currently matched characters")
+-- for i=nofcurrent+1,index-1 do
+-- lookups[i] = false
+-- end
+-- nofcurrent = index
+-- end
+-- lookups[index] = readushort(f) + 1
+-- end
+-- return lookups
+-- end
+
local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,what)
local tableoffset = lookupoffset + offset
setposition(f,tableoffset)
@@ -409,7 +449,7 @@ local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,n
for i=2,nofcurrent do
current[i] = { readushort(f) }
end
- local lookups = readlookuparray(f,noflookups)
+ local lookups = readlookuparray(f,noflookups,nofcurrent)
rules[#rules+1] = {
current = current,
lookups = lookups
@@ -433,7 +473,7 @@ local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,n
local rules = { }
if subclasssets then
coverage = readcoverage(f,tableoffset + coverage)
- currentclassdef = readclassdef(f,tableoffset + currentclassdef)
+ currentclassdef = readclassdef(f,tableoffset + currentclassdef,coverage)
local currentclasses = classtocoverage(currentclassdef,fontdata.glyphs)
for class=1,#subclasssets do
local offset = subclasssets[class]
@@ -452,7 +492,7 @@ local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,n
for i=2,nofcurrent do
current[i] = currentclasses[readushort(f) + 1]
end
- local lookups = readlookuparray(f,noflookups)
+ local lookups = readlookuparray(f,noflookups,nofcurrent)
rules[#rules+1] = {
current = current,
lookups = lookups
@@ -476,7 +516,7 @@ local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,n
elseif subtype == 3 then
local current = readarray(f)
local noflookups = readushort(f)
- local lookups = readlookuparray(f,noflookups)
+ local lookups = readlookuparray(f,noflookups,#current)
current = readcoveragearray(f,tableoffset,current,true)
return {
format = "coverage",
@@ -536,7 +576,7 @@ local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nof
end
end
local noflookups = readushort(f)
- local lookups = readlookuparray(f,noflookups)
+ local lookups = readlookuparray(f,noflookups,nofcurrent)
rules[#rules+1] = {
before = before,
current = current,
@@ -562,9 +602,9 @@ local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nof
local rules = { }
if subclasssets then
local coverage = readcoverage(f,tableoffset + coverage)
- local beforeclassdef = readclassdef(f,tableoffset + beforeclassdef)
- local currentclassdef = readclassdef(f,tableoffset + currentclassdef)
- local afterclassdef = readclassdef(f,tableoffset + afterclassdef)
+ local beforeclassdef = readclassdef(f,tableoffset + beforeclassdef,nofglyphs)
+ local currentclassdef = readclassdef(f,tableoffset + currentclassdef,coverage)
+ local afterclassdef = readclassdef(f,tableoffset + afterclassdef,nofglyphs)
local beforeclasses = classtocoverage(beforeclassdef,fontdata.glyphs)
local currentclasses = classtocoverage(currentclassdef,fontdata.glyphs)
local afterclasses = classtocoverage(afterclassdef,fontdata.glyphs)
@@ -604,7 +644,7 @@ local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nof
end
-- no sequence index here (so why in context as it saves nothing)
local noflookups = readushort(f)
- local lookups = readlookuparray(f,noflookups)
+ local lookups = readlookuparray(f,noflookups,nofcurrent)
rules[#rules+1] = {
before = before,
current = current,
@@ -632,7 +672,7 @@ local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nof
local current = readarray(f)
local after = readarray(f)
local noflookups = readushort(f)
- local lookups = readlookuparray(f,noflookups)
+ local lookups = readlookuparray(f,noflookups,#current)
before = readcoveragearray(f,tableoffset,before,true)
current = readcoveragearray(f,tableoffset,current,true)
after = readcoveragearray(f,tableoffset,after,true)
@@ -988,8 +1028,8 @@ function gposhandlers.pair(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofgly
local nofclasses2 = readushort(f) -- incl class 0
local classlist = readpairclasssets(f,nofclasses1,nofclasses2,format1,format2)
coverage = readcoverage(f,tableoffset+coverage)
- classdef1 = readclassdef(f,tableoffset+classdef1)
- classdef2 = readclassdef(f,tableoffset+classdef2)
+ classdef1 = readclassdef(f,tableoffset+classdef1,coverage)
+ classdef2 = readclassdef(f,tableoffset+classdef2,nofglyphs)
local usedcoverage = { }
for g1, c1 in next, classdef1 do
if coverage[g1] then
@@ -1246,20 +1286,50 @@ do
local plugins = { }
- function plugins.size(f,fontdata,tableoffset,parameters)
- if not fontdata.designsize then
- setposition(f,tableoffset+parameters)
- local designsize = readushort(f)
- if designsize > 0 then
- fontdata.designsize = designsize
- skipshort(f,2)
- fontdata.minsize = readushort(f)
- fontdata.maxsize = readushort(f)
+ function plugins.size(f,fontdata,tableoffset,feature)
+ if fontdata.designsize then
+ -- yes, there are fonts with multiple size entries ... it probably relates
+ -- to the other two fields (menu entries in some language)
+ else
+ local function check(offset)
+ setposition(f,offset)
+ local designsize = readushort(f)
+ if designsize > 0 then -- we could also have a threshold
+ local fontstyle = readushort(f)
+ local guimenuid = readushort(f)
+ local minsize = readushort(f)
+ local maxsize = readushort(f)
+ if minsize == 0 and maxsize == 0 and fontstyleid == 0 and guimenuid == 0 then
+ minsize = designsize
+ maxsize = designsize
+ end
+ if designsize >= minsize and designsize <= maxsize then
+ return minsize, maxsize, designsize
+ end
+ end
+ end
+ local minsize, maxsize, designsize = check(tableoffset+feature.offset+feature.parameters)
+ if not designsize then
+ -- some old adobe fonts have: tableoffset+feature.parameters and we could
+ -- use some heuristic but why bother ... this extra check will be removed
+ -- some day and/or when we run into an issue
+ minsize, maxsize, designsize = check(tableoffset+feature.parameters)
+ if designsize then
+ report("bad size feature in %a, falling back to wrong offset",fontdata.filename or "?")
+ else
+ report("bad size feature in %a,",fontdata.filename or "?")
+ end
+ end
+ if designsize then
+ fontdata.minsize = minsize
+ fontdata.maxsize = maxsize
+ fontdata.designsize = designsize
end
end
end
- -- feature order needs checking ... as we loop over a hash
+ -- feature order needs checking ... as we loop over a hash ... however, in the file
+ -- they are sorted so order is not that relevant
local function reorderfeatures(fontdata,scripts,features)
local scriptlangs = { }
@@ -1401,7 +1471,7 @@ do
feature.parameters = parameters
local plugin = plugins[feature.tag]
if plugin then
- plugin(f,fontdata,offset,parameters)
+ plugin(f,fontdata,featureoffset,feature)
end
end
end
@@ -1660,7 +1730,7 @@ do
flags = d.flags,
-- chain = d.chain,
}
- sublookuplist[nofsublookups] = h
+ sublookuplist[nofsublookups] = copy(h) -- we repack later
sublookuphash[lookupid] = nofsublookups
sublookupcheck[lookupid] = 1
else
@@ -1894,7 +1964,7 @@ function readers.gdef(f,fontdata,specification)
end
end
-- mark sets : todo: just make the same as class sets above
- if marksetsoffset then
+ if marksetsoffset and marksetsoffset > tableoffset then -- zero offset means no table
setposition(f,marksetsoffset)
local format = readushort(f)
if format == 1 then
@@ -1903,7 +1973,6 @@ function readers.gdef(f,fontdata,specification)
for i=1,nofsets do
sets[i] = readulong(f)
end
- -- somehow this fails on e.g. notosansethiopic-bold.ttf
for i=1,nofsets do
local offset = sets[i]
if offset ~= 0 then
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-gbn.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-gbn.lua
index 1ae817ddb1b..1f8df642ca6 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-gbn.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-gbn.lua
@@ -19,7 +19,7 @@ local nodes = nodes
local nuts = nodes.nuts -- context abstraction of direct nodes
local traverse_id = nuts.traverse_id
-local free_node = nuts.free
+local flush_node = nuts.flush_node
local glyph_code = nodes.nodecodes.glyph
local disc_code = nodes.nodecodes.disc
@@ -159,7 +159,7 @@ function nodes.handlers.nodepass(head)
end
end
end
- free_node(r)
+ flush_node(r)
end
end
for d in traverse_id(disc_code,nuthead) do
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-map.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-map.lua
index 6151b37f594..e2254f8ca0e 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-map.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-map.lua
@@ -12,9 +12,10 @@ local match, format, find, concat, gsub, lower = string.match, string.format, st
local P, R, S, C, Ct, Cc, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.match
local floor = math.floor
local formatters = string.formatters
+local sortedhash, sortedkeys = table.sortedhash, table.sortedkeys
-local trace_loading = false trackers.register("fonts.loading", function(v) trace_loading = v end)
-local trace_mapping = false trackers.register("fonts.mapping", function(v) trace_unimapping = v end)
+local trace_loading = false trackers.register("fonts.loading", function(v) trace_loading = v end)
+local trace_mapping = false trackers.register("fonts.mapping", function(v) trace_mapping = v end)
local report_fonts = logs.reporter("fonts","loading") -- not otf only
@@ -236,39 +237,50 @@ local namesplitter = Ct(C((1 - ligseparator - varseparator)^1) * (ligseparator *
-- to be completed .. for fonts that use unicodes for ligatures which
-- is a actually a bad thing and should be avoided in the first place
-local overloads = allocate {
- IJ = { name = "I_J", unicode = { 0x49, 0x4A }, mess = 0x0132 },
- ij = { name = "i_j", unicode = { 0x69, 0x6A }, mess = 0x0133 },
- ff = { name = "f_f", unicode = { 0x66, 0x66 }, mess = 0xFB00 },
- fi = { name = "f_i", unicode = { 0x66, 0x69 }, mess = 0xFB01 },
- fl = { name = "f_l", unicode = { 0x66, 0x6C }, mess = 0xFB02 },
- ffi = { name = "f_f_i", unicode = { 0x66, 0x66, 0x69 }, mess = 0xFB03 },
- ffl = { name = "f_f_l", unicode = { 0x66, 0x66, 0x6C }, mess = 0xFB04 },
- fj = { name = "f_j", unicode = { 0x66, 0x6A } },
- fk = { name = "f_k", unicode = { 0x66, 0x6B } },
-}
-
-for k, v in next, overloads do
- local name = v.name
- local mess = v.mess
- if name then
- overloads[name] = v
- end
- if mess then
- overloads[mess] = v
+do
+
+ local overloads = allocate {
+ IJ = { name = "I_J", unicode = { 0x49, 0x4A }, mess = 0x0132 },
+ ij = { name = "i_j", unicode = { 0x69, 0x6A }, mess = 0x0133 },
+ ff = { name = "f_f", unicode = { 0x66, 0x66 }, mess = 0xFB00 },
+ fi = { name = "f_i", unicode = { 0x66, 0x69 }, mess = 0xFB01 },
+ fl = { name = "f_l", unicode = { 0x66, 0x6C }, mess = 0xFB02 },
+ ffi = { name = "f_f_i", unicode = { 0x66, 0x66, 0x69 }, mess = 0xFB03 },
+ ffl = { name = "f_f_l", unicode = { 0x66, 0x66, 0x6C }, mess = 0xFB04 },
+ fj = { name = "f_j", unicode = { 0x66, 0x6A } },
+ fk = { name = "f_k", unicode = { 0x66, 0x6B } },
+ }
+
+ local o = { }
+
+ for k, v in next, overloads do
+ local name = v.name
+ local mess = v.mess
+ if name then
+ o[name] = v
+ end
+ if mess then
+ o[mess] = v
+ end
+ o[k] = v
end
-end
-mappings.overloads = overloads
+ mappings.overloads = o
+
+end
function mappings.addtounicode(data,filename,checklookups)
local resources = data.resources
local unicodes = resources.unicodes
if not unicodes then
+ if trace_mapping then
+ report_fonts("no unicode list, quitting tounicode for %a",filename)
+ end
return
end
local properties = data.properties
local descriptions = data.descriptions
+ local overloads = mappings.overloads
-- we need to move this code
unicodes['space'] = unicodes['space'] or 32
unicodes['hyphen'] = unicodes['hyphen'] or 45
@@ -287,17 +299,25 @@ function mappings.addtounicode(data,filename,checklookups)
local usedmap = cidinfo and fonts.cid.getmap(cidinfo)
local uparser = makenameparser() -- hm, every time?
if usedmap then
- oparser = usedmap and makenameparser(cidinfo.ordering)
- cidnames = usedmap.names
- cidcodes = usedmap.unicodes
+ oparser = usedmap and makenameparser(cidinfo.ordering)
+ cidnames = usedmap.names
+ cidcodes = usedmap.unicodes
end
- local ns = 0
- local nl = 0
+ local ns = 0
+ local nl = 0
+ --
+ -- in order to avoid differences between runs due to hash randomization we
+ -- run over a sorted list
--
- for du, glyph in next, descriptions do
- local name = glyph.name
+ local dlist = sortedkeys(descriptions)
+ --
+ -- for du, glyph in next, descriptions do
+ for i=1,#dlist do
+ local du = dlist[i]
+ local glyph = descriptions[du]
+ local name = glyph.name
if name then
- local overload = overloads[name]
+ local overload = overloads[name] or overloads[du]
if overload then
-- get rid of weird ligatures
-- glyph.name = overload.name
@@ -433,6 +453,11 @@ function mappings.addtounicode(data,filename,checklookups)
end
end
end
+ else
+ local overload = overloads[du]
+ if overload then
+ glyph.unicode = overload.unicode
+ end
end
end
if type(checklookups) == "function" then
@@ -443,7 +468,10 @@ function mappings.addtounicode(data,filename,checklookups)
local collected = false
local unicoded = 0
- for unicode, glyph in next, descriptions do
+ -- for du, glyph in next, descriptions do
+ for i=1,#dlist do
+ local du = dlist[i]
+ local glyph = descriptions[du]
if glyph.class == "ligature" and (force_ligatures or not glyph.unicode) then
if not collected then
collected = fonts.handlers.otf.readers.getcomponents(data)
@@ -451,7 +479,7 @@ function mappings.addtounicode(data,filename,checklookups)
break
end
end
- local u = collected[unicode] -- always tables
+ local u = collected[du] -- always tables
if u then
local n = #u
for i=1,n do
@@ -474,11 +502,13 @@ function mappings.addtounicode(data,filename,checklookups)
if trace_mapping and unicoded > 0 then
report_fonts("%n ligature tounicode mappings deduced from gsub ligature features",unicoded)
end
-
if trace_mapping then
- for unic, glyph in table.sortedhash(descriptions) do
- local name = glyph.name
- local index = glyph.index
+ -- for unic, glyph in sortedhash(descriptions) do
+ for i=1,#dlist do
+ local du = dlist[i]
+ local glyph = descriptions[du]
+ local name = glyph.name or "-"
+ local index = glyph.index or 0
local unicode = glyph.unicode
if unicode then
if type(unicode) == "table" then
@@ -486,12 +516,12 @@ function mappings.addtounicode(data,filename,checklookups)
for i=1,#unicode do
unicodes[i] = formatters("%U",unicode[i])
end
- report_fonts("internal slot %U, name %a, unicode %U, tounicode % t",index,name,unic,unicodes)
+ report_fonts("internal slot %U, name %a, unicode %U, tounicode % t",index,name,du,unicodes)
else
- report_fonts("internal slot %U, name %a, unicode %U, tounicode %U",index,name,unic,unicode)
+ report_fonts("internal slot %U, name %a, unicode %U, tounicode %U",index,name,du,unicode)
end
else
- report_fonts("internal slot %U, name %a, unicode %U",index,name,unic)
+ report_fonts("internal slot %U, name %a, unicode %U",index,name,du)
end
end
end
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ocl.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ocl.lua
index b2aba7ac7fe..65a1c63427c 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ocl.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ocl.lua
@@ -8,34 +8,86 @@ if not modules then modules = { } end modules ['font-ocl'] = {
-- todo : user list of colors
-local tostring, next = tostring, next
+local tostring, next, format = tostring, next, string.format
+local round, max = math.round, math.round
local formatters = string.formatters
+local tounicode = fonts.mappings.tounicode
-local otf = fonts.handlers.otf
+local otf = fonts.handlers.otf
-local f_color_start = formatters["pdf:direct: %f %f %f rg"]
-local s_color_stop = "pdf:direct:"
+local f_color = formatters["pdf:direct:%f %f %f rg"]
+local f_gray = formatters["pdf:direct:%f g"]
+local s_black = "pdf:direct:0 g"
if context then
local startactualtext = nil
local stopactualtext = nil
- function otf.getactualtext(n)
+ function otf.getactualtext(s)
if not startactualtext then
- startactualtext = backends.codeinjections.startunicodetoactualtext
- stopactualtext = backends.codeinjections.stopunicodetoactualtext
+ startactualtext = backends.codeinjections.startunicodetoactualtextdirect
+ stopactualtext = backends.codeinjections.stopunicodetoactualtextdirect
end
- return startactualtext(n), stopactualtext()
+ return startactualtext(s), stopactualtext()
end
else
local tounicode = fonts.mappings.tounicode16
- function otf.getactualtext(n)
- return "/Span << /ActualText <feff" .. tounicode(n) .. "> >> BDC", "EMC"
+ function otf.getactualtext(s)
+ return
+ "/Span << /ActualText <feff" .. n .. "> >> BDC",
+ "EMC"
+ end
+
+end
+
+local sharedpalettes = { }
+
+if context then
+
+ local graytorgb = attributes.colors.graytorgb
+ local cmyktorgb = attributes.colors.cmyktorgb
+
+ function otf.registerpalette(name,values)
+ sharedpalettes[name] = values
+ for i=1,#values do
+ local v = values[i]
+ local r, g, b
+ local s = v.s
+ if s then
+ r, g, b = graytorgb(s)
+ else
+ local c, m, y, k = v.c, v.m, v.y, v.k
+ if c or m or y or k then
+ r, g, b = cmyktorgb(c or 0,m or 0,y or 0,k or 0)
+ else
+ r, g, b = v.r, v.g, v.b
+ end
+ end
+ values[i] = {
+ max(r and round(r*255) or 0,255),
+ max(g and round(g*255) or 0,255),
+ max(b and round(b*255) or 0,255)
+ }
+ end
+ end
+
+else -- for generic
+
+ function otf.registerpalette(name,values)
+ sharedpalettes[name] = values
+ for i=1,#values do
+ local v = values[i]
+ values[i] = {
+ max(round((v.r or 0)*255),255),
+ max(round((v.g or 0)*255),255),
+ max(round((v.b or 0)*255),255)
+ }
+ end
end
end
@@ -45,7 +97,7 @@ local function initializecolr(tfmdata,kind,value) -- hm, always value
local palettes = tfmdata.resources.colorpalettes
if palettes then
--
- local palette = palettes[tonumber(value) or 1] or palettes[1] or { }
+ local palette = sharedpalettes[value] or palettes[tonumber(value) or 1] or palettes[1] or { }
local classes = #palette
if classes == 0 then
return
@@ -63,7 +115,12 @@ local function initializecolr(tfmdata,kind,value) -- hm, always value
--
for i=1,classes do
local p = palette[i]
- colorvalues[i] = { "special", f_color_start(p[1]/255,p[2]/255,p[3]/255) }
+ local r, g, b = p[1], p[2], p[3]
+ if r == g and g == b then
+ colorvalues[i] = { "special", f_gray(r/255) }
+ else
+ colorvalues[i] = { "special", f_color(r/255,g/255,b/255) }
+ end
end
--
local getactualtext = otf.getactualtext
@@ -73,22 +130,30 @@ local function initializecolr(tfmdata,kind,value) -- hm, always value
if description then
local colorlist = description.colors
if colorlist then
- local b, e = getactualtext(unicode)
+ local b, e = getactualtext(tounicode(characters[unicode].unicode or 0xFFFD))
local w = character.width or 0
local s = #colorlist
- local n = 1
local t = {
- { "special", "pdf:direct: q " .. b }
+ -- We need to force page first because otherwise the q's get outside
+ -- the font switch and as a consequence the next character has no font
+ -- set (well, it has: the preceding one). As a consequence these fonts
+ -- are somewhat inefficient as each glyph gets the font set. It's a
+ -- side effect of the fact that a font is handled when a character gets
+ -- flushed.
+ { "special", "pdf:page:q" },
+ { "special", "pdf:raw:" .. b }
}
+ local n = #t
for i=1,s do
local entry = colorlist[i]
- n = n + 1 t[n] = colorvalues[entry.class]
+ n = n + 1 t[n] = colorvalues[entry.class] or s_black
n = n + 1 t[n] = { "char", entry.slot }
if s > 1 and i < s and w ~= 0 then
n = n + 1 t[n] = { "right", -w }
end
end
- n = n + 1 t[n] = { "special", "pdf:direct:" .. e .. " Q" }
+ n = n + 1 t[n] = { "special", "pdf:page:" .. e }
+ n = n + 1 t[n] = { "special", "pdf:raw:Q" }
character.commands = t
end
end
@@ -166,34 +231,56 @@ do
end
-if context and xml.convert then
+
+do
local report_svg = logs.reporter("fonts","svg conversion")
- local xmlconvert = xml.convert
- local xmlfirst = xml.first
local loaddata = io.loaddata
local savedata = io.savedata
local remove = os.remove
+ if context and xml.convert then
+
+ local xmlconvert = xml.convert
+ local xmlfirst = xml.first
+
+ function otfsvg.filterglyph(entry,index)
+ local svg = xmlconvert(entry.data)
+ local root = svg and xmlfirst(svg,"/svg[@id='glyph"..index.."']")
+ local data = root and tostring(root)
+ -- report_svg("data for glyph %04X: %s",index,data)
+ return data
+ end
+
+ else
+
+ function otfsvg.filterglyph(entry,index) -- can be overloaded
+ return entry.data
+ end
+
+ end
+
-- function otfsvg.topdf(svgshapes)
- -- local svgfile = "temp-otf-svg-shape.svg"
- -- local pdffile = "temp-otf-svg-shape.pdf"
- -- local command = "inkscape " .. svgfile .. " --export-pdf=" .. pdffile
- -- local testrun = false
- -- local pdfshapes = { }
- -- local nofshapes = #svgshapes
+ -- local svgfile = "temp-otf-svg-shape.svg"
+ -- local pdffile = "temp-otf-svg-shape.pdf"
+ -- local command = "inkscape " .. svgfile .. " --export-pdf=" .. pdffile
+ -- local testrun = false
+ -- local pdfshapes = { }
+ -- local nofshapes = #svgshapes
+ -- local filterglyph = otfsvg.filterglyph
-- report_svg("processing %i svg containers",nofshapes)
-- statistics.starttiming()
-- for i=1,nofshapes do
-- local entry = svgshapes[i]
- -- for j=entry.first,entry.last do
- -- local svg = xmlconvert(entry.data)
- -- local data = xmlfirst(svg,"/svg[@id='glyph"..j.."']")
+ -- for index=entry.first,entry.last do
+ -- local data = filterglyph(entry,index)
-- savedata(svgfile,tostring(data))
- -- report_svg("processing svg shape of glyph %i in container %i",j,i)
- -- os.execute(command)
- -- pdfshapes[j] = loaddata(pdffile)
+ -- if data and data ~= "" then
+ -- report_svg("processing svg shape of glyph %i in container %i",index,i)
+ -- os.execute(command)
+ -- pdfshapes[index] = loaddata(pdffile)
+ -- end
-- end
-- if testrun and i > testrun then
-- report_svg("quiting test run")
@@ -207,26 +294,25 @@ if context and xml.convert then
-- end
function otfsvg.topdf(svgshapes)
- local inkscape = io.popen("inkscape --shell 2>&1","w")
- local pdfshapes = { }
- local nofshapes = #svgshapes
- local f_svgfile = formatters["temp-otf-svg-shape-%i.svg"]
- local f_pdffile = formatters["temp-otf-svg-shape-%i.pdf"]
- local f_convert = formatters["%s --export-pdf=%s\n"]
+ local inkscape = io.popen("inkscape --shell > temp-otf-svg-shape.log","w")
+ local pdfshapes = { }
+ local nofshapes = #svgshapes
+ local f_svgfile = formatters["temp-otf-svg-shape-%i.svg"]
+ local f_pdffile = formatters["temp-otf-svg-shape-%i.pdf"]
+ local f_convert = formatters["%s --export-pdf=%s\n"]
+ local filterglyph = otfsvg.filterglyph
report_svg("processing %i svg containers",nofshapes)
statistics.starttiming()
for i=1,nofshapes do
local entry = svgshapes[i]
- for j=entry.first,entry.last do
- local svg = xmlconvert(entry.data)
- local root = svg and xmlfirst(svg,"/svg[@id='glyph"..j.."']")
- local data = root and tostring(root)
+ for index=entry.first,entry.last do
+ local data = filterglyph(entry,index)
if data and data ~= "" then
- local svgfile = f_svgfile(j)
- local pdffile = f_pdffile(j)
+ local svgfile = f_svgfile(index)
+ local pdffile = f_pdffile(index)
savedata(svgfile,data)
inkscape:write(f_convert(svgfile,pdffile))
- pdfshapes[j] = true
+ pdfshapes[index] = true
end
end
end
@@ -236,39 +322,17 @@ if context and xml.convert then
-- end
inkscape:close()
report_svg("processing %i pdf results",nofshapes)
- for i in next, pdfshapes do
- local svgfile = f_svgfile(i)
- local pdffile = f_pdffile(i)
- pdfshapes[i] = loaddata(pdffile)
+ for index in next, pdfshapes do
+ local svgfile = f_svgfile(index)
+ local pdffile = f_pdffile(index)
+ pdfshapes[index] = loaddata(pdffile)
remove(svgfile)
remove(pdffile)
end
statistics.stoptiming()
- report_svg("conversion time: %0.3f",statistics.elapsedtime())
- return pdfshapes
- end
-
-else
-
- function otfsvg.topdf(svgshapes)
- local svgfile = "temp-otf-svg-shape.svg"
- local pdffile = "temp-otf-svg-shape.pdf"
- local command = "inkscape " .. svgfile .. " --export-pdf=" .. pdffile
- local pdfshapes = { }
- local nofshapes = #svgshapes
- texio.write(formatters["[converting %i svg glyphs to pdf using command %q : "](nofshapes,command))
- for i=1,nofshapes do
- local entry = svgshapes[i]
- for j=entry.first,entry.last do
- -- cross our fingers .. some, day i will filter
- texio.write(formatters["%i "](j))
- io.savedata(svgfile,tostring(entry.data))
- os.execute(command)
- pdfshapes[j] = io.loaddata(pdffile)
- end
+ if statistics.elapsedseconds then
+ report_svg("svg conversion time %s",statistics.elapsedseconds())
end
- os.remove(svgfile)
- texio.write("done]")
return pdfshapes
end
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-one.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-one.lua
index a6f47e87bfe..d9b9c65dff4 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-one.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-one.lua
@@ -29,42 +29,45 @@ local bxor, rshift = bit32.bxor, bit32.rshift
local P, S, R, Cmt, C, Ct, Cs, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch, patterns = lpeg.match, lpeg.patterns
-local trace_features = false trackers.register("afm.features", function(v) trace_features = v end)
-local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end)
-local trace_loading = false trackers.register("afm.loading", function(v) trace_loading = v end)
-local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
+local trace_features = false trackers.register("afm.features", function(v) trace_features = v end)
+local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end)
+local trace_loading = false trackers.register("afm.loading", function(v) trace_loading = v end)
+local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
-local report_afm = logs.reporter("fonts","afm loading")
+local report_afm = logs.reporter("fonts","afm loading")
-local setmetatableindex = table.setmetatableindex
-local derivetable = table.derive
+local setmetatableindex = table.setmetatableindex
+local derivetable = table.derive
-local findbinfile = resolvers.findbinfile
+local findbinfile = resolvers.findbinfile
-local definers = fonts.definers
-local readers = fonts.readers
-local constructors = fonts.constructors
+local definers = fonts.definers
+local readers = fonts.readers
+local constructors = fonts.constructors
-local afm = constructors.handlers.afm
-local pfb = constructors.handlers.pfb
-local otf = fonts.handlers.otf
+local afm = constructors.handlers.afm
+local pfb = constructors.handlers.pfb
+local otf = fonts.handlers.otf
-local otfreaders = otf.readers
-local otfenhancers = otf.enhancers
+local otfreaders = otf.readers
+local otfenhancers = otf.enhancers
-local afmfeatures = constructors.features.afm
-local registerafmfeature = afmfeatures.register
+local afmfeatures = constructors.features.afm
+local registerafmfeature = afmfeatures.register
-afm.version = 1.512 -- incrementing this number one up will force a re-cache
-afm.cache = containers.define("fonts", "afm", afm.version, true)
-afm.autoprefixed = true -- this will become false some day (catches texnansi-blabla.*)
+local afmenhancers = constructors.enhancers.afm
+local registerafmenhancer = afmenhancers.register
-afm.helpdata = { } -- set later on so no local for this
-afm.syncspace = true -- when true, nicer stretch values
+afm.version = 1.512 -- incrementing this number one up will force a re-cache
+afm.cache = containers.define("fonts", "one", afm.version, true)
+afm.autoprefixed = true -- this will become false some day (catches texnansi-blabla.*)
-local overloads = fonts.mappings.overloads
+afm.helpdata = { } -- set later on so no local for this
+afm.syncspace = true -- when true, nicer stretch values
-local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes
+local overloads = fonts.mappings.overloads
+
+local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes
--[[ldx--
<p>We cache files. Caching is taken care of in the loader. We cheat a bit by adding
@@ -76,35 +79,6 @@ fashion and later we transform it to sequences. Then we apply some methods also
used in opentype fonts (like <t>tlig</t>).</p>
--ldx]]--
-local enhancers = {
- -- It's cleaner to implement them after we've seen what we are
- -- dealing with.
-}
-
-local steps = {
- "unify names",
- "add ligatures",
- "add extra kerns",
- "normalize features",
- "fix names",
--- "add tounicode data",
-}
-
-local function applyenhancers(data,filename)
- for i=1,#steps do
- local step = steps[i]
- local enhancer = enhancers[step]
- if enhancer then
- if trace_loading then
- report_afm("applying enhancer %a",step)
- end
- enhancer(data,filename)
- else
- report_afm("invalid enhancer %a",step)
- end
- end
-end
-
function afm.load(filename)
filename = resolvers.findfile(filename,'afm') or ""
if filename ~= "" and not fonts.names.ignoredfile(filename) then
@@ -128,7 +102,7 @@ function afm.load(filename)
report_afm("reading %a",filename)
data = afm.readers.loadfont(filename,pfbname)
if data then
- applyenhancers(data,filename)
+ afmenhancers.apply(data,filename)
-- otfreaders.addunicodetable(data) -- only when not done yet
fonts.mappings.addtounicode(data,filename)
-- otfreaders.extend(data)
@@ -161,7 +135,7 @@ end
local uparser = fonts.mappings.makenameparser() -- each time
-enhancers["unify names"] = function(data, filename)
+local function enhance_unify_names(data, filename)
local unicodevector = fonts.encodings.agl.unicodes -- loaded runtime in context
local unicodes = { }
local names = { }
@@ -217,7 +191,7 @@ end
local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } }
local noflags = { false, false, false, false }
-enhancers["normalize features"] = function(data)
+local function enhance_normalize_features(data)
local ligatures = setmetatableindex("table")
local kerns = setmetatableindex("table")
local extrakerns = setmetatableindex("table")
@@ -318,7 +292,7 @@ enhancers["normalize features"] = function(data)
data.resources.sequences = sequences
end
-enhancers["fix names"] = function(data)
+local function enhance_fix_names(data)
for k, v in next, data.descriptions do
local n = v.name
local r = overloads[n]
@@ -365,14 +339,10 @@ local addthem = function(rawdata,ligatures)
end
end
-enhancers["add ligatures"] = function(rawdata)
+local function enhance_add_ligatures(rawdata)
addthem(rawdata,afm.helpdata.ligatures)
end
--- enhancers["add tex ligatures"] = function(rawdata)
--- addthem(rawdata,afm.helpdata.texligatures)
--- end
-
--[[ldx--
<p>We keep the extra kerns in separate kerning tables so that we can use
them selectively.</p>
@@ -385,7 +355,7 @@ them selectively.</p>
-- we don't use the character database. (Ok, we can have a context specific
-- variant).
-enhancers["add extra kerns"] = function(rawdata) -- using shcodes is not robust here
+local function enhance_add_extra_kerns(rawdata) -- using shcodes is not robust here
local descriptions = rawdata.descriptions
local resources = rawdata.resources
local unicodes = resources.unicodes
@@ -752,18 +722,12 @@ end
<p>We have the usual two modes and related features initializers and processors.</p>
--ldx]]--
-local function setmode(tfmdata,value)
- if value then
- tfmdata.properties.mode = lower(value)
- end
-end
-
registerafmfeature {
name = "mode",
description = "mode",
initializers = {
- base = setmode,
- node = setmode,
+ base = otf.modeinitializer,
+ node = otf.modeinitializer,
}
}
@@ -782,8 +746,6 @@ registerafmfeature {
-- readers
-local check_tfm = readers.check_tfm
-
fonts.formats.afm = "type1"
fonts.formats.pfb = "type1"
@@ -820,7 +782,8 @@ function readers.afm(specification,method)
tfmdata = check_afm(specification,specification.name .. "." .. forced)
end
if not tfmdata then
- method = method or definers.method or "afm or tfm"
+ local check_tfm = readers.check_tfm
+ method = (check_tfm and (method or definers.method or "afm or tfm")) or "afm"
if method == "tfm" then
tfmdata = check_tfm(specification,specification.name)
elseif method == "afm" then
@@ -855,3 +818,12 @@ function readers.pfb(specification,method) -- only called when forced
swap("specification")
return readers.afm(specification,method)
end
+
+-- now we register them
+
+registerafmenhancer("unify names", enhance_unify_names)
+registerafmenhancer("add ligatures", enhance_add_ligatures)
+registerafmenhancer("add extra kerns", enhance_add_extra_kerns)
+registerafmenhancer("normalize features", enhance_normalize_features)
+registerafmenhancer("check extra features", otfenhancers.enhance)
+registerafmenhancer("fix names", enhance_fix_names)
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-onr.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-onr.lua
index a4969ad73bb..6c33b24c644 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-onr.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-onr.lua
@@ -21,23 +21,21 @@ add features.</p>
local fonts, logs, trackers, resolvers = fonts, logs, trackers, resolvers
-local next, type, tonumber, rawget = next, type, tonumber, rawget
+local next, type, tonumber, rawget, rawset = next, type, tonumber, rawget, rawset
local match, lower, gsub, strip, find = string.match, string.lower, string.gsub, string.strip, string.find
local char, byte, sub = string.char, string.byte, string.sub
local abs = math.abs
local bxor, rshift = bit32.bxor, bit32.rshift
-local P, S, R, Cmt, C, Ct, Cs, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
+local P, S, R, Cmt, C, Ct, Cs, Carg, Cf, Cg = lpeg.P, lpeg.S, lpeg.R, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg, lpeg.Cf, lpeg.Cg
local lpegmatch, patterns = lpeg.match, lpeg.patterns
local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end)
local trace_loading = false trackers.register("afm.loading", function(v) trace_loading = v end)
local report_afm = logs.reporter("fonts","afm loading")
-local report_afm = logs.reporter("fonts","pfb loading")
+local report_pfb = logs.reporter("fonts","pfb loading")
-fonts = fonts or { }
-local handlers = fonts.handlers or { }
-fonts.handlers = handlers
+local handlers = fonts.handlers
local afm = handlers.afm or { }
handlers.afm = afm
local readers = afm.readers or { }
@@ -52,42 +50,10 @@ and <l n='otf'/> reader.</p>
and new vectors (we actually had one bad vector with the old loader).</p>
--ldx]]--
-local get_indexes
+local get_indexes, get_shapes
do
- local n, m
-
- local progress = function(str,position,name,size)
- local forward = position + tonumber(size) + 3 + 2
- n = n + 1
- if n >= m then
- return #str, name
- elseif forward < #str then
- return forward, name
- else
- return #str, name
- end
- end
-
- local initialize = function(str,position,size)
- n = 0
- m = tonumber(size)
- return position + 1
- end
-
- local charstrings = P("/CharStrings")
- local name = P("/") * C((R("az")+R("AZ")+R("09")+S("-_."))^1)
- local size = C(R("09")^1)
- local spaces = P(" ")^1
-
- local p_filternames = Ct (
- (1-charstrings)^0 * charstrings * spaces * Cmt(size,initialize)
- * (Cmt(name * P(" ")^1 * C(R("09")^1), progress) + P(1))^1
- )
-
- -- if one of first 4 not 0-9A-F then binary else hex
-
local decrypt
do
@@ -101,23 +67,107 @@ do
return char(plain)
end
- decrypt = function(binary)
- r, c1, c2, n = 55665, 52845, 22719, 4
+ decrypt = function(binary,initial,seed)
+ r, c1, c2, n = initial, 52845, 22719, seed
binary = gsub(binary,".",step)
return sub(binary,n+1)
end
-- local pattern = Cs((P(1) / step)^1)
--
- -- decrypt = function(binary)
- -- r, c1, c2, n = 55665, 52845, 22719, 4
+ -- decrypt = function(binary,initial,seed)
+ -- r, c1, c2, n = initial, 52845, 22719, seed
-- binary = lpegmatch(pattern,binary)
-- return sub(binary,n+1)
-- end
end
- local function loadpfbvector(filename)
+ local charstrings = P("/CharStrings")
+ local subroutines = P("/Subrs")
+ local encoding = P("/Encoding")
+ local dup = P("dup")
+ local put = P("put")
+ local array = P("array")
+ local name = P("/") * C((R("az")+R("AZ")+R("09")+S("-_."))^1)
+ local digits = R("09")^1
+ local cardinal = digits / tonumber
+ local spaces = P(" ")^1
+ local spacing = patterns.whitespace^0
+
+ local routines, vector, chars, n, m
+
+ local initialize = function(str,position,size)
+ n = 0
+ m = size -- % tonumber(size)
+ return position + 1
+ end
+
+ local setroutine = function(str,position,index,size)
+ local forward = position + tonumber(size)
+ local stream = sub(str,position+1,forward)
+ routines[index] = decrypt(stream,4330,4)
+ return forward
+ end
+
+ local setvector = function(str,position,name,size)
+ local forward = position + tonumber(size)
+ if n >= m then
+ return #str
+ elseif forward < #str then
+ vector[n] = name
+ n = n + 1 -- we compensate for notdef at the cff loader end
+ return forward
+ else
+ return #str
+ end
+ end
+
+ local setshapes = function(str,position,name,size)
+ local forward = position + tonumber(size)
+ local stream = sub(str,position+1,forward)
+ if n > m then
+ return #str
+ elseif forward < #str then
+ vector[n] = name
+ n = n + 1
+ chars [n] = decrypt(stream,4330,4)
+ return forward
+ else
+ return #str
+ end
+ end
+
+ local p_rd = spacing * (P("RD") + P("-|"))
+ local p_np = spacing * (P("NP") + P( "|"))
+ local p_nd = spacing * (P("ND") + P( "|"))
+
+ local p_filterroutines = -- dup <i> <n> RD or -| <n encrypted bytes> NP or |
+ (1-subroutines)^0 * subroutines * spaces * Cmt(cardinal,initialize)
+ * (Cmt(cardinal * spaces * cardinal * p_rd, setroutine) * p_np + P(1))^1
+
+ local p_filtershapes = -- /foo <n> RD <n encrypted bytes> ND
+ (1-charstrings)^0 * charstrings * spaces * Cmt(cardinal,initialize)
+ * (Cmt(name * spaces * cardinal * p_rd, setshapes) * p_nd + P(1))^1
+
+ local p_filternames = Ct (
+ (1-charstrings)^0 * charstrings * spaces * Cmt(cardinal,initialize)
+ * (Cmt(name * spaces * cardinal, setvector) + P(1))^1
+ )
+
+ -- /Encoding 256 array
+ -- 0 1 255 {1 index exch /.notdef put} for
+ -- dup 0 /Foo put
+
+ local p_filterencoding =
+ (1-encoding)^0 * encoding * spaces * digits * spaces * array * (1-dup)^0
+ * Cf(
+ Ct("") * Cg(spacing * dup * spaces * cardinal * spaces * name * spaces * put)^1
+ ,rawset)
+
+ -- if one of first 4 not 0-9A-F then binary else hex
+
+ local function loadpfbvector(filename,shapestoo)
-- for the moment limited to encoding only
local data = io.loaddata(resolvers.findfile(filename))
@@ -139,24 +189,43 @@ do
return
end
- binary = decrypt(binary,4)
-
- local vector = lpegmatch(p_filternames,binary)
-
- if vector[1] == ".notdef" then
- -- tricky
- vector[0] = table.remove(vector,1)
+ binary = decrypt(binary,55665,4)
+
+ local names = { }
+ local encoding = lpegmatch(p_filterencoding,ascii)
+ local glyphs = { }
+
+ routines, vector, chars = { }, { }, { }
+
+ if shapestoo then
+ lpegmatch(p_filterroutines,binary)
+ lpegmatch(p_filtershapes,binary)
+ local data = {
+ dictionaries = {
+ {
+ charstrings = chars,
+ charset = vector,
+ subroutines = routines,
+ }
+ },
+ }
+ fonts.handlers.otf.readers.parsecharstrings(data,glyphs,true,true)
+ else
+ lpegmatch(p_filternames,binary)
end
- if not vector then
- report_pfb("no vector in %a",filename)
- return
- end
+ names = vector
- return vector
+ routines, vector, chars = nil, nil, nil
+
+ return names, encoding, glyphs
end
+ local pfb = handlers.pfb or { }
+ handlers.pfb = pfb
+ pfb.loadvector = loadpfbvector
+
get_indexes = function(data,pfbname)
local vector = loadpfbvector(pfbname)
if vector then
@@ -177,6 +246,11 @@ do
end
end
+ get_shapes = function(pfbname)
+ local vector, encoding, glyphs = loadpfbvector(pfbname,true)
+ return glyphs
+ end
+
end
--[[ldx--
@@ -403,6 +477,26 @@ function readers.loadfont(afmname,pfbname)
end
end
+-- for now, todo: n and check with otf (no afm needed here)
+
+function readers.loadshapes(filename)
+ local fullname = resolvers.findfile(filename) or ""
+ if fullname == "" then
+ return {
+ filename = "not found: " .. filename,
+ glyphs = { }
+ }
+ else
+ return {
+ filename = fullname,
+ format = "opentype",
+ glyphs = get_shapes(fullname) or { },
+ units = 1000,
+ }
+ end
+end
+
+
function readers.getinfo(filename)
local data = read(resolvers.findfile(filename),infoparser)
if data then
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-osd.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-osd.lua
index a3dda6734f7..b67cc924113 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-osd.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-osd.lua
@@ -107,9 +107,9 @@ local ischar = nuts.is_char
local insert_node_after = nuts.insert_after
local copy_node = nuts.copy
-local free_node = nuts.free
local remove_node = nuts.remove
local flush_list = nuts.flush_list
+local flush_node = nuts.flush_node
local copyinjection = nodes.injections.copy -- KE: is this necessary? HH: probably not as positioning comes later and we rawget/set
@@ -613,13 +613,12 @@ local function initializedevanagi(tfmdata)
local steps = sequence.steps
local nofsteps = sequence.nofsteps
local features = sequence.features
- if features["rphf"] then
- -- deva
+ local has_rphf = features.rphf
+ local has_blwf = features.blwf
+ if has_rphf and has_rphf.deva then
devanagari.reph = true
- elseif features["blwf"] then
- -- deva
+ elseif has_blwf and has_blwf.deva then
devanagari.vattu = true
- -- dev2
for i=1,nofsteps do
local step = steps[i]
local coverage = step.coverage
@@ -632,59 +631,71 @@ local function initializedevanagi(tfmdata)
end
end
end
- if valid[kind] then
- for i=1,nofsteps do
- local step = steps[i]
- local coverage = step.coverage
- if coverage then
- local reph = false
- if step.osdstep then
- -- rphf acts on consonant + halant
- for k, v in next, ra do
- local r = coverage[k]
- if r then
- local h = false
- for k, v in next, halant do
- local h = r[k]
- if h then
- reph = h.ligature or false
- break
+ for kind, spec in next, features do -- beware, this is
+ if spec.dev2 and valid[kind] then
+ for i=1,nofsteps do
+ local step = steps[i]
+ local coverage = step.coverage
+ if coverage then
+ local reph = false
+ if kind == "rphf" then
+ --
+ -- KE: I don't understand the rationale behind osdstep. The original if
+ -- statement checked whether coverage is contextual chaining.
+ --
+ -- HH: The osdstep signals that we deal with our own feature here, not
+ -- one in the font itself so it was just a safeguard against us overloading
+ -- something driven by the font.
+ --
+ -- if step.osdstep then -- selective
+ if true then -- always
+ -- rphf acts on consonant + halant
+ for k, v in next, ra do
+ local r = coverage[k]
+ if r then
+ local h = false
+ for k, v in next, halant do
+ local h = r[k]
+ if h then
+ reph = h.ligature or false
+ break
+ end
+ end
+ if reph then
+ break
+ end
end
end
- if reph then
- break
- end
+ else
+ -- rphf might be result of other handler/chainproc
end
end
- else
- -- rphf might be result of other handler/chainproc
+ seqsubset[#seqsubset+1] = { kind, coverage, reph }
end
- seqsubset[#seqsubset+1] = { kind, coverage, reph }
end
end
- end
- if kind == "pref" then
- local sequence = dataset[3] -- was [5]
- local steps = sequence.steps
- local nofsteps = sequence.nofsteps
- for i=1,nofsteps do
- local step = steps[i]
- local coverage = step.coverage
- if coverage then
- for k, v in next, halant do
- local h = coverage[k]
- if h then
- local found = false
- for k, v in next, h do
- found = v and v.ligature
+ if kind == "pref" then
+ local steps = sequence.steps
+ local nofsteps = sequence.nofsteps
+ for i=1,nofsteps do
+ local step = steps[i]
+ local coverage = step.coverage
+ if coverage then
+ for k, v in next, halant do
+ local h = coverage[k]
+ if h then
+ local found = false
+ for k, v in next, h do
+ found = v and v.ligature
+ if found then
+ pre_base_reordering_consonants[k] = found
+ break
+ end
+ end
if found then
- pre_base_reordering_consonants[k] = found
break
end
end
- if found then
- break
- end
end
end
end
@@ -792,7 +803,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
if current == stop then
stop = getprev(stop)
head = remove_node(head,current)
- free_node(current)
+ flush_node(current)
return head, stop, nbspaces
else
nbspaces = nbspaces + 1
@@ -830,7 +841,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
setchar(current,getchar(tempcurrent)) -- we assumes that the result of blwf consists of one node
local freenode = getnext(current)
setlink(current,tmp)
- free_node(freenode)
+ flush_node(freenode)
flush_list(tempcurrent)
if changestop then
stop = current
@@ -1093,7 +1104,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
if getchar(base) == c_nbsp then
nbspaces = nbspaces - 1
head = remove_node(head,base)
- free_node(base)
+ flush_node(base)
end
return head, stop, nbspaces
@@ -1132,6 +1143,8 @@ function handlers.devanagari_reorder_matras(head,start) -- no leak
start = startnext
break
end
+ else
+ break
end
current = next
end
@@ -1171,12 +1184,12 @@ function handlers.devanagari_reorder_reph(head,start)
local startfont = getfont(start)
local startattr = getprop(start,a_syllabe)
while current do
- local char = ischar(current,font)
+ local char = ischar(current,startfont)
if char and getprop(current,a_syllabe) == startattr then -- step 2
if halant[char] and not getprop(current,a_state) then
local next = getnext(current)
if next then
- local nextchar = ischar(next,font)
+ local nextchar = ischar(next,startfont)
if nextchar and zw_char[nextchar] and getprop(next,a_syllabe) == startattr then
current = next
next = getnext(current)
@@ -1198,7 +1211,7 @@ function handlers.devanagari_reorder_reph(head,start)
if not startnext then
current = getnext(start)
while current do
- local char = ischar(current,font)
+ local char = ischar(current,startfont)
if char and getprop(current,a_syllabe) == startattr then -- step 4
if getprop(current,a_state) == s_pstf then -- post-base
startnext = getnext(start)
@@ -1223,7 +1236,7 @@ function handlers.devanagari_reorder_reph(head,start)
current = getnext(start)
local c = nil
while current do
- local char = ischar(current,font)
+ local char = ischar(current,startfont)
if char and getprop(current,a_syllabe) == startattr then -- step 5
if not c and mark_above_below_post[char] and reorder_class[char] ~= "after subscript" then
c = current
@@ -1250,7 +1263,7 @@ function handlers.devanagari_reorder_reph(head,start)
current = start
local next = getnext(current)
while next do
- local nextchar = ischar(next,font)
+ local nextchar = ischar(next,startfont)
if nextchar and getprop(next,a_syllabe) == startattr then --step 6
current = next
next = getnext(current)
@@ -1263,7 +1276,7 @@ function handlers.devanagari_reorder_reph(head,start)
head = remove_node(head,start)
local next = getnext(current)
setlink(start,next)
- setlink(current,"next",start)
+ setlink(current,start)
start = startnext
end
end
@@ -1290,12 +1303,12 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
local startattr = getprop(start,a_syllabe)
-- can be fast for loop + caching state
while current do
- local char = ischar(current,font)
+ local char = ischar(current,startfont)
if char and getprop(current,a_syllabe) == startattr then
local next = getnext(current)
if halant[char] and not getprop(current,a_state) then
if next then
- local nextchar = ischar(next,font)
+ local nextchar = ischar(next,startfont)
if nextchar and getprop(next,a_syllabe) == startattr then
if nextchar == c_zwnj or nextchar == c_zwj then
current = next
@@ -1319,13 +1332,13 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
current = getnext(start)
startattr = getprop(start,a_syllabe)
while current do
- local char = ischar(current,font)
+ local char = ischar(current,startfont)
if char and getprop(current,a_syllabe) == startattr then
if not consonant[char] and getprop(current,a_state) then -- main
startnext = getnext(start)
removenode(start,start)
local prev = getprev(current)
- setlink(start,prev)
+ setlink(prev,start)
setlink(start,current)
start = startnext
break
@@ -1426,21 +1439,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pa
local kind = subset[1]
local lookupcache = subset[2]
if kind == "rphf" then
- for k, v in next, ra do
- local r = lookupcache[k]
- if r then
- for k, v in next, halant do
- local h = r[k]
- if h then
- reph = h.ligature or false
- break
- end
- end
- if reph then
- break
- end
- end
- end
+ reph = subset[3]
local current = start
local last = getnext(stop)
while current ~= last do
@@ -1473,7 +1472,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pa
if current ~= stop then
local c = locl[current] or getchar(current)
local found = lookupcache[c]
- if found then
+ if found then -- pre-base: pref Halant + Consonant
local next = getnext(current)
local n = locl[next] or getchar(next)
if found[n] then
@@ -1571,7 +1570,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pa
if current == stop then
stop = getprev(stop)
head = remove_node(head,current)
- free_node(current)
+ flush_node(current)
return head, stop, nbspaces
else
nbspaces = nbspaces + 1
@@ -1718,7 +1717,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pa
local prev = getprev(current)
if prev ~= target then
local next = getnext(current)
- setlink(next,prev)
+ setlink(prev,next)
if current == stop then
stop = prev
end
@@ -1752,7 +1751,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pa
stop = current
end
local prev = getprev(c)
- setlink(next,prev)
+ setlink(prev,next)
local nextnext = getnext(next)
setnext(current,nextnext)
local nextnextnext = getnext(nextnext)
@@ -1766,9 +1765,12 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pa
end
if getchar(base) == c_nbsp then
+ if base == stop then
+ stop = getprev(stop)
+ end
nbspaces = nbspaces - 1
head = remove_node(head, base)
- free_node(base)
+ flush_node(base)
end
return head, stop, nbspaces
@@ -1815,7 +1817,7 @@ local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowe
elseif (vv == c_zwnj or vv == c_zwj) and halant[vvv] then
local nnnn = getnext(nnn)
if nnnn then
- local vvvv = ischar(nnnn)
+ local vvvv = ischar(nnnn,font)
if vvvv and consonant[vvvv] then
c = nnnn
end
@@ -1838,7 +1840,7 @@ local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowe
local nn = getnext(n)
if nn then
local vv = ischar(nn,font)
- if vv and zw_char[vv] then
+ if vv and zw_char[v] then
n = nn
v = vv
nn = getnext(nn)
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ota.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ota.lua
index 4ddb8310a4d..b8944e0c0c9 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ota.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ota.lua
@@ -262,36 +262,44 @@ local classifiers = characters.classifiers
if not classifiers then
- local first_arabic, last_arabic = characters.blockrange("arabic")
- local first_syriac, last_syriac = characters.blockrange("syriac")
- local first_mandiac, last_mandiac = characters.blockrange("mandiac")
- local first_nko, last_nko = characters.blockrange("nko")
+ local f_arabic, l_arabic = characters.blockrange("arabic")
+ local f_syriac, l_syriac = characters.blockrange("syriac")
+ local f_mandiac, l_mandiac = characters.blockrange("mandiac")
+ local f_nko, l_nko = characters.blockrange("nko")
+ local f_ext_a, l_ext_a = characters.blockrange("arabicextendeda")
classifiers = table.setmetatableindex(function(t,k)
- local c = chardata[k]
- local v = false
- if c then
- local arabic = c.arabic
- if arabic then
- v = mappers[arabic]
- if not v then
- log.report("analyze","error in mapping arabic %C",k)
- -- error
- v = false
- end
- elseif k >= first_arabic and k <= last_arabic or k >= first_syriac and k <= last_syriac or
- k >= first_mandiac and k <= last_mandiac or k >= first_nko and k <= last_nko then
- if categories[k] == "mn" then
- v = s_mark
- else
- v = s_rest
+ if type(k) == "number" then
+ local c = chardata[k]
+ local v = false
+ if c then
+ local arabic = c.arabic
+ if arabic then
+ v = mappers[arabic]
+ if not v then
+ log.report("analyze","error in mapping arabic %C",k)
+ -- error
+ v = false
+ end
+ elseif (k >= f_arabic and k <= l_arabic) or
+ (k >= f_syriac and k <= l_syriac) or
+ (k >= f_mandiac and k <= l_mandiac) or
+ (k >= f_nko and k <= l_nko) or
+ (k >= f_ext_a and k <= l_ext_a) then
+ if categories[k] == "mn" then
+ v = s_mark
+ else
+ v = s_rest
+ end
end
end
+ t[k] = v
+ return v
end
- t[k] = v
- return v
end)
+ characters.classifiers = classifiers
+
end
function methods.arab(head,font,attr)
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otc.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otc.lua
new file mode 100644
index 00000000000..a55320903fb
--- /dev/null
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otc.lua
@@ -0,0 +1,952 @@
+if not modules then modules = { } end modules ['font-otc'] = {
+ version = 1.001,
+ comment = "companion to font-otf.lua (context)",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, insert, sortedkeys, tohash = string.format, table.insert, table.sortedkeys, table.tohash
+local type, next = type, next
+local lpegmatch = lpeg.match
+local utfbyte, utflen = utf.byte, utf.len
+
+-- we assume that the other otf stuff is loaded already
+
+local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
+local report_otf = logs.reporter("fonts","otf loading")
+
+local fonts = fonts
+local otf = fonts.handlers.otf
+local registerotffeature = otf.features.register
+local setmetatableindex = table.setmetatableindex
+
+local normalized = {
+ substitution = "substitution",
+ single = "substitution",
+ ligature = "ligature",
+ alternate = "alternate",
+ multiple = "multiple",
+ kern = "kern",
+ pair = "pair",
+ chainsubstitution = "chainsubstitution",
+ chainposition = "chainposition",
+}
+
+local types = {
+ substitution = "gsub_single",
+ ligature = "gsub_ligature",
+ alternate = "gsub_alternate",
+ multiple = "gsub_multiple",
+ kern = "gpos_pair",
+ pair = "gpos_pair",
+ chainsubstitution = "gsub_contextchain",
+ chainposition = "gpos_contextchain",
+}
+
+local names = {
+ gsub_single = "gsub",
+ gsub_multiple = "gsub",
+ gsub_alternate = "gsub",
+ gsub_ligature = "gsub",
+ gsub_context = "gsub",
+ gsub_contextchain = "gsub",
+ gsub_reversecontextchain = "gsub",
+ gpos_single = "gpos",
+ gpos_pair = "gpos",
+ gpos_cursive = "gpos",
+ gpos_mark2base = "gpos",
+ gpos_mark2ligature = "gpos",
+ gpos_mark2mark = "gpos",
+ gpos_context = "gpos",
+ gpos_contextchain = "gpos",
+}
+
+setmetatableindex(types, function(t,k) t[k] = k return k end) -- "key"
+
+local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } }
+local noflags = { false, false, false, false }
+
+-- beware: shared, maybe we should copy the sequence
+
+local function getrange(sequences,category)
+ local count = #sequences
+ local first = nil
+ local last = nil
+ for i=1,count do
+ local t = sequences[i].type
+ if t and names[t] == category then
+ if not first then
+ first = i
+ end
+ last = i
+ end
+ end
+ return first or 1, last or count
+end
+
+local function validspecification(specification,name)
+ local dataset = specification.dataset
+ if dataset then
+ -- okay
+ elseif specification[1] then
+ dataset = specification
+ specification = { dataset = dataset }
+ else
+ dataset = { { data = specification.data } }
+ specification.data = nil
+ specification.dataset = dataset
+ end
+ local first = dataset[1]
+ if first then
+ first = first.data
+ end
+ if not first then
+ report_otf("invalid feature specification, no dataset")
+ return
+ end
+ if type(name) ~= "string" then
+ name = specification.name or first.name
+ end
+ if type(name) ~= "string" then
+ report_otf("invalid feature specification, no name")
+ return
+ end
+ local n = #dataset
+ if n > 0 then
+ for i=1,n do
+ setmetatableindex(dataset[i],specification)
+ end
+ return specification, name
+ end
+end
+
+local function addfeature(data,feature,specifications)
+
+ -- todo: add some validator / check code so that we're more tolerant to
+ -- user errors
+
+ if not specifications then
+ report_otf("missing specification")
+ return
+ end
+
+ local descriptions = data.descriptions
+ local resources = data.resources
+ local features = resources.features
+ local sequences = resources.sequences
+
+ if not features or not sequences then
+ report_otf("missing specification")
+ return
+ end
+
+ local alreadydone = resources.alreadydone
+ if not alreadydone then
+ alreadydone = { }
+ resources.alreadydone = alreadydone
+ end
+ if alreadydone[specifications] then
+ return
+ else
+ alreadydone[specifications] = true
+ end
+
+ -- feature has to be unique but the name entry wins eventually
+
+ local fontfeatures = resources.features or everywhere
+ local unicodes = resources.unicodes
+ local splitter = lpeg.splitter(" ",unicodes)
+ local done = 0
+ local skip = 0
+ local aglunicodes = false
+
+ local specifications = validspecification(specifications,feature)
+ if not specifications then
+ -- report_otf("invalid specification")
+ return
+ end
+
+ local function tounicode(code)
+ if not code then
+ return
+ end
+ if type(code) == "number" then
+ return code
+ end
+ local u = unicodes[code]
+ if u then
+ return u
+ end
+ if utflen(code) == 1 then
+ u = utfbyte(code)
+ if u then
+ return u
+ end
+ end
+ if not aglunicodes then
+ aglunicodes = fonts.encodings.agl.unicodes -- delayed
+ end
+ return aglunicodes[code]
+ end
+
+ local coverup = otf.coverup
+ local coveractions = coverup.actions
+ local stepkey = coverup.stepkey
+ local register = coverup.register
+
+ local function prepare_substitution(list,featuretype)
+ local coverage = { }
+ local cover = coveractions[featuretype]
+ for code, replacement in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if description then
+ if type(replacement) == "table" then
+ replacement = replacement[1]
+ end
+ replacement = tounicode(replacement)
+ if replacement and descriptions[replacement] then
+ cover(coverage,unicode,replacement)
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ else
+ skip = skip + 1
+ end
+ end
+ return coverage
+ end
+
+ local function prepare_alternate(list,featuretype)
+ local coverage = { }
+ local cover = coveractions[featuretype]
+ for code, replacement in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if not description then
+ skip = skip + 1
+ elseif type(replacement) == "table" then
+ local r = { }
+ for i=1,#replacement do
+ local u = tounicode(replacement[i])
+ r[i] = descriptions[u] and u or unicode
+ end
+ cover(coverage,unicode,r)
+ done = done + 1
+ else
+ local u = tounicode(replacement)
+ if u then
+ cover(coverage,unicode,{ u })
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ end
+ end
+ return coverage
+ end
+
+ local function prepare_multiple(list,featuretype)
+ local coverage = { }
+ local cover = coveractions[featuretype]
+ for code, replacement in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if not description then
+ skip = skip + 1
+ elseif type(replacement) == "table" then
+ local r, n = { }, 0
+ for i=1,#replacement do
+ local u = tounicode(replacement[i])
+ if descriptions[u] then
+ n = n + 1
+ r[n] = u
+ end
+ end
+ if n > 0 then
+ cover(coverage,unicode,r)
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ else
+ local u = tounicode(replacement)
+ if u then
+ cover(coverage,unicode,{ u })
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ end
+ end
+ return coverage
+ end
+
+ local function prepare_ligature(list,featuretype)
+ local coverage = { }
+ local cover = coveractions[featuretype]
+ for code, ligature in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if description then
+ if type(ligature) == "string" then
+ ligature = { lpegmatch(splitter,ligature) }
+ end
+ local present = true
+ for i=1,#ligature do
+ local l = ligature[i]
+ local u = tounicode(l)
+ if descriptions[u] then
+ ligature[i] = u
+ else
+ present = false
+ break
+ end
+ end
+ if present then
+ cover(coverage,unicode,ligature)
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ else
+ skip = skip + 1
+ end
+ end
+ return coverage
+ end
+
+ local function prepare_kern(list,featuretype)
+ local coverage = { }
+ local cover = coveractions[featuretype]
+ for code, replacement in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if description and type(replacement) == "table" then
+ local r = { }
+ for k, v in next, replacement do
+ local u = tounicode(k)
+ if u then
+ r[u] = v
+ end
+ end
+ if next(r) then
+ cover(coverage,unicode,r)
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ else
+ skip = skip + 1
+ end
+ end
+ return coverage
+ end
+
+ local function prepare_pair(list,featuretype)
+ local coverage = { }
+ local cover = coveractions[featuretype]
+ if cover then
+ for code, replacement in next, list do
+ local unicode = tounicode(code)
+ local description = descriptions[unicode]
+ if description and type(replacement) == "table" then
+ local r = { }
+ for k, v in next, replacement do
+ local u = tounicode(k)
+ if u then
+ r[u] = v
+ end
+ end
+ if next(r) then
+ cover(coverage,unicode,r)
+ done = done + 1
+ else
+ skip = skip + 1
+ end
+ else
+ skip = skip + 1
+ end
+ end
+ else
+ report_otf("unknown cover type %a",featuretype)
+ end
+ return coverage
+ end
+
+ local function prepare_chain(list,featuretype,sublookups)
+ -- todo: coveractions
+ local rules = list.rules
+ local coverage = { }
+ if rules then
+ local rulehash = { }
+ local rulesize = 0
+ local sequence = { }
+ local nofsequences = 0
+ local lookuptype = types[featuretype]
+ for nofrules=1,#rules do
+ local rule = rules[nofrules]
+ local current = rule.current
+ local before = rule.before
+ local after = rule.after
+ local replacements = rule.replacements or false
+ local sequence = { }
+ local nofsequences = 0
+ if before then
+ for n=1,#before do
+ nofsequences = nofsequences + 1
+ sequence[nofsequences] = before[n]
+ end
+ end
+ local start = nofsequences + 1
+ for n=1,#current do
+ nofsequences = nofsequences + 1
+ sequence[nofsequences] = current[n]
+ end
+ local stop = nofsequences
+ if after then
+ for n=1,#after do
+ nofsequences = nofsequences + 1
+ sequence[nofsequences] = after[n]
+ end
+ end
+ local lookups = rule.lookups or false
+ local subtype = nil
+ if lookups and sublookups then
+ for k, v in next, lookups do
+ local lookup = sublookups[v]
+ if lookup then
+ lookups[k] = lookup
+ if not subtype then
+ subtype = lookup.type
+ end
+ else
+ -- already expanded
+ end
+ end
+ end
+ if nofsequences > 0 then -- we merge coverage into one
+ -- we copy as we can have different fonts
+ local hashed = { }
+ for i=1,nofsequences do
+ local t = { }
+ local s = sequence[i]
+ for i=1,#s do
+ local u = tounicode(s[i])
+ if u then
+ t[u] = true
+ end
+ end
+ hashed[i] = t
+ end
+ sequence = hashed
+ -- now we create the rule
+ rulesize = rulesize + 1
+ rulehash[rulesize] = {
+ nofrules, -- 1
+ lookuptype, -- 2
+ sequence, -- 3
+ start, -- 4
+ stop, -- 5
+ lookups, -- 6 (6/7 also signal of what to do)
+ replacements, -- 7
+ subtype, -- 8
+ }
+ for unic in next, sequence[start] do
+ local cu = coverage[unic]
+ if not cu then
+ coverage[unic] = rulehash -- can now be done cleaner i think
+ end
+ end
+ end
+ end
+ end
+ return coverage
+ end
+
+ local dataset = specifications.dataset
+
+ local function report(name,category,position,first,last,sequences)
+ report_otf("injecting name %a of category %a at position %i in [%i,%i] of [%i,%i]",
+ name,category,position,first,last,1,#sequences)
+ end
+
+ local function inject(specification,sequences,sequence,first,last,category,name)
+ local position = specification.position or false
+ if not position then
+ position = specification.prepend
+ if position == true then
+ if trace_loading then
+ report(name,category,first,first,last,sequences)
+ end
+ insert(sequences,first,sequence)
+ return
+ end
+ end
+ if not position then
+ position = specification.append
+ if position == true then
+ if trace_loading then
+ report(name,category,last+1,first,last,sequences)
+ end
+ insert(sequences,last+1,sequence)
+ return
+ end
+ end
+ local kind = type(position)
+ if kind == "string" then
+ local index = false
+ for i=first,last do
+ local s = sequences[i]
+ local f = s.features
+ if f then
+ for k in next, f do
+ if k == position then
+ index = i
+ break
+ end
+ end
+ if index then
+ break
+ end
+ end
+ end
+ if index then
+ position = index
+ else
+ position = last + 1
+ end
+ elseif kind == "number" then
+ if position < 0 then
+ position = last - position + 1
+ end
+ if position > last then
+ position = last + 1
+ elseif position < first then
+ position = first
+ end
+ else
+ position = last + 1
+ end
+ if trace_loading then
+ report(name,category,position,first,last,sequences)
+ end
+ insert(sequences,position,sequence)
+ end
+
+ for s=1,#dataset do
+ local specification = dataset[s]
+ local valid = specification.valid -- nowhere used
+ local feature = specification.name or feature
+ if not feature or feature == "" then
+ report_otf("no valid name given for extra feature")
+ elseif not valid or valid(data,specification,feature) then -- anum uses this
+ local initialize = specification.initialize
+ if initialize then
+ -- when false is returned we initialize only once
+ specification.initialize = initialize(specification,data) and initialize or nil
+ end
+ local askedfeatures = specification.features or everywhere
+ local askedsteps = specification.steps or specification.subtables or { specification.data } or { }
+ local featuretype = normalized[specification.type or "substitution"] or "substitution"
+ local featureflags = specification.flags or noflags
+ local featureorder = specification.order or { feature }
+ local featurechain = (featuretype == "chainsubstitution" or featuretype == "chainposition") and 1 or 0
+ local nofsteps = 0
+ local steps = { }
+ local sublookups = specification.lookups
+ local category = nil
+ if sublookups then
+ local s = { }
+ for i=1,#sublookups do
+ local specification = sublookups[i]
+ local askedsteps = specification.steps or specification.subtables or { specification.data } or { }
+ local featuretype = normalized[specification.type or "substitution"] or "substitution"
+ local featureflags = specification.flags or noflags
+ local nofsteps = 0
+ local steps = { }
+ for i=1,#askedsteps do
+ local list = askedsteps[i]
+ local coverage = nil
+ local format = nil
+ if featuretype == "substitution" then
+ coverage = prepare_substitution(list,featuretype)
+ elseif featuretype == "ligature" then
+ coverage = prepare_ligature(list,featuretype)
+ elseif featuretype == "alternate" then
+ coverage = prepare_alternate(list,featuretype)
+ elseif featuretype == "multiple" then
+ coverage = prepare_multiple(list,featuretype)
+ elseif featuretype == "kern" then
+ format = "kern"
+ coverage = prepare_kern(list,featuretype)
+ elseif featuretype == "pair" then
+ format = "pair"
+ coverage = prepare_pair(list,featuretype)
+ end
+ if coverage and next(coverage) then
+ nofsteps = nofsteps + 1
+ steps[nofsteps] = register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
+ end
+ end
+ s[i] = {
+ [stepkey] = steps,
+ nofsteps = nofsteps,
+ type = types[featuretype],
+ }
+ end
+ sublookups = s
+ end
+ for i=1,#askedsteps do
+ local list = askedsteps[i]
+ local coverage = nil
+ local format = nil
+ if featuretype == "substitution" then
+ category = "gsub"
+ coverage = prepare_substitution(list,featuretype)
+ elseif featuretype == "ligature" then
+ category = "gsub"
+ coverage = prepare_ligature(list,featuretype)
+ elseif featuretype == "alternate" then
+ category = "gsub"
+ coverage = prepare_alternate(list,featuretype)
+ elseif featuretype == "multiple" then
+ category = "gsub"
+ coverage = prepare_multiple(list,featuretype)
+ elseif featuretype == "kern" then
+ category = "gpos"
+ format = "kern"
+ coverage = prepare_kern(list,featuretype)
+ elseif featuretype == "pair" then
+ category = "gpos"
+ format = "pair"
+ coverage = prepare_pair(list,featuretype)
+ elseif featuretype == "chainsubstitution" then
+ category = "gsub"
+ coverage = prepare_chain(list,featuretype,sublookups)
+ elseif featuretype == "chainposition" then
+ category = "gpos"
+ coverage = prepare_chain(list,featuretype,sublookups)
+ else
+ report_otf("not registering feature %a, unknown category",feature)
+ return
+ end
+ if coverage and next(coverage) then
+ nofsteps = nofsteps + 1
+ steps[nofsteps] = register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
+ end
+ end
+ if nofsteps > 0 then
+ -- script = { lang1, lang2, lang3 } or script = { lang1 = true, ... }
+ for k, v in next, askedfeatures do
+ if v[1] then
+ askedfeatures[k] = tohash(v)
+ end
+ end
+ if featureflags[1] then featureflags[1] = "mark" end
+ if featureflags[2] then featureflags[2] = "ligature" end
+ if featureflags[3] then featureflags[3] = "base" end
+ local steptype = types[featuretype]
+ local sequence = {
+ chain = featurechain,
+ features = { [feature] = askedfeatures },
+ flags = featureflags,
+ name = feature, -- redundant
+ order = featureorder,
+ [stepkey] = steps,
+ nofsteps = nofsteps,
+ type = steptype,
+ }
+ -- position | prepend | append
+ local first, last = getrange(sequences,category)
+ inject(specification,sequences,sequence,first,last,category,feature)
+ -- register in metadata (merge as there can be a few)
+ local features = fontfeatures[category]
+ if not features then
+ features = { }
+ fontfeatures[category] = features
+ end
+ local k = features[feature]
+ if not k then
+ k = { }
+ features[feature] = k
+ end
+ --
+ for script, languages in next, askedfeatures do
+ local kk = k[script]
+ if not kk then
+ kk = { }
+ k[script] = kk
+ end
+ for language, value in next, languages do
+ kk[language] = value
+ end
+ end
+ end
+ end
+ end
+ if trace_loading then
+ report_otf("registering feature %a, affected glyphs %a, skipped glyphs %a",feature,done,skip)
+ end
+end
+
+otf.enhancers.addfeature = addfeature
+
+local extrafeatures = { }
+local knownfeatures = { }
+
+function otf.addfeature(name,specification)
+ if type(name) == "table" then
+ specification = name
+ end
+ if type(specification) ~= "table" then
+ report_otf("invalid feature specification, no valid table")
+ return
+ end
+ specification, name = validspecification(specification,name)
+ if name and specification then
+ local slot = knownfeatures[name]
+ if slot then
+ -- we overload one .. should be option
+ else
+ slot = #extrafeatures + 1
+ knownfeatures[name] = slot
+ end
+ specification.name = name -- to be sure
+ extrafeatures[slot] = specification
+ -- report_otf("adding feature %a @ %i",name,slot)
+ end
+end
+
+-- for feature, specification in next, extrafeatures do
+-- addfeature(data,feature,specification)
+-- end
+
+local function enhance(data,filename,raw)
+ for slot=1,#extrafeatures do
+ local specification = extrafeatures[slot]
+ addfeature(data,specification.name,specification)
+ end
+end
+
+otf.enhancers.enhance = enhance
+
+otf.enhancers.register("check extra features",enhance)
+
+-- tlig --
+
+local tlig = { -- we need numbers for some fonts so ...
+ -- endash = "hyphen hyphen",
+ -- emdash = "hyphen hyphen hyphen",
+ [0x2013] = { 0x002D, 0x002D },
+ [0x2014] = { 0x002D, 0x002D, 0x002D },
+ -- quotedblleft = "quoteleft quoteleft",
+ -- quotedblright = "quoteright quoteright",
+ -- quotedblleft = "grave grave",
+ -- quotedblright = "quotesingle quotesingle",
+ -- quotedblbase = "comma comma",
+}
+
+local tlig_specification = {
+ type = "ligature",
+ features = everywhere,
+ data = tlig,
+ order = { "tlig" },
+ flags = noflags,
+ prepend = true,
+}
+
+otf.addfeature("tlig",tlig_specification)
+
+registerotffeature {
+ -- this makes it a known feature (in tables)
+ name = 'tlig',
+ description = 'tex ligatures',
+}
+
+-- trep
+
+local trep = {
+ -- [0x0022] = 0x201D,
+ [0x0027] = 0x2019,
+ -- [0x0060] = 0x2018,
+}
+
+local trep_specification = {
+ type = "substitution",
+ features = everywhere,
+ data = trep,
+ order = { "trep" },
+ flags = noflags,
+ prepend = true,
+}
+
+otf.addfeature("trep",trep_specification)
+
+registerotffeature {
+ -- this makes it a known feature (in tables)
+ name = 'trep',
+ description = 'tex replacements',
+}
+
+-- -- tcom (obsolete, was already not set for a while)
+
+-- if characters.combined then
+--
+-- local tcom = { }
+--
+-- local function initialize()
+-- characters.initialize()
+-- for first, seconds in next, characters.combined do
+-- for second, combination in next, seconds do
+-- tcom[combination] = { first, second }
+-- end
+-- end
+-- -- return false
+-- end
+--
+-- local tcom_specification = {
+-- type = "ligature",
+-- features = everywhere,
+-- data = tcom,
+-- order = { "tcom" },
+-- flags = noflags,
+-- initialize = initialize,
+-- }
+--
+-- otf.addfeature("tcom",tcom_specification)
+--
+-- registerotffeature {
+-- name = 'tcom',
+-- description = 'tex combinations',
+-- }
+--
+-- end
+
+-- anum
+
+local anum_arabic = {
+ [0x0030] = 0x0660,
+ [0x0031] = 0x0661,
+ [0x0032] = 0x0662,
+ [0x0033] = 0x0663,
+ [0x0034] = 0x0664,
+ [0x0035] = 0x0665,
+ [0x0036] = 0x0666,
+ [0x0037] = 0x0667,
+ [0x0038] = 0x0668,
+ [0x0039] = 0x0669,
+}
+
+local anum_persian = {
+ [0x0030] = 0x06F0,
+ [0x0031] = 0x06F1,
+ [0x0032] = 0x06F2,
+ [0x0033] = 0x06F3,
+ [0x0034] = 0x06F4,
+ [0x0035] = 0x06F5,
+ [0x0036] = 0x06F6,
+ [0x0037] = 0x06F7,
+ [0x0038] = 0x06F8,
+ [0x0039] = 0x06F9,
+}
+
+local function valid(data)
+ local features = data.resources.features
+ if features then
+ for k, v in next, features do
+ for k, v in next, v do
+ if v.arab then
+ return true
+ end
+ end
+ end
+ end
+end
+
+local anum_specification = {
+ {
+ type = "substitution",
+ features = { arab = { urd = true, dflt = true } },
+ order = { "anum" },
+ data = anum_arabic,
+ flags = noflags, -- { },
+ valid = valid,
+ },
+ {
+ type = "substitution",
+ features = { arab = { urd = true } },
+ order = { "anum" },
+ data = anum_persian,
+ flags = noflags, -- { },
+ valid = valid,
+ },
+}
+
+otf.addfeature("anum",anum_specification) -- todo: only when there is already an arab script feature
+
+registerotffeature {
+ -- this makes it a known feature (in tables)
+ name = 'anum',
+ description = 'arabic digits',
+}
+
+-- maybe:
+
+-- fonts.handlers.otf.addfeature("hangulfix",{
+-- type = "substitution",
+-- features = { ["hang"] = { ["*"] = true } },
+-- data = {
+-- [0x1160] = 0x119E,
+-- },
+-- order = { "hangulfix" },
+-- flags = { },
+-- prepend = true,
+-- })
+
+-- fonts.handlers.otf.features.register {
+-- name = 'hangulfix',
+-- description = 'fixes for hangul',
+-- }
+
+-- fonts.handlers.otf.addfeature {
+-- name = "stest",
+-- type = "substitution",
+-- data = {
+-- a = "X",
+-- b = "P",
+-- }
+-- }
+-- fonts.handlers.otf.addfeature {
+-- name = "atest",
+-- type = "alternate",
+-- data = {
+-- a = { "X", "Y" },
+-- b = { "P", "Q" },
+-- }
+-- }
+-- fonts.handlers.otf.addfeature {
+-- name = "mtest",
+-- type = "multiple",
+-- data = {
+-- a = { "X", "Y" },
+-- b = { "P", "Q" },
+-- }
+-- }
+-- fonts.handlers.otf.addfeature {
+-- name = "ltest",
+-- type = "ligature",
+-- data = {
+-- X = { "a", "b" },
+-- Y = { "d", "a" },
+-- }
+-- }
+-- fonts.handlers.otf.addfeature {
+-- name = "ktest",
+-- type = "kern",
+-- data = {
+-- a = { b = -500 },
+-- }
+-- }
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otd.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otd.lua
deleted file mode 100644
index 64cb1bcb42c..00000000000
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otd.lua
+++ /dev/null
@@ -1,268 +0,0 @@
-if not modules then modules = { } end modules ['font-otd'] = {
- version = 1.001,
- comment = "companion to font-ini.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local type = type
-local match = string.match
-local sequenced = table.sequenced
-
-local trace_dynamics = false trackers.register("otf.dynamics", function(v) trace_dynamics = v end)
-local trace_applied = false trackers.register("otf.applied", function(v) trace_applied = v end)
-
-local report_otf = logs.reporter("fonts","otf loading")
-local report_process = logs.reporter("fonts","otf process")
-
-local allocate = utilities.storage.allocate
-
-local fonts = fonts
-local otf = fonts.handlers.otf
-local hashes = fonts.hashes
-local definers = fonts.definers
-local constructors = fonts.constructors
-local specifiers = fonts.specifiers
-
-local fontidentifiers = hashes.identifiers
-local fontresources = hashes.resources
-local fontproperties = hashes.properties
-local fontdynamics = hashes.dynamics
-
-local contextsetups = specifiers.contextsetups
-local contextnumbers = specifiers.contextnumbers
-local contextmerged = specifiers.contextmerged
-
-local setmetatableindex = table.setmetatableindex
-
-local a_to_script = { }
-local a_to_language = { }
-
--- we can have a scripts hash in fonts.hashes
-
-function otf.setdynamics(font,attribute)
- -- local features = contextsetups[contextnumbers[attribute]] -- can be moved to caller
- local features = contextsetups[attribute]
- if features then
- local dynamics = fontdynamics[font]
- dynamic = contextmerged[attribute] or 0
- local script, language
- if dynamic == 2 then -- merge
- language = features.language or fontproperties[font].language or "dflt"
- script = features.script or fontproperties[font].script or "dflt"
- else -- if dynamic == 1 then -- replace
- language = features.language or "dflt"
- script = features.script or "dflt"
- end
- if script == "auto" then
- -- checkedscript and resources are defined later so we cannot shortcut them -- todo: make installer
- script = definers.checkedscript(fontidentifiers[font],fontresources[font],features)
- end
- local ds = dynamics[script] -- can be metatable magic (less testing)
--- or dynamics.dflt
- if not ds then
- ds = { }
- dynamics[script] = ds
- end
- local dsl = ds[language]
--- or ds.dflt
- if not dsl then
- dsl = { }
- ds[language] = dsl
- end
- local dsla = dsl[attribute]
- if not dsla then
- local tfmdata = fontidentifiers[font]
- a_to_script [attribute] = script
- a_to_language[attribute] = language
- -- we need to save some values .. quite messy
- local properties = tfmdata.properties
- local shared = tfmdata.shared
- local s_script = properties.script
- local s_language = properties.language
- local s_mode = properties.mode
- local s_features = shared.features
- properties.mode = "node"
- properties.language = language
- properties.script = script
- properties.dynamics = true -- handy for tracing
- shared.features = { }
- -- end of save
- local set = constructors.checkedfeatures("otf",features)
- set.mode = "node" -- really needed
- dsla = otf.setfeatures(tfmdata,set)
- if trace_dynamics then
- report_otf("setting dynamics %s: attribute %a, script %a, language %a, set %a",contextnumbers[attribute],attribute,script,language,set)
- end
- -- we need to restore some values
- properties.script = s_script
- properties.language = s_language
- properties.mode = s_mode
- shared.features = s_features
- -- end of restore
- dynamics[script][language][attribute] = dsla -- cache
- elseif trace_dynamics then
- -- report_otf("using dynamics %s: attribute %a, script %a, language %a",contextnumbers[attribute],attribute,script,language)
- end
- return dsla
- end
-end
-
-function otf.scriptandlanguage(tfmdata,attr)
- local properties = tfmdata.properties
- if attr and attr > 0 then
- return a_to_script[attr] or properties.script or "dflt", a_to_language[attr] or properties.language or "dflt"
- else
- return properties.script or "dflt", properties.language or "dflt"
- end
-end
-
--- we reimplement the dataset resolver
-
-local autofeatures = fonts.analyzers.features
-local featuretypes = otf.tables.featuretypes
-local defaultscript = otf.features.checkeddefaultscript
-local defaultlanguage = otf.features.checkeddefaultlanguage
-
-local resolved = { } -- we only resolve a font,script,language,attribute pair once
-local wildcard = "*"
-
--- what about analyze in local and not in font
-
--- needs checking: some added features can pass twice
-
-local P, C, Cc, lpegmatch = lpeg.P, lpeg.C, lpeg.Cc, lpeg.match
-
-local pattern = P("always") * (P(-1) * Cc(true) + P(":") * C((1-P(-1))^1))
-
-local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr,dynamic,ra,autoscript,autolanguage)
- local features = sequence.features
- if features then
- local order = sequence.order
- if order then
- local featuretype = featuretypes[sequence.type or "unknown"]
- for i=1,#order do --
- local kind = order[i] --
- local e_e
- local a_e = a_enabled and a_enabled[kind] -- the value (location)
- if a_e ~= nil then
- e_e = a_e
- else
- e_e = s_enabled and s_enabled[kind] -- the value (font)
- end
- if e_e then
- local valid = type(e_e) == "string" and lpegmatch(pattern,e_e)
- if valid then
- -- we have hit always
- local attribute = autofeatures[kind] or false
- if trace_applied then
- report_process(
- "font %s, dynamic %a (%a), feature %a, script %a, language %a, lookup %a, value %a",
- font,attr or 0,dynamic,kind,"*","*",sequence.name,valid)
- end
- ra[#ra+1] = { valid, attribute, sequence, kind }
- else
- -- we already checked for e_e
- local scripts = features[kind] --
- local languages = scripts[script] or scripts[wildcard]
- if not languages and autoscript then
- langages = defaultscript(featuretype,autoscript,scripts)
- end
- if languages then
- -- we need detailed control over default becase we want to trace
- -- only first attribute match check, so we assume simple fina's
- -- local valid = false
- if languages[language] then
- valid = e_e
- elseif languages[wildcard] then
- valid = e_e
- elseif autolanguage and defaultlanguage(featuretype,autolanguage,languages) then
- valid = e_e
- end
- end
- if valid then
- local attribute = autofeatures[kind] or false
- if trace_applied then
- report_process(
- "font %s, dynamic %a (%a), feature %a, script %a, language %a, lookup %a, value %a",
- font,attr or 0,dynamic,kind,script,language,sequence.name,valid)
- end
- ra[#ra+1] = { valid, attribute, sequence, kind }
- end
- end
- end
- end
- end
- end
-end
-
--- there is some fuzzy language/script state stuff in properties (temporary)
-
-function otf.dataset(tfmdata,font,attr) -- attr only when explicit (as in special parbuilder)
-
- local script, language, s_enabled, a_enabled, dynamic
-
- if attr and attr ~= 0 then
- dynamic = contextmerged[attr] or 0
- -- local features = contextsetups[contextnumbers[attr]] -- could be a direct list
- local features = contextsetups[attr]
- a_enabled = features -- location based
- if dynamic == 1 then -- or dynamic == -1 then
- -- replace
- language = features.language or "dflt"
- script = features.script or "dflt"
- elseif dynamic == 2 then -- or dynamic == -2 then
- -- merge
- local properties = tfmdata.properties
- s_enabled = tfmdata.shared.features -- font based
- language = features.language or properties.language or "dflt"
- script = features.script or properties.script or "dflt"
- else
- -- error
- local properties = tfmdata.properties
- language = properties.language or "dflt"
- script = properties.script or "dflt"
- end
- else
- local properties = tfmdata.properties
- language = properties.language or "dflt"
- script = properties.script or "dflt"
- s_enabled = tfmdata.shared.features -- can be made local to the resolver
- dynamic = 0
- end
-
- local res = resolved[font]
- if not res then
- res = { }
- resolved[font] = res
- end
- local rs = res[script]
- if not rs then
- rs = { }
- res[script] = rs
- end
- local rl = rs[language]
- if not rl then
- rl = { }
- rs[language] = rl
- end
- local ra = rl[attr]
- if ra == nil then -- attr can be false
- ra = {
- -- indexed but we can also add specific data by key in:
- }
- rl[attr] = ra
- local sequences = tfmdata.resources.sequences
- if sequences then
- local autoscript = (s_enabled and s_enabled.autoscript ) or (a_enabled and a_enabled.autoscript )
- local autolanguage = (s_enabled and s_enabled.autolanguage) or (a_enabled and a_enabled.autolanguage)
- for s=1,#sequences do
- -- just return nil or ra step
- initialize(sequences[s],script,language,s_enabled,a_enabled,font,attr,dynamic,ra,autoscript,autolanguage)
- end
- end
- end
- return ra
-
-end
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oti.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oti.lua
index d74d2d502cd..e10a261cd2b 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oti.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oti.lua
@@ -34,6 +34,8 @@ local function setmode(tfmdata,value)
end
end
+otf.modeinitializer = setmode
+
local function setlanguage(tfmdata,value)
if value then
local cleanvalue = lower(value)
@@ -70,6 +72,7 @@ registerotffeature {
initializers = {
base = setmode,
node = setmode,
+ plug = setmode,
}
}
@@ -79,6 +82,7 @@ registerotffeature {
initializers = {
base = setlanguage,
node = setlanguage,
+ plug = setlanguage,
}
}
@@ -88,6 +92,7 @@ registerotffeature {
initializers = {
base = setscript,
node = setscript,
+ plug = setscript,
}
}
@@ -155,4 +160,3 @@ function otffeatures.checkeddefaultlanguage(featuretype,autolanguage,languages)
end
end
end
-
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otj.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otj.lua
index d1408fd52ee..68cf608ec94 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otj.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otj.lua
@@ -36,7 +36,7 @@ local registertracker = trackers.register
local trace_injections = false registertracker("fonts.injections", function(v) trace_injections = v end)
local trace_marks = false registertracker("fonts.injections.marks", function(v) trace_marks = v end)
local trace_cursive = false registertracker("fonts.injections.cursive", function(v) trace_cursive = v end)
-local trace_spaces = false registertracker("otf.spaces", function(v) trace_spaces = v end)
+local trace_spaces = false registertracker("fonts.injections.spaces", function(v) trace_spaces = v end)
-- use_advance is just an experiment: it makes copying glyphs (instead of new_glyph) dangerous
@@ -377,7 +377,8 @@ function injections.setkern(current,factor,rlmode,x,injection)
end
end
-function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk) -- ba=baseanchor, ma=markanchor
+function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk,checkmark) -- ba=baseanchor, ma=markanchor
+
local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2])
nofregisteredmarks = nofregisteredmarks + 1
if rlmode >= 0 then
@@ -398,6 +399,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk) -- ba=b
i.markbase = nofregisteredmarks
i.markbasenode = base
i.markmark = mkmk
+ i.checkmark = checkmark
end
else
p.injections = {
@@ -407,6 +409,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk) -- ba=b
markbase = nofregisteredmarks,
markbasenode = base,
markmark = mkmk,
+ checkmark = checkmark,
}
end
else
@@ -418,6 +421,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk) -- ba=b
markbase = nofregisteredmarks,
markbasenode = base,
markmark = mkmk,
+ checkmark = checkmark,
},
}
end
@@ -1062,11 +1066,22 @@ local function inject_everything(head,where)
ox = px - pn.markx
-- report_injections("l2r case 3: %p",ox)
-- end
- local wn = getfield(n,"width") -- in arial marks have widths
- if wn ~= 0 then
- -- bad: we should center
- pn.leftkern = -wn/2
- pn.rightkern = -wn/2
+ if pn.checkmark then
+ local wn = getfield(n,"width") -- in arial marks have widths
+ if wn ~= 0 then
+ wn = wn/2
+ if trace_injections then
+ report_injections("correcting non zero width mark %C",getchar(n))
+ end
+ -- -- bad: we should center
+ -- pn.leftkern = -wn
+ -- pn.rightkern = -wn
+ -- -- we're too late anyway as kerns are already injected so
+ -- -- we do it the ugly way (no checking if the previous is
+ -- -- already a kern) .. maybe we should fix the font instead
+ insert_node_before(n,n,newkern(-wn))
+ insert_node_after(n,n,newkern(-wn))
+ end
end
end
local oy = getfield(n,"yoffset") + getfield(p,"yoffset") + pn.marky
@@ -1092,6 +1107,10 @@ local function inject_everything(head,where)
nofmarks = nofmarks + 1
marks[nofmarks] = current
else
+ local yoffset = i.yoffset
+ if yoffset and yoffset ~= 0 then
+ setfield(current,"yoffset",yoffset)
+ end
if hascursives then
local cursivex = i.cursivex
if cursivex then
@@ -1144,10 +1163,6 @@ local function inject_everything(head,where)
end
end
-- left|glyph|right
- local yoffset = i.yoffset
- if yoffset and yoffset ~= 0 then
- setfield(current,"yoffset",yoffset)
- end
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
insert_node_before(head,current,newkern(leftkern))
@@ -1162,7 +1177,7 @@ local function inject_everything(head,where)
local i = p.emptyinjections
if i then
-- glyph|disc|glyph (special case)
--- okay?
+ -- okay?
local rightkern = i.rightkern
if rightkern and rightkern ~= 0 then
if next and getid(next) == disc_code then
@@ -1422,6 +1437,48 @@ function nodes.injections.setspacekerns(font,sequence)
end
end
+local getthreshold
+
+if context then
+
+ local threshold = 1 -- todo: add a few methods for context
+ local parameters = fonts.hashes.parameters
+
+ directives.register("otf.threshold", function(v) threshold = tonumber(v) or 1 end)
+
+ getthreshold = function(font)
+ local p = parameters[font]
+ local f = p.factor
+ local s = p.spacing
+ local t = threshold * (s and s.width or p.space or 0) - 2
+ return t > 0 and t or 0, f
+ end
+
+else
+
+ injections.threshold = 0
+
+ getthreshold = function(font)
+ local p = fontdata[font].parameters
+ local f = p.factor
+ local s = p.spacing
+ local t = injections.threshold * (s and s.width or p.space or 0) - 2
+ return t > 0 and t or 0, f
+ end
+
+end
+
+injections.getthreshold = getthreshold
+
+function injections.isspace(n,threshold)
+ if getid(n) == glue_code then
+ local w = getfield(n,"width")
+ if threshold and w > threshold then -- was >=
+ return 32
+ end
+ end
+end
+
local function injectspaces(head)
if not triggers then
@@ -1438,18 +1495,11 @@ local function injectspaces(head)
local rightkern = false
local function updatefont(font,trig)
- -- local resources = resources[font]
- -- local spacekerns = resources.spacekerns
- -- if spacekerns then
- -- leftkerns = spacekerns.left
- -- rightkerns = spacekerns.right
- -- end
leftkerns = trig.left
rightkerns = trig.right
- local par = fontdata[font].parameters -- fallback for generic
- factor = par.factor
- threshold = par.spacing.width - 1 -- get rid of rounding errors
lastfont = font
+ threshold,
+ factor = getthreshold(font)
end
for n in traverse_id(glue_code,tonut(head)) do
@@ -1469,7 +1519,7 @@ local function injectspaces(head)
end
end
if prevchar then
- local font = getfont(next)
+ local font = getfont(prev)
local trig = triggers[font]
if trig then
if lastfont ~= font then
@@ -1482,7 +1532,7 @@ local function injectspaces(head)
end
if leftkern then
local old = getfield(n,"width")
- if old >= threshold then
+ if old > threshold then
if rightkern then
local new = old + (leftkern + rightkern) * factor
if trace_spaces then
@@ -1501,7 +1551,7 @@ local function injectspaces(head)
leftkern = false
elseif rightkern then
local old = getfield(n,"width")
- if old >= threshold then
+ if old > threshold then
local new = old + rightkern * factor
if trace_spaces then
report_spaces("[%p -> %p] %C",nextchar,old,new)
@@ -1522,6 +1572,7 @@ function injections.handler(head,where)
if triggers then
head = injectspaces(head)
end
+ -- todo: marks only run too
if nofregisteredmarks > 0 or nofregisteredcursives > 0 then
if trace_injections then
report_injections("injection variant %a","everything")
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otl.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otl.lua
index 59d868beee8..d4eaed763ba 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otl.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otl.lua
@@ -26,70 +26,67 @@ if not modules then modules = { } end modules ['font-otl'] = {
local gmatch, find, match, lower, strip = string.gmatch, string.find, string.match, string.lower, string.strip
local type, next, tonumber, tostring, unpack = type, next, tonumber, tostring, unpack
local abs = math.abs
-local ioflush = io.flush
local derivetable = table.derive
local formatters = string.formatters
-local setmetatableindex = table.setmetatableindex
-local allocate = utilities.storage.allocate
-local registertracker = trackers.register
-local registerdirective = directives.register
-local starttiming = statistics.starttiming
-local stoptiming = statistics.stoptiming
-local elapsedtime = statistics.elapsedtime
-local findbinfile = resolvers.findbinfile
+local setmetatableindex = table.setmetatableindex
+local allocate = utilities.storage.allocate
+local registertracker = trackers.register
+local registerdirective = directives.register
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+local elapsedtime = statistics.elapsedtime
+local findbinfile = resolvers.findbinfile
------ trace_private = false registertracker("otf.private", function(v) trace_private = v end)
------ trace_subfonts = false registertracker("otf.subfonts", function(v) trace_subfonts = v end)
-local trace_loading = false registertracker("otf.loading", function(v) trace_loading = v end)
-local trace_features = false registertracker("otf.features", function(v) trace_features = v end)
------ trace_dynamics = false registertracker("otf.dynamics", function(v) trace_dynamics = v end)
------ trace_sequences = false registertracker("otf.sequences", function(v) trace_sequences = v end)
------ trace_markwidth = false registertracker("otf.markwidth", function(v) trace_markwidth = v end)
-local trace_defining = false registertracker("fonts.defining", function(v) trace_defining = v end)
+----- trace_private = false registertracker("otf.private", function(v) trace_private = v end)
+----- trace_subfonts = false registertracker("otf.subfonts", function(v) trace_subfonts = v end)
+local trace_loading = false registertracker("otf.loading", function(v) trace_loading = v end)
+local trace_features = false registertracker("otf.features", function(v) trace_features = v end)
+----- trace_dynamics = false registertracker("otf.dynamics", function(v) trace_dynamics = v end)
+----- trace_sequences = false registertracker("otf.sequences", function(v) trace_sequences = v end)
+----- trace_markwidth = false registertracker("otf.markwidth", function(v) trace_markwidth = v end)
+local trace_defining = false registertracker("fonts.defining", function(v) trace_defining = v end)
-local report_otf = logs.reporter("fonts","otf loading")
+local report_otf = logs.reporter("fonts","otf loading")
-local fonts = fonts
-local otf = fonts.handlers.otf
+local fonts = fonts
+local otf = fonts.handlers.otf
-otf.version = 3.023 -- beware: also sync font-mis.lua and in mtx-fonts
-otf.cache = containers.define("fonts", "otl", otf.version, true)
-otf.svgcache = containers.define("fonts", "svg", otf.version, true)
-otf.pdfcache = containers.define("fonts", "pdf", otf.version, true)
+otf.version = 3.027 -- beware: also sync font-mis.lua and in mtx-fonts
+otf.cache = containers.define("fonts", "otl", otf.version, true)
+otf.svgcache = containers.define("fonts", "svg", otf.version, true)
+otf.pdfcache = containers.define("fonts", "pdf", otf.version, true)
-otf.svgenabled = false
+otf.svgenabled = false
-local otfreaders = otf.readers
+local otfreaders = otf.readers
-local hashes = fonts.hashes
-local definers = fonts.definers
-local readers = fonts.readers
-local constructors = fonts.constructors
+local hashes = fonts.hashes
+local definers = fonts.definers
+local readers = fonts.readers
+local constructors = fonts.constructors
-local otffeatures = constructors.features.otf
-local registerotffeature = otffeatures.register
+local otffeatures = constructors.features.otf
+local registerotffeature = otffeatures.register
-local enhancers = allocate()
-otf.enhancers = enhancers
-local patches = { }
-enhancers.patches = patches
+local otfenhancers = constructors.enhancers.otf
+local registerotfenhancer = otfenhancers.register
-local forceload = false
-local cleanup = 0 -- mk: 0=885M 1=765M 2=735M (regular run 730M)
-local syncspace = true
-local forcenotdef = false
+local forceload = false
+local cleanup = 0 -- mk: 0=885M 1=765M 2=735M (regular run 730M)
+local syncspace = true
+local forcenotdef = false
-local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes
+local applyruntimefixes = fonts.treatments and fonts.treatments.applyfixes
-local wildcard = "*"
-local default = "dflt"
+local wildcard = "*"
+local default = "dflt"
-local formats = fonts.formats
+local formats = fonts.formats
-formats.otf = "opentype"
-formats.ttf = "truetype"
-formats.ttc = "truetype"
+formats.otf = "opentype"
+formats.ttf = "truetype"
+formats.ttc = "truetype"
registerdirective("fonts.otf.loader.cleanup", function(v) cleanup = tonumber(v) or (v and 1) or 0 end)
registerdirective("fonts.otf.loader.force", function(v) forceload = v end)
@@ -105,92 +102,9 @@ registerdirective("fonts.otf.loader.forcenotdef", function(v) forcenotdef =
-- end
-- end
--- Enhancers are used to apply fixes and extensions to fonts. For instance, we use them
--- to implement tlig and trep features. They are not neccessarily bound to opentype
--- fonts but can also apply to type one fonts, given that they obey the structure of an
--- opentype font. They are not to be confused with format specific features but maybe
--- some are so generic that they might eventually move to this mechanism.
+-- otfenhancers.patch("before","migrate metadata","cambria",function() end)
-local ordered_enhancers = {
- "check extra features",
-}
-
-local actions = allocate()
-local before = allocate()
-local after = allocate()
-
-patches.before = before
-patches.after = after
-
-local function enhance(name,data,filename,raw)
- local enhancer = actions[name]
- if enhancer then
- if trace_loading then
- report_otf("apply enhancement %a to file %a",name,filename)
- ioflush()
- end
- enhancer(data,filename,raw)
- else
- -- no message as we can have private ones
- end
-end
-
-function enhancers.apply(data,filename,raw)
- local basename = file.basename(lower(filename))
- if trace_loading then
- report_otf("%s enhancing file %a","start",filename)
- end
- ioflush() -- we want instant messages
- for e=1,#ordered_enhancers do
- local enhancer = ordered_enhancers[e]
- local b = before[enhancer]
- if b then
- for pattern, action in next, b do
- if find(basename,pattern) then
- action(data,filename,raw)
- end
- end
- end
- enhance(enhancer,data,filename,raw)
- local a = after[enhancer]
- if a then
- for pattern, action in next, a do
- if find(basename,pattern) then
- action(data,filename,raw)
- end
- end
- end
- ioflush() -- we want instant messages
- end
- if trace_loading then
- report_otf("%s enhancing file %a","stop",filename)
- end
- ioflush() -- we want instant messages
-end
-
--- patches.register("before","migrate metadata","cambria",function() end)
-
-function patches.register(what,where,pattern,action)
- local pw = patches[what]
- if pw then
- local ww = pw[where]
- if ww then
- ww[pattern] = action
- else
- pw[where] = { [pattern] = action}
- end
- end
-end
-
-function patches.report(fmt,...)
- if trace_loading then
- report_otf("patching: %s",formatters[fmt](...))
- end
-end
-
-function enhancers.register(what,action) -- only already registered can be overloaded
- actions[what] = action
-end
+registerotfenhancer("check extra features", function() end) -- placeholder
function otf.load(filename,sub,featurefile) -- second argument (format) is gone !
--
@@ -305,7 +219,7 @@ function otf.load(filename,sub,featurefile) -- second argument (format) is gone
collectgarbage("collect")
end
stoptiming(otfreaders)
- if elapsedtime then -- not in generic
+ if elapsedtime then
report_otf("loading, optimizing, packing and caching time %s", elapsedtime(otfreaders))
end
if cleanup > 3 then
@@ -329,7 +243,7 @@ function otf.load(filename,sub,featurefile) -- second argument (format) is gone
otfreaders.expand(data) -- inline tables
otfreaders.addunicodetable(data) -- only when not done yet
--
- enhancers.apply(data,filename,data)
+ otfenhancers.apply(data,filename,data)
--
-- constructors.addcoreunicodes(data.resources.unicodes) -- still needed ?
--
@@ -340,7 +254,6 @@ function otf.load(filename,sub,featurefile) -- second argument (format) is gone
data.metadata.math = data.resources.mathconstants
end
-
return data
end
@@ -507,14 +420,14 @@ local function copytotfm(data,cache_id)
spaceunits, spacer = charwidth, "charwidth"
end
end
- spaceunits = tonumber(spaceunits) or 500 -- brrr
+ spaceunits = tonumber(spaceunits) or units/2
--
parameters.slant = 0
- parameters.space = spaceunits -- 3.333 (cmr10)
+ parameters.space = spaceunits -- 3.333 (cmr10)
parameters.space_stretch = 1*units/2 -- 500 -- 1.666 (cmr10)
- parameters.space_shrink = 1*units/3 -- 333 -- 1.111 (cmr10)
- parameters.x_height = 2*units/5 -- 400
- parameters.quad = units -- 1000
+ parameters.space_shrink = 1*units/3 -- 333 -- 1.111 (cmr10)
+ parameters.x_height = 2*units/5 -- 400
+ parameters.quad = units -- 1000
if spaceunits < 2*units/5 then
-- todo: warning
end
@@ -575,10 +488,48 @@ local function copytotfm(data,cache_id)
end
end
+-- These woff files are a kind of joke in a tex environment because one can simply convert
+-- them to ttf/otf and use them as such (after all, we cache them too). The successor format
+-- woff2 is more complex so there we can as well call an external converter which in the end
+-- makes this code kind of obsolete before it's even used. Although ... it might become a
+-- more general conversion plug in.
+
+local converters = {
+ woff = {
+ cachename = "webfonts",
+ action = otf.readers.woff2otf,
+ }
+}
+
+local function checkconversion(specification)
+ local filename = specification.filename
+ local converter = converters[lower(file.suffix(filename))]
+ if converter then
+ local base = file.basename(filename)
+ local name = file.removesuffix(base)
+ local attr = lfs.attributes(filename)
+ local size = attr and attr.size or 0
+ local time = attr and attr.modification or 0
+ if size > 0 then
+ local cleanname = containers.cleanname(name)
+ local cachename = caches.setfirstwritablefile(cleanname,converter.cachename)
+ if not io.exists(cachename) or (time ~= lfs.attributes(cachename).modification) then
+ report_otf("caching font %a in %a",filename,cachename)
+ converter.action(filename,cachename) -- todo infoonly
+ lfs.touch(cachename,time,time)
+ end
+ specification.filename = cachename
+ end
+ end
+end
+
local function otftotfm(specification)
local cache_id = specification.hash
local tfmdata = containers.read(constructors.cache,cache_id)
if not tfmdata then
+
+ checkconversion(specification) -- for the moment here
+
local name = specification.name
local sub = specification.sub
local subindex = specification.subindex
@@ -724,7 +675,7 @@ local function getgsub(tfmdata,k,kind,value)
local properties = tfmdata.properties
local validlookups, lookuplist = otf.collectlookups(rawdata,kind,properties.script,properties.language)
if validlookups then
- local choice = tonumber(value) or 1 -- no random here (yet)
+ -- local choice = tonumber(value) or 1 -- no random here (yet)
for i=1,#lookuplist do
local lookup = lookuplist[i]
local steps = lookup.steps
@@ -812,9 +763,14 @@ end
readers.opentype = opentypereader -- kind of useless and obsolete
-function readers.otf (specification) return opentypereader(specification,"otf") end
-function readers.ttf (specification) return opentypereader(specification,"ttf") end
-function readers.ttc (specification) return opentypereader(specification,"ttf") end
+function readers.otf(specification) return opentypereader(specification,"otf") end
+function readers.ttf(specification) return opentypereader(specification,"ttf") end
+function readers.ttc(specification) return opentypereader(specification,"ttf") end
+
+function readers.woff(specification)
+ checkconversion(specification)
+ opentypereader(specification,"")
+end
-- this will be overloaded
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oto.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oto.lua
index 119977835c2..13568799b75 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oto.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oto.lua
@@ -120,7 +120,7 @@ local function registerbasehash(tfmdata)
basehash[hash] = base
end
properties.basehash = base
- properties.fullname = properties.fullname .. "-" .. base
+ properties.fullname = (properties.fullname or properties.name) .. "-" .. base
-- report_prepare("fullname base hash '%a, featureset %a",tfmdata.properties.fullname,hash)
applied = { }
end
@@ -225,6 +225,11 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
local trace_alternatives = trace_baseinit and trace_alternatives
local trace_ligatures = trace_baseinit and trace_ligatures
+ if not changed then
+ changed = { }
+ tfmdata.changed = changed
+ end
+
for i=1,#lookuplist do
local sequence = lookuplist[i]
local steps = sequence.steps
@@ -232,12 +237,12 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
if kind == "gsub_single" then
for i=1,#steps do
for unicode, data in next, steps[i].coverage do
- if not changed[unicode] then
+ -- if not changed[unicode] then -- fails for multiple subs in some math fonts
if trace_singles then
report_substitution(feature,sequence,descriptions,unicode,data)
end
changed[unicode] = data
- end
+ -- end
end
end
elseif kind == "gsub_alternate" then
@@ -392,7 +397,8 @@ local function featuresinitializer(tfmdata,value)
local properties = tfmdata.properties
local script = properties.script
local language = properties.language
- local rawfeatures = rawdata.resources.features
+ local rawresources = rawdata.resources
+ local rawfeatures = rawresources and rawresources.features
local basesubstitutions = rawfeatures and rawfeatures.gsub
local basepositionings = rawfeatures and rawfeatures.gpos
--
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otr.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otr.lua
index 7d0bf046c45..a9d3a8b2931 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otr.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otr.lua
@@ -94,8 +94,10 @@ otf.readers = readers
----- streamreader = utilities.streams -- faster on big files
local streamreader = utilities.files -- faster on identify
+local streamwriter = utilities.files
readers.streamreader = streamreader
+readers.streamwriter = streamwriter
local openfile = streamreader.open
local closefile = streamreader.close
@@ -643,7 +645,7 @@ local weights = {
[300] = "light",
[400] = "normal",
[500] = "medium",
- [600] = "semibold",
+ [600] = "semibold", -- demi demibold
[700] = "bold",
[800] = "extrabold",
[900] = "black",
@@ -973,7 +975,7 @@ readers.head = function(f,fontdata)
end
-- This table is a rather simple one. No treatment of values is needed here. Most
--- variables are not used but nofhmetrics is quite important.
+-- variables are not used but nofmetrics is quite important.
readers.hhea = function(f,fontdata,specification)
if specification.details then
@@ -981,7 +983,7 @@ readers.hhea = function(f,fontdata,specification)
if datatable then
setposition(f,datatable.offset)
fontdata.horizontalheader = {
- version = readfixed(f),
+ version = readfixed(f), -- two ushorts: major minor
ascender = readfword(f),
descender = readfword(f),
linegap = readfword(f),
@@ -997,11 +999,45 @@ readers.hhea = function(f,fontdata,specification)
reserved_3 = readshort(f),
reserved_4 = readshort(f),
metricdataformat = readshort(f),
- nofhmetrics = readushort(f),
+ nofmetrics = readushort(f),
}
else
fontdata.horizontalheader = {
- nofhmetrics = 0,
+ nofmetrics = 0,
+ }
+ end
+ end
+end
+
+readers.vhea = function(f,fontdata,specification)
+ if specification.details then
+ local datatable = fontdata.tables.vhea
+ if datatable then
+ setposition(f,datatable.offset)
+ local version = readfixed(f)
+ fontdata.verticalheader = {
+ version = version,
+ ascender = readfword(f),
+ descender = readfword(f),
+ linegap = readfword(f),
+ maxadvanceheight = readufword(f),
+ mintopsidebearing = readfword(f),
+ minbottomsidebearing = readfword(f),
+ maxextent = readfword(f),
+ caretsloperise = readshort(f),
+ caretsloperun = readshort(f),
+ caretoffset = readshort(f),
+ reserved_1 = readshort(f),
+ reserved_2 = readshort(f),
+ reserved_3 = readshort(f),
+ reserved_4 = readshort(f),
+ metricdataformat = readshort(f),
+ nofmetrics = readushort(f),
+ }
+-- inspect(fontdata.verticalheader)
+ else
+ fontdata.verticalheader = {
+ nofmetrics = 0,
}
end
end
@@ -1062,11 +1098,12 @@ readers.hmtx = function(f,fontdata,specification)
local datatable = fontdata.tables.hmtx
if datatable then
setposition(f,datatable.offset)
- local nofmetrics = fontdata.horizontalheader.nofhmetrics
- local glyphs = fontdata.glyphs
- local nofglyphs = fontdata.nofglyphs
- local width = 0 -- advance
- local leftsidebearing = 0
+ local horizontalheader = fontdata.horizontalheader
+ local nofmetrics = horizontalheader.nofmetrics
+ local glyphs = fontdata.glyphs
+ local nofglyphs = fontdata.nofglyphs
+ local width = 0 -- advance
+ local leftsidebearing = 0
for i=0,nofmetrics-1 do
local glyph = glyphs[i]
width = readshort(f)
@@ -1093,6 +1130,53 @@ readers.hmtx = function(f,fontdata,specification)
end
end
+readers.vmtx = function(f,fontdata,specification)
+ if specification.glyphs then
+ local datatable = fontdata.tables.vmtx
+ if datatable then
+ setposition(f,datatable.offset)
+ local verticalheader = fontdata.verticalheader
+ local nofmetrics = verticalheader.nofmetrics
+ local glyphs = fontdata.glyphs
+ local nofglyphs = fontdata.nofglyphs
+ local vheight = 0
+ local vdefault = verticalheader.ascender + verticalheader.descender
+ local topsidebearing = 0
+ for i=0,nofmetrics-1 do
+ local glyph = glyphs[i]
+ vheight = readshort(f)
+ topsidebearing = readshort(f)
+ if vheight ~= 0 and vheight ~= vdefault then
+ glyph.vheight = vheight
+ end
+ -- if topsidebearing ~= 0 then
+ -- glyph.tsb = topsidebearing
+ -- end
+ end
+ -- The next can happen in for instance a monospace font or in a cjk font
+ -- with fixed heights.
+ for i=nofmetrics,nofglyphs-1 do
+ local glyph = glyphs[i]
+ if vheight ~= 0 and vheight ~= vdefault then
+ glyph.vheight = vheight
+ end
+ -- if topsidebearing ~= 0 then
+ -- glyph.tsb = topsidebearing
+ -- end
+ end
+ end
+ end
+end
+
+readers.vorg = function(f,fontdata,specification)
+ if specification.glyphs then
+ local datatable = fontdata.tables.vorg
+ if datatable then
+ report("todo: %s","vorg")
+ end
+ end
+end
+
-- The post table relates to postscript (printing) but has some relevant properties for other
-- usage as well. We just use the names from the microsoft specification. The version 2.0
-- description is somewhat fuzzy but it is a hybrid with overloads.
@@ -1745,123 +1829,11 @@ function readers.math(f,fontdata,specification)
end
end
--- Goodie. A sequence instead of segments costs a bit more memory, some 300K on a
--- dejavu serif and about the same on a pagella regular.
-
-local function packoutlines(data,makesequence)
- local subfonts = data.subfonts
- if subfonts then
- for i=1,#subfonts do
- packoutlines(subfonts[i],makesequence)
- end
- return
- end
- local common = data.segments
- if common then
- return
- end
- local glyphs = data.glyphs
- if not glyphs then
- return
- end
- if makesequence then
- for index=1,#glyphs do
- local glyph = glyphs[index]
- local segments = glyph.segments
- if segments then
- local sequence = { }
- local nofsequence = 0
- for i=1,#segments do
- local segment = segments[i]
- local nofsegment = #segment
- nofsequence = nofsequence + 1
- sequence[nofsequence] = segment[nofsegment]
- for i=1,nofsegment-1 do
- nofsequence = nofsequence + 1
- sequence[nofsequence] = segment[i]
- end
- end
- glyph.sequence = sequence
- glyph.segments = nil
- end
- end
- else
- local hash = { }
- local common = { }
- local reverse = { }
- local last = 0
- for index=1,#glyphs do
- local segments = glyphs[index].segments
- if segments then
- for i=1,#segments do
- local h = concat(segments[i]," ")
- hash[h] = (hash[h] or 0) + 1
- end
- end
- end
- for index=1,#glyphs do
- local segments = glyphs[index].segments
- if segments then
- for i=1,#segments do
- local segment = segments[i]
- local h = concat(segment," ")
- if hash[h] > 1 then -- minimal one shared in order to hash
- local idx = reverse[h]
- if not idx then
- last = last + 1
- reverse[h] = last
- common[last] = segment
- idx = last
- end
- segments[i] = idx
- end
- end
- end
- end
- if last > 0 then
- data.segments = common
- end
- end
-end
-
-local function unpackoutlines(data)
- local subfonts = data.subfonts
- if subfonts then
- for i=1,#subfonts do
- unpackoutlines(subfonts[i])
- end
- return
- end
- local common = data.segments
- if not common then
- return
- end
- local glyphs = data.glyphs
- if not glyphs then
- return
- end
- for index=1,#glyphs do
- local segments = glyphs[index].segments
- if segments then
- for i=1,#segments do
- local c = common[segments[i]]
- if c then
- segments[i] = c
- end
- end
- end
- end
- data.segments = nil
-end
-
-otf.packoutlines = packoutlines
-otf.unpackoutlines = unpackoutlines
-
-- Now comes the loader. The order of reading these matters as we need to know
-- some properties in order to read following tables. When details is true we also
-- initialize the glyphs data.
-local function getinfo(maindata,sub,platformnames,rawfamilynames)
+local function getinfo(maindata,sub,platformnames,rawfamilynames,metricstoo)
local fontdata = sub and maindata.subfonts and maindata.subfonts[sub] or maindata
local names = fontdata.names
local info = nil
@@ -1871,8 +1843,8 @@ local function getinfo(maindata,sub,platformnames,rawfamilynames)
local fontheader = fontdata.fontheader or { }
local cffinfo = fontdata.cffinfo or { }
local filename = fontdata.filename
- local weight = getname(fontdata,"weight") or cffinfo.weight or metrics.weight
- local width = getname(fontdata,"width") or cffinfo.width or metrics.width
+ local weight = getname(fontdata,"weight") or (cffinfo and cffinfo.weight) or (metrics and metrics.weight)
+ local width = getname(fontdata,"width") or (cffinfo and cffinfo.width ) or (metrics and metrics.width )
local fontname = getname(fontdata,"postscriptname")
local fullname = getname(fontdata,"fullname")
local family = getname(fontdata,"family")
@@ -1918,6 +1890,29 @@ local function getinfo(maindata,sub,platformnames,rawfamilynames)
descender = metrics.typodescender,
platformnames = platformnames and fontdata.platformnames or nil,
}
+ if metricstoo then
+ local keys = {
+ "version",
+ "ascender", "descender", "linegap",
+ -- "caretoffset", "caretsloperise", "caretsloperun",
+ "maxadvancewidth", "maxadvanceheight", "maxextent",
+ -- "metricdataformat",
+ "minbottomsidebearing", "mintopsidebearing",
+ }
+ local h = fontdata.horizontalheader or { }
+ local v = fontdata.verticalheader or { }
+ if h then
+ local th = { }
+ local tv = { }
+ for i=1,#keys do
+ local key = keys[i]
+ th[key] = h[key] or 0
+ tv[key] = v[key] or 0
+ end
+ info.horizontalmetrics = th
+ info.verticalmetrics = tv
+ end
+ end
elseif n then
info = {
filename = fontdata.filename,
@@ -2010,7 +2005,10 @@ local function readdata(f,offset,specification)
readers["head"](f,fontdata,specification)
readers["maxp"](f,fontdata,specification)
readers["hhea"](f,fontdata,specification)
+ readers["vhea"](f,fontdata,specification)
readers["hmtx"](f,fontdata,specification)
+ readers["vmtx"](f,fontdata,specification)
+ readers["vorg"](f,fontdata,specification)
readers["post"](f,fontdata,specification)
readers["cff" ](f,fontdata,specification)
readers["cmap"](f,fontdata,specification)
@@ -2150,6 +2148,15 @@ function readers.loadshapes(filename,n)
shapes = true,
subfont = n,
}
+ if fontdata then
+ -- easier on luajit but still we can hit the 64 K stack constants issue
+ for k, v in next, fontdata.glyphs do
+ v.class = nil
+ v.index = nil
+ v.math = nil
+ -- v.name = nil
+ end
+ end
return fontdata and {
-- version = 0.123 -- todo
filename = filename,
@@ -2185,7 +2192,7 @@ function readers.loadfont(filename,n)
descriptions = fontdata.descriptions,
format = fontdata.format,
goodies = { },
- metadata = getinfo(fontdata,n), -- no platformnames here !
+ metadata = getinfo(fontdata,n,false,false,true), -- no platformnames here !
properties = {
hasitalics = fontdata.hasitalics or false,
maxcolorclass = fontdata.maxcolorclass,
@@ -2300,63 +2307,3 @@ function readers.extend(fontdata)
end
end
end
-
--- for now .. this will move to a context specific file
-
-if fonts.hashes then
-
- local identifiers = fonts.hashes.identifiers
- local loadshapes = readers.loadshapes
-
- readers.version = 0.006
- readers.cache = containers.define("fonts", "shapes", readers.version, true)
-
- -- todo: loaders per format
-
- local function load(filename,sub)
- local base = file.basename(filename)
- local name = file.removesuffix(base)
- local kind = file.suffix(filename)
- local attr = lfs.attributes(filename)
- local size = attr and attr.size or 0
- local time = attr and attr.modification or 0
- local sub = tonumber(sub)
- if size > 0 and (kind == "otf" or kind == "ttf" or kind == "tcc") then
- local hash = containers.cleanname(base) -- including suffix
- if sub then
- hash = hash .. "-" .. sub
- end
- data = containers.read(readers.cache,hash)
- if not data or data.time ~= time or data.size ~= size then
- data = loadshapes(filename,sub)
- if data then
- data.size = size
- data.format = data.format or (kind == "otf" and "opentype") or "truetype"
- data.time = time
- packoutlines(data)
- containers.write(readers.cache,hash,data)
- data = containers.read(readers.cache,hash) -- frees old mem
- end
- end
- unpackoutlines(data)
- else
- data = {
- filename = filename,
- size = 0,
- time = time,
- format = "unknown",
- units = 1000,
- glyphs = { }
- }
- end
- return data
- end
-
- fonts.hashes.shapes = table.setmetatableindex(function(t,k)
- local d = identifiers[k]
- local v = load(d.properties.filename,d.subindex)
- t[k] = v
- return v
- end)
-
-end
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ots.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ots.lua
index d63d524ccb2..1f84214812f 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ots.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ots.lua
@@ -128,18 +128,16 @@ local trace_details = false registertracker("otf.details", function(v
local trace_steps = false registertracker("otf.steps", function(v) trace_steps = v end)
local trace_skips = false registertracker("otf.skips", function(v) trace_skips = v end)
local trace_directions = false registertracker("otf.directions", function(v) trace_directions = v end)
+local trace_plugins = false registertracker("otf.plugins", function(v) trace_plugins = v end)
local trace_kernruns = false registertracker("otf.kernruns", function(v) trace_kernruns = v end)
local trace_discruns = false registertracker("otf.discruns", function(v) trace_discruns = v end)
local trace_compruns = false registertracker("otf.compruns", function(v) trace_compruns = v end)
local trace_testruns = false registertracker("otf.testruns", function(v) trace_testruns = v end)
-local quit_on_no_replacement = true -- maybe per font
-local zwnjruns = true
-local optimizekerns = true
-
-registerdirective("otf.zwnjruns", function(v) zwnjruns = v end)
-registerdirective("otf.chain.quitonnoreplacement",function(value) quit_on_no_replacement = value end)
+----- zwnjruns = true registerdirective("otf.zwnjruns", function(v) zwnjruns = v end)
+local optimizekerns = true
+local alwaysdisc = true registerdirective("otf.alwaysdisc", function(v) alwaysdisc = v end)
local report_direct = logs.reporter("fonts","otf direct")
local report_subchain = logs.reporter("fonts","otf subchain")
@@ -188,7 +186,7 @@ local copy_node = nuts.copy
local copy_node_list = nuts.copy_list
local find_node_tail = nuts.tail
local flush_node_list = nuts.flush_list
-local free_node = nuts.free
+local flush_node = nuts.flush_node
local end_of_math = nuts.end_of_math
local traverse_nodes = nuts.traverse
local traverse_id = nuts.traverse_id
@@ -239,12 +237,15 @@ local cursonce = true
local fonthashes = fonts.hashes
local fontdata = fonthashes.identifiers
+local fontfeatures = fonthashes.features
local otffeatures = fonts.constructors.features.otf
local registerotffeature = otffeatures.register
local onetimemessage = fonts.loggers.onetimemessage or function() end
+local getrandom = utilities and utilities.randomizer and utilities.randomizer.get
+
otf.defaultnodealternate = "none" -- first last
-- We use a few global variables. The handler can be called nested but this assumes that the
@@ -257,6 +258,7 @@ local marks = false
local currentfont = false
local factor = 0
local threshold = 0
+local checkmarks = false
local sweepnode = nil
local sweepprev = nil
@@ -269,16 +271,8 @@ local notmatchreplace = { }
local handlers = { }
--- helper
-
-local function isspace(n)
- if getid(n) == glue_code then
- local w = getfield(n,"width")
- if w >= threshold then
- return 32
- end
- end
-end
+local isspace = injections.isspace
+local getthreshold = injections.getthreshold
-- we use this for special testing and documentation
@@ -286,6 +280,13 @@ local checkstep = (nodes and nodes.tracers and nodes.tracers.steppers.chec
local registerstep = (nodes and nodes.tracers and nodes.tracers.steppers.register) or function() end
local registermessage = (nodes and nodes.tracers and nodes.tracers.steppers.message) or function() end
+local function checkdisccontent(d)
+ local pre, post, replace = getdisc(d)
+ if pre then for n in traverse_id(glue_code,pre) do print("pre",nodes.idstostring(pre)) break end end
+ if post then for n in traverse_id(glue_code,post) do print("pos",nodes.idstostring(post)) break end end
+ if replace then for n in traverse_id(glue_code,replace) do print("rep",nodes.idstostring(replace)) break end end
+end
+
local function logprocess(...)
if trace_steps then
registermessage(...)
@@ -362,7 +363,7 @@ end
local function copy_glyph(g) -- next and prev are untouched !
local components = getfield(g,"components")
if components then
- setfield(g,"components",nil)
+ setfield(g,"components")
local n = copy_node(g)
copyinjection(n,g) -- we need to preserve the lig indices
setfield(g,"components",components)
@@ -375,11 +376,18 @@ local function copy_glyph(g) -- next and prev are untouched !
end
local function flattendisk(head,disc)
- local _, _, replace, _, _, replacetail = getdisc(disc,true)
- setfield(disc,"replace",nil)
- free_node(disc)
- if head == disc then
- local next = getnext(disc)
+ local pre, post, replace, pretail, posttail, replacetail = getdisc(disc,true)
+ local prev, next = getboth(disc)
+ local ishead = head == disc
+ setdisc(disc)
+ flush_node(disc)
+ if pre then
+ flush_node_list(pre)
+ end
+ if post then
+ flush_node_list(post)
+ end
+ if ishead then
if replace then
if next then
setlink(replacetail,next)
@@ -391,7 +399,6 @@ local function flattendisk(head,disc)
return -- maybe warning
end
else
- local prev, next = getboth(disc)
if replace then
if next then
setlink(replacetail,next)
@@ -430,8 +437,8 @@ local function markstoligature(head,start,stop,char)
else
local prev = getprev(start)
local next = getnext(stop)
- setprev(start,nil)
- setnext(stop,nil)
+ setprev(start)
+ setnext(stop)
local base = copy_glyph(start)
if head == start then
head = base
@@ -493,8 +500,8 @@ local function toligature(head,start,stop,char,dataset,sequence,markflag,discfou
local prev = getprev(start)
local next = getnext(stop)
local comp = start
- setprev(start,nil)
- setnext(stop,nil)
+ setprev(start)
+ setnext(stop)
local base = copy_glyph(start)
if start == head then
head = base
@@ -564,40 +571,39 @@ local function toligature(head,start,stop,char,dataset,sequence,markflag,discfou
-- anyway
local pre, post, replace, pretail, posttail, replacetail = getdisc(discfound,true)
if not replace then -- todo: signal simple hyphen
- local prev = getprev(base)
--- local copied = copy_node_list(comp)
-local current = comp
-local previous = nil
-local copied = nil
-while current do
- if getid(current) == glyph_code then
- local n = copy_node(current)
- if copied then
- setlink(previous,n)
- else
- copied = n
- end
- previous = n
- end
- current = getnext(current)
-end
- setprev(discnext,nil) -- also blocks funny assignments
- setnext(discprev,nil) -- also blocks funny assignments
+ local prev = getprev(base)
+ local current = comp
+ local previous = nil
+ local copied = nil
+ while current do
+ if getid(current) == glyph_code then
+ local n = copy_node(current)
+ if copied then
+ setlink(previous,n)
+ else
+ copied = n
+ end
+ previous = n
+ end
+ current = getnext(current)
+ end
+ setprev(discnext) -- also blocks funny assignments
+ setnext(discprev) -- also blocks funny assignments
if pre then
setlink(discprev,pre)
end
pre = comp
if post then
setlink(posttail,discnext)
- setprev(post,nil)
+ setprev(post)
else
post = discnext
end
setlink(prev,discfound)
setlink(discfound,next)
- setboth(base,nil,nil)
+ setboth(base)
setfield(base,"components",copied)
- setdisc(discfound,pre,post,base,discretionary_code)
+ setdisc(discfound,pre,post,base) -- was discretionary_code
base = prev -- restart
end
end
@@ -605,7 +611,7 @@ end
return head, base
end
-local function multiple_glyphs(head,start,multiple,ignoremarks)
+local function multiple_glyphs(head,start,multiple,ignoremarks,what)
local nofmultiples = #multiple
if nofmultiples > 0 then
resetinjection(start)
@@ -613,17 +619,29 @@ local function multiple_glyphs(head,start,multiple,ignoremarks)
if nofmultiples > 1 then
local sn = getnext(start)
for k=2,nofmultiples do
--- untested:
---
--- while ignoremarks and marks[getchar(sn)] then
--- local sn = getnext(sn)
--- end
+ -- untested:
+ --
+ -- while ignoremarks and marks[getchar(sn)] then
+ -- local sn = getnext(sn)
+ -- end
local n = copy_node(start) -- ignore components
resetinjection(n)
setchar(n,multiple[k])
insert_node_after(head,start,n)
start = n
end
+ if what == true then
+ -- we're ok
+ elseif what > 1 then
+ local m = multiple[nofmultiples]
+ for i=2,what do
+ local n = copy_node(start) -- ignore components
+ resetinjection(n)
+ setchar(n,m)
+ insert_node_after(head,start,n)
+ start = n
+ end
+ end
end
return head, start, true
else
@@ -637,7 +655,7 @@ end
local function get_alternative_glyph(start,alternatives,value)
local n = #alternatives
if value == "random" then
- local r = random(1,n)
+ local r = getrandom and getrandom("glyph",1,n) or random(1,n)
return alternatives[r], trace_alternatives and formatters["value %a, taking %a"](value,r)
elseif value == "first" then
return alternatives[1], trace_alternatives and formatters["value %a, taking %a"](value,1)
@@ -705,7 +723,7 @@ function handlers.gsub_multiple(head,start,dataset,sequence,multiple)
if trace_multiples then
logprocess("%s: replacing %s by multiple %s",pref(dataset,sequence),gref(getchar(start)),gref(multiple))
end
- return multiple_glyphs(head,start,multiple,sequence.flags[1])
+ return multiple_glyphs(head,start,multiple,sequence.flags[1],dataset[1])
end
function handlers.gsub_ligature(head,start,dataset,sequence,ligature)
@@ -946,7 +964,7 @@ function handlers.gpos_mark2base(head,start,dataset,sequence,markanchors,rlmode)
local ba = markanchors[1][basechar]
if ba then
local ma = markanchors[2]
- local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
+ local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -1002,7 +1020,7 @@ function handlers.gpos_mark2ligature(head,start,dataset,sequence,markanchors,rlm
local index = getligaindex(start)
ba = ba[index]
if ba then
- local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar]) -- index
+ local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks)
if trace_marks then
logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
pref(dataset,sequence),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy)
@@ -1051,7 +1069,7 @@ function handlers.gpos_mark2mark(head,start,dataset,sequence,markanchors,rlmode)
local ba = markanchors[1][basechar] -- slot 1 has been made copy of the class hash
if ba then
local ma = markanchors[2]
- local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true)
+ local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true,checkmarks)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -1237,7 +1255,7 @@ function chainprocs.gsub_multiple(head,start,stop,dataset,sequence,currentlookup
if trace_multiples then
logprocess("%s: replacing %s by multiple characters %s",cref(dataset,sequence),gref(startchar),gref(replacement))
end
- return multiple_glyphs(head,start,replacement,sequence.flags[1])
+ return multiple_glyphs(head,start,replacement,sequence.flags[1],dataset[1])
end
return head, start, false
end
@@ -1262,7 +1280,7 @@ function chainprocs.gsub_alternate(head,start,stop,dataset,sequence,currentlooku
end
local kind = dataset[4]
local what = dataset[1]
- local value = what == true and tfmdata.shared.features[kind] or what
+ local value = what == true and tfmdata.shared.features[kind] or what -- todo: optimize in ctx
local current = start
while current do
local currentchar = ischar(current)
@@ -1519,7 +1537,7 @@ function chainprocs.gpos_mark2base(head,start,stop,dataset,sequence,currentlooku
if ba then
local ma = markanchors[2]
if ma then
- local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
+ local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -1586,7 +1604,7 @@ function chainprocs.gpos_mark2ligature(head,start,stop,dataset,sequence,currentl
local index = getligaindex(start)
ba = ba[index]
if ba then
- local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
+ local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
cref(dataset,sequence),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy)
@@ -1639,7 +1657,7 @@ function chainprocs.gpos_mark2mark(head,start,stop,dataset,sequence,currentlooku
if ba then
local ma = markanchors[2]
if ma then
- local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true)
+ local dx, dy, bound = setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true,checkmarks)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -1750,6 +1768,42 @@ end
-- order to handle that we need more complex code which also slows down even more. The main
-- loop variant could deal with that: test, collapse, backtrack.
+local new_kern = nuts.pool.kern
+
+local function checked(head)
+ local current = head
+ while current do
+ if getid(current) == glue_code then
+ local kern = new_kern(getfield(current,"width"))
+ if head == current then
+ local next = getnext(current)
+ if next then
+ setlink(kern,next)
+ end
+ flush_node(current)
+ head = kern
+ current = next
+ else
+ local prev, next = getboth(current)
+ setlink(prev,kern)
+ setlink(kern,next)
+ flush_node(current)
+ current = next
+ end
+ else
+ current = getnext(current)
+ end
+ end
+ return head
+end
+
+local function setdiscchecked(d,pre,post,replace)
+ if pre then pre = checked(pre) end
+ if post then post = checked(post) end
+ if replace then replace = checked(replace) end
+ setdisc(d,pre,post,replace)
+end
+
local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,ck,chainproc)
if not start then
@@ -1772,8 +1826,10 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
local current = start
local last = start
local prev = getprev(start)
+ local hasglue = false
-- fishy: so we can overflow and then go on in the sweep?
+ -- todo : id can also be glue_code as we checked spaces
local i = f
while i <= l do
@@ -1782,6 +1838,11 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
i = i + 1
last = current
current = getnext(current)
+ elseif id == glue_code then
+ i = i + 1
+ last = current
+ current = getnext(current)
+ hasglue = true
elseif id == disc_code then
if keepdisc then
keepdisc = false
@@ -1834,8 +1895,8 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
tail = find_node_tail(head)
end
setnext(sweepnode,current)
- setprev(head,nil)
- setnext(tail,nil)
+ setprev(head)
+ setnext(tail)
appenddisc(sweepnode,head)
end
end
@@ -1848,6 +1909,10 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
if id == glyph_code then
i = i + 1
current = getnext(current)
+ elseif id == glue_code then
+ i = i + 1
+ current = getnext(current)
+ hasglue = true
elseif id == disc_code then
if keepdisc then
keepdisc = false
@@ -1890,6 +1955,9 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
local id = getid(current)
if id == glyph_code then
i = i - 1
+ elseif id == glue_code then
+ i = i - 1
+ hasglue = true
elseif id == disc_code then
if keepdisc then
keepdisc = false
@@ -1938,8 +2006,8 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
if cprev then
setnext(cprev,lookaheaddisc)
end
- setprev(cf,nil)
- setnext(cl,nil)
+ setprev(cf)
+ setnext(cl)
if startishead then
head = lookaheaddisc
end
@@ -1966,7 +2034,11 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
local tail = find_node_tail(new)
setlink(tail,replace)
end
- setdisc(lookaheaddisc,cf,post,new)
+ if hasglue then
+ setdiscchecked(lookaheaddisc,cf,post,new)
+ else
+ setdisc(lookaheaddisc,cf,post,new)
+ end
start = getprev(lookaheaddisc)
sweephead[cf] = getnext(clast)
sweephead[new] = getnext(last)
@@ -1992,8 +2064,8 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
setprev(cnext,backtrackdisc)
end
setnext(backtrackdisc,cnext)
- setprev(cf,nil)
- setnext(cl,nil)
+ setprev(cf)
+ setnext(cl)
local pre, post, replace, pretail, posttail, replacetail = getdisc(backtrackdisc,true)
local new = copy_node_list(cf)
local cnew = find_node_tail(new)
@@ -2020,7 +2092,11 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
else
replace = new
end
- setdisc(backtrackdisc,pre,post,replace)
+ if hasglue then
+ setdiscchecked(backtrackdisc,pre,post,replace)
+ else
+ setdisc(backtrackdisc,pre,post,replace)
+ end
start = getprev(backtrackdisc)
sweephead[post] = getnext(clast)
sweephead[replace] = getnext(last)
@@ -2295,16 +2371,13 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
-- maybe only if match
prev = getprev(prev)
- elseif seq[n][32] then
+ elseif seq[n][32] and isspace(prev,threshold) then
n = n - 1
prev = getprev(prev)
else
match = false
break
end
- elseif seq[n][32] then -- somewhat special, as zapfino can have many preceding spaces
- n = n - 1
- prev = getprev(prev) -- was absent
else
match = false
break
@@ -2424,15 +2497,13 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
-- maybe only if match
current = getnext(current)
- elseif seq[n][32] then -- brrr
+ elseif seq[n][32] and isspace(current,threshold) then
n = n + 1
+ current = getnext(current)
else
match = false
break
end
- elseif seq[n][32] then
- n = n + 1
- current = getnext(current)
else
match = false
break
@@ -2545,7 +2616,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if replacements then
head, start, done = reversesub(head,start,last,dataset,sequence,replacements,rlmode)
else
- done = quit_on_no_replacement -- can be meant to be skipped / quite inconsistent in fonts
+ done = true
if trace_contexts then
logprocess("%s: skipping match",cref(dataset,sequence))
end
@@ -2685,10 +2756,12 @@ function otf.dataset(tfmdata,font) -- generic variant, overloaded in context
}
rs[language] = rl
local sequences = tfmdata.resources.sequences
- for s=1,#sequences do
- local v = enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
- if v then
- rl[#rl+1] = v
+ if sequences then
+ for s=1,#sequences do
+ local v = enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
+ if v then
+ rl[#rl+1] = v
+ end
end
end
end
@@ -2728,10 +2801,10 @@ local function kernrun(disc,k_run,font,attr,...)
end
end
--
- if prev and (pre or replace) and not ischar(prev,font) then
+ if prev and not ischar(prev,font) then -- and (pre or replace)
prev = false
end
- if next and (post or replace) and not ischar(next,font) then
+ if next and not ischar(next,font) then -- and (post or replace)
next = false
end
--
@@ -2748,6 +2821,7 @@ local function kernrun(disc,k_run,font,attr,...)
done = true
end
setprev(pre,nest)
+-- setprev(pre)
setnext(prev,disc)
end
end
@@ -2761,7 +2835,7 @@ local function kernrun(disc,k_run,font,attr,...)
if k_run(posttail,"postinjections",next,font,attr,...) then
done = true
end
- setnext(posttail,nil)
+ setnext(posttail)
setprev(next,disc)
end
end
@@ -2777,6 +2851,7 @@ local function kernrun(disc,k_run,font,attr,...)
done = true
end
setprev(replace,nest)
+-- setprev(replace)
setnext(prev,disc)
end
if next then
@@ -2784,7 +2859,7 @@ local function kernrun(disc,k_run,font,attr,...)
if k_run(replacetail,"replaceinjections",next,font,attr,...) then
done = true
end
- setnext(replacetail,nil)
+ setnext(replacetail)
setprev(next,disc)
end
elseif prev and next then
@@ -2864,7 +2939,7 @@ local function testrun(disc,t_run,c_run,...)
local ok, overflow = t_run(replace,next,...)
if ok and overflow then
-- so, we can have crossed the boundary
- setfield(disc,"replace",nil)
+ setfield(disc,"replace")
setlink(prev,replace)
-- setlink(replacetail,next)
setboth(disc)
@@ -2976,7 +3051,11 @@ end
-- -- local a = getattr(start,0)
-- -- if not a or (a == attr) then
--
--- and even that one is probably not needed.
+-- and even that one is probably not needed. However, we can handle interesting
+-- cases now:
+--
+-- 1{2{\oldstyle\discretionary{3}{4}{5}}6}7\par
+-- 1{2\discretionary{3{\oldstyle3}}{{\oldstyle4}4}{5{\oldstyle5}5}6}7\par
local nesting = 0
@@ -3006,6 +3085,7 @@ local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlm
start = getnext(start)
end
else
+ -- go on can be a mixed one
start = getnext(start)
end
elseif char == false then
@@ -3051,6 +3131,8 @@ local function t_run_single(start,stop,font,attr,lookupcache)
return true, d > 1
end
end
+ else
+ -- go on can be a mixed one
end
start = getnext(start)
else
@@ -3136,6 +3218,7 @@ local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlm
start = getnext(start)
end
else
+ -- go on can be a mixed one
start = getnext(start)
end
elseif char == false then
@@ -3190,6 +3273,8 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
report_missing_coverage(dataset,sequence)
end
end
+ else
+ -- go on can be a mixed one
end
start = getnext(start)
else
@@ -3253,7 +3338,7 @@ local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,datase
end
end
--- to be checkedL nowadays we probably can assume properly matched directions
+-- to be checked, nowadays we probably can assume properly matched directions
-- so maybe we no longer need a stack
local function txtdirstate(start,stack,top,rlparmode)
@@ -3294,6 +3379,10 @@ local function pardirstate(start)
return getnext(start), new, new
end
+otf.helpers = otf.helpers or { }
+otf.helpers.txtdirstate = txtdirstate
+otf.helpers.pardirstate = pardirstate
+
local function featuresprocessor(head,font,attr)
local sequences = sequencelists[font] -- temp hack
@@ -3306,13 +3395,14 @@ local function featuresprocessor(head,font,attr)
if nesting == 1 then
- currentfont = font
- tfmdata = fontdata[font]
- descriptions = tfmdata.descriptions
- characters = tfmdata.characters
- marks = tfmdata.resources.marks
- factor = tfmdata.parameters.factor
- threshold = tfmdata.parameters.spacing.width or 65536*10
+ currentfont = font
+ tfmdata = fontdata[font]
+ descriptions = tfmdata.descriptions
+ characters = tfmdata.characters
+ marks = tfmdata.resources.marks
+ threshold,
+ factor = getthreshold(font)
+ checkmarks = tfmdata.properties.checkmarks
elseif currentfont ~= font then
@@ -3341,6 +3431,8 @@ local function featuresprocessor(head,font,attr)
local done = false
local datasets = otf.dataset(tfmdata,font,attr)
+ local forcedisc = alwaysdisc or not attr
+
local dirstack = { } -- could move outside function but we can have local runs
sweephead = { }
@@ -3353,7 +3445,7 @@ local function featuresprocessor(head,font,attr)
-- Keeping track of the headnode is needed for devanagari (I generalized it a bit
-- so that multiple cases are also covered.)
- -- We don't goto the next node of a disc node is created so that we can then treat
+ -- We don't goto the next node when a disc node is created so that we can then treat
-- the pre, post and replace. It's a bit of a hack but works out ok for most cases.
for s=1,#datasets do
@@ -3371,15 +3463,12 @@ local function featuresprocessor(head,font,attr)
local nofsteps = sequence.nofsteps
if not steps then
-- this permits injection, watch the different arguments
- local h, d, ok = handler(head,start,dataset,sequence,nil,nil,nil,0,font,attr)
+ local h, d, ok = handler(head,head,dataset,sequence,nil,nil,nil,0,font,attr)
if ok then
success = true
if h then
head = h
end
- if d then
- start = d
- end
end
elseif typ == "gsub_reversecontextchain" then
-- this is a limited case, no special treatments like 'init' etc
@@ -3458,16 +3547,26 @@ local function featuresprocessor(head,font,attr)
-- whatever glyph
start = getnext(start)
elseif id == disc_code then
- local ok
- if gpossing then
- start, ok = kernrun(start,k_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- elseif typ == "gsub_ligature" then
- start, ok = testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ -- ctx: we could assume the same attr as the surrounding glyphs but then we loose
+ -- the option to have interesting disc nodes (we gain upto 10% on extreme tests);
+ -- if a disc would have a font field we could even be more strict (see oldstyle test
+ -- case)
+ local a = forcedisc or getsubtype(start) == discretionary_code or getattr(start,0) == attr
+ if a then
+ -- local attr = false
+ local ok
+ if gpossing then
+ start, ok = kernrun(start,k_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ elseif typ == "gsub_ligature" then
+ start, ok = testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ else
+ start, ok = comprun(start,c_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ end
+ if ok then
+ success = true
+ end
else
- start, ok = comprun(start,c_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- end
- if ok then
- success = true
+ start = getnext(start)
end
elseif id == math_code then
start = getnext(end_of_math(start))
@@ -3527,16 +3626,22 @@ local function featuresprocessor(head,font,attr)
elseif char == false then
start = getnext(start)
elseif id == disc_code then
- local ok
- if gpossing then
- start, ok = kernrun(start,k_run_multiple, font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- elseif typ == "gsub_ligature" then
- start, ok = testrun(start,t_run_multiple,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ -- see comment above
+ local a = forcedisc or getsubtype(start) == discretionary_code or getattr(start,0) == attr
+ if a then
+ local ok
+ if gpossing then
+ start, ok = kernrun(start,k_run_multiple, font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ elseif typ == "gsub_ligature" then
+ start, ok = testrun(start,t_run_multiple,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ else
+ start, ok = comprun(start,c_run_multiple, font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ end
+ if ok then
+ success = true
+ end
else
- start, ok = comprun(start,c_run_multiple, font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- end
- if ok then
- success = true
+ start = getnext(start)
end
elseif id == math_code then
start = getnext(end_of_math(start))
@@ -3568,6 +3673,34 @@ end
-- so far
+local plugins = { }
+otf.plugins = plugins
+
+function otf.registerplugin(name,f)
+ if type(name) == "string" and type(f) == "function" then
+ plugins[name] = { name, f }
+ end
+end
+
+local function plugininitializer(tfmdata,value)
+ if type(value) == "string" then
+ tfmdata.shared.plugin = plugins[value]
+ end
+end
+
+local function pluginprocessor(head,font)
+ local s = fontdata[font].shared
+ local p = s and s.plugin
+ if p then
+ if trace_plugins then
+ report_process("applying plugin %a",p[1])
+ end
+ return p[2](head,font)
+ else
+ return head, false
+ end
+end
+
local function featuresinitializer(tfmdata,value)
-- nothing done here any more
end
@@ -3579,9 +3712,11 @@ registerotffeature {
initializers = {
position = 1,
node = featuresinitializer,
+ plug = plugininitializer,
},
processors = {
node = featuresprocessor,
+ plug = pluginprocessor,
}
}
@@ -3596,12 +3731,29 @@ otf.handlers = handlers -- used in devanagari
local setspacekerns = nodes.injections.setspacekerns if not setspacekerns then os.exit() end
-function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr)
- -- if not setspacekerns then
- -- setspacekerns = nodes.injections.setspacekerns
- -- end
- setspacekerns(font,sequence)
- return head, start, true
+if fontfeatures then
+
+ function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr)
+ local features = fontfeatures[font]
+ local enabled = features and features.spacekern and features.kern
+ if enabled then
+ setspacekerns(font,sequence)
+ end
+ return head, start, enabled
+ end
+
+else -- generic (no hashes)
+
+ function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr)
+ local shared = fontdata[font].shared
+ local features = shared and shared.features
+ local enabled = features and features.spacekern and features.kern
+ if enabled then
+ setspacekerns(font,sequence)
+ end
+ return head, start, enabled
+ end
+
end
local function hasspacekerns(data)
@@ -3636,11 +3788,13 @@ otf.readers.registerextender {
end
}
+-- we merge the lookups but we still honor the language / script
+
local function spaceinitializer(tfmdata,value) -- attr
local resources = tfmdata.resources
local spacekerns = resources and resources.spacekerns
- if spacekerns == nil then
- local properties = tfmdata.properties
+ local properties = tfmdata.properties
+ if value and spacekerns == nil then
if properties and properties.hasspacekerns then
local sequences = resources.sequences
local left = { }
@@ -3653,28 +3807,57 @@ local function spaceinitializer(tfmdata,value) -- attr
if steps then
local kern = sequence.features.kern
if kern then
- feat = feat or kern -- or maybe merge
+ if feat then
+ for script, languages in next, kern do
+ local f = feat[script]
+ if f then
+ for l in next, languages do
+ f[l] = true
+ end
+ else
+ feat[script] = languages
+ end
+ end
+ else
+ feat = kern
+ end
for i=1,#steps do
- local step = steps[i]
+ local step = steps[i]
local coverage = step.coverage
- if coverage then
- local kerns = coverage[32]
+ local rules = step.rules
+ local format = step.format
+ if rules then
+ -- not now: analyze (simple) rules
+ elseif coverage then
+ -- what to do if we have no [1] but only [2]
+ local single = format == gpos_single
+ local kerns = coverage[32]
if kerns then
for k, v in next, kerns do
- if type(v) == "table" then
- right[k] = v[3] -- needs checking
- else
+ if type(v) ~= "table" then
right[k] = v
+ elseif single then
+ right[k] = v[3]
+ else
+ local one = v[1]
+ if one then
+ right[k] = one[3]
+ end
end
end
end
for k, v in next, coverage do
local kern = v[32]
if kern then
- if type(kern) == "table" then
- left[k] = kern[3] -- needs checking
- else
+ if type(kern) ~= "table" then
left[k] = kern
+ elseif single then
+ left[k] = v[3]
+ else
+ local one = v[1]
+ if one then
+ left[k] = one[3]
+ end
end
end
end
@@ -3725,3 +3908,17 @@ registerotffeature {
node = spaceinitializer,
},
}
+
+local function markinitializer(tfmdata,value)
+ local properties = tfmdata.properties
+ properties.checkmarks = value
+end
+
+registerotffeature {
+ name = "checkmarks",
+ description = "check mark widths",
+ default = true,
+ initializers = {
+ node = markinitializer,
+ },
+}
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oup.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oup.lua
index 571c69f13ba..cfa90c7944a 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oup.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oup.lua
@@ -29,7 +29,12 @@ local f_index = formatters["I%05X"]
local f_character_y = formatters["%C"]
local f_character_n = formatters["[ %C ]"]
-local doduplicates = true -- can become an option (pseudo feature)
+local check_duplicates = true -- can become an option (pseudo feature) / aways needed anyway
+local check_soft_hyphen = false -- can become an option (pseudo feature) / needed for tagging
+
+directives.register("otf.checksofthyphen",function(v)
+ check_soft_hyphen = v
+end)
local function replaced(list,index,replacement)
if type(list) == "number" then
@@ -106,7 +111,7 @@ local function unifyresources(fontdata,indices)
--
local done = { } -- we need to deal with shared !
--
- local duplicates = doduplicates and resources.duplicates
+ local duplicates = check_duplicates and resources.duplicates
if duplicates and not next(duplicates) then
duplicates = false
end
@@ -359,12 +364,34 @@ local function unifyresources(fontdata,indices)
end
local function copyduplicates(fontdata)
- if doduplicates then
+ if check_duplicates then
local descriptions = fontdata.descriptions
local resources = fontdata.resources
local duplicates = resources.duplicates
+ if check_soft_hyphen then
+ -- ebgaramond has a zero width empty soft hyphen
+ local ds = descriptions[0xAD]
+ if not ds or ds.width == 0 then
+ if ds then
+ descriptions[0xAD] = nil
+ report("patching soft hyphen")
+ else
+ report("adding soft hyphen")
+ end
+ if not duplicates then
+ duplicates = { }
+ resources.duplicates = duplicates
+ end
+ local dh = duplicates[0x2D]
+ if dh then
+ dh[#dh+1] = { [0xAD] = true }
+ else
+ duplicates[0x2D] = { [0xAD] = true }
+ end
+ end
+ end
if duplicates then
- for u, d in next, duplicates do
+ for u, d in next, duplicates do
local du = descriptions[u]
if du then
local t = { f_character_y(u), "@", f_index(du.index), "->" }
@@ -848,6 +875,8 @@ function readers.getcomponents(fontdata) -- handy for resolving ligatures when n
end
end
+readers.unifymissing = unifymissing
+
function readers.rehash(fontdata,hashmethod) -- TODO: combine loops in one
if not (fontdata and fontdata.glyphs) then
return
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-tfm.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-tfm.lua
index ab6d795bbae..6584190ce38 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-tfm.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-tfm.lua
@@ -6,8 +6,9 @@ if not modules then modules = { } end modules ['font-tfm'] = {
license = "see context related readme files"
}
-local next = next
-local match = string.match
+local next, type = next, type
+local match, format = string.match, string.format
+local concat, sortedhash = table.concat, table.sortedhash
local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
local trace_features = false trackers.register("tfm.features", function(v) trace_features = v end)
@@ -16,6 +17,7 @@ local report_defining = logs.reporter("fonts","defining")
local report_tfm = logs.reporter("fonts","tfm loading")
local findbinfile = resolvers.findbinfile
+local setmetatableindex = table.setmetatableindex
local fonts = fonts
local handlers = fonts.handlers
@@ -28,8 +30,14 @@ tfm.version = 1.000
tfm.maxnestingdepth = 5
tfm.maxnestingsize = 65536*1024
+local otf = fonts.handlers.otf
+local otfenhancers = otf.enhancers
+
local tfmfeatures = constructors.features.tfm
------ registertfmfeature = tfmfeatures.register
+local registertfmfeature = tfmfeatures.register
+
+local tfmenhancers = constructors.enhancers.tfm
+local registertfmenhancer = tfmenhancers.register
constructors.resolvevirtualtoo = false -- wil be set in font-ctx.lua
@@ -71,6 +79,42 @@ end
local depth = { } -- table.setmetatableindex("number")
+-- Normally we just load the tfm data and go on. However there was some demand for
+-- loading good old tfm /pfb files where afm files were lacking and even enc files
+-- of dubious quality so we now support loading such (often messy) setups too.
+--
+-- Because such fonts also use (ugly) tweaks achieve some purpose (like swapping
+-- accents) we need to delay the unicoding actions till after the features have been
+-- applied.
+--
+-- It must be noted that in ConTeXt we don't expect this to be used at all. Here is
+-- example:
+--
+-- tfm metrics + pfb vector for index + pfb file for shapes
+--
+-- \font\foo=file:csr10.tfm:reencode=auto;mode=node;liga=yes;kern=yes
+--
+-- tfm metrics + pfb vector for index + enc file for tfm mapping + pfb file for shapes
+--
+-- \font\foo=file:csr10.tfm:reencode=csr.enc;mode=node;liga=yes;kern=yes
+--
+-- tfm metrics + enc file for mapping to tfm + bitmaps shapes
+--
+-- \font\foo=file:csr10.tfm:reencode=csr.enc;bitmap=yes;mode=node;liga=yes;kern=yes
+--
+-- One can add features:
+--
+-- fonts.handlers.otf.addfeature {
+-- name = "czechdqcheat",
+-- type = "substitution",
+-- data = {
+-- quotedblright = "csquotedblright",
+-- },
+-- }
+--
+-- So "czechdqcheat=yes" is then a valid feature. And yes, it's a cheat.
+
+
local function read_from_tfm(specification)
local filename = specification.filename
local size = specification.size
@@ -80,26 +124,116 @@ local function read_from_tfm(specification)
end
local tfmdata = font.read_tfm(filename,size) -- not cached, fast enough
if tfmdata then
- local features = specification.features and specification.features.normal or { }
+
+ local features = specification.features and specification.features.normal or { }
+ local features = constructors.checkedfeatures("tfm",features)
+ specification.features.normal = features
+
+ -- If reencode returns a new table, we assume that we're doing something
+ -- special. An 'auto' reencode pickt up its vector from the pfb file.
+
+ local newtfmdata = (depth[filename] == 1) and tfm.reencode(tfmdata,specification)
+ if newtfmdata then
+ tfmdata = newtfmdata
+ end
+
local resources = tfmdata.resources or { }
local properties = tfmdata.properties or { }
local parameters = tfmdata.parameters or { }
local shared = tfmdata.shared or { }
- properties.name = tfmdata.name
- properties.fontname = tfmdata.fontname
- properties.psname = tfmdata.psname
- properties.filename = specification.filename
- properties.format = fonts.formats.tfm -- better than nothing
- parameters.size = size
+ --
+ shared.features = features
+ shared.resources = resources
+ --
+ properties.name = tfmdata.name -- todo: fallback
+ properties.fontname = tfmdata.fontname -- todo: fallback
+ properties.psname = tfmdata.psname -- todo: fallback
+ properties.fullname = tfmdata.fullname -- todo: fallback
+ properties.filename = specification.filename -- todo: fallback
+ properties.format = fonts.formats.tfm -- better than nothing
--
tfmdata.properties = properties
tfmdata.resources = resources
tfmdata.parameters = parameters
tfmdata.shared = shared
--
- shared.rawdata = { }
+ shared.rawdata = { resources = resources }
shared.features = features
+ --
+ -- The next branch is only entered when we have a proper encoded file i.e.
+ -- unicodes and such. It really nakes no sense to do feature juggling when
+ -- we have no names and unicodes.
+ --
+ if newtfmdata then
+ --
+ -- Some opentype processing assumes these to be present:
+ --
+ if not resources.marks then
+ resources.marks = { }
+ end
+ if not resources.sequences then
+ resources.sequences = { }
+ end
+ if not resources.features then
+ resources.features = {
+ gsub = { },
+ gpos = { },
+ }
+ end
+ if not tfmdata.changed then
+ tfmdata.changed = { }
+ end
+ if not tfmdata.descriptions then
+ tfmdata.descriptions = tfmdata.characters
+ end
+ --
+ -- It might be handy to have this:
+ --
+ otf.readers.addunicodetable(tfmdata)
+ --
+ -- We make a pseudo opentype font, e.g. kerns and ligatures etc:
+ --
+ tfmenhancers.apply(tfmdata,filename)
+ --
+ -- Now user stuff can kick in.
+ --
+ constructors.applymanipulators("tfm",tfmdata,features,trace_features,report_tfm)
+ --
+ -- As that can also mess with names and such, we are now ready for finalizing
+ -- the unicode information. This is a different order that for instance type one
+ -- (afm) files. First we try to deduce unicodes from already present information.
+ --
+ otf.readers.unifymissing(tfmdata)
+ --
+ -- Next we fill in the gaps, based on names from teh agl. Probably not much will
+ -- happen here.
+ --
+ fonts.mappings.addtounicode(tfmdata,filename)
+ --
+ -- The tounicode data is passed to the backend that constructs the vectors for us.
+ --
+ tfmdata.tounicode = 1
+ local tounicode = fonts.mappings.tounicode
+ for unicode, v in next, tfmdata.characters do
+ local u = v.unicode
+ if u then
+ v.tounicode = tounicode(u)
+ end
+ end
+ --
+ -- However, when we use a bitmap font those vectors can't be constructed because
+ -- that information is not carried with those fonts (there is no name info, nor
+ -- proper index info, nor unicodes at that end). So, we provide it ourselves.
+ --
+ if tfmdata.usedbitmap then
+ tfm.addtounicode(tfmdata)
+ end
+ end
+ --
shared.processes = next(features) and tfm.setfeatures(tfmdata,features) or nil
+ --
+ parameters.factor = 1 -- already scaled
+ parameters.size = size
parameters.slant = parameters.slant or parameters[1] or 0
parameters.space = parameters.space or parameters[2] or 0
parameters.space_stretch = parameters.space_stretch or parameters[3] or 0
@@ -110,7 +244,12 @@ local function read_from_tfm(specification)
--
constructors.enhanceparameters(parameters) -- official copies for us
--
- if constructors.resolvevirtualtoo then
+ if newtfmdata then
+ --
+ -- We do nothing as we assume flat tfm files. It would become real messy
+ -- otherwise and I don't have something for testing on my system anyway.
+ --
+ elseif constructors.resolvevirtualtoo then
fonts.loggers.register(tfmdata,file.suffix(filename),specification) -- strange, why here
local vfname = findbinfile(specification.name, 'ovf')
if vfname and vfname ~= "" then
@@ -145,21 +284,26 @@ local function read_from_tfm(specification)
end
end
--
- local allfeatures = tfmdata.shared.features or specification.features.normal
- constructors.applymanipulators("tfm",tfmdata,allfeatures.normal,trace_features,report_tfm)
- if not features.encoding then
- local encoding, filename = match(properties.filename,"^(.-)%-(.*)$") -- context: encoding-name.*
- if filename and encoding and encodings.known and encodings.known[encoding] then
- features.encoding = encoding
- end
- end
- -- let's play safe:
+ -- This is for old times sake (and context specific) so we comment it. It has
+ -- to do with encoding prefixes (a context naming that was later adopted by
+ -- the lm/gyre project)
+ --
+ -- if not features.encoding then
+ -- local encoding, filename = match(properties.filename,"^(.-)%-(.*)$")
+ -- if filename and encoding and encodings.known and encodings.known[encoding] then
+ -- features.encoding = encoding
+ -- end
+ -- end
+ --
+ -- Some afterthoughts:
+ --
properties.haskerns = true
properties.hasligatures = true
resources.unicodes = { }
resources.lookuptags = { }
--
depth[filename] = depth[filename] - 1
+ --
return tfmdata
else
depth[filename] = depth[filename] - 1
@@ -199,3 +343,369 @@ function readers.tfm(specification)
end
readers.ofm = readers.tfm
+
+-- The reencoding acts upon the 'reencode' feature which can have values 'auto' or
+-- an enc file. You can also specify a 'pfbfile' feature (but it defaults to the
+-- tfm filename) and a 'bitmap' feature. When no enc file is givven (auto) we will
+-- get the vectors from the pfb file.
+
+do
+
+ local outfiles = { }
+
+ local tfmcache = table.setmetatableindex(function(t,tfmdata)
+ local id = font.define(tfmdata)
+ t[tfmdata] = id
+ return id
+ end)
+
+ local encdone = table.setmetatableindex("table")
+
+ function tfm.reencode(tfmdata,specification)
+
+ local features = specification.features
+
+ if not features then
+ return
+ end
+
+ local features = features.normal
+
+ if not features then
+ return
+ end
+
+ local tfmfile = file.basename(tfmdata.name)
+ local encfile = features.reencode -- or features.enc
+ local pfbfile = features.pfbfile -- or features.pfb
+ local bitmap = features.bitmap -- or features.pk
+
+ if not encfile then
+ return
+ end
+
+ local pfbfile = outfiles[tfmfile]
+
+ if pfbfile == nil then
+ if bitmap then
+ pfbfile = false
+ elseif type(pfbfile) ~= "string" then
+ pfbfile = tfmfile
+ end
+ if type(pfbfile) == "string" then
+ pfbfile = file.addsuffix(pfbfile,"pfb")
+ -- pdf.mapline(tfmfile .. "<" .. pfbfile)
+ report_tfm("using type1 shapes from %a for %a",pfbfile,tfmfile)
+ else
+ report_tfm("using bitmap shapes for %a",tfmfile)
+ pfbfile = false -- use bitmap
+ end
+ outfiles[tfmfile] = pfbfile
+ end
+
+ local encoding = false
+ local vector = false
+
+ if type(pfbfile) == "string" then
+ local pfb = fonts.constructors.handlers.pfb
+ if pfb and pfb.loadvector then
+ local v, e = pfb.loadvector(pfbfile)
+ if v then
+ vector = v
+ end
+ if e then
+ encoding = e
+ end
+ end
+ end
+ if type(encfile) == "string" and encfile ~= "auto" then
+ encoding = fonts.encodings.load(file.addsuffix(encfile,"enc"))
+ if encoding then
+ encoding = encoding.vector
+ end
+ end
+ if not encoding then
+ report_tfm("bad encoding for %a, quitting",tfmfile)
+ return
+ end
+
+ local unicoding = fonts.encodings.agl and fonts.encodings.agl.unicodes
+ local virtualid = tfmcache[tfmdata]
+ local tfmdata = table.copy(tfmdata) -- good enough for small fonts
+ local characters = { }
+ local originals = tfmdata.characters
+ local indices = { }
+ local parentfont = { "font", 1 }
+ local private = fonts.constructors.privateoffset
+ local reported = encdone[tfmfile][encfile]
+
+ -- create characters table
+
+ local backmap = vector and table.swapped(vector)
+ local done = { } -- prevent duplicate
+
+ for index, name in sortedhash(encoding) do -- predictable order
+ local unicode = unicoding[name]
+ local original = originals[index]
+ if original then
+ if unicode then
+ original.unicode = unicode
+ else
+ unicode = private
+ private = private + 1
+ if not reported then
+ report_tfm("glyph %a in font %a with encoding %a gets unicode %U",name,tfmfile,encfile,unicode)
+ end
+ end
+ characters[unicode] = original
+ indices[index] = unicode
+ original.name = name -- so one can lookup weird names
+ if backmap then
+ original.index = backmap[name]
+ else -- probably bitmap
+ original.commands = { parentfont, { "char", index } }
+ original.oindex = index
+ end
+ done[name] = true
+ elseif not done[name] then
+ report_tfm("bad index %a in font %a with name %a",index,tfmfile,name)
+ end
+ end
+
+ encdone[tfmfile][encfile] = true
+
+ -- redo kerns and ligatures
+
+ for k, v in next, characters do
+ local kerns = v.kerns
+ if kerns then
+ local t = { }
+ for k, v in next, kerns do
+ local i = indices[k]
+ if i then
+ t[i] = v
+ end
+ end
+ v.kerns = next(t) and t or nil
+ end
+ local ligatures = v.ligatures
+ if ligatures then
+ local t = { }
+ for k, v in next, ligatures do
+ local i = indices[k]
+ if i then
+ t[i] = v
+ v.char = indices[v.char]
+ end
+ end
+ v.ligatures = next(t) and t or nil
+ end
+ end
+
+ -- wrap up
+
+ tfmdata.fonts = { { id = virtualid } }
+ tfmdata.characters = characters
+ tfmdata.fullname = tfmdata.fullname or tfmdata.name
+ tfmdata.psname = file.nameonly(pfbfile or tfmdata.name)
+ tfmdata.filename = pfbfile
+ tfmdata.encodingbytes = 2
+ tfmdata.format = "type1"
+ tfmdata.tounicode = 1
+ tfmdata.embedding = "subset"
+ tfmdata.usedbitmap = bitmap and virtualid
+
+ return tfmdata
+ end
+
+end
+
+-- This code adds a ToUnicode vector for bitmap fonts. We don't bother about
+-- ranges because we have small fonts. it works ok with acrobat but fails with
+-- the other viewers (they get confused by the bitmaps I guess).
+
+do
+
+ local template = [[
+/CIDInit /ProcSet findresource begin
+ 12 dict begin
+ begincmap
+ /CIDSystemInfo << /Registry (TeX) /Ordering (bitmap-%s) /Supplement 0 >> def
+ /CMapName /TeX-bitmap-%s def
+ /CMapType 2 def
+ 1 begincodespacerange
+ <00> <FF>
+ endcodespacerange
+ %s beginbfchar
+%s
+ endbfchar
+ endcmap
+CMapName currentdict /CMap defineresource pop end
+end
+end
+]]
+
+ local flushstreamobject = lpdf and lpdf.flushstreamobject
+ local setfontattributes = pdf.setfontattributes
+
+ if not flushstreamobject then
+ flushstreamobject = function(data)
+ return pdf.obj {
+ immediate = true,
+ type = "stream",
+ string = data,
+ }
+ end
+ end
+
+ if not setfontattributes then
+ setfontattributes = function(id,data)
+ print(format("your luatex is too old so no tounicode bitmap font%i",id))
+ end
+ end
+
+ function tfm.addtounicode(tfmdata)
+ local id = tfmdata.usedbitmap
+ local map = { }
+ local char = { } -- no need for range, hardly used
+ for k, v in next, tfmdata.characters do
+ local index = v.oindex
+ local tounicode = v.tounicode
+ if index and tounicode then
+ map[index] = tounicode
+ end
+ end
+ for k, v in sortedhash(map) do
+ char[#char+1] = format("<%02X> <%s>",k,v)
+ end
+ char = concat(char,"\n")
+ local stream = format(template,id,id,#char,char)
+ local reference = flushstreamobject(stream,nil,true)
+ setfontattributes(id,format("/ToUnicode %i 0 R",reference))
+ end
+
+end
+
+-- Now we implement the regular features handlers. We need to convert the
+-- tfm specific structures to opentype structures. In basemode they are
+-- converted back so that is a bti of a waste but it's fast enough.
+
+do
+
+ local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } }
+ local noflags = { false, false, false, false }
+
+ local function enhance_normalize_features(data)
+ local ligatures = setmetatableindex("table")
+ local kerns = setmetatableindex("table")
+ local characters = data.characters
+ for u, c in next, characters do
+ local l = c.ligatures
+ local k = c.kerns
+ if l then
+ ligatures[u] = l
+ for u, v in next, l do
+ l[u] = { ligature = v.char }
+ end
+ c.ligatures = nil
+ end
+ if k then
+ kerns[u] = k
+ for u, v in next, k do
+ k[u] = v -- { v, 0 }
+ end
+ c.kerns = nil
+ end
+ end
+
+ for u, l in next, ligatures do
+ for k, v in next, l do
+ local vl = v.ligature
+ local dl = ligatures[vl]
+ if dl then
+ for kk, vv in next, dl do
+ v[kk] = vv -- table.copy(vv)
+ end
+ end
+ end
+ end
+
+ local features = {
+ gpos = { },
+ gsub = { },
+ }
+ local sequences = {
+ -- only filled ones
+ }
+ if next(ligatures) then
+ features.gsub.liga = everywhere
+ data.properties.hasligatures = true
+ sequences[#sequences+1] = {
+ features = {
+ liga = everywhere,
+ },
+ flags = noflags,
+ name = "s_s_0",
+ nofsteps = 1,
+ order = { "liga" },
+ type = "gsub_ligature",
+ steps = {
+ {
+ coverage = ligatures,
+ },
+ },
+ }
+ end
+ if next(kerns) then
+ features.gpos.kern = everywhere
+ data.properties.haskerns = true
+ sequences[#sequences+1] = {
+ features = {
+ kern = everywhere,
+ },
+ flags = noflags,
+ name = "p_s_0",
+ nofsteps = 1,
+ order = { "kern" },
+ type = "gpos_pair",
+ steps = {
+ {
+ format = "kern",
+ coverage = kerns,
+ },
+ },
+ }
+ end
+ data.resources.features = features
+ data.resources.sequences = sequences
+ data.shared.resources = data.shared.resources or resources
+ end
+
+ registertfmenhancer("normalize features", enhance_normalize_features)
+ registertfmenhancer("check extra features", otfenhancers.enhance)
+
+end
+
+-- As with type one (afm) loading, we just use the opentype ones:
+
+registertfmfeature {
+ name = "mode",
+ description = "mode",
+ initializers = {
+ base = otf.modeinitializer,
+ node = otf.modeinitializer,
+ }
+}
+
+registertfmfeature {
+ name = "features",
+ description = "features",
+ default = true,
+ initializers = {
+ base = otf.basemodeinitializer,
+ node = otf.nodemodeinitializer,
+ },
+ processors = {
+ node = otf.featuresprocessor,
+ }
+}
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-demo-vf-1.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-demo-vf-1.lua
index 13acd16ca90..793526f7be3 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-demo-vf-1.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-demo-vf-1.lua
@@ -1,3 +1,11 @@
+if not modules then modules = { } end modules ['luatex-fonts-demo-vf-1'] = {
+ version = 1.001,
+ comment = "companion to luatex-*.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
local identifiers = fonts.hashes.identifiers
return function(specification)
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-enc.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-enc.lua
index 2e1c6a46674..c076d59477d 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-enc.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-enc.lua
@@ -11,19 +11,66 @@ if context then
os.exit()
end
-local fonts = fonts
-fonts.encodings = { }
-fonts.encodings.agl = { }
-fonts.encodings.known = { }
+local fonts = fonts
+local encodings = { }
+fonts.encodings = encodings
+encodings.agl = { }
+encodings.known = { }
-setmetatable(fonts.encodings.agl, { __index = function(t,k)
+setmetatable(encodings.agl, { __index = function(t,k)
if k == "unicodes" then
texio.write(" <loading (extended) adobe glyph list>")
local unicodes = dofile(resolvers.findfile("font-age.lua"))
- fonts.encodings.agl = { unicodes = unicodes }
+ encodings.agl = { unicodes = unicodes }
return unicodes
else
return nil
end
end })
+-- adapted for generic
+
+encodings.cache = containers.define("fonts", "enc", encodings.version, true)
+
+function encodings.load(filename)
+ local name = file.removesuffix(filename)
+ local data = containers.read(encodings.cache,name)
+ if data then
+ return data
+ end
+ local vector, tag, hash, unicodes = { }, "", { }, { }
+ local foundname = resolvers.findfile(filename,'enc')
+ if foundname and foundname ~= "" then
+ local ok, encoding, size = resolvers.loadbinfile(foundname)
+ if ok and encoding then
+ encoding = string.gsub(encoding,"%%(.-)\n","")
+ local unicoding = encodings.agl.unicodes
+ local tag, vec = string.match(encoding,"/(%w+)%s*%[(.*)%]%s*def")
+ local i = 0
+ for ch in string.gmatch(vec,"/([%a%d%.]+)") do
+ if ch ~= ".notdef" then
+ vector[i] = ch
+ if not hash[ch] then
+ hash[ch] = i
+ else
+ -- duplicate, play safe for tex ligs and take first
+ end
+ local u = unicoding[ch]
+ if u then
+ unicodes[u] = i
+ end
+ end
+ i = i + 1
+ end
+ end
+ end
+ local data = {
+ name = name,
+ tag = tag,
+ vector = vector,
+ hash = hash,
+ unicodes = unicodes
+ }
+ return containers.write(encodings.cache, name, data)
+end
+
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-ext.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-ext.lua
index 9d8d3070b9c..0b61e27fd67 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-ext.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-ext.lua
@@ -270,3 +270,18 @@ otffeatures.register {
node = reencode,
}
}
+
+local function ignore(tfmdata,key,value)
+ if value then
+ tfmdata.mathparameters = nil
+ end
+end
+
+otffeatures.register {
+ name = "ignoremathconstants",
+ description = "ignore math constants table",
+ initializers = {
+ base = ignore,
+ node = ignore,
+ }
+}
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts.lua
index 83d52d9a560..c21389c71de 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts.lua
@@ -230,7 +230,6 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then
loadmodule('luatex-fonts-syn.lua')
- loadmodule('font-tfm.lua')
loadmodule('font-oti.lua')
-- These are the old loader and processing modules. These use the built-in font loader and
@@ -260,12 +259,18 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then
loadmodule('font-osd.lua')
loadmodule('font-ocl.lua') -- svg needs 0.97 (for fix in memstreams)
+ loadmodule('font-otc.lua')
+
-- type one code
loadmodule('font-onr.lua') -- was font-afm.lua
loadmodule('font-one.lua') -- was font-afm.lua
loadmodule('font-afk.lua')
+ -- traditional code
+
+ loadmodule('font-tfm.lua')
+
-- common code
loadmodule('font-lua.lua')
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-file.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-file.lua
index b6822e95479..f2a27ad1832 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-file.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-file.lua
@@ -607,14 +607,17 @@ function file.robustname(str,strict)
end
end
-file.readdata = io.loaddata
-file.savedata = io.savedata
+local loaddata = io.loaddata
+local savedata = io.savedata
+
+file.readdata = loaddata
+file.savedata = savedata
function file.copy(oldname,newname)
if oldname and newname then
- local data = io.loaddata(oldname)
+ local data = loaddata(oldname)
if data and data ~= "" then
- file.savedata(newname,data)
+ savedata(newname,data)
end
end
end
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-io.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-io.lua
index a91d44d8776..2039017b25d 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-io.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-io.lua
@@ -7,6 +7,7 @@ if not modules then modules = { } end modules ['l-io'] = {
}
local io = io
+local open, flush, write, read = io.open, io.flush, io.write, io.read
local byte, find, gsub, format = string.byte, string.find, string.gsub, string.format
local concat = table.concat
local floor = math.floor
@@ -30,15 +31,13 @@ local function readall(f)
local size = f:seek("end")
if size == 0 then
return ""
- elseif size < 1024*1024 then
- f:seek("set",0)
+ end
+ f:seek("set",0)
+ if size < 1024*1024 then
return f:read('*all')
else
- local done = f:seek("set",0)
local step
- if size < 1024*1024 then
- step = 1024 * 1024
- elseif size > 16*1024*1024 then
+ if size > 16*1024*1024 then
step = 16*1024*1024
else
step = floor(size/(1024*1024)) * 1024 * 1024 / 8
@@ -58,9 +57,8 @@ end
io.readall = readall
function io.loaddata(filename,textmode) -- return nil if empty
- local f = io.open(filename,(textmode and 'r') or 'rb')
+ local f = open(filename,(textmode and 'r') or 'rb')
if f then
- -- local data = f:read('*all')
local data = readall(f)
f:close()
if #data > 0 then
@@ -69,8 +67,55 @@ function io.loaddata(filename,textmode) -- return nil if empty
end
end
+function io.copydata(source,target,action)
+ local f = open(source,"rb")
+ if f then
+ local g = open(target,"wb")
+ if g then
+ local size = f:seek("end")
+ if size == 0 then
+ -- empty
+ else
+ f:seek("set",0)
+ if size < 1024*1024 then
+ local data = f:read('*all')
+ if action then
+ data = action(data)
+ end
+ if data then
+ g:write(data)
+ end
+ else
+ local step
+ if size > 16*1024*1024 then
+ step = 16*1024*1024
+ else
+ step = floor(size/(1024*1024)) * 1024 * 1024 / 8
+ end
+ while true do
+ local data = f:read(step)
+ if data then
+ if action then
+ data = action(data)
+ end
+ if data then
+ g:write(data)
+ end
+ else
+ break
+ end
+ end
+ end
+ end
+ g:close()
+ end
+ f:close()
+ flush()
+ end
+end
+
function io.savedata(filename,data,joiner)
- local f = io.open(filename,"wb")
+ local f = open(filename,"wb")
if f then
if type(data) == "table" then
f:write(concat(data,joiner or ""))
@@ -80,7 +125,7 @@ function io.savedata(filename,data,joiner)
f:write(data or "")
end
f:close()
- io.flush()
+ flush()
return true
else
return false
@@ -90,7 +135,7 @@ end
-- we can also chunk this one if needed: io.lines(filename,chunksize,"*l")
function io.loadlines(filename,n) -- return nil if empty
- local f = io.open(filename,'r')
+ local f = open(filename,'r')
if not f then
-- no file
elseif n then
@@ -118,7 +163,7 @@ function io.loadlines(filename,n) -- return nil if empty
end
function io.loadchunk(filename,n)
- local f = io.open(filename,'rb')
+ local f = open(filename,'rb')
if f then
local data = f:read(n or 1024)
f:close()
@@ -129,7 +174,7 @@ function io.loadchunk(filename,n)
end
function io.exists(filename)
- local f = io.open(filename)
+ local f = open(filename)
if f == nil then
return false
else
@@ -139,7 +184,7 @@ function io.exists(filename)
end
function io.size(filename)
- local f = io.open(filename)
+ local f = open(filename)
if f == nil then
return 0
else
@@ -149,11 +194,11 @@ function io.size(filename)
end
end
-function io.noflines(f)
+local function noflines(f)
if type(f) == "string" then
- local f = io.open(filename)
+ local f = open(filename)
if f then
- local n = f and io.noflines(f) or 0
+ local n = f and noflines(f) or 0
f:close()
return n
else
@@ -169,6 +214,10 @@ function io.noflines(f)
end
end
+io.noflines = noflines
+
+-- inlined is faster
+
local nextchar = {
[ 4] = function(f)
return f:read(1,1,1,1)
@@ -250,16 +299,16 @@ end
function io.ask(question,default,options)
while true do
- io.write(question)
+ write(question)
if options then
- io.write(format(" [%s]",concat(options,"|")))
+ write(format(" [%s]",concat(options,"|")))
end
if default then
- io.write(format(" [%s]",default))
+ write(format(" [%s]",default))
end
- io.write(format(" "))
- io.flush()
- local answer = io.read()
+ write(format(" "))
+ flush()
+ local answer = read()
answer = gsub(answer,"^%s*(.*)%s*$","%1")
if answer == "" and default then
return default
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-lua.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-lua.lua
index b90f37e3db3..35715383635 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-lua.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-lua.lua
@@ -198,3 +198,4 @@ if flush then
local popen = io.popen if popen then function io.popen (...) flush() return popen (...) end end
end
+
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-string.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-string.lua
index e9dc2bbbcff..be8f397aee3 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-string.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-string.lua
@@ -75,19 +75,19 @@ local collapser = patterns.collapser
local longtostring = patterns.longtostring
function string.strip(str)
- return lpegmatch(stripper,str) or ""
+ return str and lpegmatch(stripper,str) or ""
end
function string.fullstrip(str)
- return lpegmatch(fullstripper,str) or ""
+ return str and lpegmatch(fullstripper,str) or ""
end
function string.collapsespaces(str)
- return lpegmatch(collapser,str) or ""
+ return str and lpegmatch(collapser,str) or ""
end
function string.longtostring(str)
- return lpegmatch(longtostring,str) or ""
+ return str and lpegmatch(longtostring,str) or ""
end
-- function string.is_empty(str)
@@ -99,7 +99,7 @@ local pattern = P(" ")^0 * P(-1) -- maybe also newlines
-- patterns.onlyspaces = pattern
function string.is_empty(str)
- if str == "" then
+ if not str or str == "" then
return true
else
return lpegmatch(pattern,str) and true or false
@@ -163,7 +163,7 @@ function string.escapedpattern(str,simple)
end
function string.topattern(str,lowercase,strict)
- if str=="" or type(str) ~= "string" then
+ if str == "" or type(str) ~= "string" then
return ".*"
elseif strict then
str = lpegmatch(pattern_c,str)
@@ -177,6 +177,7 @@ function string.topattern(str,lowercase,strict)
end
end
+-- print(string.escapedpattern("abc*234",true))
-- print(string.escapedpattern("12+34*.tex",false))
-- print(string.escapedpattern("12+34*.tex",true))
-- print(string.topattern ("12+34*.tex",false,false))
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-table.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-table.lua
index 552097e1c10..39357bd25e6 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-table.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-table.lua
@@ -478,7 +478,7 @@ function table.fromhash(t)
return hsh
end
-local noquotes, hexify, handle, compact, inline, functions
+local noquotes, hexify, handle, compact, inline, functions, metacheck
local reserved = table.tohash { -- intercept a language inconvenience: no reserved words as key
'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', 'function', 'if',
@@ -608,7 +608,8 @@ local function do_serialize(root,name,depth,level,indexed)
if compact then
last = #root
for k=1,last do
- if root[k] == nil then
+ -- if root[k] == nil then
+ if rawget(root,k) == nil then
last = k - 1
break
end
@@ -673,6 +674,8 @@ local function do_serialize(root,name,depth,level,indexed)
else
handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) -- %.99g
end
+ elseif tk ~= "string" then
+ -- ignore
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
if hexify then
handle(format("%s %s=0x%X,",depth,k,v))
@@ -695,6 +698,8 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]=%q,",depth,k and "true" or "false",v))
+ elseif tk ~= "string" then
+ -- ignore
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%q,",depth,k,v))
else
@@ -710,6 +715,8 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]={},",depth,k and "true" or "false"))
+ elseif tk ~= "string" then
+ -- ignore
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s={},",depth,k))
else
@@ -726,6 +733,8 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]={ %s },",depth,k and "true" or "false",concat(st,", ")))
+ elseif tk ~= "string" then
+ -- ignore
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
else
@@ -746,6 +755,8 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]=%s,",depth,tostring(k),v and "true" or "false"))
+ elseif tk ~= "string" then
+ -- ignore
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%s,",depth,k,v and "true" or "false"))
else
@@ -763,6 +774,8 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f))
+ elseif tk ~= "string" then
+ -- ignore
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=load(%q),",depth,k,f))
else
@@ -778,6 +791,8 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk == "boolean" then
handle(format("%s [%s]=%q,",depth,k and "true" or "false",tostring(v)))
+ elseif tk ~= "string" then
+ -- ignore
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%q,",depth,k,tostring(v)))
else
@@ -803,6 +818,7 @@ local function serialize(_handle,root,name,specification) -- handle wins
functions = specification.functions
compact = specification.compact
inline = specification.inline and compact
+ metacheck = specification.metacheck
if functions == nil then
functions = true
end
@@ -812,6 +828,9 @@ local function serialize(_handle,root,name,specification) -- handle wins
if inline == nil then
inline = compact
end
+ if metacheck == nil then
+ metacheck = true
+ end
else
noquotes = false
hexify = false
@@ -819,6 +838,7 @@ local function serialize(_handle,root,name,specification) -- handle wins
compact = true
inline = true
functions = true
+ metacheck = true
end
if tname == "string" then
if name == "return" then
@@ -843,8 +863,9 @@ local function serialize(_handle,root,name,specification) -- handle wins
end
if root then
-- The dummy access will initialize a table that has a delayed initialization
- -- using a metatable. (maybe explicitly test for metatable)
- if getmetatable(root) then -- todo: make this an option, maybe even per subtable
+ -- using a metatable. (maybe explicitly test for metatable). This can crash on
+ -- metatables that check the index against a number.
+ if metacheck and getmetatable(root) then
local dummy = root._w_h_a_t_e_v_e_r_
root._w_h_a_t_e_v_e_r_ = nil
end
@@ -950,6 +971,41 @@ end
table.flattened = flattened
+local function collapsed(t,f,h)
+ if f == nil then
+ f = { }
+ h = { }
+ end
+ for k=1,#t do
+ local v = t[k]
+ if type(v) == "table" then
+ collapsed(v,f,h)
+ elseif not h[v] then
+ f[#f+1] = v
+ h[v] = true
+ end
+ end
+ return f
+end
+
+local function collapsedhash(t,h)
+ if h == nil then
+ h = { }
+ end
+ for k=1,#t do
+ local v = t[k]
+ if type(v) == "table" then
+ collapsedhash(v,h)
+ else
+ h[v] = true
+ end
+ end
+ return h
+end
+
+table.collapsed = collapsed -- 20% faster than unique(collapsed(t))
+table.collapsedhash = collapsedhash
+
local function unnest(t,f) -- only used in mk, for old times sake
if not f then -- and only relevant for token lists
f = { } -- this one can become obsolete
@@ -1056,7 +1112,7 @@ function table.count(t)
return n
end
-function table.swapped(t,s) -- hash
+function table.swapped(t,s) -- hash, we need to make sure we don't mess up next
local n = { }
if s then
for k, v in next, s do
@@ -1069,7 +1125,14 @@ function table.swapped(t,s) -- hash
return n
end
-function table.mirrored(t) -- hash
+function table.hashed(t) -- list, add hash to index (save because we are not yet mixed
+ for i=1,#t do
+ t[t[i]] = i
+ end
+ return t
+end
+
+function table.mirrored(t) -- hash, we need to make sure we don't mess up next
local n = { }
for k, v in next, t do
n[v] = k
@@ -1165,7 +1228,7 @@ function table.has_one_entry(t)
return t and next(t,next(t)) == nil
end
--- new
+-- new (rather basic, not indexed and nested)
function table.loweredkeys(t) -- maybe utf
local l = { }
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-mplib.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-mplib.lua
index fd6eb975c84..976bb59f91b 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-mplib.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-mplib.lua
@@ -352,7 +352,7 @@ else
return not (sx==1 and rx==0 and ry==0 and sy==1 and tx==0 and ty==0), t.width
end
- local function concat(px, py) -- no tx, ty here
+ local function concatinated(px, py) -- no tx, ty here
return (sy*px-ry*py)/divider,(sx*py-rx*px)/divider
end
@@ -401,29 +401,29 @@ else
for i=1,#path do
pth = path[i]
if not ith then
- pdf_literalcode("%f %f m",concat(pth.x_coord,pth.y_coord))
+ pdf_literalcode("%f %f m",concatinated(pth.x_coord,pth.y_coord))
elseif curved(ith,pth) then
- local a, b = concat(ith.right_x,ith.right_y)
- local c, d = concat(pth.left_x,pth.left_y)
- pdf_literalcode("%f %f %f %f %f %f c",a,b,c,d,concat(pth.x_coord, pth.y_coord))
+ local a, b = concatinated(ith.right_x,ith.right_y)
+ local c, d = concatinated(pth.left_x,pth.left_y)
+ pdf_literalcode("%f %f %f %f %f %f c",a,b,c,d,concatinated(pth.x_coord, pth.y_coord))
else
- pdf_literalcode("%f %f l",concat(pth.x_coord, pth.y_coord))
+ pdf_literalcode("%f %f l",concatinated(pth.x_coord, pth.y_coord))
end
ith = pth
end
if not open then
local one = path[1]
if curved(pth,one) then
- local a, b = concat(pth.right_x,pth.right_y)
- local c, d = concat(one.left_x,one.left_y)
- pdf_literalcode("%f %f %f %f %f %f c",a,b,c,d,concat(one.x_coord, one.y_coord))
+ local a, b = concatinated(pth.right_x,pth.right_y)
+ local c, d = concatinated(one.left_x,one.left_y)
+ pdf_literalcode("%f %f %f %f %f %f c",a,b,c,d,concatinated(one.x_coord, one.y_coord))
else
- pdf_literalcode("%f %f l",concat(one.x_coord,one.y_coord))
+ pdf_literalcode("%f %f l",concatinated(one.x_coord,one.y_coord))
end
elseif #path == 1 then
-- special case .. draw point
local one = path[1]
- pdf_literalcode("%f %f l",concat(one.x_coord,one.y_coord))
+ pdf_literalcode("%f %f l",concatinated(one.x_coord,one.y_coord))
end
return t
end
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-plain.tex b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-plain.tex
index 99347ed2ce5..0a806c76ff1 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-plain.tex
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-plain.tex
@@ -17,7 +17,9 @@
\input luatex-pdf \relax
\fi
-\pdfoutput 1
+\outputmode 1
+
+% \outputmode 0 \magnification\magstep5
% We set the page dimensions because otherwise the backend does weird things
% when we have for instance this on a line of its own:
@@ -31,8 +33,8 @@
% has to deal with the lack of a page concept on tex by some guessing. Normally
% a macro package will set the dimensions to something reasonable anyway.
-\pagewidth 8.5in
-\pageheight 11.0in
+\pagewidth 8.5truein
+\pageheight 11.0truein
% We load some code at runtime:
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua
index 97859888193..3a4a70c6261 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua
@@ -1,6 +1,6 @@
-- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua
-- parent file : c:/data/develop/context/sources/luatex-fonts.lua
--- merge date : 06/15/16 20:18:05
+-- merge date : 01/27/17 14:39:39
do -- begin closure to overcome local limits and interference
@@ -964,20 +964,20 @@ local fullstripper=patterns.fullstripper
local collapser=patterns.collapser
local longtostring=patterns.longtostring
function string.strip(str)
- return lpegmatch(stripper,str) or ""
+ return str and lpegmatch(stripper,str) or ""
end
function string.fullstrip(str)
- return lpegmatch(fullstripper,str) or ""
+ return str and lpegmatch(fullstripper,str) or ""
end
function string.collapsespaces(str)
- return lpegmatch(collapser,str) or ""
+ return str and lpegmatch(collapser,str) or ""
end
function string.longtostring(str)
- return lpegmatch(longtostring,str) or ""
+ return str and lpegmatch(longtostring,str) or ""
end
local pattern=P(" ")^0*P(-1)
function string.is_empty(str)
- if str=="" then
+ if not str or str=="" then
return true
else
return lpegmatch(pattern,str) and true or false
@@ -1352,7 +1352,7 @@ function table.fromhash(t)
end
return hsh
end
-local noquotes,hexify,handle,compact,inline,functions
+local noquotes,hexify,handle,compact,inline,functions,metacheck
local reserved=table.tohash {
'and','break','do','else','elseif','end','false','for','function','if',
'in','local','nil','not','or','repeat','return','then','true','until','while',
@@ -1422,7 +1422,7 @@ local function do_serialize(root,name,depth,level,indexed)
if compact then
last=#root
for k=1,last do
- if root[k]==nil then
+ if rawget(root,k)==nil then
last=k-1
break
end
@@ -1487,6 +1487,7 @@ local function do_serialize(root,name,depth,level,indexed)
else
handle(format("%s [%s]=%s,",depth,k and "true" or "false",v))
end
+ elseif tk~="string" then
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
if hexify then
handle(format("%s %s=0x%X,",depth,k,v))
@@ -1509,6 +1510,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk=="boolean" then
handle(format("%s [%s]=%q,",depth,k and "true" or "false",v))
+ elseif tk~="string" then
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%q,",depth,k,v))
else
@@ -1524,6 +1526,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk=="boolean" then
handle(format("%s [%s]={},",depth,k and "true" or "false"))
+ elseif tk~="string" then
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s={},",depth,k))
else
@@ -1540,6 +1543,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk=="boolean" then
handle(format("%s [%s]={ %s },",depth,k and "true" or "false",concat(st,", ")))
+ elseif tk~="string" then
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
else
@@ -1560,6 +1564,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk=="boolean" then
handle(format("%s [%s]=%s,",depth,tostring(k),v and "true" or "false"))
+ elseif tk~="string" then
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%s,",depth,k,v and "true" or "false"))
else
@@ -1576,6 +1581,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk=="boolean" then
handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f))
+ elseif tk~="string" then
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=load(%q),",depth,k,f))
else
@@ -1591,6 +1597,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tk=="boolean" then
handle(format("%s [%s]=%q,",depth,k and "true" or "false",tostring(v)))
+ elseif tk~="string" then
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
handle(format("%s %s=%q,",depth,k,tostring(v)))
else
@@ -1612,6 +1619,7 @@ local function serialize(_handle,root,name,specification)
functions=specification.functions
compact=specification.compact
inline=specification.inline and compact
+ metacheck=specification.metacheck
if functions==nil then
functions=true
end
@@ -1621,6 +1629,9 @@ local function serialize(_handle,root,name,specification)
if inline==nil then
inline=compact
end
+ if metacheck==nil then
+ metacheck=true
+ end
else
noquotes=false
hexify=false
@@ -1628,6 +1639,7 @@ local function serialize(_handle,root,name,specification)
compact=true
inline=true
functions=true
+ metacheck=true
end
if tname=="string" then
if name=="return" then
@@ -1651,7 +1663,7 @@ local function serialize(_handle,root,name,specification)
handle("t={")
end
if root then
- if getmetatable(root) then
+ if metacheck and getmetatable(root) then
local dummy=root._w_h_a_t_e_v_e_r_
root._w_h_a_t_e_v_e_r_=nil
end
@@ -1727,6 +1739,38 @@ local function flattened(t,f,depth)
return f
end
table.flattened=flattened
+local function collapsed(t,f,h)
+ if f==nil then
+ f={}
+ h={}
+ end
+ for k=1,#t do
+ local v=t[k]
+ if type(v)=="table" then
+ collapsed(v,f,h)
+ elseif not h[v] then
+ f[#f+1]=v
+ h[v]=true
+ end
+ end
+ return f
+end
+local function collapsedhash(t,h)
+ if h==nil then
+ h={}
+ end
+ for k=1,#t do
+ local v=t[k]
+ if type(v)=="table" then
+ collapsedhash(v,h)
+ else
+ h[v]=true
+ end
+ end
+ return h
+end
+table.collapsed=collapsed
+table.collapsedhash=collapsedhash
local function unnest(t,f)
if not f then
f={}
@@ -1833,6 +1877,12 @@ function table.swapped(t,s)
end
return n
end
+function table.hashed(t)
+ for i=1,#t do
+ t[t[i]]=i
+ end
+ return t
+end
function table.mirrored(t)
local n={}
for k,v in next,t do
@@ -2006,6 +2056,7 @@ if not modules then modules={} end modules ['l-io']={
license="see context related readme files"
}
local io=io
+local open,flush,write,read=io.open,io.flush,io.write,io.read
local byte,find,gsub,format=string.byte,string.find,string.gsub,string.format
local concat=table.concat
local floor=math.floor
@@ -2022,15 +2073,13 @@ local function readall(f)
local size=f:seek("end")
if size==0 then
return ""
- elseif size<1024*1024 then
- f:seek("set",0)
+ end
+ f:seek("set",0)
+ if size<1024*1024 then
return f:read('*all')
else
- local done=f:seek("set",0)
local step
- if size<1024*1024 then
- step=1024*1024
- elseif size>16*1024*1024 then
+ if size>16*1024*1024 then
step=16*1024*1024
else
step=floor(size/(1024*1024))*1024*1024/8
@@ -2048,7 +2097,7 @@ local function readall(f)
end
io.readall=readall
function io.loaddata(filename,textmode)
- local f=io.open(filename,(textmode and 'r') or 'rb')
+ local f=open(filename,(textmode and 'r') or 'rb')
if f then
local data=readall(f)
f:close()
@@ -2057,8 +2106,53 @@ function io.loaddata(filename,textmode)
end
end
end
+function io.copydata(source,target,action)
+ local f=open(source,"rb")
+ if f then
+ local g=open(target,"wb")
+ if g then
+ local size=f:seek("end")
+ if size==0 then
+ else
+ f:seek("set",0)
+ if size<1024*1024 then
+ local data=f:read('*all')
+ if action then
+ data=action(data)
+ end
+ if data then
+ g:write(data)
+ end
+ else
+ local step
+ if size>16*1024*1024 then
+ step=16*1024*1024
+ else
+ step=floor(size/(1024*1024))*1024*1024/8
+ end
+ while true do
+ local data=f:read(step)
+ if data then
+ if action then
+ data=action(data)
+ end
+ if data then
+ g:write(data)
+ end
+ else
+ break
+ end
+ end
+ end
+ end
+ g:close()
+ end
+ f:close()
+ flush()
+ end
+end
function io.savedata(filename,data,joiner)
- local f=io.open(filename,"wb")
+ local f=open(filename,"wb")
if f then
if type(data)=="table" then
f:write(concat(data,joiner or ""))
@@ -2068,14 +2162,14 @@ function io.savedata(filename,data,joiner)
f:write(data or "")
end
f:close()
- io.flush()
+ flush()
return true
else
return false
end
end
function io.loadlines(filename,n)
- local f=io.open(filename,'r')
+ local f=open(filename,'r')
if not f then
elseif n then
local lines={}
@@ -2101,7 +2195,7 @@ function io.loadlines(filename,n)
end
end
function io.loadchunk(filename,n)
- local f=io.open(filename,'rb')
+ local f=open(filename,'rb')
if f then
local data=f:read(n or 1024)
f:close()
@@ -2111,7 +2205,7 @@ function io.loadchunk(filename,n)
end
end
function io.exists(filename)
- local f=io.open(filename)
+ local f=open(filename)
if f==nil then
return false
else
@@ -2120,7 +2214,7 @@ function io.exists(filename)
end
end
function io.size(filename)
- local f=io.open(filename)
+ local f=open(filename)
if f==nil then
return 0
else
@@ -2129,11 +2223,11 @@ function io.size(filename)
return s
end
end
-function io.noflines(f)
+local function noflines(f)
if type(f)=="string" then
- local f=io.open(filename)
+ local f=open(filename)
if f then
- local n=f and io.noflines(f) or 0
+ local n=f and noflines(f) or 0
f:close()
return n
else
@@ -2148,6 +2242,7 @@ function io.noflines(f)
return n
end
end
+io.noflines=noflines
local nextchar={
[ 4]=function(f)
return f:read(1,1,1,1)
@@ -2225,16 +2320,16 @@ function io.bytes(f,n)
end
function io.ask(question,default,options)
while true do
- io.write(question)
+ write(question)
if options then
- io.write(format(" [%s]",concat(options,"|")))
+ write(format(" [%s]",concat(options,"|")))
end
if default then
- io.write(format(" [%s]",default))
+ write(format(" [%s]",default))
end
- io.write(format(" "))
- io.flush()
- local answer=io.read()
+ write(format(" "))
+ flush()
+ local answer=read()
answer=gsub(answer,"^%s*(.*)%s*$","%1")
if answer=="" and default then
return default
@@ -2643,13 +2738,15 @@ function file.robustname(str,strict)
end
end
end
-file.readdata=io.loaddata
-file.savedata=io.savedata
+local loaddata=io.loaddata
+local savedata=io.savedata
+file.readdata=loaddata
+file.savedata=savedata
function file.copy(oldname,newname)
if oldname and newname then
- local data=io.loaddata(oldname)
+ local data=loaddata(oldname)
if data and data~="" then
- file.savedata(newname,data)
+ savedata(newname,data)
end
end
end
@@ -3409,7 +3506,7 @@ if not modules then modules={} end modules ['util-str']={
utilities=utilities or {}
utilities.strings=utilities.strings or {}
local strings=utilities.strings
-local format,gsub,rep,sub=string.format,string.gsub,string.rep,string.sub
+local format,gsub,rep,sub,find=string.format,string.gsub,string.rep,string.sub,string.find
local load,dump=load,string.dump
local tonumber,type,tostring=tonumber,type,tostring
local unpack,concat=table.unpack,table.concat
@@ -3592,6 +3689,25 @@ function number.signed(i)
return "-",-i
end
end
+local digit=patterns.digit
+local period=patterns.period
+local three=digit*digit*digit
+local splitter=Cs (
+ (((1-(three^1*period))^1+C(three))*(Carg(1)*three)^1+C((1-period)^1))*(P(1)/""*Carg(2))*C(2)
+)
+patterns.formattednumber=splitter
+function number.formatted(n,sep1,sep2)
+ local s=type(s)=="string" and n or format("%0.2f",n)
+ if sep1==true then
+ return lpegmatch(splitter,s,1,".",",")
+ elseif sep1=="." then
+ return lpegmatch(splitter,s,1,sep1,sep2 or ",")
+ elseif sep1=="," then
+ return lpegmatch(splitter,s,1,sep1,sep2 or ".")
+ else
+ return lpegmatch(splitter,s,1,sep1 or ",",sep2 or ".")
+ end
+end
local zero=P("0")^1/""
local plus=P("+")/""
local minus=P("-")
@@ -3875,25 +3991,6 @@ end
local format_W=function(f)
return format("nspaces[%s]",tonumber(f) or 0)
end
-local digit=patterns.digit
-local period=patterns.period
-local three=digit*digit*digit
-local splitter=Cs (
- (((1-(three^1*period))^1+C(three))*(Carg(1)*three)^1+C((1-period)^1))*(P(1)/""*Carg(2))*C(2)
-)
-patterns.formattednumber=splitter
-function number.formatted(n,sep1,sep2)
- local s=type(s)=="string" and n or format("%0.2f",n)
- if sep1==true then
- return lpegmatch(splitter,s,1,".",",")
- elseif sep1=="." then
- return lpegmatch(splitter,s,1,sep1,sep2 or ",")
- elseif sep1=="," then
- return lpegmatch(splitter,s,1,sep1,sep2 or ".")
- else
- return lpegmatch(splitter,s,1,sep1 or ",",sep2 or ".")
- end
-end
local format_m=function(f)
n=n+1
if not f or f=="" then
@@ -3918,9 +4015,16 @@ end
local format_extension=function(extensions,f,name)
local extension=extensions[name] or "tostring(%s)"
local f=tonumber(f) or 1
+ local w=find(extension,"%.%.%.")
if f==0 then
+ if w then
+ extension=gsub(extension,"%.%.%.","")
+ end
return extension
elseif f==1 then
+ if w then
+ extension=gsub(extension,"%.%.%.","%%s")
+ end
n=n+1
local a="a"..n
return format(extension,a,a)
@@ -3928,10 +4032,13 @@ local format_extension=function(extensions,f,name)
local a="a"..(n+f+1)
return format(extension,a,a)
else
+ if w then
+ extension=gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
+ end
local t={}
for i=1,f do
n=n+1
- t[#t+1]="a"..n
+ t[i]="a"..n
end
return format(extension,unpack(t))
end
@@ -4096,7 +4203,9 @@ if not modules then modules={} end modules ['util-fil']={
license="see context related readme files"
}
local byte=string.byte
-local extract=bit32.extract
+local char=string.char
+local extract=bit32 and bit32.extract
+local floor=math.floor
utilities=utilities or {}
local files={}
utilities.files=files
@@ -4115,6 +4224,7 @@ end
function files.size(f)
return f:seek("end")
end
+files.getsize=files.size
function files.setposition(f,n)
if zerobased[f] then
f:seek("set",n)
@@ -4161,7 +4271,7 @@ end
function files.readinteger1(f)
local n=byte(f:read(1))
if n>=0x80 then
- return n-0xFF-1
+ return n-0x100
else
return n
end
@@ -4173,11 +4283,24 @@ function files.readcardinal2(f)
local a,b=byte(f:read(2),1,2)
return 0x100*a+b
end
+function files.readcardinal2le(f)
+ local b,a=byte(f:read(2),1,2)
+ return 0x100*a+b
+end
function files.readinteger2(f)
local a,b=byte(f:read(2),1,2)
local n=0x100*a+b
if n>=0x8000 then
- return n-0xFFFF-1
+ return n-0x10000
+ else
+ return n
+ end
+end
+function files.readinteger2le(f)
+ local b,a=byte(f:read(2),1,2)
+ local n=0x100*a+b
+ if n>=0x8000 then
+ return n-0x10000
else
return n
end
@@ -4186,15 +4309,50 @@ function files.readcardinal3(f)
local a,b,c=byte(f:read(3),1,3)
return 0x10000*a+0x100*b+c
end
+function files.readcardinal3le(f)
+ local c,b,a=byte(f:read(3),1,3)
+ return 0x10000*a+0x100*b+c
+end
+function files.readinteger3(f)
+ local a,b,c=byte(f:read(3),1,3)
+ local n=0x10000*a+0x100*b+c
+ if n>=0x80000 then
+ return n-0x1000000
+ else
+ return n
+ end
+end
+function files.readinteger3le(f)
+ local c,b,a=byte(f:read(3),1,3)
+ local n=0x10000*a+0x100*b+c
+ if n>=0x80000 then
+ return n-0x1000000
+ else
+ return n
+ end
+end
function files.readcardinal4(f)
local a,b,c,d=byte(f:read(4),1,4)
return 0x1000000*a+0x10000*b+0x100*c+d
end
+function files.readcardinal4le(f)
+ local d,c,b,a=byte(f:read(4),1,4)
+ return 0x1000000*a+0x10000*b+0x100*c+d
+end
function files.readinteger4(f)
local a,b,c,d=byte(f:read(4),1,4)
local n=0x1000000*a+0x10000*b+0x100*c+d
if n>=0x8000000 then
- return n-0xFFFFFFFF-1
+ return n-0x100000000
+ else
+ return n
+ end
+end
+function files.readinteger4le(f)
+ local d,c,b,a=byte(f:read(4),1,4)
+ local n=0x1000000*a+0x10000*b+0x100*c+d
+ if n>=0x8000000 then
+ return n-0x100000000
else
return n
end
@@ -4203,21 +4361,23 @@ function files.readfixed4(f)
local a,b,c,d=byte(f:read(4),1,4)
local n=0x100*a+b
if n>=0x8000 then
- return n-0xFFFF-1+(0x100*c+d)/0xFFFF
+ return n-0x10000+(0x100*c+d)/0xFFFF
else
return n+(0x100*c+d)/0xFFFF
end
end
-function files.read2dot14(f)
- local a,b=byte(f:read(2),1,2)
- local n=0x100*a+b
- local m=extract(n,0,30)
- if n>0x7FFF then
- n=extract(n,30,2)
- return m/0x4000-4
- else
- n=extract(n,30,2)
- return n+m/0x4000
+if extract then
+ function files.read2dot14(f)
+ local a,b=byte(f:read(2),1,2)
+ local n=0x100*a+b
+ local m=extract(n,0,30)
+ if n>0x7FFF then
+ n=extract(n,30,2)
+ return m/0x4000-4
+ else
+ n=extract(n,30,2)
+ return n+m/0x4000
+ end
end
end
function files.skipshort(f,n)
@@ -4226,6 +4386,28 @@ end
function files.skiplong(f,n)
f:read(4*(n or 1))
end
+function files.writecardinal2(f,n)
+ local a=char(n%256)
+ n=floor(n/256)
+ local b=char(n%256)
+ f:write(b,a)
+end
+function files.writecardinal4(f,n)
+ local a=char(n%256)
+ n=floor(n/256)
+ local b=char(n%256)
+ n=floor(n/256)
+ local c=char(n%256)
+ n=floor(n/256)
+ local d=char(n%256)
+ f:write(d,c,b,a)
+end
+function files.writestring(f,s)
+ f:write(char(byte(s,1,#s)))
+end
+function files.writebyte(f,b)
+ f:write(char(b))
+end
end -- closure
@@ -4311,6 +4493,7 @@ local remapper={
cidmap="cid maps",
pfb="type1 fonts",
afm="afm",
+ enc="enc files",
}
function resolvers.findfile(name,fileformat)
name=string.gsub(name,"\\","/")
@@ -4424,44 +4607,42 @@ function caches.is_writable(path,name)
local fullname=makefullname(path,name)
return fullname and file.is_writable(fullname)
end
-function caches.loaddata(paths,name)
- for i=1,#paths do
- local data=false
- local luaname,lucname=makefullname(paths[i],name)
- if lucname and not lfs.isfile(lucname) and type(caches.compile)=="function" then
- texio.write(string.format("(compiling luc: %s)",lucname))
- data=loadfile(luaname)
- if data then
- data=data()
- end
- if data then
- caches.compile(data,luaname,lucname)
- return data
- end
- end
- if lucname and lfs.isfile(lucname) then
+function caches.loaddata(readables,name,writable)
+ for i=1,#readables do
+ local path=readables[i]
+ local loader=false
+ local luaname,lucname=makefullname(path,name)
+ if lfs.isfile(lucname) then
texio.write(string.format("(load luc: %s)",lucname))
- data=loadfile(lucname)
- if data then
- data=data()
+ loader=loadfile(lucname)
+ end
+ if not loader and lfs.isfile(luaname) then
+ local luacrap,lucname=makefullname(writable,name)
+ texio.write(string.format("(compiling luc: %s)",lucname))
+ if lfs.isfile(lucname) then
+ loader=loadfile(lucname)
end
- if data then
- return data
+ caches.compile(data,luaname,lucname)
+ if lfs.isfile(lucname) then
+ texio.write(string.format("(load luc: %s)",lucname))
+ loader=loadfile(lucname)
else
texio.write(string.format("(loading failed: %s)",lucname))
end
- end
- if luaname and lfs.isfile(luaname) then
- texio.write(string.format("(load lua: %s)",luaname))
- data=loadfile(luaname)
- if data then
- data=data()
- end
- if data then
- return data
+ if not loader then
+ texio.write(string.format("(load lua: %s)",luaname))
+ loader=loadfile(luaname)
+ else
+ texio.write(string.format("(loading failed: %s)",luaname))
end
end
+ if loader then
+ loader=loader()
+ collectgarbage("step")
+ return loader
+ end
end
+ return false
end
function caches.savedata(path,name,data)
local luaname,lucname=makefullname(path,name)
@@ -4588,7 +4769,7 @@ function containers.read(container,name)
local storage=container.storage
local stored=storage[name]
if not stored and container.enabled and caches and containers.usecache then
- stored=caches.loaddata(container.readables,name)
+ stored=caches.loaddata(container.readables,name,container.writable)
if stored and stored.cache_version==container.version then
if trace_cache or trace_containers then
report_containers("action %a, category %a, name %a","load",container.subcategory,name)
@@ -4687,7 +4868,7 @@ end
nodes.nodecodes=nodecodes
nodes.glyphcodes=glyphcodes
nodes.disccodes=disccodes
-local free_node=node.free
+local flush_node=node.flush_node
local remove_node=node.remove
local new_node=node.new
local traverse_id=node.traverse_id
@@ -4707,7 +4888,7 @@ function nodes.remove(head,current,free_too)
head,current=remove_node(head,current)
if t then
if free_too then
- free_node(t)
+ flush_node(t)
t=nil
else
t.next,t.prev=nil,nil
@@ -4731,12 +4912,14 @@ nodes.getattr=getfield
nodes.setattr=setfield
nodes.tostring=node.tostring or tostring
nodes.copy=node.copy
+nodes.copy_node=node.copy
nodes.copy_list=node.copy_list
nodes.delete=node.delete
nodes.dimensions=node.dimensions
nodes.end_of_math=node.end_of_math
nodes.flush_list=node.flush_list
nodes.flush_node=node.flush_node
+nodes.flush=node.flush_node
nodes.free=node.free
nodes.insert_after=node.insert_after
nodes.insert_before=node.insert_before
@@ -4750,7 +4933,6 @@ nodes.vpack=node.vpack
nodes.first_glyph=node.first_glyph
nodes.has_glyph=node.has_glyph or node.first_glyph
nodes.current_attr=node.current_attr
-nodes.do_ligature_n=node.do_ligature_n
nodes.has_field=node.has_field
nodes.last_node=node.last_node
nodes.usedlist=node.usedlist
@@ -4837,9 +5019,12 @@ nuts.insert_before=direct.insert_before
nuts.insert_after=direct.insert_after
nuts.delete=direct.delete
nuts.copy=direct.copy
+nuts.copy_node=direct.copy
nuts.copy_list=direct.copy_list
nuts.tail=direct.tail
nuts.flush_list=direct.flush_list
+nuts.flush_node=direct.flush_node
+nuts.flush=direct.flush
nuts.free=direct.free
nuts.remove=direct.remove
nuts.is_node=direct.is_node
@@ -5673,9 +5858,10 @@ if not modules then modules={} end modules ['font-con']={
license="see context related readme files"
}
local next,tostring,rawget=next,tostring,rawget
-local format,match,lower,gsub=string.format,string.match,string.lower,string.gsub
+local format,match,lower,gsub,find=string.format,string.match,string.lower,string.gsub,string.find
local sort,insert,concat,sortedkeys,serialize,fastcopy=table.sort,table.insert,table.concat,table.sortedkeys,table.serialize,table.fastcopy
local derivetable=table.derive
+local ioflush=io.flush
local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
local trace_scaling=false trackers.register("fonts.scaling",function(v) trace_scaling=v end)
local report_defining=logs.reporter("fonts","defining")
@@ -5693,89 +5879,6 @@ constructors.version=1.01
constructors.cache=containers.define("fonts","constructors",constructors.version,false)
constructors.privateoffset=0xF0000
constructors.cacheintex=true
-constructors.keys={
- properties={
- encodingbytes="number",
- embedding="number",
- cidinfo={},
- format="string",
- fontname="string",
- fullname="string",
- filename="filename",
- psname="string",
- name="string",
- virtualized="boolean",
- hasitalics="boolean",
- autoitalicamount="basepoints",
- nostackmath="boolean",
- noglyphnames="boolean",
- mode="string",
- hasmath="boolean",
- mathitalics="boolean",
- textitalics="boolean",
- finalized="boolean",
- },
- parameters={
- mathsize="number",
- scriptpercentage="float",
- scriptscriptpercentage="float",
- units="cardinal",
- designsize="scaledpoints",
- expansion={
- stretch="integerscale",
- shrink="integerscale",
- step="integerscale",
- auto="boolean",
- },
- protrusion={
- auto="boolean",
- },
- slantfactor="float",
- extendfactor="float",
- factor="float",
- hfactor="float",
- vfactor="float",
- size="scaledpoints",
- units="scaledpoints",
- scaledpoints="scaledpoints",
- slantperpoint="scaledpoints",
- spacing={
- width="scaledpoints",
- stretch="scaledpoints",
- shrink="scaledpoints",
- extra="scaledpoints",
- },
- xheight="scaledpoints",
- quad="scaledpoints",
- ascender="scaledpoints",
- descender="scaledpoints",
- synonyms={
- space="spacing.width",
- spacestretch="spacing.stretch",
- spaceshrink="spacing.shrink",
- extraspace="spacing.extra",
- x_height="xheight",
- space_stretch="spacing.stretch",
- space_shrink="spacing.shrink",
- extra_space="spacing.extra",
- em="quad",
- ex="xheight",
- slant="slantperpoint",
- },
- },
- description={
- width="basepoints",
- height="basepoints",
- depth="basepoints",
- boundingbox={},
- },
- character={
- width="scaledpoints",
- height="scaledpoints",
- depth="scaledpoints",
- italic="scaledpoints",
- },
-}
local designsizes=allocate()
constructors.designsizes=designsizes
local loadedfonts=allocate()
@@ -5821,7 +5924,9 @@ end
local unscaled={
ScriptPercentScaleDown=true,
ScriptScriptPercentScaleDown=true,
- RadicalDegreeBottomRaisePercent=true
+ RadicalDegreeBottomRaisePercent=true,
+ NoLimitSupFactor=true,
+ NoLimitSubFactor=true,
}
function constructors.assignmathparameters(target,original)
local mathparameters=original.mathparameters
@@ -5913,6 +6018,23 @@ local function mathkerns(v,vdelta)
end
return k
end
+local psfake=0
+local function fixedpsname(psname,fallback)
+ local usedname=psname
+ if psname and psname~="" then
+ if find(psname," ") then
+ usedname=gsub(psname,"[%s]+","-")
+ else
+ end
+ elseif not fallback or fallback=="" then
+ psfake=psfake+1
+ psname="fakename-"..psfake
+ else
+ psname=fallback
+ usedname=gsub(psname,"[^a-zA-Z0-9]+","-")
+ end
+ return usedname,psname~=usedname
+end
function constructors.scale(tfmdata,specification)
local target={}
if tonumber(specification) then
@@ -5986,14 +6108,12 @@ function constructors.scale(tfmdata,specification)
target.cidinfo=properties.cidinfo
target.format=properties.format
target.cache=constructors.cacheintex and "yes" or "renew"
- local fontname=properties.fontname or tfmdata.fontname
- local fullname=properties.fullname or tfmdata.fullname
- local filename=properties.filename or tfmdata.filename
- local psname=properties.psname or tfmdata.psname
+ local fontname=properties.fontname or tfmdata.fontname
+ local fullname=properties.fullname or tfmdata.fullname
+ local filename=properties.filename or tfmdata.filename
+ local psname=properties.psname or tfmdata.psname
local name=properties.name or tfmdata.name
- if not psname or psname=="" then
- psname=fontname or (fullname and fonts.names.cleanname(fullname))
- end
+ local psname,psfixed=fixedpsname(psname,fontname or fullname or file.nameonly(filename))
target.fontname=fontname
target.fullname=fullname
target.filename=filename
@@ -6043,10 +6163,14 @@ function constructors.scale(tfmdata,specification)
local haskerns=properties.haskerns or properties.mode=="base"
local hasligatures=properties.hasligatures or properties.mode=="base"
local realdimensions=properties.realdimensions
+ local writingmode=properties.writingmode or "horizontal"
+ local identity=properties.identity or "horizontal"
if changed and not next(changed) then
changed=false
end
target.type=isvirtual and "virtual" or "real"
+ target.writingmode=writingmode=="vertical" and "vertical" or "horizontal"
+ target.identity=identity=="vertical" and "vertical" or "horizontal"
target.postprocessors=tfmdata.postprocessors
local targetslant=(parameters.slant or parameters[1] or 0)*factors.pt
local targetspace=(parameters.space or parameters[2] or 0)*hdelta
@@ -6106,8 +6230,9 @@ function constructors.scale(tfmdata,specification)
end
end
if trace_defining then
- report_defining("defining tfm, name %a, fullname %a, filename %a, hscale %a, vscale %a, math %a, italics %a",
- name,fullname,filename,hdelta,vdelta,hasmath and "enabled" or "disabled",hasitalics and "enabled" or "disabled")
+ report_defining("defining tfm, name %a, fullname %a, filename %a, %spsname %a, hscale %a, vscale %a, math %a, italics %a",
+ name,fullname,filename,psfixed and "(fixed) " or "",psname,hdelta,vdelta,
+ hasmath and "enabled" or "disabled",hasitalics and "enabled" or "disabled")
end
constructors.beforecopyingcharacters(target,tfmdata)
local sharedkerns={}
@@ -6431,6 +6556,8 @@ function constructors.finalize(tfmdata)
cidinfo=tfmdata.cidinfo or nil,
format=tfmdata.format or "type1",
direction=tfmdata.direction or 0,
+ writingmode=tfmdata.writingmode or "horizontal",
+ identity=tfmdata.identity or "horizontal",
}
end
if not tfmdata.resources then
@@ -6568,134 +6695,232 @@ setmetatableindex(formats,function(t,k)
end
return rawget(t,file.suffix(l))
end)
-local locations={}
-local function setindeed(mode,target,group,name,action,position)
- local t=target[mode]
- if not t then
- report_defining("fatal error in setting feature %a, group %a, mode %a",name,group,mode)
- os.exit()
- elseif position then
- insert(t,position,{ name=name,action=action })
- else
- for i=1,#t do
- local ti=t[i]
- if ti.name==name then
- ti.action=action
- return
+do
+ local function setindeed(mode,source,target,group,name,position)
+ local action=source[mode]
+ if not action then
+ return
+ end
+ local t=target[mode]
+ if not t then
+ report_defining("fatal error in setting feature %a, group %a, mode %a",name,group,mode)
+ os.exit()
+ elseif position then
+ insert(t,position,{ name=name,action=action })
+ else
+ for i=1,#t do
+ local ti=t[i]
+ if ti.name==name then
+ ti.action=action
+ return
+ end
end
+ insert(t,{ name=name,action=action })
end
- insert(t,{ name=name,action=action })
- end
-end
-local function set(group,name,target,source)
- target=target[group]
- if not target then
- report_defining("fatal target error in setting feature %a, group %a",name,group)
- os.exit()
end
- local source=source[group]
- if not source then
- report_defining("fatal source error in setting feature %a, group %a",name,group)
- os.exit()
- end
- local node=source.node
- local base=source.base
- local position=source.position
- if node then
- setindeed("node",target,group,name,node,position)
- end
- if base then
- setindeed("base",target,group,name,base,position)
- end
-end
-local function register(where,specification)
- local name=specification.name
- if name and name~="" then
- local default=specification.default
- local description=specification.description
- local initializers=specification.initializers
- local processors=specification.processors
- local manipulators=specification.manipulators
- local modechecker=specification.modechecker
- if default then
- where.defaults[name]=default
- end
- if description and description~="" then
- where.descriptions[name]=description
+ local function set(group,name,target,source)
+ target=target[group]
+ if not target then
+ report_defining("fatal target error in setting feature %a, group %a",name,group)
+ os.exit()
end
- if initializers then
- set('initializers',name,where,specification)
- end
- if processors then
- set('processors',name,where,specification)
+ local source=source[group]
+ if not source then
+ report_defining("fatal source error in setting feature %a, group %a",name,group)
+ os.exit()
end
- if manipulators then
- set('manipulators',name,where,specification)
- end
- if modechecker then
- where.modechecker=modechecker
+ local position=source.position
+ setindeed("node",source,target,group,name,position)
+ setindeed("base",source,target,group,name,position)
+ setindeed("plug",source,target,group,name,position)
+ end
+ local function register(where,specification)
+ local name=specification.name
+ if name and name~="" then
+ local default=specification.default
+ local description=specification.description
+ local initializers=specification.initializers
+ local processors=specification.processors
+ local manipulators=specification.manipulators
+ local modechecker=specification.modechecker
+ if default then
+ where.defaults[name]=default
+ end
+ if description and description~="" then
+ where.descriptions[name]=description
+ end
+ if initializers then
+ set('initializers',name,where,specification)
+ end
+ if processors then
+ set('processors',name,where,specification)
+ end
+ if manipulators then
+ set('manipulators',name,where,specification)
+ end
+ if modechecker then
+ where.modechecker=modechecker
+ end
end
end
-end
-constructors.registerfeature=register
-function constructors.getfeatureaction(what,where,mode,name)
- what=handlers[what].features
- if what then
- where=what[where]
- if where then
- mode=where[mode]
- if mode then
- for i=1,#mode do
- local m=mode[i]
- if m.name==name then
- return m.action
+ constructors.registerfeature=register
+ function constructors.getfeatureaction(what,where,mode,name)
+ what=handlers[what].features
+ if what then
+ where=what[where]
+ if where then
+ mode=where[mode]
+ if mode then
+ for i=1,#mode do
+ local m=mode[i]
+ if m.name==name then
+ return m.action
+ end
end
end
end
end
end
-end
-local newhandler={}
-constructors.handlers=newhandler
-constructors.newhandler=newhandler
-local function setnewhandler(what)
- local handler=handlers[what]
- if not handler then
- handler={}
- handlers[what]=handler
+ local newfeatures={}
+ constructors.newfeatures=newfeatures
+ constructors.features=newfeatures
+ local function setnewfeatures(what)
+ local handler=handlers[what]
+ local features=handler.features
+ if not features then
+ local tables=handler.tables
+ local statistics=handler.statistics
+ features=allocate {
+ defaults={},
+ descriptions=tables and tables.features or {},
+ used=statistics and statistics.usedfeatures or {},
+ initializers={ base={},node={},plug={} },
+ processors={ base={},node={},plug={} },
+ manipulators={ base={},node={},plug={} },
+ }
+ features.register=function(specification) return register(features,specification) end
+ handler.features=features
+ end
+ return features
end
- return handler
+ setmetatable(newfeatures,{
+ __call=function(t,k) local v=t[k] return v end,
+ __index=function(t,k) local v=setnewfeatures(k) t[k]=v return v end,
+ })
end
-setmetatable(newhandler,{
- __call=function(t,k) local v=t[k] return v end,
- __index=function(t,k) local v=setnewhandler(k) t[k]=v return v end,
-})
-local newfeatures={}
-constructors.newfeatures=newfeatures
-constructors.features=newfeatures
-local function setnewfeatures(what)
- local handler=handlers[what]
- local features=handler.features
- if not features then
- local tables=handler.tables
- local statistics=handler.statistics
- features=allocate {
- defaults={},
- descriptions=tables and tables.features or {},
- used=statistics and statistics.usedfeatures or {},
- initializers={ base={},node={} },
- processors={ base={},node={} },
- manipulators={ base={},node={} },
- }
- features.register=function(specification) return register(features,specification) end
- handler.features=features
+do
+ local newhandler={}
+ constructors.handlers=newhandler
+ constructors.newhandler=newhandler
+ local function setnewhandler(what)
+ local handler=handlers[what]
+ if not handler then
+ handler={}
+ handlers[what]=handler
+ end
+ return handler
+ end
+ setmetatable(newhandler,{
+ __call=function(t,k) local v=t[k] return v end,
+ __index=function(t,k) local v=setnewhandler(k) t[k]=v return v end,
+ })
+end
+do
+ local newenhancer={}
+ constructors.enhancers=newenhancer
+ constructors.newenhancer=newenhancer
+ local function setnewenhancer(format)
+ local handler=handlers[format]
+ local enhancers=handler.enhancers
+ if not enhancers then
+ local actions=allocate()
+ local before=allocate()
+ local after=allocate()
+ local order=allocate()
+ local patches={ before=before,after=after }
+ local trace=false
+ local report=logs.reporter("fonts",format.." enhancing")
+ trackers.register(format..".loading",function(v) trace=v end)
+ local function enhance(name,data,filename,raw)
+ local enhancer=actions[name]
+ if enhancer then
+ if trace then
+ report("apply enhancement %a to file %a",name,filename)
+ ioflush()
+ end
+ enhancer(data,filename,raw)
+ else
+ end
+ end
+ local function apply(data,filename,raw)
+ local basename=file.basename(lower(filename))
+ if trace then
+ report("%s enhancing file %a","start",filename)
+ end
+ ioflush()
+ for e=1,#order do
+ local enhancer=order[e]
+ local b=before[enhancer]
+ if b then
+ for pattern,action in next,b do
+ if find(basename,pattern) then
+ action(data,filename,raw)
+ end
+ end
+ end
+ enhance(enhancer,data,filename,raw)
+ local a=after[enhancer]
+ if a then
+ for pattern,action in next,a do
+ if find(basename,pattern) then
+ action(data,filename,raw)
+ end
+ end
+ end
+ ioflush()
+ end
+ if trace then
+ report("%s enhancing file %a","stop",filename)
+ end
+ ioflush()
+ end
+ local function register(what,action)
+ if action then
+ if actions[what] then
+ else
+ order[#order+1]=what
+ end
+ actions[what]=action
+ else
+ report("bad enhancer %a",what)
+ end
+ end
+ local function patch(what,where,pattern,action)
+ local pw=patches[what]
+ if pw then
+ local ww=pw[where]
+ if ww then
+ ww[pattern]=action
+ else
+ pw[where]={ [pattern]=action}
+ end
+ end
+ end
+ enhancers={
+ register=register,
+ apply=apply,
+ patch=patch,
+ patches={ register=patch },
+ }
+ handler.enhancers=enhancers
+ end
+ return enhancers
end
- return features
+ setmetatable(newenhancer,{
+ __call=function(t,k) local v=t[k] return v end,
+ __index=function(t,k) local v=setnewenhancer(k) t[k]=v return v end,
+ })
end
-setmetatable(newfeatures,{
- __call=function(t,k) local v=t[k] return v end,
- __index=function(t,k) local v=setnewfeatures(k) t[k]=v return v end,
-})
function constructors.checkedfeatures(what,features)
local defaults=handlers[what].features.defaults
if features and next(features) then
@@ -6849,19 +7074,61 @@ if context then
os.exit()
end
local fonts=fonts
-fonts.encodings={}
-fonts.encodings.agl={}
-fonts.encodings.known={}
-setmetatable(fonts.encodings.agl,{ __index=function(t,k)
+local encodings={}
+fonts.encodings=encodings
+encodings.agl={}
+encodings.known={}
+setmetatable(encodings.agl,{ __index=function(t,k)
if k=="unicodes" then
texio.write(" <loading (extended) adobe glyph list>")
local unicodes=dofile(resolvers.findfile("font-age.lua"))
- fonts.encodings.agl={ unicodes=unicodes }
+ encodings.agl={ unicodes=unicodes }
return unicodes
else
return nil
end
end })
+encodings.cache=containers.define("fonts","enc",encodings.version,true)
+function encodings.load(filename)
+ local name=file.removesuffix(filename)
+ local data=containers.read(encodings.cache,name)
+ if data then
+ return data
+ end
+ local vector,tag,hash,unicodes={},"",{},{}
+ local foundname=resolvers.findfile(filename,'enc')
+ if foundname and foundname~="" then
+ local ok,encoding,size=resolvers.loadbinfile(foundname)
+ if ok and encoding then
+ encoding=string.gsub(encoding,"%%(.-)\n","")
+ local unicoding=encodings.agl.unicodes
+ local tag,vec=string.match(encoding,"/(%w+)%s*%[(.*)%]%s*def")
+ local i=0
+ for ch in string.gmatch(vec,"/([%a%d%.]+)") do
+ if ch~=".notdef" then
+ vector[i]=ch
+ if not hash[ch] then
+ hash[ch]=i
+ else
+ end
+ local u=unicoding[ch]
+ if u then
+ unicodes[u]=i
+ end
+ end
+ i=i+1
+ end
+ end
+ end
+ local data={
+ name=name,
+ tag=tag,
+ vector=vector,
+ hash=hash,
+ unicodes=unicodes
+ }
+ return containers.write(encodings.cache,name,data)
+end
end -- closure
@@ -7032,8 +7299,9 @@ local match,format,find,concat,gsub,lower=string.match,string.format,string.find
local P,R,S,C,Ct,Cc,lpegmatch=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.match
local floor=math.floor
local formatters=string.formatters
+local sortedhash,sortedkeys=table.sortedhash,table.sortedkeys
local trace_loading=false trackers.register("fonts.loading",function(v) trace_loading=v end)
-local trace_mapping=false trackers.register("fonts.mapping",function(v) trace_unimapping=v end)
+local trace_mapping=false trackers.register("fonts.mapping",function(v) trace_mapping=v end)
local report_fonts=logs.reporter("fonts","loading")
local force_ligatures=false directives.register("fonts.mapping.forceligatures",function(v) force_ligatures=v end)
local fonts=fonts or {}
@@ -7123,36 +7391,44 @@ mappings.fromunicode16=fromunicode16
local ligseparator=P("_")
local varseparator=P(".")
local namesplitter=Ct(C((1-ligseparator-varseparator)^1)*(ligseparator*C((1-ligseparator-varseparator)^1))^0)
-local overloads=allocate {
- IJ={ name="I_J",unicode={ 0x49,0x4A },mess=0x0132 },
- ij={ name="i_j",unicode={ 0x69,0x6A },mess=0x0133 },
- ff={ name="f_f",unicode={ 0x66,0x66 },mess=0xFB00 },
- fi={ name="f_i",unicode={ 0x66,0x69 },mess=0xFB01 },
- fl={ name="f_l",unicode={ 0x66,0x6C },mess=0xFB02 },
- ffi={ name="f_f_i",unicode={ 0x66,0x66,0x69 },mess=0xFB03 },
- ffl={ name="f_f_l",unicode={ 0x66,0x66,0x6C },mess=0xFB04 },
- fj={ name="f_j",unicode={ 0x66,0x6A } },
- fk={ name="f_k",unicode={ 0x66,0x6B } },
-}
-for k,v in next,overloads do
- local name=v.name
- local mess=v.mess
- if name then
- overloads[name]=v
- end
- if mess then
- overloads[mess]=v
+do
+ local overloads=allocate {
+ IJ={ name="I_J",unicode={ 0x49,0x4A },mess=0x0132 },
+ ij={ name="i_j",unicode={ 0x69,0x6A },mess=0x0133 },
+ ff={ name="f_f",unicode={ 0x66,0x66 },mess=0xFB00 },
+ fi={ name="f_i",unicode={ 0x66,0x69 },mess=0xFB01 },
+ fl={ name="f_l",unicode={ 0x66,0x6C },mess=0xFB02 },
+ ffi={ name="f_f_i",unicode={ 0x66,0x66,0x69 },mess=0xFB03 },
+ ffl={ name="f_f_l",unicode={ 0x66,0x66,0x6C },mess=0xFB04 },
+ fj={ name="f_j",unicode={ 0x66,0x6A } },
+ fk={ name="f_k",unicode={ 0x66,0x6B } },
+ }
+ local o={}
+ for k,v in next,overloads do
+ local name=v.name
+ local mess=v.mess
+ if name then
+ o[name]=v
+ end
+ if mess then
+ o[mess]=v
+ end
+ o[k]=v
end
+ mappings.overloads=o
end
-mappings.overloads=overloads
function mappings.addtounicode(data,filename,checklookups)
local resources=data.resources
local unicodes=resources.unicodes
if not unicodes then
+ if trace_mapping then
+ report_fonts("no unicode list, quitting tounicode for %a",filename)
+ end
return
end
local properties=data.properties
local descriptions=data.descriptions
+ local overloads=mappings.overloads
unicodes['space']=unicodes['space'] or 32
unicodes['hyphen']=unicodes['hyphen'] or 45
unicodes['zwj']=unicodes['zwj'] or 0x200D
@@ -7175,10 +7451,13 @@ function mappings.addtounicode(data,filename,checklookups)
end
local ns=0
local nl=0
- for du,glyph in next,descriptions do
+ local dlist=sortedkeys(descriptions)
+ for i=1,#dlist do
+ local du=dlist[i]
+ local glyph=descriptions[du]
local name=glyph.name
if name then
- local overload=overloads[name]
+ local overload=overloads[name] or overloads[du]
if overload then
glyph.unicode=overload.unicode
else
@@ -7297,6 +7576,11 @@ function mappings.addtounicode(data,filename,checklookups)
end
end
end
+ else
+ local overload=overloads[du]
+ if overload then
+ glyph.unicode=overload.unicode
+ end
end
end
if type(checklookups)=="function" then
@@ -7304,7 +7588,9 @@ function mappings.addtounicode(data,filename,checklookups)
end
local collected=false
local unicoded=0
- for unicode,glyph in next,descriptions do
+ for i=1,#dlist do
+ local du=dlist[i]
+ local glyph=descriptions[du]
if glyph.class=="ligature" and (force_ligatures or not glyph.unicode) then
if not collected then
collected=fonts.handlers.otf.readers.getcomponents(data)
@@ -7312,7 +7598,7 @@ function mappings.addtounicode(data,filename,checklookups)
break
end
end
- local u=collected[unicode]
+ local u=collected[du]
if u then
local n=#u
for i=1,n do
@@ -7336,9 +7622,11 @@ function mappings.addtounicode(data,filename,checklookups)
report_fonts("%n ligature tounicode mappings deduced from gsub ligature features",unicoded)
end
if trace_mapping then
- for unic,glyph in table.sortedhash(descriptions) do
- local name=glyph.name
- local index=glyph.index
+ for i=1,#dlist do
+ local du=dlist[i]
+ local glyph=descriptions[du]
+ local name=glyph.name or "-"
+ local index=glyph.index or 0
local unicode=glyph.unicode
if unicode then
if type(unicode)=="table" then
@@ -7346,12 +7634,12 @@ function mappings.addtounicode(data,filename,checklookups)
for i=1,#unicode do
unicodes[i]=formatters("%U",unicode[i])
end
- report_fonts("internal slot %U, name %a, unicode %U, tounicode % t",index,name,unic,unicodes)
+ report_fonts("internal slot %U, name %a, unicode %U, tounicode % t",index,name,du,unicodes)
else
- report_fonts("internal slot %U, name %a, unicode %U, tounicode %U",index,name,unic,unicode)
+ report_fonts("internal slot %U, name %a, unicode %U, tounicode %U",index,name,du,unicode)
end
else
- report_fonts("internal slot %U, name %a, unicode %U",index,name,unic)
+ report_fonts("internal slot %U, name %a, unicode %U",index,name,du)
end
end
end
@@ -7441,164 +7729,6 @@ end -- closure
do -- begin closure to overcome local limits and interference
-if not modules then modules={} end modules ['font-tfm']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local next=next
-local match=string.match
-local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
-local trace_features=false trackers.register("tfm.features",function(v) trace_features=v end)
-local report_defining=logs.reporter("fonts","defining")
-local report_tfm=logs.reporter("fonts","tfm loading")
-local findbinfile=resolvers.findbinfile
-local fonts=fonts
-local handlers=fonts.handlers
-local readers=fonts.readers
-local constructors=fonts.constructors
-local encodings=fonts.encodings
-local tfm=constructors.handlers.tfm
-tfm.version=1.000
-tfm.maxnestingdepth=5
-tfm.maxnestingsize=65536*1024
-local tfmfeatures=constructors.features.tfm
-constructors.resolvevirtualtoo=false
-fonts.formats.tfm="type1"
-fonts.formats.ofm="type1"
-function tfm.setfeatures(tfmdata,features)
- local okay=constructors.initializefeatures("tfm",tfmdata,features,trace_features,report_tfm)
- if okay then
- return constructors.collectprocessors("tfm",tfmdata,features,trace_features,report_tfm)
- else
- return {}
- end
-end
-local depth={}
-local function read_from_tfm(specification)
- local filename=specification.filename
- local size=specification.size
- depth[filename]=(depth[filename] or 0)+1
- if trace_defining then
- report_defining("loading tfm file %a at size %s",filename,size)
- end
- local tfmdata=font.read_tfm(filename,size)
- if tfmdata then
- local features=specification.features and specification.features.normal or {}
- local resources=tfmdata.resources or {}
- local properties=tfmdata.properties or {}
- local parameters=tfmdata.parameters or {}
- local shared=tfmdata.shared or {}
- properties.name=tfmdata.name
- properties.fontname=tfmdata.fontname
- properties.psname=tfmdata.psname
- properties.filename=specification.filename
- properties.format=fonts.formats.tfm
- parameters.size=size
- tfmdata.properties=properties
- tfmdata.resources=resources
- tfmdata.parameters=parameters
- tfmdata.shared=shared
- shared.rawdata={}
- shared.features=features
- shared.processes=next(features) and tfm.setfeatures(tfmdata,features) or nil
- parameters.slant=parameters.slant or parameters[1] or 0
- parameters.space=parameters.space or parameters[2] or 0
- parameters.space_stretch=parameters.space_stretch or parameters[3] or 0
- parameters.space_shrink=parameters.space_shrink or parameters[4] or 0
- parameters.x_height=parameters.x_height or parameters[5] or 0
- parameters.quad=parameters.quad or parameters[6] or 0
- parameters.extra_space=parameters.extra_space or parameters[7] or 0
- constructors.enhanceparameters(parameters)
- if constructors.resolvevirtualtoo then
- fonts.loggers.register(tfmdata,file.suffix(filename),specification)
- local vfname=findbinfile(specification.name,'ovf')
- if vfname and vfname~="" then
- local vfdata=font.read_vf(vfname,size)
- if vfdata then
- local chars=tfmdata.characters
- for k,v in next,vfdata.characters do
- chars[k].commands=v.commands
- end
- properties.virtualized=true
- tfmdata.fonts=vfdata.fonts
- tfmdata.type="virtual"
- local fontlist=vfdata.fonts
- local name=file.nameonly(filename)
- for i=1,#fontlist do
- local n=fontlist[i].name
- local s=fontlist[i].size
- local d=depth[filename]
- s=constructors.scaled(s,vfdata.designsize)
- if d>tfm.maxnestingdepth then
- report_defining("too deeply nested virtual font %a with size %a, max nesting depth %s",n,s,tfm.maxnestingdepth)
- fontlist[i]={ id=0 }
- elseif (d>1) and (s>tfm.maxnestingsize) then
- report_defining("virtual font %a exceeds size %s",n,s)
- fontlist[i]={ id=0 }
- else
- local t,id=fonts.constructors.readanddefine(n,s)
- fontlist[i]={ id=id }
- end
- end
- end
- end
- end
- local allfeatures=tfmdata.shared.features or specification.features.normal
- constructors.applymanipulators("tfm",tfmdata,allfeatures.normal,trace_features,report_tfm)
- if not features.encoding then
- local encoding,filename=match(properties.filename,"^(.-)%-(.*)$")
- if filename and encoding and encodings.known and encodings.known[encoding] then
- features.encoding=encoding
- end
- end
- properties.haskerns=true
- properties.hasligatures=true
- resources.unicodes={}
- resources.lookuptags={}
- depth[filename]=depth[filename]-1
- return tfmdata
- else
- depth[filename]=depth[filename]-1
- end
-end
-local function check_tfm(specification,fullname)
- local foundname=findbinfile(fullname,'tfm') or ""
- if foundname=="" then
- foundname=findbinfile(fullname,'ofm') or ""
- end
- if foundname=="" then
- foundname=fonts.names.getfilename(fullname,"tfm") or ""
- end
- if foundname~="" then
- specification.filename=foundname
- specification.format="ofm"
- return read_from_tfm(specification)
- elseif trace_defining then
- report_defining("loading tfm with name %a fails",specification.name)
- end
-end
-readers.check_tfm=check_tfm
-function readers.tfm(specification)
- local fullname=specification.filename or ""
- if fullname=="" then
- local forced=specification.forced or ""
- if forced~="" then
- fullname=specification.name.."."..forced
- else
- fullname=specification.name
- end
- end
- return check_tfm(specification,fullname)
-end
-readers.ofm=readers.tfm
-
-end -- closure
-
-do -- begin closure to overcome local limits and interference
-
if not modules then modules={} end modules ['font-oti']={
version=1.001,
comment="companion to font-ini.mkiv",
@@ -7625,6 +7755,7 @@ local function setmode(tfmdata,value)
tfmdata.properties.mode=lower(value)
end
end
+otf.modeinitializer=setmode
local function setlanguage(tfmdata,value)
if value then
local cleanvalue=lower(value)
@@ -7659,6 +7790,7 @@ registerotffeature {
initializers={
base=setmode,
node=setmode,
+ plug=setmode,
}
}
registerotffeature {
@@ -7667,6 +7799,7 @@ registerotffeature {
initializers={
base=setlanguage,
node=setlanguage,
+ plug=setlanguage,
}
}
registerotffeature {
@@ -7675,6 +7808,7 @@ registerotffeature {
initializers={
base=setscript,
node=setscript,
+ plug=setscript,
}
}
otftables.featuretypes=allocate {
@@ -7770,7 +7904,9 @@ handlers.otf=otf
local readers=otf.readers or {}
otf.readers=readers
local streamreader=utilities.files
+local streamwriter=utilities.files
readers.streamreader=streamreader
+readers.streamwriter=streamwriter
local openfile=streamreader.open
local closefile=streamreader.close
local setposition=streamreader.setposition
@@ -8242,11 +8378,43 @@ readers.hhea=function(f,fontdata,specification)
reserved_3=readshort(f),
reserved_4=readshort(f),
metricdataformat=readshort(f),
- nofhmetrics=readushort(f),
+ nofmetrics=readushort(f),
}
else
fontdata.horizontalheader={
- nofhmetrics=0,
+ nofmetrics=0,
+ }
+ end
+ end
+end
+readers.vhea=function(f,fontdata,specification)
+ if specification.details then
+ local datatable=fontdata.tables.vhea
+ if datatable then
+ setposition(f,datatable.offset)
+ local version=readfixed(f)
+ fontdata.verticalheader={
+ version=version,
+ ascender=readfword(f),
+ descender=readfword(f),
+ linegap=readfword(f),
+ maxadvanceheight=readufword(f),
+ mintopsidebearing=readfword(f),
+ minbottomsidebearing=readfword(f),
+ maxextent=readfword(f),
+ caretsloperise=readshort(f),
+ caretsloperun=readshort(f),
+ caretoffset=readshort(f),
+ reserved_1=readshort(f),
+ reserved_2=readshort(f),
+ reserved_3=readshort(f),
+ reserved_4=readshort(f),
+ metricdataformat=readshort(f),
+ nofmetrics=readushort(f),
+ }
+ else
+ fontdata.verticalheader={
+ nofmetrics=0,
}
end
end
@@ -8297,7 +8465,8 @@ readers.hmtx=function(f,fontdata,specification)
local datatable=fontdata.tables.hmtx
if datatable then
setposition(f,datatable.offset)
- local nofmetrics=fontdata.horizontalheader.nofhmetrics
+ local horizontalheader=fontdata.horizontalheader
+ local nofmetrics=horizontalheader.nofmetrics
local glyphs=fontdata.glyphs
local nofglyphs=fontdata.nofglyphs
local width=0
@@ -8319,6 +8488,43 @@ readers.hmtx=function(f,fontdata,specification)
end
end
end
+readers.vmtx=function(f,fontdata,specification)
+ if specification.glyphs then
+ local datatable=fontdata.tables.vmtx
+ if datatable then
+ setposition(f,datatable.offset)
+ local verticalheader=fontdata.verticalheader
+ local nofmetrics=verticalheader.nofmetrics
+ local glyphs=fontdata.glyphs
+ local nofglyphs=fontdata.nofglyphs
+ local vheight=0
+ local vdefault=verticalheader.ascender+verticalheader.descender
+ local topsidebearing=0
+ for i=0,nofmetrics-1 do
+ local glyph=glyphs[i]
+ vheight=readshort(f)
+ topsidebearing=readshort(f)
+ if vheight~=0 and vheight~=vdefault then
+ glyph.vheight=vheight
+ end
+ end
+ for i=nofmetrics,nofglyphs-1 do
+ local glyph=glyphs[i]
+ if vheight~=0 and vheight~=vdefault then
+ glyph.vheight=vheight
+ end
+ end
+ end
+ end
+end
+readers.vorg=function(f,fontdata,specification)
+ if specification.glyphs then
+ local datatable=fontdata.tables.vorg
+ if datatable then
+ report("todo: %s","vorg")
+ end
+ end
+end
readers.post=function(f,fontdata,specification)
local datatable=fontdata.tables.post
if datatable then
@@ -8876,113 +9082,7 @@ function readers.math(f,fontdata,specification)
reportskippedtable("math")
end
end
-local function packoutlines(data,makesequence)
- local subfonts=data.subfonts
- if subfonts then
- for i=1,#subfonts do
- packoutlines(subfonts[i],makesequence)
- end
- return
- end
- local common=data.segments
- if common then
- return
- end
- local glyphs=data.glyphs
- if not glyphs then
- return
- end
- if makesequence then
- for index=1,#glyphs do
- local glyph=glyphs[index]
- local segments=glyph.segments
- if segments then
- local sequence={}
- local nofsequence=0
- for i=1,#segments do
- local segment=segments[i]
- local nofsegment=#segment
- nofsequence=nofsequence+1
- sequence[nofsequence]=segment[nofsegment]
- for i=1,nofsegment-1 do
- nofsequence=nofsequence+1
- sequence[nofsequence]=segment[i]
- end
- end
- glyph.sequence=sequence
- glyph.segments=nil
- end
- end
- else
- local hash={}
- local common={}
- local reverse={}
- local last=0
- for index=1,#glyphs do
- local segments=glyphs[index].segments
- if segments then
- for i=1,#segments do
- local h=concat(segments[i]," ")
- hash[h]=(hash[h] or 0)+1
- end
- end
- end
- for index=1,#glyphs do
- local segments=glyphs[index].segments
- if segments then
- for i=1,#segments do
- local segment=segments[i]
- local h=concat(segment," ")
- if hash[h]>1 then
- local idx=reverse[h]
- if not idx then
- last=last+1
- reverse[h]=last
- common[last]=segment
- idx=last
- end
- segments[i]=idx
- end
- end
- end
- end
- if last>0 then
- data.segments=common
- end
- end
-end
-local function unpackoutlines(data)
- local subfonts=data.subfonts
- if subfonts then
- for i=1,#subfonts do
- unpackoutlines(subfonts[i])
- end
- return
- end
- local common=data.segments
- if not common then
- return
- end
- local glyphs=data.glyphs
- if not glyphs then
- return
- end
- for index=1,#glyphs do
- local segments=glyphs[index].segments
- if segments then
- for i=1,#segments do
- local c=common[segments[i]]
- if c then
- segments[i]=c
- end
- end
- end
- end
- data.segments=nil
-end
-otf.packoutlines=packoutlines
-otf.unpackoutlines=unpackoutlines
-local function getinfo(maindata,sub,platformnames,rawfamilynames)
+local function getinfo(maindata,sub,platformnames,rawfamilynames,metricstoo)
local fontdata=sub and maindata.subfonts and maindata.subfonts[sub] or maindata
local names=fontdata.names
local info=nil
@@ -8992,8 +9092,8 @@ local function getinfo(maindata,sub,platformnames,rawfamilynames)
local fontheader=fontdata.fontheader or {}
local cffinfo=fontdata.cffinfo or {}
local filename=fontdata.filename
- local weight=getname(fontdata,"weight") or cffinfo.weight or metrics.weight
- local width=getname(fontdata,"width") or cffinfo.width or metrics.width
+ local weight=getname(fontdata,"weight") or (cffinfo and cffinfo.weight) or (metrics and metrics.weight)
+ local width=getname(fontdata,"width") or (cffinfo and cffinfo.width ) or (metrics and metrics.width )
local fontname=getname(fontdata,"postscriptname")
local fullname=getname(fontdata,"fullname")
local family=getname(fontdata,"family")
@@ -9035,6 +9135,27 @@ local function getinfo(maindata,sub,platformnames,rawfamilynames)
descender=metrics.typodescender,
platformnames=platformnames and fontdata.platformnames or nil,
}
+ if metricstoo then
+ local keys={
+ "version",
+ "ascender","descender","linegap",
+ "maxadvancewidth","maxadvanceheight","maxextent",
+ "minbottomsidebearing","mintopsidebearing",
+ }
+ local h=fontdata.horizontalheader or {}
+ local v=fontdata.verticalheader or {}
+ if h then
+ local th={}
+ local tv={}
+ for i=1,#keys do
+ local key=keys[i]
+ th[key]=h[key] or 0
+ tv[key]=v[key] or 0
+ end
+ info.horizontalmetrics=th
+ info.verticalmetrics=tv
+ end
+ end
elseif n then
info={
filename=fontdata.filename,
@@ -9118,7 +9239,10 @@ local function readdata(f,offset,specification)
readers["head"](f,fontdata,specification)
readers["maxp"](f,fontdata,specification)
readers["hhea"](f,fontdata,specification)
+ readers["vhea"](f,fontdata,specification)
readers["hmtx"](f,fontdata,specification)
+ readers["vmtx"](f,fontdata,specification)
+ readers["vorg"](f,fontdata,specification)
readers["post"](f,fontdata,specification)
readers["cff" ](f,fontdata,specification)
readers["cmap"](f,fontdata,specification)
@@ -9249,6 +9373,13 @@ function readers.loadshapes(filename,n)
shapes=true,
subfont=n,
}
+ if fontdata then
+ for k,v in next,fontdata.glyphs do
+ v.class=nil
+ v.index=nil
+ v.math=nil
+ end
+ end
return fontdata and {
filename=filename,
format=fontdata.format,
@@ -9279,7 +9410,7 @@ function readers.loadfont(filename,n)
descriptions=fontdata.descriptions,
format=fontdata.format,
goodies={},
- metadata=getinfo(fontdata,n),
+ metadata=getinfo(fontdata,n,false,false,true),
properties={
hasitalics=fontdata.hasitalics or false,
maxcolorclass=fontdata.maxcolorclass,
@@ -9378,56 +9509,6 @@ function readers.extend(fontdata)
end
end
end
-if fonts.hashes then
- local identifiers=fonts.hashes.identifiers
- local loadshapes=readers.loadshapes
- readers.version=0.006
- readers.cache=containers.define("fonts","shapes",readers.version,true)
- local function load(filename,sub)
- local base=file.basename(filename)
- local name=file.removesuffix(base)
- local kind=file.suffix(filename)
- local attr=lfs.attributes(filename)
- local size=attr and attr.size or 0
- local time=attr and attr.modification or 0
- local sub=tonumber(sub)
- if size>0 and (kind=="otf" or kind=="ttf" or kind=="tcc") then
- local hash=containers.cleanname(base)
- if sub then
- hash=hash.."-"..sub
- end
- data=containers.read(readers.cache,hash)
- if not data or data.time~=time or data.size~=size then
- data=loadshapes(filename,sub)
- if data then
- data.size=size
- data.format=data.format or (kind=="otf" and "opentype") or "truetype"
- data.time=time
- packoutlines(data)
- containers.write(readers.cache,hash,data)
- data=containers.read(readers.cache,hash)
- end
- end
- unpackoutlines(data)
- else
- data={
- filename=filename,
- size=0,
- time=time,
- format="unknown",
- units=1000,
- glyphs={}
- }
- end
- return data
- end
- fonts.hashes.shapes=table.setmetatableindex(function(t,k)
- local d=identifiers[k]
- local v=load(d.properties.filename,d.subindex)
- t[k]=v
- return v
- end)
-end
end -- closure
@@ -9446,6 +9527,7 @@ local concat,remove=table.concat,table.remove
local floor,abs,round,ceil=math.floor,math.abs,math.round,math.ceil
local P,C,R,S,C,Cs,Ct=lpeg.P,lpeg.C,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Ct
local lpegmatch=lpeg.match
+local formatters=string.formatters
local readers=fonts.handlers.otf.readers
local streamreader=readers.streamreader
local readbytes=streamreader.readbytes
@@ -9846,6 +9928,7 @@ do
local ymax=0
local checked=false
local keepcurve=false
+ local version=2
local function showstate(where)
report("%w%-10s : [%s] n=%i",depth*2,where,concat(stack," ",1,top),top)
end
@@ -10268,9 +10351,91 @@ do
return floor((stems+7)/8)
end
end
- local function unsupported()
+ local function unsupported(t)
if trace_charstrings then
- showstate("unsupported")
+ showstate("unsupported "..t)
+ end
+ top=0
+ end
+ local function unsupportedsub(t)
+ if trace_charstrings then
+ showstate("unsupported sub "..t)
+ end
+ top=0
+ end
+ local function getstem3()
+ if trace_charstrings then
+ showstate("stem3")
+ end
+ top=0
+ end
+ local function divide()
+ if version==1 then
+ local d=stack[top]
+ top=top-1
+ stack[top]=stack[top]/d
+ end
+ end
+ local function closepath()
+ if version==1 then
+ if trace_charstrings then
+ showstate("closepath")
+ end
+ end
+ top=0
+ end
+ local function hsbw()
+ if version==1 then
+ if trace_charstrings then
+ showstate("dotsection")
+ end
+ width=stack[top]
+ end
+ top=0
+ end
+ local function seac()
+ if version==1 then
+ if trace_charstrings then
+ showstate("seac")
+ end
+ end
+ top=0
+ end
+ local function sbw()
+ if version==1 then
+ if trace_charstrings then
+ showstate("sbw")
+ end
+ width=stack[top-1]
+ end
+ top=0
+ end
+ local function callothersubr()
+ if version==1 then
+ if trace_charstrings then
+ showstate("callothersubr (unsupported)")
+ end
+ end
+ top=0
+ end
+ local function pop()
+ if version==1 then
+ if trace_charstrings then
+ showstate("pop (unsupported)")
+ end
+ top=top+1
+ stack[top]=0
+ else
+ top=0
+ end
+ end
+ local function setcurrentpoint()
+ if version==1 then
+ if trace_charstrings then
+ showstate("pop (unsupported)")
+ end
+ x=x+stack[top-1]
+ y=y+stack[top]
end
top=0
end
@@ -10287,7 +10452,7 @@ do
unsupported,
unsupported,
unsupported,
- unsupported,
+ hsbw,
unsupported,
unsupported,
unsupported,
@@ -10308,6 +10473,15 @@ do
hvcurveto,
}
local subactions={
+ [000]=dotsection,
+ [001]=getstem3,
+ [002]=getstem3,
+ [006]=seac,
+ [007]=sbw,
+ [012]=divide,
+ [016]=callothersubr,
+ [017]=pop,
+ [033]=setcurrentpoint,
[034]=hflex,
[035]=flex,
[036]=hflex1,
@@ -10315,23 +10489,29 @@ do
}
local p_bytes=Ct((P(1)/byte)^0)
local function call(scope,list,bias,process)
- local index=stack[top]+bias
- top=top-1
- if trace_charstrings then
- showvalue(scope,index,true)
- end
- local str=list[index]
- if str then
- if type(str)=="string" then
- str=lpegmatch(p_bytes,str)
- list[index]=str
- end
- depth=depth+1
- process(str)
- depth=depth-1
+ depth=depth+1
+ if top==0 then
+ showstate(formatters["unknown %s call"](scope))
+ top=0
else
- report("unknown %s %i",scope,index)
+ local index=stack[top]+bias
+ top=top-1
+ if trace_charstrings then
+ showvalue(scope,index,true)
+ end
+ local tab=list[index]
+ if tab then
+ if type(tab)=="string" then
+ tab=lpegmatch(p_bytes,tab)
+ list[index]=tab
+ end
+ process(tab)
+ else
+ showstate(formatters["unknown %s call %i"](scope,index))
+ top=0
+ end
end
+ depth=depth-1
end
local function process(tab)
local i=1
@@ -10398,7 +10578,7 @@ do
local t=tab[i]
local a=subactions[t]
if a then
- a()
+ a(t)
else
if trace_charstrings then
showvalue("<subaction>",t)
@@ -10409,7 +10589,7 @@ do
else
local a=actions[t]
if a then
- local s=a()
+ local s=a(t)
if s then
i=i+s
end
@@ -10423,25 +10603,38 @@ do
end
end
end
- parsecharstrings=function(data,glyphs,doshapes)
+ local function setbias(globals,locals)
+ if version==1 then
+ return
+ false,
+ false
+ else
+ local g,l=#globals,#locals
+ return
+ ((g<1240 and 107) or (g<33900 and 1131) or 32768)+1,
+ ((l<1240 and 107) or (l<33900 and 1131) or 32768)+1
+ end
+ end
+ parsecharstrings=function(data,glyphs,doshapes,tversion)
local dictionary=data.dictionaries[1]
local charstrings=dictionary.charstrings
local charset=dictionary.charset
+ local private=dictionary.private or { data={} }
keepcurve=doshapes
+ version=tversion
stack={}
glyphs=glyphs or {}
strings=data.strings
- locals=dictionary.subroutines
- globals=data.routines
- globalbias=#globals
- localbias=#locals
- globalbias=((globalbias<1240 and 107) or (globalbias<33900 and 1131) or 32768)+1
- localbias=((localbias<1240 and 107) or (localbias<33900 and 1131) or 32768)+1
- local nominalwidth=dictionary.private.data.nominalwidthx or 0
- local defaultwidth=dictionary.private.data.defaultwidthx or 0
+ globals=data.routines or {}
+ locals=dictionary.subroutines or {}
+ globalbias,localbias=setbias(globals,locals)
+ local nominalwidth=private.data.nominalwidthx or 0
+ local defaultwidth=private.data.defaultwidthx or 0
for i=1,#charstrings do
- local str=charstrings[i]
- local tab=lpegmatch(p_bytes,str)
+ local tab=charstrings[i]
+ if type(tab)=="string" then
+ tab=lpegmatch(p_bytes,tab)
+ end
local index=i-1
x=0
y=0
@@ -10492,19 +10685,19 @@ do
end
return glyphs
end
- parsecharstring=function(data,dictionary,charstring,glyphs,index,doshapes)
+ parsecharstring=function(data,dictionary,tab,glyphs,index,doshapes,tversion)
local private=dictionary.private
keepcurve=doshapes
+ version=tversion
strings=data.strings
locals=dictionary.subroutines or {}
globals=data.routines or {}
- globalbias=#globals
- localbias=#locals
- globalbias=((globalbias<1240 and 107) or (globalbias<33900 and 1131) or 32768)+1
- localbias=((localbias<1240 and 107) or (localbias<33900 and 1131) or 32768)+1
+ globalbias,localbias=setbias(globals,locals)
local nominalwidth=private and private.data.nominalwidthx or 0
local defaultwidth=private and private.data.defaultwidthx or 0
- local tab=lpegmatch(p_bytes,charstring)
+ if type(tab)=="string" then
+ tab=lpegmatch(p_bytes,tab)
+ end
x=0
y=0
width=false
@@ -10528,7 +10721,7 @@ do
else
width=nominalwidth+width
end
-index=index-1
+ index=index-1
local glyph=glyphs[index]
if not glyph then
glyphs[index]={
@@ -10551,7 +10744,6 @@ index=index-1
report("width: %s",tostring(width))
report("boundingbox: % t",boundingbox)
end
- return charstring
end
resetcharstrings=function()
result={}
@@ -10665,7 +10857,7 @@ local function readcidprivates(f,data)
end
parseprivates(data,dictionaries)
end
-local function readnoselect(f,data,glyphs,doshapes)
+local function readnoselect(f,data,glyphs,doshapes,version)
local dictionaries=data.dictionaries
local dictionary=dictionaries[1]
readglobals(f,data)
@@ -10675,10 +10867,11 @@ local function readnoselect(f,data,glyphs,doshapes)
readprivates(f,data)
parseprivates(data,data.dictionaries)
readlocals(f,data,dictionary)
- parsecharstrings(data,glyphs,doshapes)
+ parsecharstrings(data,glyphs,doshapes,version)
resetcharstrings()
end
-local function readfdselect(f,data,glyphs,doshapes)
+readers.parsecharstrings=parsecharstrings
+local function readfdselect(f,data,glyphs,doshapes,version)
local header=data.header
local dictionaries=data.dictionaries
local dictionary=dictionaries[1]
@@ -10736,7 +10929,7 @@ local function readfdselect(f,data,glyphs,doshapes)
readlocals(f,data,dictionaries[i])
end
for i=1,#charstrings do
- parsecharstring(data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes)
+ parsecharstring(data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes,version)
end
resetcharstrings()
end
@@ -11230,6 +11423,7 @@ local bittest=bit32.btest
local rshift=bit32.rshift
local concat=table.concat
local lower=string.lower
+local copy=table.copy
local sub=string.sub
local strip=string.strip
local tohash=table.tohash
@@ -11242,6 +11436,7 @@ local report=logs.reporter("otf reader")
local readers=fonts.handlers.otf.readers
local streamreader=readers.streamreader
local setposition=streamreader.setposition
+local getposition=streamreader.getposition
local skipshort=streamreader.skipshort
local readushort=streamreader.readcardinal2
local readulong=streamreader.readcardinal4
@@ -11355,10 +11550,15 @@ local function readcoverage(f,offset,simple)
end
return coverage
end
-local function readclassdef(f,offset)
+local function readclassdef(f,offset,preset)
setposition(f,offset)
local classdefformat=readushort(f)
local classdef={}
+ if type(preset)=="number" then
+ for k=0,preset-1 do
+ classdef[k]=1
+ end
+ end
if classdefformat==1 then
local index=readushort(f)
local nofclassdef=readushort(f)
@@ -11380,6 +11580,13 @@ local function readclassdef(f,offset)
else
report("unknown classdef format %a ",classdefformat)
end
+ if type(preset)=="table" then
+ for k in next,preset do
+ if not classdef[k] then
+ classdef[k]=1
+ end
+ end
+ end
return classdef
end
local function classtocoverage(defs)
@@ -11479,7 +11686,7 @@ local function covered(subset,all)
end
return used
end
-local function readlookuparray(f,noflookups)
+local function readlookuparray(f,noflookups,nofcurrent)
local lookups={}
if noflookups>0 then
local length=0
@@ -11522,7 +11729,7 @@ local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,n
for i=2,nofcurrent do
current[i]={ readushort(f) }
end
- local lookups=readlookuparray(f,noflookups)
+ local lookups=readlookuparray(f,noflookups,nofcurrent)
rules[#rules+1]={
current=current,
lookups=lookups
@@ -11544,7 +11751,7 @@ local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,n
local rules={}
if subclasssets then
coverage=readcoverage(f,tableoffset+coverage)
- currentclassdef=readclassdef(f,tableoffset+currentclassdef)
+ currentclassdef=readclassdef(f,tableoffset+currentclassdef,coverage)
local currentclasses=classtocoverage(currentclassdef,fontdata.glyphs)
for class=1,#subclasssets do
local offset=subclasssets[class]
@@ -11563,7 +11770,7 @@ local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,n
for i=2,nofcurrent do
current[i]=currentclasses[readushort(f)+1]
end
- local lookups=readlookuparray(f,noflookups)
+ local lookups=readlookuparray(f,noflookups,nofcurrent)
rules[#rules+1]={
current=current,
lookups=lookups
@@ -11587,7 +11794,7 @@ local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,n
elseif subtype==3 then
local current=readarray(f)
local noflookups=readushort(f)
- local lookups=readlookuparray(f,noflookups)
+ local lookups=readlookuparray(f,noflookups,#current)
current=readcoveragearray(f,tableoffset,current,true)
return {
format="coverage",
@@ -11642,7 +11849,7 @@ local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nof
end
end
local noflookups=readushort(f)
- local lookups=readlookuparray(f,noflookups)
+ local lookups=readlookuparray(f,noflookups,nofcurrent)
rules[#rules+1]={
before=before,
current=current,
@@ -11668,9 +11875,9 @@ local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nof
local rules={}
if subclasssets then
local coverage=readcoverage(f,tableoffset+coverage)
- local beforeclassdef=readclassdef(f,tableoffset+beforeclassdef)
- local currentclassdef=readclassdef(f,tableoffset+currentclassdef)
- local afterclassdef=readclassdef(f,tableoffset+afterclassdef)
+ local beforeclassdef=readclassdef(f,tableoffset+beforeclassdef,nofglyphs)
+ local currentclassdef=readclassdef(f,tableoffset+currentclassdef,coverage)
+ local afterclassdef=readclassdef(f,tableoffset+afterclassdef,nofglyphs)
local beforeclasses=classtocoverage(beforeclassdef,fontdata.glyphs)
local currentclasses=classtocoverage(currentclassdef,fontdata.glyphs)
local afterclasses=classtocoverage(afterclassdef,fontdata.glyphs)
@@ -11707,7 +11914,7 @@ local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nof
end
end
local noflookups=readushort(f)
- local lookups=readlookuparray(f,noflookups)
+ local lookups=readlookuparray(f,noflookups,nofcurrent)
rules[#rules+1]={
before=before,
current=current,
@@ -11735,7 +11942,7 @@ local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nof
local current=readarray(f)
local after=readarray(f)
local noflookups=readushort(f)
- local lookups=readlookuparray(f,noflookups)
+ local lookups=readlookuparray(f,noflookups,#current)
before=readcoveragearray(f,tableoffset,before,true)
current=readcoveragearray(f,tableoffset,current,true)
after=readcoveragearray(f,tableoffset,after,true)
@@ -12061,8 +12268,8 @@ function gposhandlers.pair(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofgly
local nofclasses2=readushort(f)
local classlist=readpairclasssets(f,nofclasses1,nofclasses2,format1,format2)
coverage=readcoverage(f,tableoffset+coverage)
- classdef1=readclassdef(f,tableoffset+classdef1)
- classdef2=readclassdef(f,tableoffset+classdef2)
+ classdef1=readclassdef(f,tableoffset+classdef1,coverage)
+ classdef2=readclassdef(f,tableoffset+classdef2,nofglyphs)
local usedcoverage={}
for g1,c1 in next,classdef1 do
if coverage[g1] then
@@ -12285,15 +12492,39 @@ function gposhandlers.extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,n
end
do
local plugins={}
- function plugins.size(f,fontdata,tableoffset,parameters)
- if not fontdata.designsize then
- setposition(f,tableoffset+parameters)
- local designsize=readushort(f)
- if designsize>0 then
+ function plugins.size(f,fontdata,tableoffset,feature)
+ if fontdata.designsize then
+ else
+ local function check(offset)
+ setposition(f,offset)
+ local designsize=readushort(f)
+ if designsize>0 then
+ local fontstyle=readushort(f)
+ local guimenuid=readushort(f)
+ local minsize=readushort(f)
+ local maxsize=readushort(f)
+ if minsize==0 and maxsize==0 and fontstyleid==0 and guimenuid==0 then
+ minsize=designsize
+ maxsize=designsize
+ end
+ if designsize>=minsize and designsize<=maxsize then
+ return minsize,maxsize,designsize
+ end
+ end
+ end
+ local minsize,maxsize,designsize=check(tableoffset+feature.offset+feature.parameters)
+ if not designsize then
+ minsize,maxsize,designsize=check(tableoffset+feature.parameters)
+ if designsize then
+ report("bad size feature in %a, falling back to wrong offset",fontdata.filename or "?")
+ else
+ report("bad size feature in %a,",fontdata.filename or "?")
+ end
+ end
+ if designsize then
+ fontdata.minsize=minsize
+ fontdata.maxsize=maxsize
fontdata.designsize=designsize
- skipshort(f,2)
- fontdata.minsize=readushort(f)
- fontdata.maxsize=readushort(f)
end
end
end
@@ -12430,7 +12661,7 @@ do
feature.parameters=parameters
local plugin=plugins[feature.tag]
if plugin then
- plugin(f,fontdata,offset,parameters)
+ plugin(f,fontdata,featureoffset,feature)
end
end
end
@@ -12651,7 +12882,7 @@ do
markclass=d.markclass or nil,
flags=d.flags,
}
- sublookuplist[nofsublookups]=h
+ sublookuplist[nofsublookups]=copy(h)
sublookuphash[lookupid]=nofsublookups
sublookupcheck[lookupid]=1
else
@@ -12863,7 +13094,7 @@ function readers.gdef(f,fontdata,specification)
end
end
end
- if marksetsoffset then
+ if marksetsoffset and marksetsoffset>tableoffset then
setposition(f,marksetsoffset)
local format=readushort(f)
if format==1 then
@@ -13341,7 +13572,11 @@ local f_unicode=formatters["U%05X"]
local f_index=formatters["I%05X"]
local f_character_y=formatters["%C"]
local f_character_n=formatters["[ %C ]"]
-local doduplicates=true
+local check_duplicates=true
+local check_soft_hyphen=false
+directives.register("otf.checksofthyphen",function(v)
+ check_soft_hyphen=v
+end)
local function replaced(list,index,replacement)
if type(list)=="number" then
return replacement
@@ -13409,7 +13644,7 @@ local function unifyresources(fontdata,indices)
end
end
local done={}
- local duplicates=doduplicates and resources.duplicates
+ local duplicates=check_duplicates and resources.duplicates
if duplicates and not next(duplicates) then
duplicates=false
end
@@ -13646,10 +13881,31 @@ local function unifyresources(fontdata,indices)
unifythem(resources.sublookups)
end
local function copyduplicates(fontdata)
- if doduplicates then
+ if check_duplicates then
local descriptions=fontdata.descriptions
local resources=fontdata.resources
local duplicates=resources.duplicates
+ if check_soft_hyphen then
+ local ds=descriptions[0xAD]
+ if not ds or ds.width==0 then
+ if ds then
+ descriptions[0xAD]=nil
+ report("patching soft hyphen")
+ else
+ report("adding soft hyphen")
+ end
+ if not duplicates then
+ duplicates={}
+ resources.duplicates=duplicates
+ end
+ local dh=duplicates[0x2D]
+ if dh then
+ dh[#dh+1]={ [0xAD]=true }
+ else
+ duplicates[0x2D]={ [0xAD]=true }
+ end
+ end
+ end
if duplicates then
for u,d in next,duplicates do
local du=descriptions[u]
@@ -14090,6 +14346,7 @@ function readers.getcomponents(fontdata)
end
end
end
+readers.unifymissing=unifymissing
function readers.rehash(fontdata,hashmethod)
if not (fontdata and fontdata.glyphs) then
return
@@ -15346,7 +15603,6 @@ if not modules then modules={} end modules ['font-otl']={
local gmatch,find,match,lower,strip=string.gmatch,string.find,string.match,string.lower,string.strip
local type,next,tonumber,tostring,unpack=type,next,tonumber,tostring,unpack
local abs=math.abs
-local ioflush=io.flush
local derivetable=table.derive
local formatters=string.formatters
local setmetatableindex=table.setmetatableindex
@@ -15363,7 +15619,7 @@ local trace_defining=false registertracker("fonts.defining",function(v) trace_de
local report_otf=logs.reporter("fonts","otf loading")
local fonts=fonts
local otf=fonts.handlers.otf
-otf.version=3.023
+otf.version=3.027
otf.cache=containers.define("fonts","otl",otf.version,true)
otf.svgcache=containers.define("fonts","svg",otf.version,true)
otf.pdfcache=containers.define("fonts","pdf",otf.version,true)
@@ -15375,10 +15631,8 @@ local readers=fonts.readers
local constructors=fonts.constructors
local otffeatures=constructors.features.otf
local registerotffeature=otffeatures.register
-local enhancers=allocate()
-otf.enhancers=enhancers
-local patches={}
-enhancers.patches=patches
+local otfenhancers=constructors.enhancers.otf
+local registerotfenhancer=otfenhancers.register
local forceload=false
local cleanup=0
local syncspace=true
@@ -15394,76 +15648,7 @@ registerdirective("fonts.otf.loader.cleanup",function(v) cleanup=tonumber(v) or
registerdirective("fonts.otf.loader.force",function(v) forceload=v end)
registerdirective("fonts.otf.loader.syncspace",function(v) syncspace=v end)
registerdirective("fonts.otf.loader.forcenotdef",function(v) forcenotdef=v end)
-local ordered_enhancers={
- "check extra features",
-}
-local actions=allocate()
-local before=allocate()
-local after=allocate()
-patches.before=before
-patches.after=after
-local function enhance(name,data,filename,raw)
- local enhancer=actions[name]
- if enhancer then
- if trace_loading then
- report_otf("apply enhancement %a to file %a",name,filename)
- ioflush()
- end
- enhancer(data,filename,raw)
- else
- end
-end
-function enhancers.apply(data,filename,raw)
- local basename=file.basename(lower(filename))
- if trace_loading then
- report_otf("%s enhancing file %a","start",filename)
- end
- ioflush()
- for e=1,#ordered_enhancers do
- local enhancer=ordered_enhancers[e]
- local b=before[enhancer]
- if b then
- for pattern,action in next,b do
- if find(basename,pattern) then
- action(data,filename,raw)
- end
- end
- end
- enhance(enhancer,data,filename,raw)
- local a=after[enhancer]
- if a then
- for pattern,action in next,a do
- if find(basename,pattern) then
- action(data,filename,raw)
- end
- end
- end
- ioflush()
- end
- if trace_loading then
- report_otf("%s enhancing file %a","stop",filename)
- end
- ioflush()
-end
-function patches.register(what,where,pattern,action)
- local pw=patches[what]
- if pw then
- local ww=pw[where]
- if ww then
- ww[pattern]=action
- else
- pw[where]={ [pattern]=action}
- end
- end
-end
-function patches.report(fmt,...)
- if trace_loading then
- report_otf("patching: %s",formatters[fmt](...))
- end
-end
-function enhancers.register(what,action)
- actions[what]=action
-end
+registerotfenhancer("check extra features",function() end)
function otf.load(filename,sub,featurefile)
local featurefile=nil
local base=file.basename(file.removesuffix(filename))
@@ -15541,7 +15726,7 @@ function otf.load(filename,sub,featurefile)
collectgarbage("collect")
end
stoptiming(otfreaders)
- if elapsedtime then
+ if elapsedtime then
report_otf("loading, optimizing, packing and caching time %s",elapsedtime(otfreaders))
end
if cleanup>3 then
@@ -15563,7 +15748,7 @@ function otf.load(filename,sub,featurefile)
otfreaders.unpack(data)
otfreaders.expand(data)
otfreaders.addunicodetable(data)
- enhancers.apply(data,filename,data)
+ otfenhancers.apply(data,filename,data)
if applyruntimefixes then
applyruntimefixes(filename,data)
end
@@ -15703,13 +15888,13 @@ local function copytotfm(data,cache_id)
spaceunits,spacer=charwidth,"charwidth"
end
end
- spaceunits=tonumber(spaceunits) or 500
+ spaceunits=tonumber(spaceunits) or units/2
parameters.slant=0
- parameters.space=spaceunits
+ parameters.space=spaceunits
parameters.space_stretch=1*units/2
- parameters.space_shrink=1*units/3
- parameters.x_height=2*units/5
- parameters.quad=units
+ parameters.space_shrink=1*units/3
+ parameters.x_height=2*units/5
+ parameters.quad=units
if spaceunits<2*units/5 then
end
if italicangle and italicangle~=0 then
@@ -15762,10 +15947,38 @@ local function copytotfm(data,cache_id)
}
end
end
+local converters={
+ woff={
+ cachename="webfonts",
+ action=otf.readers.woff2otf,
+ }
+}
+local function checkconversion(specification)
+ local filename=specification.filename
+ local converter=converters[lower(file.suffix(filename))]
+ if converter then
+ local base=file.basename(filename)
+ local name=file.removesuffix(base)
+ local attr=lfs.attributes(filename)
+ local size=attr and attr.size or 0
+ local time=attr and attr.modification or 0
+ if size>0 then
+ local cleanname=containers.cleanname(name)
+ local cachename=caches.setfirstwritablefile(cleanname,converter.cachename)
+ if not io.exists(cachename) or (time~=lfs.attributes(cachename).modification) then
+ report_otf("caching font %a in %a",filename,cachename)
+ converter.action(filename,cachename)
+ lfs.touch(cachename,time,time)
+ end
+ specification.filename=cachename
+ end
+ end
+end
local function otftotfm(specification)
local cache_id=specification.hash
local tfmdata=containers.read(constructors.cache,cache_id)
if not tfmdata then
+ checkconversion(specification)
local name=specification.name
local sub=specification.sub
local subindex=specification.subindex
@@ -15895,7 +16108,6 @@ local function getgsub(tfmdata,k,kind,value)
local properties=tfmdata.properties
local validlookups,lookuplist=otf.collectlookups(rawdata,kind,properties.script,properties.language)
if validlookups then
- local choice=tonumber(value) or 1
for i=1,#lookuplist do
local lookup=lookuplist[i]
local steps=lookup.steps
@@ -15973,9 +16185,13 @@ local function opentypereader(specification,suffix)
end
end
readers.opentype=opentypereader
-function readers.otf (specification) return opentypereader(specification,"otf") end
-function readers.ttf (specification) return opentypereader(specification,"ttf") end
-function readers.ttc (specification) return opentypereader(specification,"ttf") end
+function readers.otf(specification) return opentypereader(specification,"otf") end
+function readers.ttf(specification) return opentypereader(specification,"ttf") end
+function readers.ttc(specification) return opentypereader(specification,"ttf") end
+function readers.woff(specification)
+ checkconversion(specification)
+ opentypereader(specification,"")
+end
function otf.scriptandlanguage(tfmdata,attr)
local properties=tfmdata.properties
return properties.script or "dflt",properties.language or "dflt"
@@ -16119,7 +16335,7 @@ local function registerbasehash(tfmdata)
basehash[hash]=base
end
properties.basehash=base
- properties.fullname=properties.fullname.."-"..base
+ properties.fullname=(properties.fullname or properties.name).."-"..base
applied={}
end
local function registerbasefeature(feature,value)
@@ -16187,6 +16403,10 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
local trace_singles=trace_baseinit and trace_singles
local trace_alternatives=trace_baseinit and trace_alternatives
local trace_ligatures=trace_baseinit and trace_ligatures
+ if not changed then
+ changed={}
+ tfmdata.changed=changed
+ end
for i=1,#lookuplist do
local sequence=lookuplist[i]
local steps=sequence.steps
@@ -16194,12 +16414,10 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
if kind=="gsub_single" then
for i=1,#steps do
for unicode,data in next,steps[i].coverage do
- if not changed[unicode] then
if trace_singles then
report_substitution(feature,sequence,descriptions,unicode,data)
end
changed[unicode]=data
- end
end
end
elseif kind=="gsub_alternate" then
@@ -16340,7 +16558,8 @@ local function featuresinitializer(tfmdata,value)
local properties=tfmdata.properties
local script=properties.script
local language=properties.language
- local rawfeatures=rawdata.resources.features
+ local rawresources=rawdata.resources
+ local rawfeatures=rawresources and rawresources.features
local basesubstitutions=rawfeatures and rawfeatures.gsub
local basepositionings=rawfeatures and rawfeatures.gpos
if basesubstitutions or basepositionings then
@@ -16411,7 +16630,7 @@ local registertracker=trackers.register
local trace_injections=false registertracker("fonts.injections",function(v) trace_injections=v end)
local trace_marks=false registertracker("fonts.injections.marks",function(v) trace_marks=v end)
local trace_cursive=false registertracker("fonts.injections.cursive",function(v) trace_cursive=v end)
-local trace_spaces=false registertracker("otf.spaces",function(v) trace_spaces=v end)
+local trace_spaces=false registertracker("fonts.injections.spaces",function(v) trace_spaces=v end)
local use_advance=false directives.register("fonts.injections.advance",function(v) use_advance=v end)
local report_injections=logs.reporter("fonts","injections")
local report_spaces=logs.reporter("fonts","spaces")
@@ -16677,7 +16896,7 @@ function injections.setkern(current,factor,rlmode,x,injection)
return 0,0
end
end
-function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk)
+function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk,checkmark)
local dx,dy=factor*(ba[1]-ma[1]),factor*(ba[2]-ma[2])
nofregisteredmarks=nofregisteredmarks+1
if rlmode>=0 then
@@ -16695,6 +16914,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk)
i.markbase=nofregisteredmarks
i.markbasenode=base
i.markmark=mkmk
+ i.checkmark=checkmark
end
else
p.injections={
@@ -16704,6 +16924,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk)
markbase=nofregisteredmarks,
markbasenode=base,
markmark=mkmk,
+ checkmark=checkmark,
}
end
else
@@ -16715,6 +16936,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk)
markbase=nofregisteredmarks,
markbasenode=base,
markmark=mkmk,
+ checkmark=checkmark,
},
}
end
@@ -17266,10 +17488,16 @@ local function inject_everything(head,where)
end
else
ox=px-pn.markx
- local wn=getfield(n,"width")
- if wn~=0 then
- pn.leftkern=-wn/2
- pn.rightkern=-wn/2
+ if pn.checkmark then
+ local wn=getfield(n,"width")
+ if wn~=0 then
+ wn=wn/2
+ if trace_injections then
+ report_injections("correcting non zero width mark %C",getchar(n))
+ end
+ insert_node_before(n,n,newkern(-wn))
+ insert_node_after(n,n,newkern(-wn))
+ end
end
end
local oy=getfield(n,"yoffset")+getfield(p,"yoffset")+pn.marky
@@ -17293,6 +17521,10 @@ local function inject_everything(head,where)
nofmarks=nofmarks+1
marks[nofmarks]=current
else
+ local yoffset=i.yoffset
+ if yoffset and yoffset~=0 then
+ setfield(current,"yoffset",yoffset)
+ end
if hascursives then
local cursivex=i.cursivex
if cursivex then
@@ -17344,10 +17576,6 @@ local function inject_everything(head,where)
cursiveanchor=nil
end
end
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(current,"yoffset",yoffset)
- end
local leftkern=i.leftkern
if leftkern and leftkern~=0 then
insert_node_before(head,current,newkern(leftkern))
@@ -17594,6 +17822,37 @@ function nodes.injections.setspacekerns(font,sequence)
triggers={ [font]=sequence }
end
end
+local getthreshold
+if context then
+ local threshold=1
+ local parameters=fonts.hashes.parameters
+ directives.register("otf.threshold",function(v) threshold=tonumber(v) or 1 end)
+ getthreshold=function(font)
+ local p=parameters[font]
+ local f=p.factor
+ local s=p.spacing
+ local t=threshold*(s and s.width or p.space or 0)-2
+ return t>0 and t or 0,f
+ end
+else
+ injections.threshold=0
+ getthreshold=function(font)
+ local p=fontdata[font].parameters
+ local f=p.factor
+ local s=p.spacing
+ local t=injections.threshold*(s and s.width or p.space or 0)-2
+ return t>0 and t or 0,f
+ end
+end
+injections.getthreshold=getthreshold
+function injections.isspace(n,threshold)
+ if getid(n)==glue_code then
+ local w=getfield(n,"width")
+ if threshold and w>threshold then
+ return 32
+ end
+ end
+end
local function injectspaces(head)
if not triggers then
return head,false
@@ -17609,10 +17868,9 @@ local function injectspaces(head)
local function updatefont(font,trig)
leftkerns=trig.left
rightkerns=trig.right
- local par=fontdata[font].parameters
- factor=par.factor
- threshold=par.spacing.width-1
lastfont=font
+ threshold,
+ factor=getthreshold(font)
end
for n in traverse_id(glue_code,tonut(head)) do
local prev,next=getboth(n)
@@ -17631,7 +17889,7 @@ local function injectspaces(head)
end
end
if prevchar then
- local font=getfont(next)
+ local font=getfont(prev)
local trig=triggers[font]
if trig then
if lastfont~=font then
@@ -17644,7 +17902,7 @@ local function injectspaces(head)
end
if leftkern then
local old=getfield(n,"width")
- if old>=threshold then
+ if old>threshold then
if rightkern then
local new=old+(leftkern+rightkern)*factor
if trace_spaces then
@@ -17663,7 +17921,7 @@ local function injectspaces(head)
leftkern=false
elseif rightkern then
local old=getfield(n,"width")
- if old>=threshold then
+ if old>threshold then
local new=old+rightkern*factor
if trace_spaces then
report_spaces("[%p -> %p] %C",nextchar,old,new)
@@ -17907,33 +18165,40 @@ local mappers={
}
local classifiers=characters.classifiers
if not classifiers then
- local first_arabic,last_arabic=characters.blockrange("arabic")
- local first_syriac,last_syriac=characters.blockrange("syriac")
- local first_mandiac,last_mandiac=characters.blockrange("mandiac")
- local first_nko,last_nko=characters.blockrange("nko")
+ local f_arabic,l_arabic=characters.blockrange("arabic")
+ local f_syriac,l_syriac=characters.blockrange("syriac")
+ local f_mandiac,l_mandiac=characters.blockrange("mandiac")
+ local f_nko,l_nko=characters.blockrange("nko")
+ local f_ext_a,l_ext_a=characters.blockrange("arabicextendeda")
classifiers=table.setmetatableindex(function(t,k)
- local c=chardata[k]
- local v=false
- if c then
- local arabic=c.arabic
- if arabic then
- v=mappers[arabic]
- if not v then
- log.report("analyze","error in mapping arabic %C",k)
- v=false
- end
- elseif k>=first_arabic and k<=last_arabic or k>=first_syriac and k<=last_syriac or
- k>=first_mandiac and k<=last_mandiac or k>=first_nko and k<=last_nko then
- if categories[k]=="mn" then
- v=s_mark
- else
- v=s_rest
+ if type(k)=="number" then
+ local c=chardata[k]
+ local v=false
+ if c then
+ local arabic=c.arabic
+ if arabic then
+ v=mappers[arabic]
+ if not v then
+ log.report("analyze","error in mapping arabic %C",k)
+ v=false
+ end
+ elseif (k>=f_arabic and k<=l_arabic) or
+ (k>=f_syriac and k<=l_syriac) or
+ (k>=f_mandiac and k<=l_mandiac) or
+ (k>=f_nko and k<=l_nko) or
+ (k>=f_ext_a and k<=l_ext_a) then
+ if categories[k]=="mn" then
+ v=s_mark
+ else
+ v=s_rest
+ end
end
end
+ t[k]=v
+ return v
end
- t[k]=v
- return v
end)
+ characters.classifiers=classifiers
end
function methods.arab(head,font,attr)
local first,last=nil,nil
@@ -18110,15 +18375,13 @@ local trace_details=false registertracker("otf.details",function(v) trace_detail
local trace_steps=false registertracker("otf.steps",function(v) trace_steps=v end)
local trace_skips=false registertracker("otf.skips",function(v) trace_skips=v end)
local trace_directions=false registertracker("otf.directions",function(v) trace_directions=v end)
+local trace_plugins=false registertracker("otf.plugins",function(v) trace_plugins=v end)
local trace_kernruns=false registertracker("otf.kernruns",function(v) trace_kernruns=v end)
local trace_discruns=false registertracker("otf.discruns",function(v) trace_discruns=v end)
local trace_compruns=false registertracker("otf.compruns",function(v) trace_compruns=v end)
local trace_testruns=false registertracker("otf.testruns",function(v) trace_testruns=v end)
-local quit_on_no_replacement=true
-local zwnjruns=true
local optimizekerns=true
-registerdirective("otf.zwnjruns",function(v) zwnjruns=v end)
-registerdirective("otf.chain.quitonnoreplacement",function(value) quit_on_no_replacement=value end)
+local alwaysdisc=true registerdirective("otf.alwaysdisc",function(v) alwaysdisc=v end)
local report_direct=logs.reporter("fonts","otf direct")
local report_subchain=logs.reporter("fonts","otf subchain")
local report_chain=logs.reporter("fonts","otf chain")
@@ -18160,7 +18423,7 @@ local copy_node=nuts.copy
local copy_node_list=nuts.copy_list
local find_node_tail=nuts.tail
local flush_node_list=nuts.flush_list
-local free_node=nuts.free
+local flush_node=nuts.flush_node
local end_of_math=nuts.end_of_math
local traverse_nodes=nuts.traverse
local traverse_id=nuts.traverse_id
@@ -18195,9 +18458,11 @@ local getligaindex=injections.getligaindex
local cursonce=true
local fonthashes=fonts.hashes
local fontdata=fonthashes.identifiers
+local fontfeatures=fonthashes.features
local otffeatures=fonts.constructors.features.otf
local registerotffeature=otffeatures.register
local onetimemessage=fonts.loggers.onetimemessage or function() end
+local getrandom=utilities and utilities.randomizer and utilities.randomizer.get
otf.defaultnodealternate="none"
local tfmdata=false
local characters=false
@@ -18206,6 +18471,7 @@ local marks=false
local currentfont=false
local factor=0
local threshold=0
+local checkmarks=false
local sweepnode=nil
local sweepprev=nil
local sweepnext=nil
@@ -18214,17 +18480,17 @@ local notmatchpre={}
local notmatchpost={}
local notmatchreplace={}
local handlers={}
-local function isspace(n)
- if getid(n)==glue_code then
- local w=getfield(n,"width")
- if w>=threshold then
- return 32
- end
- end
-end
+local isspace=injections.isspace
+local getthreshold=injections.getthreshold
local checkstep=(nodes and nodes.tracers and nodes.tracers.steppers.check) or function() end
local registerstep=(nodes and nodes.tracers and nodes.tracers.steppers.register) or function() end
local registermessage=(nodes and nodes.tracers and nodes.tracers.steppers.message) or function() end
+local function checkdisccontent(d)
+ local pre,post,replace=getdisc(d)
+ if pre then for n in traverse_id(glue_code,pre) do print("pre",nodes.idstostring(pre)) break end end
+ if post then for n in traverse_id(glue_code,post) do print("pos",nodes.idstostring(post)) break end end
+ if replace then for n in traverse_id(glue_code,replace) do print("rep",nodes.idstostring(replace)) break end end
+end
local function logprocess(...)
if trace_steps then
registermessage(...)
@@ -18285,7 +18551,7 @@ end
local function copy_glyph(g)
local components=getfield(g,"components")
if components then
- setfield(g,"components",nil)
+ setfield(g,"components")
local n=copy_node(g)
copyinjection(n,g)
setfield(g,"components",components)
@@ -18297,11 +18563,18 @@ local function copy_glyph(g)
end
end
local function flattendisk(head,disc)
- local _,_,replace,_,_,replacetail=getdisc(disc,true)
- setfield(disc,"replace",nil)
- free_node(disc)
- if head==disc then
- local next=getnext(disc)
+ local pre,post,replace,pretail,posttail,replacetail=getdisc(disc,true)
+ local prev,next=getboth(disc)
+ local ishead=head==disc
+ setdisc(disc)
+ flush_node(disc)
+ if pre then
+ flush_node_list(pre)
+ end
+ if post then
+ flush_node_list(post)
+ end
+ if ishead then
if replace then
if next then
setlink(replacetail,next)
@@ -18313,7 +18586,6 @@ local function flattendisk(head,disc)
return
end
else
- local prev,next=getboth(disc)
if replace then
if next then
setlink(replacetail,next)
@@ -18348,8 +18620,8 @@ local function markstoligature(head,start,stop,char)
else
local prev=getprev(start)
local next=getnext(stop)
- setprev(start,nil)
- setnext(stop,nil)
+ setprev(start)
+ setnext(stop)
local base=copy_glyph(start)
if head==start then
head=base
@@ -18396,8 +18668,8 @@ local function toligature(head,start,stop,char,dataset,sequence,markflag,discfou
local prev=getprev(start)
local next=getnext(stop)
local comp=start
- setprev(start,nil)
- setnext(stop,nil)
+ setprev(start)
+ setnext(stop)
local base=copy_glyph(start)
if start==head then
head=base
@@ -18461,45 +18733,45 @@ local function toligature(head,start,stop,char,dataset,sequence,markflag,discfou
local pre,post,replace,pretail,posttail,replacetail=getdisc(discfound,true)
if not replace then
local prev=getprev(base)
-local current=comp
-local previous=nil
-local copied=nil
-while current do
- if getid(current)==glyph_code then
- local n=copy_node(current)
- if copied then
- setlink(previous,n)
- else
- copied=n
- end
- previous=n
- end
- current=getnext(current)
-end
- setprev(discnext,nil)
- setnext(discprev,nil)
+ local current=comp
+ local previous=nil
+ local copied=nil
+ while current do
+ if getid(current)==glyph_code then
+ local n=copy_node(current)
+ if copied then
+ setlink(previous,n)
+ else
+ copied=n
+ end
+ previous=n
+ end
+ current=getnext(current)
+ end
+ setprev(discnext)
+ setnext(discprev)
if pre then
setlink(discprev,pre)
end
pre=comp
if post then
setlink(posttail,discnext)
- setprev(post,nil)
+ setprev(post)
else
post=discnext
end
setlink(prev,discfound)
setlink(discfound,next)
- setboth(base,nil,nil)
+ setboth(base)
setfield(base,"components",copied)
- setdisc(discfound,pre,post,base,discretionary_code)
+ setdisc(discfound,pre,post,base)
base=prev
end
end
end
return head,base
end
-local function multiple_glyphs(head,start,multiple,ignoremarks)
+local function multiple_glyphs(head,start,multiple,ignoremarks,what)
local nofmultiples=#multiple
if nofmultiples>0 then
resetinjection(start)
@@ -18513,6 +18785,17 @@ local function multiple_glyphs(head,start,multiple,ignoremarks)
insert_node_after(head,start,n)
start=n
end
+ if what==true then
+ elseif what>1 then
+ local m=multiple[nofmultiples]
+ for i=2,what do
+ local n=copy_node(start)
+ resetinjection(n)
+ setchar(n,m)
+ insert_node_after(head,start,n)
+ start=n
+ end
+ end
end
return head,start,true
else
@@ -18525,7 +18808,7 @@ end
local function get_alternative_glyph(start,alternatives,value)
local n=#alternatives
if value=="random" then
- local r=random(1,n)
+ local r=getrandom and getrandom("glyph",1,n) or random(1,n)
return alternatives[r],trace_alternatives and formatters["value %a, taking %a"](value,r)
elseif value=="first" then
return alternatives[1],trace_alternatives and formatters["value %a, taking %a"](value,1)
@@ -18583,7 +18866,7 @@ function handlers.gsub_multiple(head,start,dataset,sequence,multiple)
if trace_multiples then
logprocess("%s: replacing %s by multiple %s",pref(dataset,sequence),gref(getchar(start)),gref(multiple))
end
- return multiple_glyphs(head,start,multiple,sequence.flags[1])
+ return multiple_glyphs(head,start,multiple,sequence.flags[1],dataset[1])
end
function handlers.gsub_ligature(head,start,dataset,sequence,ligature)
local current=getnext(start)
@@ -18804,7 +19087,7 @@ function handlers.gpos_mark2base(head,start,dataset,sequence,markanchors,rlmode)
local ba=markanchors[1][basechar]
if ba then
local ma=markanchors[2]
- local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
+ local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -18859,7 +19142,7 @@ function handlers.gpos_mark2ligature(head,start,dataset,sequence,markanchors,rlm
local index=getligaindex(start)
ba=ba[index]
if ba then
- local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
+ local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks)
if trace_marks then
logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
pref(dataset,sequence),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy)
@@ -18906,7 +19189,7 @@ function handlers.gpos_mark2mark(head,start,dataset,sequence,markanchors,rlmode)
local ba=markanchors[1][basechar]
if ba then
local ma=markanchors[2]
- local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true)
+ local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true,checkmarks)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -19038,7 +19321,7 @@ function chainprocs.gsub_multiple(head,start,stop,dataset,sequence,currentlookup
if trace_multiples then
logprocess("%s: replacing %s by multiple characters %s",cref(dataset,sequence),gref(startchar),gref(replacement))
end
- return multiple_glyphs(head,start,replacement,sequence.flags[1])
+ return multiple_glyphs(head,start,replacement,sequence.flags[1],dataset[1])
end
return head,start,false
end
@@ -19050,7 +19333,7 @@ function chainprocs.gsub_alternate(head,start,stop,dataset,sequence,currentlooku
end
local kind=dataset[4]
local what=dataset[1]
- local value=what==true and tfmdata.shared.features[kind] or what
+ local value=what==true and tfmdata.shared.features[kind] or what
local current=start
while current do
local currentchar=ischar(current)
@@ -19288,7 +19571,7 @@ function chainprocs.gpos_mark2base(head,start,stop,dataset,sequence,currentlooku
if ba then
local ma=markanchors[2]
if ma then
- local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
+ local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -19354,7 +19637,7 @@ function chainprocs.gpos_mark2ligature(head,start,stop,dataset,sequence,currentl
local index=getligaindex(start)
ba=ba[index]
if ba then
- local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar])
+ local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
cref(dataset,sequence),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy)
@@ -19406,7 +19689,7 @@ function chainprocs.gpos_mark2mark(head,start,stop,dataset,sequence,currentlooku
if ba then
local ma=markanchors[2]
if ma then
- local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true)
+ local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true,checkmarks)
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
@@ -19483,6 +19766,39 @@ end
local function show_skip(dataset,sequence,char,ck,class)
logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(dataset,sequence),gref(char),class,ck[1],ck[8] or ck[2])
end
+local new_kern=nuts.pool.kern
+local function checked(head)
+ local current=head
+ while current do
+ if getid(current)==glue_code then
+ local kern=new_kern(getfield(current,"width"))
+ if head==current then
+ local next=getnext(current)
+ if next then
+ setlink(kern,next)
+ end
+ flush_node(current)
+ head=kern
+ current=next
+ else
+ local prev,next=getboth(current)
+ setlink(prev,kern)
+ setlink(kern,next)
+ flush_node(current)
+ current=next
+ end
+ else
+ current=getnext(current)
+ end
+ end
+ return head
+end
+local function setdiscchecked(d,pre,post,replace)
+ if pre then pre=checked(pre) end
+ if post then post=checked(post) end
+ if replace then replace=checked(replace) end
+ setdisc(d,pre,post,replace)
+end
local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,ck,chainproc)
if not start then
return head,start,false
@@ -19503,6 +19819,7 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
local current=start
local last=start
local prev=getprev(start)
+ local hasglue=false
local i=f
while i<=l do
local id=getid(current)
@@ -19510,6 +19827,11 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
i=i+1
last=current
current=getnext(current)
+ elseif id==glue_code then
+ i=i+1
+ last=current
+ current=getnext(current)
+ hasglue=true
elseif id==disc_code then
if keepdisc then
keepdisc=false
@@ -19559,8 +19881,8 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
tail=find_node_tail(head)
end
setnext(sweepnode,current)
- setprev(head,nil)
- setnext(tail,nil)
+ setprev(head)
+ setnext(tail)
appenddisc(sweepnode,head)
end
end
@@ -19572,6 +19894,10 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
if id==glyph_code then
i=i+1
current=getnext(current)
+ elseif id==glue_code then
+ i=i+1
+ current=getnext(current)
+ hasglue=true
elseif id==disc_code then
if keepdisc then
keepdisc=false
@@ -19613,6 +19939,9 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
local id=getid(current)
if id==glyph_code then
i=i-1
+ elseif id==glue_code then
+ i=i-1
+ hasglue=true
elseif id==disc_code then
if keepdisc then
keepdisc=false
@@ -19657,8 +19986,8 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
if cprev then
setnext(cprev,lookaheaddisc)
end
- setprev(cf,nil)
- setnext(cl,nil)
+ setprev(cf)
+ setnext(cl)
if startishead then
head=lookaheaddisc
end
@@ -19685,7 +20014,11 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
local tail=find_node_tail(new)
setlink(tail,replace)
end
- setdisc(lookaheaddisc,cf,post,new)
+ if hasglue then
+ setdiscchecked(lookaheaddisc,cf,post,new)
+ else
+ setdisc(lookaheaddisc,cf,post,new)
+ end
start=getprev(lookaheaddisc)
sweephead[cf]=getnext(clast)
sweephead[new]=getnext(last)
@@ -19708,8 +20041,8 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
setprev(cnext,backtrackdisc)
end
setnext(backtrackdisc,cnext)
- setprev(cf,nil)
- setnext(cl,nil)
+ setprev(cf)
+ setnext(cl)
local pre,post,replace,pretail,posttail,replacetail=getdisc(backtrackdisc,true)
local new=copy_node_list(cf)
local cnew=find_node_tail(new)
@@ -19736,7 +20069,11 @@ local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,c
else
replace=new
end
- setdisc(backtrackdisc,pre,post,replace)
+ if hasglue then
+ setdiscchecked(backtrackdisc,pre,post,replace)
+ else
+ setdisc(backtrackdisc,pre,post,replace)
+ end
start=getprev(backtrackdisc)
sweephead[post]=getnext(clast)
sweephead[replace]=getnext(last)
@@ -19991,16 +20328,13 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
end
prev=getprev(prev)
- elseif seq[n][32] then
+ elseif seq[n][32] and isspace(prev,threshold) then
n=n-1
prev=getprev(prev)
else
match=false
break
end
- elseif seq[n][32] then
- n=n-1
- prev=getprev(prev)
else
match=false
break
@@ -20114,15 +20448,13 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
else
end
current=getnext(current)
- elseif seq[n][32] then
+ elseif seq[n][32] and isspace(current,threshold) then
n=n+1
+ current=getnext(current)
else
match=false
break
end
- elseif seq[n][32] then
- n=n+1
- current=getnext(current)
else
match=false
break
@@ -20217,7 +20549,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
if replacements then
head,start,done=reversesub(head,start,last,dataset,sequence,replacements,rlmode)
else
- done=quit_on_no_replacement
+ done=true
if trace_contexts then
logprocess("%s: skipping match",cref(dataset,sequence))
end
@@ -20337,10 +20669,12 @@ function otf.dataset(tfmdata,font)
}
rs[language]=rl
local sequences=tfmdata.resources.sequences
- for s=1,#sequences do
- local v=enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
- if v then
- rl[#rl+1]=v
+ if sequences then
+ for s=1,#sequences do
+ local v=enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
+ if v then
+ rl[#rl+1]=v
+ end
end
end
end
@@ -20366,10 +20700,10 @@ local function kernrun(disc,k_run,font,attr,...)
break
end
end
- if prev and (pre or replace) and not ischar(prev,font) then
+ if prev and not ischar(prev,font) then
prev=false
end
- if next and (post or replace) and not ischar(next,font) then
+ if next and not ischar(next,font) then
next=false
end
if pre then
@@ -20395,7 +20729,7 @@ local function kernrun(disc,k_run,font,attr,...)
if k_run(posttail,"postinjections",next,font,attr,...) then
done=true
end
- setnext(posttail,nil)
+ setnext(posttail)
setprev(next,disc)
end
end
@@ -20417,7 +20751,7 @@ local function kernrun(disc,k_run,font,attr,...)
if k_run(replacetail,"replaceinjections",next,font,attr,...) then
done=true
end
- setnext(replacetail,nil)
+ setnext(replacetail)
setprev(next,disc)
end
elseif prev and next then
@@ -20484,7 +20818,7 @@ local function testrun(disc,t_run,c_run,...)
setlink(replacetail,next)
local ok,overflow=t_run(replace,next,...)
if ok and overflow then
- setfield(disc,"replace",nil)
+ setfield(disc,"replace")
setlink(prev,replace)
setboth(disc)
flush_node_list(disc)
@@ -20599,6 +20933,7 @@ local function t_run_single(start,stop,font,attr,lookupcache)
return true,d>1
end
end
+ else
end
start=getnext(start)
else
@@ -20712,6 +21047,7 @@ local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
report_missing_coverage(dataset,sequence)
end
end
+ else
end
start=getnext(start)
else
@@ -20783,6 +21119,9 @@ local function pardirstate(start)
end
return getnext(start),new,new
end
+otf.helpers=otf.helpers or {}
+otf.helpers.txtdirstate=txtdirstate
+otf.helpers.pardirstate=pardirstate
local function featuresprocessor(head,font,attr)
local sequences=sequencelists[font]
if not sequencelists then
@@ -20795,8 +21134,9 @@ local function featuresprocessor(head,font,attr)
descriptions=tfmdata.descriptions
characters=tfmdata.characters
marks=tfmdata.resources.marks
- factor=tfmdata.parameters.factor
- threshold=tfmdata.parameters.spacing.width or 65536*10
+ threshold,
+ factor=getthreshold(font)
+ checkmarks=tfmdata.properties.checkmarks
elseif currentfont~=font then
report_warning("nested call with a different font, level %s, quitting",nesting)
nesting=nesting-1
@@ -20809,6 +21149,7 @@ local function featuresprocessor(head,font,attr)
local rlmode=0
local done=false
local datasets=otf.dataset(tfmdata,font,attr)
+ local forcedisc=alwaysdisc or not attr
local dirstack={}
sweephead={}
for s=1,#datasets do
@@ -20824,15 +21165,12 @@ local function featuresprocessor(head,font,attr)
local steps=sequence.steps
local nofsteps=sequence.nofsteps
if not steps then
- local h,d,ok=handler(head,start,dataset,sequence,nil,nil,nil,0,font,attr)
+ local h,d,ok=handler(head,head,dataset,sequence,nil,nil,nil,0,font,attr)
if ok then
success=true
if h then
head=h
end
- if d then
- start=d
- end
end
elseif typ=="gsub_reversecontextchain" then
local start=find_node_tail(head)
@@ -20904,16 +21242,21 @@ local function featuresprocessor(head,font,attr)
elseif char==false then
start=getnext(start)
elseif id==disc_code then
- local ok
- if gpossing then
- start,ok=kernrun(start,k_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- elseif typ=="gsub_ligature" then
- start,ok=testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ local a=forcedisc or getsubtype(start)==discretionary_code or getattr(start,0)==attr
+ if a then
+ local ok
+ if gpossing then
+ start,ok=kernrun(start,k_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ elseif typ=="gsub_ligature" then
+ start,ok=testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ else
+ start,ok=comprun(start,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
+ end
+ if ok then
+ success=true
+ end
else
- start,ok=comprun(start,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- end
- if ok then
- success=true
+ start=getnext(start)
end
elseif id==math_code then
start=getnext(end_of_math(start))
@@ -20965,16 +21308,21 @@ local function featuresprocessor(head,font,attr)
elseif char==false then
start=getnext(start)
elseif id==disc_code then
- local ok
- if gpossing then
- start,ok=kernrun(start,k_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- elseif typ=="gsub_ligature" then
- start,ok=testrun(start,t_run_multiple,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ local a=forcedisc or getsubtype(start)==discretionary_code or getattr(start,0)==attr
+ if a then
+ local ok
+ if gpossing then
+ start,ok=kernrun(start,k_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ elseif typ=="gsub_ligature" then
+ start,ok=testrun(start,t_run_multiple,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ else
+ start,ok=comprun(start,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
+ end
+ if ok then
+ success=true
+ end
else
- start,ok=comprun(start,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- end
- if ok then
- success=true
+ start=getnext(start)
end
elseif id==math_code then
start=getnext(end_of_math(start))
@@ -20999,6 +21347,30 @@ local function featuresprocessor(head,font,attr)
head=tonode(head)
return head,done
end
+local plugins={}
+otf.plugins=plugins
+function otf.registerplugin(name,f)
+ if type(name)=="string" and type(f)=="function" then
+ plugins[name]={ name,f }
+ end
+end
+local function plugininitializer(tfmdata,value)
+ if type(value)=="string" then
+ tfmdata.shared.plugin=plugins[value]
+ end
+end
+local function pluginprocessor(head,font)
+ local s=fontdata[font].shared
+ local p=s and s.plugin
+ if p then
+ if trace_plugins then
+ report_process("applying plugin %a",p[1])
+ end
+ return p[2](head,font)
+ else
+ return head,false
+ end
+end
local function featuresinitializer(tfmdata,value)
end
registerotffeature {
@@ -21008,18 +21380,36 @@ registerotffeature {
initializers={
position=1,
node=featuresinitializer,
+ plug=plugininitializer,
},
processors={
node=featuresprocessor,
+ plug=pluginprocessor,
}
}
otf.nodemodeinitializer=featuresinitializer
otf.featuresprocessor=featuresprocessor
otf.handlers=handlers
local setspacekerns=nodes.injections.setspacekerns if not setspacekerns then os.exit() end
-function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr)
- setspacekerns(font,sequence)
- return head,start,true
+if fontfeatures then
+ function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr)
+ local features=fontfeatures[font]
+ local enabled=features and features.spacekern and features.kern
+ if enabled then
+ setspacekerns(font,sequence)
+ end
+ return head,start,enabled
+ end
+else
+ function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr)
+ local shared=fontdata[font].shared
+ local features=shared and shared.features
+ local enabled=features and features.spacekern and features.kern
+ if enabled then
+ setspacekerns(font,sequence)
+ end
+ return head,start,enabled
+ end
end
local function hasspacekerns(data)
local sequences=data.resources.sequences
@@ -21053,8 +21443,8 @@ otf.readers.registerextender {
local function spaceinitializer(tfmdata,value)
local resources=tfmdata.resources
local spacekerns=resources and resources.spacekerns
- if spacekerns==nil then
- local properties=tfmdata.properties
+ local properties=tfmdata.properties
+ if value and spacekerns==nil then
if properties and properties.hasspacekerns then
local sequences=resources.sequences
local left={}
@@ -21067,28 +21457,55 @@ local function spaceinitializer(tfmdata,value)
if steps then
local kern=sequence.features.kern
if kern then
- feat=feat or kern
+ if feat then
+ for script,languages in next,kern do
+ local f=feat[script]
+ if f then
+ for l in next,languages do
+ f[l]=true
+ end
+ else
+ feat[script]=languages
+ end
+ end
+ else
+ feat=kern
+ end
for i=1,#steps do
local step=steps[i]
local coverage=step.coverage
- if coverage then
+ local rules=step.rules
+ local format=step.format
+ if rules then
+ elseif coverage then
+ local single=format==gpos_single
local kerns=coverage[32]
if kerns then
for k,v in next,kerns do
- if type(v)=="table" then
- right[k]=v[3]
- else
+ if type(v)~="table" then
right[k]=v
+ elseif single then
+ right[k]=v[3]
+ else
+ local one=v[1]
+ if one then
+ right[k]=one[3]
+ end
end
end
end
for k,v in next,coverage do
local kern=v[32]
if kern then
- if type(kern)=="table" then
- left[k]=kern[3]
- else
+ if type(kern)~="table" then
left[k]=kern
+ elseif single then
+ left[k]=v[3]
+ else
+ local one=v[1]
+ if one then
+ left[k]=one[3]
+ end
end
end
end
@@ -21136,6 +21553,18 @@ registerotffeature {
node=spaceinitializer,
},
}
+local function markinitializer(tfmdata,value)
+ local properties=tfmdata.properties
+ properties.checkmarks=value
+end
+registerotffeature {
+ name="checkmarks",
+ description="check mark widths",
+ default=true,
+ initializers={
+ node=markinitializer,
+ },
+}
end -- closure
@@ -21178,9 +21607,9 @@ local setprop=nuts.setprop
local ischar=nuts.is_char
local insert_node_after=nuts.insert_after
local copy_node=nuts.copy
-local free_node=nuts.free
local remove_node=nuts.remove
local flush_list=nuts.flush_list
+local flush_node=nuts.flush_node
local copyinjection=nodes.injections.copy
local unsetvalue=attributes.unsetvalue
local fontdata=fonts.hashes.identifiers
@@ -21539,9 +21968,11 @@ local function initializedevanagi(tfmdata)
local steps=sequence.steps
local nofsteps=sequence.nofsteps
local features=sequence.features
- if features["rphf"] then
+ local has_rphf=features.rphf
+ local has_blwf=features.blwf
+ if has_rphf and has_rphf.deva then
devanagari.reph=true
- elseif features["blwf"] then
+ elseif has_blwf and has_blwf.deva then
devanagari.vattu=true
for i=1,nofsteps do
local step=steps[i]
@@ -21555,57 +21986,60 @@ local function initializedevanagi(tfmdata)
end
end
end
- if valid[kind] then
- for i=1,nofsteps do
- local step=steps[i]
- local coverage=step.coverage
- if coverage then
- local reph=false
- if step.osdstep then
- for k,v in next,ra do
- local r=coverage[k]
- if r then
- local h=false
- for k,v in next,halant do
- local h=r[k]
- if h then
- reph=h.ligature or false
- break
+ for kind,spec in next,features do
+ if spec.dev2 and valid[kind] then
+ for i=1,nofsteps do
+ local step=steps[i]
+ local coverage=step.coverage
+ if coverage then
+ local reph=false
+ if kind=="rphf" then
+ if true then
+ for k,v in next,ra do
+ local r=coverage[k]
+ if r then
+ local h=false
+ for k,v in next,halant do
+ local h=r[k]
+ if h then
+ reph=h.ligature or false
+ break
+ end
+ end
+ if reph then
+ break
+ end
end
end
- if reph then
- break
- end
+ else
end
end
- else
+ seqsubset[#seqsubset+1]={ kind,coverage,reph }
end
- seqsubset[#seqsubset+1]={ kind,coverage,reph }
end
end
- end
- if kind=="pref" then
- local sequence=dataset[3]
- local steps=sequence.steps
- local nofsteps=sequence.nofsteps
- for i=1,nofsteps do
- local step=steps[i]
- local coverage=step.coverage
- if coverage then
- for k,v in next,halant do
- local h=coverage[k]
- if h then
- local found=false
- for k,v in next,h do
- found=v and v.ligature
+ if kind=="pref" then
+ local steps=sequence.steps
+ local nofsteps=sequence.nofsteps
+ for i=1,nofsteps do
+ local step=steps[i]
+ local coverage=step.coverage
+ if coverage then
+ for k,v in next,halant do
+ local h=coverage[k]
+ if h then
+ local found=false
+ for k,v in next,h do
+ found=v and v.ligature
+ if found then
+ pre_base_reordering_consonants[k]=found
+ break
+ end
+ end
if found then
- pre_base_reordering_consonants[k]=found
break
end
end
- if found then
- break
- end
end
end
end
@@ -21690,7 +22124,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
if current==stop then
stop=getprev(stop)
head=remove_node(head,current)
- free_node(current)
+ flush_node(current)
return head,stop,nbspaces
else
nbspaces=nbspaces+1
@@ -21728,7 +22162,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
setchar(current,getchar(tempcurrent))
local freenode=getnext(current)
setlink(current,tmp)
- free_node(freenode)
+ flush_node(freenode)
flush_list(tempcurrent)
if changestop then
stop=current
@@ -21965,7 +22399,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
if getchar(base)==c_nbsp then
nbspaces=nbspaces-1
head=remove_node(head,base)
- free_node(base)
+ flush_node(base)
end
return head,stop,nbspaces
end
@@ -21992,6 +22426,8 @@ function handlers.devanagari_reorder_matras(head,start)
start=startnext
break
end
+ else
+ break
end
current=next
end
@@ -22004,12 +22440,12 @@ function handlers.devanagari_reorder_reph(head,start)
local startfont=getfont(start)
local startattr=getprop(start,a_syllabe)
while current do
- local char=ischar(current,font)
+ local char=ischar(current,startfont)
if char and getprop(current,a_syllabe)==startattr then
if halant[char] and not getprop(current,a_state) then
local next=getnext(current)
if next then
- local nextchar=ischar(next,font)
+ local nextchar=ischar(next,startfont)
if nextchar and zw_char[nextchar] and getprop(next,a_syllabe)==startattr then
current=next
next=getnext(current)
@@ -22031,7 +22467,7 @@ function handlers.devanagari_reorder_reph(head,start)
if not startnext then
current=getnext(start)
while current do
- local char=ischar(current,font)
+ local char=ischar(current,startfont)
if char and getprop(current,a_syllabe)==startattr then
if getprop(current,a_state)==s_pstf then
startnext=getnext(start)
@@ -22053,7 +22489,7 @@ function handlers.devanagari_reorder_reph(head,start)
current=getnext(start)
local c=nil
while current do
- local char=ischar(current,font)
+ local char=ischar(current,startfont)
if char and getprop(current,a_syllabe)==startattr then
if not c and mark_above_below_post[char] and reorder_class[char]~="after subscript" then
c=current
@@ -22077,7 +22513,7 @@ function handlers.devanagari_reorder_reph(head,start)
current=start
local next=getnext(current)
while next do
- local nextchar=ischar(next,font)
+ local nextchar=ischar(next,startfont)
if nextchar and getprop(next,a_syllabe)==startattr then
current=next
next=getnext(current)
@@ -22090,7 +22526,7 @@ function handlers.devanagari_reorder_reph(head,start)
head=remove_node(head,start)
local next=getnext(current)
setlink(start,next)
- setlink(current,"next",start)
+ setlink(current,start)
start=startnext
end
end
@@ -22103,12 +22539,12 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
local startfont=getfont(start)
local startattr=getprop(start,a_syllabe)
while current do
- local char=ischar(current,font)
+ local char=ischar(current,startfont)
if char and getprop(current,a_syllabe)==startattr then
local next=getnext(current)
if halant[char] and not getprop(current,a_state) then
if next then
- local nextchar=ischar(next,font)
+ local nextchar=ischar(next,startfont)
if nextchar and getprop(next,a_syllabe)==startattr then
if nextchar==c_zwnj or nextchar==c_zwj then
current=next
@@ -22132,13 +22568,13 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
current=getnext(start)
startattr=getprop(start,a_syllabe)
while current do
- local char=ischar(current,font)
+ local char=ischar(current,startfont)
if char and getprop(current,a_syllabe)==startattr then
if not consonant[char] and getprop(current,a_state) then
startnext=getnext(start)
removenode(start,start)
local prev=getprev(current)
- setlink(start,prev)
+ setlink(prev,start)
setlink(start,current)
start=startnext
break
@@ -22198,21 +22634,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces)
local kind=subset[1]
local lookupcache=subset[2]
if kind=="rphf" then
- for k,v in next,ra do
- local r=lookupcache[k]
- if r then
- for k,v in next,halant do
- local h=r[k]
- if h then
- reph=h.ligature or false
- break
- end
- end
- if reph then
- break
- end
- end
- end
+ reph=subset[3]
local current=start
local last=getnext(stop)
while current~=last do
@@ -22245,7 +22667,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces)
if current~=stop then
local c=locl[current] or getchar(current)
local found=lookupcache[c]
- if found then
+ if found then
local next=getnext(current)
local n=locl[next] or getchar(next)
if found[n] then
@@ -22333,7 +22755,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces)
if current==stop then
stop=getprev(stop)
head=remove_node(head,current)
- free_node(current)
+ flush_node(current)
return head,stop,nbspaces
else
nbspaces=nbspaces+1
@@ -22472,7 +22894,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces)
local prev=getprev(current)
if prev~=target then
local next=getnext(current)
- setlink(next,prev)
+ setlink(prev,next)
if current==stop then
stop=prev
end
@@ -22503,7 +22925,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces)
stop=current
end
local prev=getprev(c)
- setlink(next,prev)
+ setlink(prev,next)
local nextnext=getnext(next)
setnext(current,nextnext)
local nextnextnext=getnext(nextnext)
@@ -22516,9 +22938,12 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces)
current=getnext(current)
end
if getchar(base)==c_nbsp then
+ if base==stop then
+ stop=getprev(stop)
+ end
nbspaces=nbspaces-1
head=remove_node(head,base)
- free_node(base)
+ flush_node(base)
end
return head,stop,nbspaces
end
@@ -22557,7 +22982,7 @@ local function analyze_next_chars_one(c,font,variant)
elseif (vv==c_zwnj or vv==c_zwj) and halant[vvv] then
local nnnn=getnext(nnn)
if nnnn then
- local vvvv=ischar(nnnn)
+ local vvvv=ischar(nnnn,font)
if vvvv and consonant[vvvv] then
c=nnnn
end
@@ -22580,7 +23005,7 @@ local function analyze_next_chars_one(c,font,variant)
local nn=getnext(n)
if nn then
local vv=ischar(nn,font)
- if vv and zw_char[vv] then
+ if vv and zw_char[v] then
n=nn
v=vv
nn=getnext(nn)
@@ -23117,32 +23542,77 @@ if not modules then modules={} end modules ['font-ocl']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local tostring,next=tostring,next
+local tostring,next,format=tostring,next,string.format
+local round,max=math.round,math.round
local formatters=string.formatters
+local tounicode=fonts.mappings.tounicode
local otf=fonts.handlers.otf
-local f_color_start=formatters["pdf:direct: %f %f %f rg"]
-local s_color_stop="pdf:direct:"
+local f_color=formatters["pdf:direct:%f %f %f rg"]
+local f_gray=formatters["pdf:direct:%f g"]
+local s_black="pdf:direct:0 g"
if context then
local startactualtext=nil
local stopactualtext=nil
- function otf.getactualtext(n)
+ function otf.getactualtext(s)
if not startactualtext then
- startactualtext=backends.codeinjections.startunicodetoactualtext
- stopactualtext=backends.codeinjections.stopunicodetoactualtext
+ startactualtext=backends.codeinjections.startunicodetoactualtextdirect
+ stopactualtext=backends.codeinjections.stopunicodetoactualtextdirect
end
- return startactualtext(n),stopactualtext()
+ return startactualtext(s),stopactualtext()
end
else
local tounicode=fonts.mappings.tounicode16
- function otf.getactualtext(n)
- return "/Span << /ActualText <feff"..tounicode(n).."> >> BDC","EMC"
+ function otf.getactualtext(s)
+ return
+ "/Span << /ActualText <feff"..n.."> >> BDC",
+ "EMC"
+ end
+end
+local sharedpalettes={}
+if context then
+ local graytorgb=attributes.colors.graytorgb
+ local cmyktorgb=attributes.colors.cmyktorgb
+ function otf.registerpalette(name,values)
+ sharedpalettes[name]=values
+ for i=1,#values do
+ local v=values[i]
+ local r,g,b
+ local s=v.s
+ if s then
+ r,g,b=graytorgb(s)
+ else
+ local c,m,y,k=v.c,v.m,v.y,v.k
+ if c or m or y or k then
+ r,g,b=cmyktorgb(c or 0,m or 0,y or 0,k or 0)
+ else
+ r,g,b=v.r,v.g,v.b
+ end
+ end
+ values[i]={
+ max(r and round(r*255) or 0,255),
+ max(g and round(g*255) or 0,255),
+ max(b and round(b*255) or 0,255)
+ }
+ end
+ end
+else
+ function otf.registerpalette(name,values)
+ sharedpalettes[name]=values
+ for i=1,#values do
+ local v=values[i]
+ values[i]={
+ max(round((v.r or 0)*255),255),
+ max(round((v.g or 0)*255),255),
+ max(round((v.b or 0)*255),255)
+ }
+ end
end
end
local function initializecolr(tfmdata,kind,value)
if value then
local palettes=tfmdata.resources.colorpalettes
if palettes then
- local palette=palettes[tonumber(value) or 1] or palettes[1] or {}
+ local palette=sharedpalettes[value] or palettes[tonumber(value) or 1] or palettes[1] or {}
local classes=#palette
if classes==0 then
return
@@ -23157,7 +23627,12 @@ local function initializecolr(tfmdata,kind,value)
}
for i=1,classes do
local p=palette[i]
- colorvalues[i]={ "special",f_color_start(p[1]/255,p[2]/255,p[3]/255) }
+ local r,g,b=p[1],p[2],p[3]
+ if r==g and g==b then
+ colorvalues[i]={ "special",f_gray(r/255) }
+ else
+ colorvalues[i]={ "special",f_color(r/255,g/255,b/255) }
+ end
end
local getactualtext=otf.getactualtext
for unicode,character in next,characters do
@@ -23165,22 +23640,24 @@ local function initializecolr(tfmdata,kind,value)
if description then
local colorlist=description.colors
if colorlist then
- local b,e=getactualtext(unicode)
+ local b,e=getactualtext(tounicode(characters[unicode].unicode or 0xFFFD))
local w=character.width or 0
local s=#colorlist
- local n=1
local t={
- { "special","pdf:direct: q "..b }
+ { "special","pdf:page:q" },
+ { "special","pdf:raw:"..b }
}
+ local n=#t
for i=1,s do
local entry=colorlist[i]
- n=n+1 t[n]=colorvalues[entry.class]
+ n=n+1 t[n]=colorvalues[entry.class] or s_black
n=n+1 t[n]={ "char",entry.slot }
if s>1 and i<s and w~=0 then
n=n+1 t[n]={ "right",-w }
end
end
- n=n+1 t[n]={ "special","pdf:direct:"..e.." Q" }
+ n=n+1 t[n]={ "special","pdf:page:"..e }
+ n=n+1 t[n]={ "special","pdf:raw:Q" }
character.commands=t
end
end
@@ -23234,70 +23711,62 @@ do
end
end
end
-if context and xml.convert then
+do
local report_svg=logs.reporter("fonts","svg conversion")
- local xmlconvert=xml.convert
- local xmlfirst=xml.first
local loaddata=io.loaddata
local savedata=io.savedata
local remove=os.remove
+ if context and xml.convert then
+ local xmlconvert=xml.convert
+ local xmlfirst=xml.first
+ function otfsvg.filterglyph(entry,index)
+ local svg=xmlconvert(entry.data)
+ local root=svg and xmlfirst(svg,"/svg[@id='glyph"..index.."']")
+ local data=root and tostring(root)
+ return data
+ end
+ else
+ function otfsvg.filterglyph(entry,index)
+ return entry.data
+ end
+ end
function otfsvg.topdf(svgshapes)
- local inkscape=io.popen("inkscape --shell 2>&1","w")
+ local inkscape=io.popen("inkscape --shell > temp-otf-svg-shape.log","w")
local pdfshapes={}
local nofshapes=#svgshapes
local f_svgfile=formatters["temp-otf-svg-shape-%i.svg"]
local f_pdffile=formatters["temp-otf-svg-shape-%i.pdf"]
local f_convert=formatters["%s --export-pdf=%s\n"]
+ local filterglyph=otfsvg.filterglyph
report_svg("processing %i svg containers",nofshapes)
statistics.starttiming()
for i=1,nofshapes do
local entry=svgshapes[i]
- for j=entry.first,entry.last do
- local svg=xmlconvert(entry.data)
- local root=svg and xmlfirst(svg,"/svg[@id='glyph"..j.."']")
- local data=root and tostring(root)
+ for index=entry.first,entry.last do
+ local data=filterglyph(entry,index)
if data and data~="" then
- local svgfile=f_svgfile(j)
- local pdffile=f_pdffile(j)
+ local svgfile=f_svgfile(index)
+ local pdffile=f_pdffile(index)
savedata(svgfile,data)
inkscape:write(f_convert(svgfile,pdffile))
- pdfshapes[j]=true
+ pdfshapes[index]=true
end
end
end
inkscape:write("quit\n")
inkscape:close()
report_svg("processing %i pdf results",nofshapes)
- for i in next,pdfshapes do
- local svgfile=f_svgfile(i)
- local pdffile=f_pdffile(i)
- pdfshapes[i]=loaddata(pdffile)
+ for index in next,pdfshapes do
+ local svgfile=f_svgfile(index)
+ local pdffile=f_pdffile(index)
+ pdfshapes[index]=loaddata(pdffile)
remove(svgfile)
remove(pdffile)
end
statistics.stoptiming()
- report_svg("conversion time: %0.3f",statistics.elapsedtime())
- return pdfshapes
- end
-else
- function otfsvg.topdf(svgshapes)
- local svgfile="temp-otf-svg-shape.svg"
- local pdffile="temp-otf-svg-shape.pdf"
- local command="inkscape "..svgfile.." --export-pdf="..pdffile
- local pdfshapes={}
- local nofshapes=#svgshapes
- texio.write(formatters["[converting %i svg glyphs to pdf using command %q : "](nofshapes,command))
- for i=1,nofshapes do
- local entry=svgshapes[i]
- for j=entry.first,entry.last do
- texio.write(formatters["%i "](j))
- io.savedata(svgfile,tostring(entry.data))
- os.execute(command)
- pdfshapes[j]=io.loaddata(pdffile)
- end
+ if statistics.elapsedseconds then
+ report_svg("svg conversion time %s",statistics.elapsedseconds())
end
- os.remove(svgfile)
- texio.write("done]")
return pdfshapes
end
end
@@ -23372,6 +23841,777 @@ end -- closure
do -- begin closure to overcome local limits and interference
+if not modules then modules={} end modules ['font-otc']={
+ version=1.001,
+ comment="companion to font-otf.lua (context)",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local format,insert,sortedkeys,tohash=string.format,table.insert,table.sortedkeys,table.tohash
+local type,next=type,next
+local lpegmatch=lpeg.match
+local utfbyte,utflen=utf.byte,utf.len
+local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end)
+local report_otf=logs.reporter("fonts","otf loading")
+local fonts=fonts
+local otf=fonts.handlers.otf
+local registerotffeature=otf.features.register
+local setmetatableindex=table.setmetatableindex
+local normalized={
+ substitution="substitution",
+ single="substitution",
+ ligature="ligature",
+ alternate="alternate",
+ multiple="multiple",
+ kern="kern",
+ pair="pair",
+ chainsubstitution="chainsubstitution",
+ chainposition="chainposition",
+}
+local types={
+ substitution="gsub_single",
+ ligature="gsub_ligature",
+ alternate="gsub_alternate",
+ multiple="gsub_multiple",
+ kern="gpos_pair",
+ pair="gpos_pair",
+ chainsubstitution="gsub_contextchain",
+ chainposition="gpos_contextchain",
+}
+local names={
+ gsub_single="gsub",
+ gsub_multiple="gsub",
+ gsub_alternate="gsub",
+ gsub_ligature="gsub",
+ gsub_context="gsub",
+ gsub_contextchain="gsub",
+ gsub_reversecontextchain="gsub",
+ gpos_single="gpos",
+ gpos_pair="gpos",
+ gpos_cursive="gpos",
+ gpos_mark2base="gpos",
+ gpos_mark2ligature="gpos",
+ gpos_mark2mark="gpos",
+ gpos_context="gpos",
+ gpos_contextchain="gpos",
+}
+setmetatableindex(types,function(t,k) t[k]=k return k end)
+local everywhere={ ["*"]={ ["*"]=true } }
+local noflags={ false,false,false,false }
+local function getrange(sequences,category)
+ local count=#sequences
+ local first=nil
+ local last=nil
+ for i=1,count do
+ local t=sequences[i].type
+ if t and names[t]==category then
+ if not first then
+ first=i
+ end
+ last=i
+ end
+ end
+ return first or 1,last or count
+end
+local function validspecification(specification,name)
+ local dataset=specification.dataset
+ if dataset then
+ elseif specification[1] then
+ dataset=specification
+ specification={ dataset=dataset }
+ else
+ dataset={ { data=specification.data } }
+ specification.data=nil
+ specification.dataset=dataset
+ end
+ local first=dataset[1]
+ if first then
+ first=first.data
+ end
+ if not first then
+ report_otf("invalid feature specification, no dataset")
+ return
+ end
+ if type(name)~="string" then
+ name=specification.name or first.name
+ end
+ if type(name)~="string" then
+ report_otf("invalid feature specification, no name")
+ return
+ end
+ local n=#dataset
+ if n>0 then
+ for i=1,n do
+ setmetatableindex(dataset[i],specification)
+ end
+ return specification,name
+ end
+end
+local function addfeature(data,feature,specifications)
+ if not specifications then
+ report_otf("missing specification")
+ return
+ end
+ local descriptions=data.descriptions
+ local resources=data.resources
+ local features=resources.features
+ local sequences=resources.sequences
+ if not features or not sequences then
+ report_otf("missing specification")
+ return
+ end
+ local alreadydone=resources.alreadydone
+ if not alreadydone then
+ alreadydone={}
+ resources.alreadydone=alreadydone
+ end
+ if alreadydone[specifications] then
+ return
+ else
+ alreadydone[specifications]=true
+ end
+ local fontfeatures=resources.features or everywhere
+ local unicodes=resources.unicodes
+ local splitter=lpeg.splitter(" ",unicodes)
+ local done=0
+ local skip=0
+ local aglunicodes=false
+ local specifications=validspecification(specifications,feature)
+ if not specifications then
+ return
+ end
+ local function tounicode(code)
+ if not code then
+ return
+ end
+ if type(code)=="number" then
+ return code
+ end
+ local u=unicodes[code]
+ if u then
+ return u
+ end
+ if utflen(code)==1 then
+ u=utfbyte(code)
+ if u then
+ return u
+ end
+ end
+ if not aglunicodes then
+ aglunicodes=fonts.encodings.agl.unicodes
+ end
+ return aglunicodes[code]
+ end
+ local coverup=otf.coverup
+ local coveractions=coverup.actions
+ local stepkey=coverup.stepkey
+ local register=coverup.register
+ local function prepare_substitution(list,featuretype)
+ local coverage={}
+ local cover=coveractions[featuretype]
+ for code,replacement in next,list do
+ local unicode=tounicode(code)
+ local description=descriptions[unicode]
+ if description then
+ if type(replacement)=="table" then
+ replacement=replacement[1]
+ end
+ replacement=tounicode(replacement)
+ if replacement and descriptions[replacement] then
+ cover(coverage,unicode,replacement)
+ done=done+1
+ else
+ skip=skip+1
+ end
+ else
+ skip=skip+1
+ end
+ end
+ return coverage
+ end
+ local function prepare_alternate(list,featuretype)
+ local coverage={}
+ local cover=coveractions[featuretype]
+ for code,replacement in next,list do
+ local unicode=tounicode(code)
+ local description=descriptions[unicode]
+ if not description then
+ skip=skip+1
+ elseif type(replacement)=="table" then
+ local r={}
+ for i=1,#replacement do
+ local u=tounicode(replacement[i])
+ r[i]=descriptions[u] and u or unicode
+ end
+ cover(coverage,unicode,r)
+ done=done+1
+ else
+ local u=tounicode(replacement)
+ if u then
+ cover(coverage,unicode,{ u })
+ done=done+1
+ else
+ skip=skip+1
+ end
+ end
+ end
+ return coverage
+ end
+ local function prepare_multiple(list,featuretype)
+ local coverage={}
+ local cover=coveractions[featuretype]
+ for code,replacement in next,list do
+ local unicode=tounicode(code)
+ local description=descriptions[unicode]
+ if not description then
+ skip=skip+1
+ elseif type(replacement)=="table" then
+ local r,n={},0
+ for i=1,#replacement do
+ local u=tounicode(replacement[i])
+ if descriptions[u] then
+ n=n+1
+ r[n]=u
+ end
+ end
+ if n>0 then
+ cover(coverage,unicode,r)
+ done=done+1
+ else
+ skip=skip+1
+ end
+ else
+ local u=tounicode(replacement)
+ if u then
+ cover(coverage,unicode,{ u })
+ done=done+1
+ else
+ skip=skip+1
+ end
+ end
+ end
+ return coverage
+ end
+ local function prepare_ligature(list,featuretype)
+ local coverage={}
+ local cover=coveractions[featuretype]
+ for code,ligature in next,list do
+ local unicode=tounicode(code)
+ local description=descriptions[unicode]
+ if description then
+ if type(ligature)=="string" then
+ ligature={ lpegmatch(splitter,ligature) }
+ end
+ local present=true
+ for i=1,#ligature do
+ local l=ligature[i]
+ local u=tounicode(l)
+ if descriptions[u] then
+ ligature[i]=u
+ else
+ present=false
+ break
+ end
+ end
+ if present then
+ cover(coverage,unicode,ligature)
+ done=done+1
+ else
+ skip=skip+1
+ end
+ else
+ skip=skip+1
+ end
+ end
+ return coverage
+ end
+ local function prepare_kern(list,featuretype)
+ local coverage={}
+ local cover=coveractions[featuretype]
+ for code,replacement in next,list do
+ local unicode=tounicode(code)
+ local description=descriptions[unicode]
+ if description and type(replacement)=="table" then
+ local r={}
+ for k,v in next,replacement do
+ local u=tounicode(k)
+ if u then
+ r[u]=v
+ end
+ end
+ if next(r) then
+ cover(coverage,unicode,r)
+ done=done+1
+ else
+ skip=skip+1
+ end
+ else
+ skip=skip+1
+ end
+ end
+ return coverage
+ end
+ local function prepare_pair(list,featuretype)
+ local coverage={}
+ local cover=coveractions[featuretype]
+ if cover then
+ for code,replacement in next,list do
+ local unicode=tounicode(code)
+ local description=descriptions[unicode]
+ if description and type(replacement)=="table" then
+ local r={}
+ for k,v in next,replacement do
+ local u=tounicode(k)
+ if u then
+ r[u]=v
+ end
+ end
+ if next(r) then
+ cover(coverage,unicode,r)
+ done=done+1
+ else
+ skip=skip+1
+ end
+ else
+ skip=skip+1
+ end
+ end
+ else
+ report_otf("unknown cover type %a",featuretype)
+ end
+ return coverage
+ end
+ local function prepare_chain(list,featuretype,sublookups)
+ local rules=list.rules
+ local coverage={}
+ if rules then
+ local rulehash={}
+ local rulesize=0
+ local sequence={}
+ local nofsequences=0
+ local lookuptype=types[featuretype]
+ for nofrules=1,#rules do
+ local rule=rules[nofrules]
+ local current=rule.current
+ local before=rule.before
+ local after=rule.after
+ local replacements=rule.replacements or false
+ local sequence={}
+ local nofsequences=0
+ if before then
+ for n=1,#before do
+ nofsequences=nofsequences+1
+ sequence[nofsequences]=before[n]
+ end
+ end
+ local start=nofsequences+1
+ for n=1,#current do
+ nofsequences=nofsequences+1
+ sequence[nofsequences]=current[n]
+ end
+ local stop=nofsequences
+ if after then
+ for n=1,#after do
+ nofsequences=nofsequences+1
+ sequence[nofsequences]=after[n]
+ end
+ end
+ local lookups=rule.lookups or false
+ local subtype=nil
+ if lookups and sublookups then
+ for k,v in next,lookups do
+ local lookup=sublookups[v]
+ if lookup then
+ lookups[k]=lookup
+ if not subtype then
+ subtype=lookup.type
+ end
+ else
+ end
+ end
+ end
+ if nofsequences>0 then
+ local hashed={}
+ for i=1,nofsequences do
+ local t={}
+ local s=sequence[i]
+ for i=1,#s do
+ local u=tounicode(s[i])
+ if u then
+ t[u]=true
+ end
+ end
+ hashed[i]=t
+ end
+ sequence=hashed
+ rulesize=rulesize+1
+ rulehash[rulesize]={
+ nofrules,
+ lookuptype,
+ sequence,
+ start,
+ stop,
+ lookups,
+ replacements,
+ subtype,
+ }
+ for unic in next,sequence[start] do
+ local cu=coverage[unic]
+ if not cu then
+ coverage[unic]=rulehash
+ end
+ end
+ end
+ end
+ end
+ return coverage
+ end
+ local dataset=specifications.dataset
+ local function report(name,category,position,first,last,sequences)
+ report_otf("injecting name %a of category %a at position %i in [%i,%i] of [%i,%i]",
+ name,category,position,first,last,1,#sequences)
+ end
+ local function inject(specification,sequences,sequence,first,last,category,name)
+ local position=specification.position or false
+ if not position then
+ position=specification.prepend
+ if position==true then
+ if trace_loading then
+ report(name,category,first,first,last,sequences)
+ end
+ insert(sequences,first,sequence)
+ return
+ end
+ end
+ if not position then
+ position=specification.append
+ if position==true then
+ if trace_loading then
+ report(name,category,last+1,first,last,sequences)
+ end
+ insert(sequences,last+1,sequence)
+ return
+ end
+ end
+ local kind=type(position)
+ if kind=="string" then
+ local index=false
+ for i=first,last do
+ local s=sequences[i]
+ local f=s.features
+ if f then
+ for k in next,f do
+ if k==position then
+ index=i
+ break
+ end
+ end
+ if index then
+ break
+ end
+ end
+ end
+ if index then
+ position=index
+ else
+ position=last+1
+ end
+ elseif kind=="number" then
+ if position<0 then
+ position=last-position+1
+ end
+ if position>last then
+ position=last+1
+ elseif position<first then
+ position=first
+ end
+ else
+ position=last+1
+ end
+ if trace_loading then
+ report(name,category,position,first,last,sequences)
+ end
+ insert(sequences,position,sequence)
+ end
+ for s=1,#dataset do
+ local specification=dataset[s]
+ local valid=specification.valid
+ local feature=specification.name or feature
+ if not feature or feature=="" then
+ report_otf("no valid name given for extra feature")
+ elseif not valid or valid(data,specification,feature) then
+ local initialize=specification.initialize
+ if initialize then
+ specification.initialize=initialize(specification,data) and initialize or nil
+ end
+ local askedfeatures=specification.features or everywhere
+ local askedsteps=specification.steps or specification.subtables or { specification.data } or {}
+ local featuretype=normalized[specification.type or "substitution"] or "substitution"
+ local featureflags=specification.flags or noflags
+ local featureorder=specification.order or { feature }
+ local featurechain=(featuretype=="chainsubstitution" or featuretype=="chainposition") and 1 or 0
+ local nofsteps=0
+ local steps={}
+ local sublookups=specification.lookups
+ local category=nil
+ if sublookups then
+ local s={}
+ for i=1,#sublookups do
+ local specification=sublookups[i]
+ local askedsteps=specification.steps or specification.subtables or { specification.data } or {}
+ local featuretype=normalized[specification.type or "substitution"] or "substitution"
+ local featureflags=specification.flags or noflags
+ local nofsteps=0
+ local steps={}
+ for i=1,#askedsteps do
+ local list=askedsteps[i]
+ local coverage=nil
+ local format=nil
+ if featuretype=="substitution" then
+ coverage=prepare_substitution(list,featuretype)
+ elseif featuretype=="ligature" then
+ coverage=prepare_ligature(list,featuretype)
+ elseif featuretype=="alternate" then
+ coverage=prepare_alternate(list,featuretype)
+ elseif featuretype=="multiple" then
+ coverage=prepare_multiple(list,featuretype)
+ elseif featuretype=="kern" then
+ format="kern"
+ coverage=prepare_kern(list,featuretype)
+ elseif featuretype=="pair" then
+ format="pair"
+ coverage=prepare_pair(list,featuretype)
+ end
+ if coverage and next(coverage) then
+ nofsteps=nofsteps+1
+ steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
+ end
+ end
+ s[i]={
+ [stepkey]=steps,
+ nofsteps=nofsteps,
+ type=types[featuretype],
+ }
+ end
+ sublookups=s
+ end
+ for i=1,#askedsteps do
+ local list=askedsteps[i]
+ local coverage=nil
+ local format=nil
+ if featuretype=="substitution" then
+ category="gsub"
+ coverage=prepare_substitution(list,featuretype)
+ elseif featuretype=="ligature" then
+ category="gsub"
+ coverage=prepare_ligature(list,featuretype)
+ elseif featuretype=="alternate" then
+ category="gsub"
+ coverage=prepare_alternate(list,featuretype)
+ elseif featuretype=="multiple" then
+ category="gsub"
+ coverage=prepare_multiple(list,featuretype)
+ elseif featuretype=="kern" then
+ category="gpos"
+ format="kern"
+ coverage=prepare_kern(list,featuretype)
+ elseif featuretype=="pair" then
+ category="gpos"
+ format="pair"
+ coverage=prepare_pair(list,featuretype)
+ elseif featuretype=="chainsubstitution" then
+ category="gsub"
+ coverage=prepare_chain(list,featuretype,sublookups)
+ elseif featuretype=="chainposition" then
+ category="gpos"
+ coverage=prepare_chain(list,featuretype,sublookups)
+ else
+ report_otf("not registering feature %a, unknown category",feature)
+ return
+ end
+ if coverage and next(coverage) then
+ nofsteps=nofsteps+1
+ steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
+ end
+ end
+ if nofsteps>0 then
+ for k,v in next,askedfeatures do
+ if v[1] then
+ askedfeatures[k]=tohash(v)
+ end
+ end
+ if featureflags[1] then featureflags[1]="mark" end
+ if featureflags[2] then featureflags[2]="ligature" end
+ if featureflags[3] then featureflags[3]="base" end
+ local steptype=types[featuretype]
+ local sequence={
+ chain=featurechain,
+ features={ [feature]=askedfeatures },
+ flags=featureflags,
+ name=feature,
+ order=featureorder,
+ [stepkey]=steps,
+ nofsteps=nofsteps,
+ type=steptype,
+ }
+ local first,last=getrange(sequences,category)
+ inject(specification,sequences,sequence,first,last,category,feature)
+ local features=fontfeatures[category]
+ if not features then
+ features={}
+ fontfeatures[category]=features
+ end
+ local k=features[feature]
+ if not k then
+ k={}
+ features[feature]=k
+ end
+ for script,languages in next,askedfeatures do
+ local kk=k[script]
+ if not kk then
+ kk={}
+ k[script]=kk
+ end
+ for language,value in next,languages do
+ kk[language]=value
+ end
+ end
+ end
+ end
+ end
+ if trace_loading then
+ report_otf("registering feature %a, affected glyphs %a, skipped glyphs %a",feature,done,skip)
+ end
+end
+otf.enhancers.addfeature=addfeature
+local extrafeatures={}
+local knownfeatures={}
+function otf.addfeature(name,specification)
+ if type(name)=="table" then
+ specification=name
+ end
+ if type(specification)~="table" then
+ report_otf("invalid feature specification, no valid table")
+ return
+ end
+ specification,name=validspecification(specification,name)
+ if name and specification then
+ local slot=knownfeatures[name]
+ if slot then
+ else
+ slot=#extrafeatures+1
+ knownfeatures[name]=slot
+ end
+ specification.name=name
+ extrafeatures[slot]=specification
+ end
+end
+local function enhance(data,filename,raw)
+ for slot=1,#extrafeatures do
+ local specification=extrafeatures[slot]
+ addfeature(data,specification.name,specification)
+ end
+end
+otf.enhancers.enhance=enhance
+otf.enhancers.register("check extra features",enhance)
+local tlig={
+ [0x2013]={ 0x002D,0x002D },
+ [0x2014]={ 0x002D,0x002D,0x002D },
+}
+local tlig_specification={
+ type="ligature",
+ features=everywhere,
+ data=tlig,
+ order={ "tlig" },
+ flags=noflags,
+ prepend=true,
+}
+otf.addfeature("tlig",tlig_specification)
+registerotffeature {
+ name='tlig',
+ description='tex ligatures',
+}
+local trep={
+ [0x0027]=0x2019,
+}
+local trep_specification={
+ type="substitution",
+ features=everywhere,
+ data=trep,
+ order={ "trep" },
+ flags=noflags,
+ prepend=true,
+}
+otf.addfeature("trep",trep_specification)
+registerotffeature {
+ name='trep',
+ description='tex replacements',
+}
+local anum_arabic={
+ [0x0030]=0x0660,
+ [0x0031]=0x0661,
+ [0x0032]=0x0662,
+ [0x0033]=0x0663,
+ [0x0034]=0x0664,
+ [0x0035]=0x0665,
+ [0x0036]=0x0666,
+ [0x0037]=0x0667,
+ [0x0038]=0x0668,
+ [0x0039]=0x0669,
+}
+local anum_persian={
+ [0x0030]=0x06F0,
+ [0x0031]=0x06F1,
+ [0x0032]=0x06F2,
+ [0x0033]=0x06F3,
+ [0x0034]=0x06F4,
+ [0x0035]=0x06F5,
+ [0x0036]=0x06F6,
+ [0x0037]=0x06F7,
+ [0x0038]=0x06F8,
+ [0x0039]=0x06F9,
+}
+local function valid(data)
+ local features=data.resources.features
+ if features then
+ for k,v in next,features do
+ for k,v in next,v do
+ if v.arab then
+ return true
+ end
+ end
+ end
+ end
+end
+local anum_specification={
+ {
+ type="substitution",
+ features={ arab={ urd=true,dflt=true } },
+ order={ "anum" },
+ data=anum_arabic,
+ flags=noflags,
+ valid=valid,
+ },
+ {
+ type="substitution",
+ features={ arab={ urd=true } },
+ order={ "anum" },
+ data=anum_persian,
+ flags=noflags,
+ valid=valid,
+ },
+}
+otf.addfeature("anum",anum_specification)
+registerotffeature {
+ name='anum',
+ description='arabic digits',
+}
+
+end -- closure
+
+do -- begin closure to overcome local limits and interference
+
if not modules then modules={} end modules ['font-onr']={
version=1.001,
comment="companion to font-ini.mkiv",
@@ -23380,51 +24620,25 @@ if not modules then modules={} end modules ['font-onr']={
license="see context related readme files"
}
local fonts,logs,trackers,resolvers=fonts,logs,trackers,resolvers
-local next,type,tonumber,rawget=next,type,tonumber,rawget
+local next,type,tonumber,rawget,rawset=next,type,tonumber,rawget,rawset
local match,lower,gsub,strip,find=string.match,string.lower,string.gsub,string.strip,string.find
local char,byte,sub=string.char,string.byte,string.sub
local abs=math.abs
local bxor,rshift=bit32.bxor,bit32.rshift
-local P,S,R,Cmt,C,Ct,Cs,Carg=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg
+local P,S,R,Cmt,C,Ct,Cs,Carg,Cf,Cg=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg,lpeg.Cf,lpeg.Cg
local lpegmatch,patterns=lpeg.match,lpeg.patterns
local trace_indexing=false trackers.register("afm.indexing",function(v) trace_indexing=v end)
local trace_loading=false trackers.register("afm.loading",function(v) trace_loading=v end)
local report_afm=logs.reporter("fonts","afm loading")
-local report_afm=logs.reporter("fonts","pfb loading")
-fonts=fonts or {}
-local handlers=fonts.handlers or {}
-fonts.handlers=handlers
+local report_pfb=logs.reporter("fonts","pfb loading")
+local handlers=fonts.handlers
local afm=handlers.afm or {}
handlers.afm=afm
local readers=afm.readers or {}
afm.readers=readers
afm.version=1.512
-local get_indexes
+local get_indexes,get_shapes
do
- local n,m
- local progress=function(str,position,name,size)
- local forward=position+tonumber(size)+3+2
- n=n+1
- if n>=m then
- return #str,name
- elseif forward<#str then
- return forward,name
- else
- return #str,name
- end
- end
- local initialize=function(str,position,size)
- n=0
- m=tonumber(size)
- return position+1
- end
- local charstrings=P("/CharStrings")
- local name=P("/")*C((R("az")+R("AZ")+R("09")+S("-_."))^1)
- local size=C(R("09")^1)
- local spaces=P(" ")^1
- local p_filternames=Ct (
- (1-charstrings)^0*charstrings*spaces*Cmt(size,initialize)*(Cmt(name*P(" ")^1*C(R("09")^1),progress)+P(1))^1
- )
local decrypt
do
local r,c1,c2,n=0,0,0,0
@@ -23434,13 +24648,75 @@ do
r=((cipher+r)*c1+c2)%65536
return char(plain)
end
- decrypt=function(binary)
- r,c1,c2,n=55665,52845,22719,4
+ decrypt=function(binary,initial,seed)
+ r,c1,c2,n=initial,52845,22719,seed
binary=gsub(binary,".",step)
return sub(binary,n+1)
end
end
- local function loadpfbvector(filename)
+ local charstrings=P("/CharStrings")
+ local subroutines=P("/Subrs")
+ local encoding=P("/Encoding")
+ local dup=P("dup")
+ local put=P("put")
+ local array=P("array")
+ local name=P("/")*C((R("az")+R("AZ")+R("09")+S("-_."))^1)
+ local digits=R("09")^1
+ local cardinal=digits/tonumber
+ local spaces=P(" ")^1
+ local spacing=patterns.whitespace^0
+ local routines,vector,chars,n,m
+ local initialize=function(str,position,size)
+ n=0
+ m=size
+ return position+1
+ end
+ local setroutine=function(str,position,index,size)
+ local forward=position+tonumber(size)
+ local stream=sub(str,position+1,forward)
+ routines[index]=decrypt(stream,4330,4)
+ return forward
+ end
+ local setvector=function(str,position,name,size)
+ local forward=position+tonumber(size)
+ if n>=m then
+ return #str
+ elseif forward<#str then
+ vector[n]=name
+ n=n+1
+ return forward
+ else
+ return #str
+ end
+ end
+ local setshapes=function(str,position,name,size)
+ local forward=position+tonumber(size)
+ local stream=sub(str,position+1,forward)
+ if n>m then
+ return #str
+ elseif forward<#str then
+ vector[n]=name
+ n=n+1
+ chars [n]=decrypt(stream,4330,4)
+ return forward
+ else
+ return #str
+ end
+ end
+ local p_rd=spacing*(P("RD")+P("-|"))
+ local p_np=spacing*(P("NP")+P("|"))
+ local p_nd=spacing*(P("ND")+P("|"))
+ local p_filterroutines=
+ (1-subroutines)^0*subroutines*spaces*Cmt(cardinal,initialize)*(Cmt(cardinal*spaces*cardinal*p_rd,setroutine)*p_np+P(1))^1
+ local p_filtershapes=
+ (1-charstrings)^0*charstrings*spaces*Cmt(cardinal,initialize)*(Cmt(name*spaces*cardinal*p_rd,setshapes)*p_nd+P(1))^1
+ local p_filternames=Ct (
+ (1-charstrings)^0*charstrings*spaces*Cmt(cardinal,initialize)*(Cmt(name*spaces*cardinal,setvector)+P(1))^1
+ )
+ local p_filterencoding=(1-encoding)^0*encoding*spaces*digits*spaces*array*(1-dup)^0*Cf(
+ Ct("")*Cg(spacing*dup*spaces*cardinal*spaces*name*spaces*put)^1
+,rawset)
+ local function loadpfbvector(filename,shapestoo)
local data=io.loaddata(resolvers.findfile(filename))
if not data then
report_pfb("no data in %a",filename)
@@ -23455,17 +24731,34 @@ do
report_pfb("no binary data in %a",filename)
return
end
- binary=decrypt(binary,4)
- local vector=lpegmatch(p_filternames,binary)
- if vector[1]==".notdef" then
- vector[0]=table.remove(vector,1)
- end
- if not vector then
- report_pfb("no vector in %a",filename)
- return
+ binary=decrypt(binary,55665,4)
+ local names={}
+ local encoding=lpegmatch(p_filterencoding,ascii)
+ local glyphs={}
+ routines,vector,chars={},{},{}
+ if shapestoo then
+ lpegmatch(p_filterroutines,binary)
+ lpegmatch(p_filtershapes,binary)
+ local data={
+ dictionaries={
+ {
+ charstrings=chars,
+ charset=vector,
+ subroutines=routines,
+ }
+ },
+ }
+ fonts.handlers.otf.readers.parsecharstrings(data,glyphs,true,true)
+ else
+ lpegmatch(p_filternames,binary)
end
- return vector
+ names=vector
+ routines,vector,chars=nil,nil,nil
+ return names,encoding,glyphs
end
+ local pfb=handlers.pfb or {}
+ handlers.pfb=pfb
+ pfb.loadvector=loadpfbvector
get_indexes=function(data,pfbname)
local vector=loadpfbvector(pfbname)
if vector then
@@ -23485,6 +24778,10 @@ do
end
end
end
+ get_shapes=function(pfbname)
+ local vector,encoding,glyphs=loadpfbvector(pfbname,true)
+ return glyphs
+ end
end
local spacer=patterns.spacer
local whitespace=patterns.whitespace
@@ -23633,6 +24930,22 @@ function readers.loadfont(afmname,pfbname)
return data
end
end
+function readers.loadshapes(filename)
+ local fullname=resolvers.findfile(filename) or ""
+ if fullname=="" then
+ return {
+ filename="not found: "..filename,
+ glyphs={}
+ }
+ else
+ return {
+ filename=fullname,
+ format="opentype",
+ glyphs=get_shapes(fullname) or {},
+ units=1000,
+ }
+ end
+end
function readers.getinfo(filename)
local data=read(resolvers.findfile(filename),infoparser)
if data then
@@ -23677,36 +24990,15 @@ local otfreaders=otf.readers
local otfenhancers=otf.enhancers
local afmfeatures=constructors.features.afm
local registerafmfeature=afmfeatures.register
+local afmenhancers=constructors.enhancers.afm
+local registerafmenhancer=afmenhancers.register
afm.version=1.512
-afm.cache=containers.define("fonts","afm",afm.version,true)
+afm.cache=containers.define("fonts","one",afm.version,true)
afm.autoprefixed=true
afm.helpdata={}
afm.syncspace=true
local overloads=fonts.mappings.overloads
local applyruntimefixes=fonts.treatments and fonts.treatments.applyfixes
-local enhancers={
-}
-local steps={
- "unify names",
- "add ligatures",
- "add extra kerns",
- "normalize features",
- "fix names",
-}
-local function applyenhancers(data,filename)
- for i=1,#steps do
- local step=steps[i]
- local enhancer=enhancers[step]
- if enhancer then
- if trace_loading then
- report_afm("applying enhancer %a",step)
- end
- enhancer(data,filename)
- else
- report_afm("invalid enhancer %a",step)
- end
- end
-end
function afm.load(filename)
filename=resolvers.findfile(filename,'afm') or ""
if filename~="" and not fonts.names.ignoredfile(filename) then
@@ -23729,7 +25021,7 @@ function afm.load(filename)
report_afm("reading %a",filename)
data=afm.readers.loadfont(filename,pfbname)
if data then
- applyenhancers(data,filename)
+ afmenhancers.apply(data,filename)
fonts.mappings.addtounicode(data,filename)
otfreaders.pack(data)
data.size=size
@@ -23754,7 +25046,7 @@ function afm.load(filename)
end
end
local uparser=fonts.mappings.makenameparser()
-enhancers["unify names"]=function(data,filename)
+local function enhance_unify_names(data,filename)
local unicodevector=fonts.encodings.agl.unicodes
local unicodes={}
local names={}
@@ -23806,7 +25098,7 @@ enhancers["unify names"]=function(data,filename)
end
local everywhere={ ["*"]={ ["*"]=true } }
local noflags={ false,false,false,false }
-enhancers["normalize features"]=function(data)
+local function enhance_normalize_features(data)
local ligatures=setmetatableindex("table")
local kerns=setmetatableindex("table")
local extrakerns=setmetatableindex("table")
@@ -23904,7 +25196,7 @@ enhancers["normalize features"]=function(data)
data.resources.features=features
data.resources.sequences=sequences
end
-enhancers["fix names"]=function(data)
+local function enhance_fix_names(data)
for k,v in next,data.descriptions do
local n=v.name
local r=overloads[n]
@@ -23943,10 +25235,10 @@ local addthem=function(rawdata,ligatures)
end
end
end
-enhancers["add ligatures"]=function(rawdata)
+local function enhance_add_ligatures(rawdata)
addthem(rawdata,afm.helpdata.ligatures)
end
-enhancers["add extra kerns"]=function(rawdata)
+local function enhance_add_extra_kerns(rawdata)
local descriptions=rawdata.descriptions
local resources=rawdata.resources
local unicodes=resources.unicodes
@@ -24265,17 +25557,12 @@ local function read_from_afm(specification)
end
return tfmdata
end
-local function setmode(tfmdata,value)
- if value then
- tfmdata.properties.mode=lower(value)
- end
-end
registerafmfeature {
name="mode",
description="mode",
initializers={
- base=setmode,
- node=setmode,
+ base=otf.modeinitializer,
+ node=otf.modeinitializer,
}
}
registerafmfeature {
@@ -24290,7 +25577,6 @@ registerafmfeature {
node=otf.featuresprocessor,
}
}
-local check_tfm=readers.check_tfm
fonts.formats.afm="type1"
fonts.formats.pfb="type1"
local function check_afm(specification,fullname)
@@ -24325,7 +25611,8 @@ function readers.afm(specification,method)
tfmdata=check_afm(specification,specification.name.."."..forced)
end
if not tfmdata then
- method=method or definers.method or "afm or tfm"
+ local check_tfm=readers.check_tfm
+ method=(check_tfm and (method or definers.method or "afm or tfm")) or "afm"
if method=="tfm" then
tfmdata=check_tfm(specification,specification.name)
elseif method=="afm" then
@@ -24359,6 +25646,12 @@ function readers.pfb(specification,method)
swap("specification")
return readers.afm(specification,method)
end
+registerafmenhancer("unify names",enhance_unify_names)
+registerafmenhancer("add ligatures",enhance_add_ligatures)
+registerafmenhancer("add extra kerns",enhance_add_extra_kerns)
+registerafmenhancer("normalize features",enhance_normalize_features)
+registerafmenhancer("check extra features",otfenhancers.enhance)
+registerafmenhancer("fix names",enhance_fix_names)
end -- closure
@@ -24533,6 +25826,514 @@ end -- closure
do -- begin closure to overcome local limits and interference
+if not modules then modules={} end modules ['font-tfm']={
+ version=1.001,
+ comment="companion to font-ini.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local next,type=next,type
+local match,format=string.match,string.format
+local concat,sortedhash=table.concat,table.sortedhash
+local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
+local trace_features=false trackers.register("tfm.features",function(v) trace_features=v end)
+local report_defining=logs.reporter("fonts","defining")
+local report_tfm=logs.reporter("fonts","tfm loading")
+local findbinfile=resolvers.findbinfile
+local setmetatableindex=table.setmetatableindex
+local fonts=fonts
+local handlers=fonts.handlers
+local readers=fonts.readers
+local constructors=fonts.constructors
+local encodings=fonts.encodings
+local tfm=constructors.handlers.tfm
+tfm.version=1.000
+tfm.maxnestingdepth=5
+tfm.maxnestingsize=65536*1024
+local otf=fonts.handlers.otf
+local otfenhancers=otf.enhancers
+local tfmfeatures=constructors.features.tfm
+local registertfmfeature=tfmfeatures.register
+local tfmenhancers=constructors.enhancers.tfm
+local registertfmenhancer=tfmenhancers.register
+constructors.resolvevirtualtoo=false
+fonts.formats.tfm="type1"
+fonts.formats.ofm="type1"
+function tfm.setfeatures(tfmdata,features)
+ local okay=constructors.initializefeatures("tfm",tfmdata,features,trace_features,report_tfm)
+ if okay then
+ return constructors.collectprocessors("tfm",tfmdata,features,trace_features,report_tfm)
+ else
+ return {}
+ end
+end
+local depth={}
+local function read_from_tfm(specification)
+ local filename=specification.filename
+ local size=specification.size
+ depth[filename]=(depth[filename] or 0)+1
+ if trace_defining then
+ report_defining("loading tfm file %a at size %s",filename,size)
+ end
+ local tfmdata=font.read_tfm(filename,size)
+ if tfmdata then
+ local features=specification.features and specification.features.normal or {}
+ local features=constructors.checkedfeatures("tfm",features)
+ specification.features.normal=features
+ local newtfmdata=(depth[filename]==1) and tfm.reencode(tfmdata,specification)
+ if newtfmdata then
+ tfmdata=newtfmdata
+ end
+ local resources=tfmdata.resources or {}
+ local properties=tfmdata.properties or {}
+ local parameters=tfmdata.parameters or {}
+ local shared=tfmdata.shared or {}
+ shared.features=features
+ shared.resources=resources
+ properties.name=tfmdata.name
+ properties.fontname=tfmdata.fontname
+ properties.psname=tfmdata.psname
+ properties.fullname=tfmdata.fullname
+ properties.filename=specification.filename
+ properties.format=fonts.formats.tfm
+ tfmdata.properties=properties
+ tfmdata.resources=resources
+ tfmdata.parameters=parameters
+ tfmdata.shared=shared
+ shared.rawdata={ resources=resources }
+ shared.features=features
+ if newtfmdata then
+ if not resources.marks then
+ resources.marks={}
+ end
+ if not resources.sequences then
+ resources.sequences={}
+ end
+ if not resources.features then
+ resources.features={
+ gsub={},
+ gpos={},
+ }
+ end
+ if not tfmdata.changed then
+ tfmdata.changed={}
+ end
+ if not tfmdata.descriptions then
+ tfmdata.descriptions=tfmdata.characters
+ end
+ otf.readers.addunicodetable(tfmdata)
+ tfmenhancers.apply(tfmdata,filename)
+ constructors.applymanipulators("tfm",tfmdata,features,trace_features,report_tfm)
+ otf.readers.unifymissing(tfmdata)
+ fonts.mappings.addtounicode(tfmdata,filename)
+ tfmdata.tounicode=1
+ local tounicode=fonts.mappings.tounicode
+ for unicode,v in next,tfmdata.characters do
+ local u=v.unicode
+ if u then
+ v.tounicode=tounicode(u)
+ end
+ end
+ if tfmdata.usedbitmap then
+ tfm.addtounicode(tfmdata)
+ end
+ end
+ shared.processes=next(features) and tfm.setfeatures(tfmdata,features) or nil
+ parameters.factor=1
+ parameters.size=size
+ parameters.slant=parameters.slant or parameters[1] or 0
+ parameters.space=parameters.space or parameters[2] or 0
+ parameters.space_stretch=parameters.space_stretch or parameters[3] or 0
+ parameters.space_shrink=parameters.space_shrink or parameters[4] or 0
+ parameters.x_height=parameters.x_height or parameters[5] or 0
+ parameters.quad=parameters.quad or parameters[6] or 0
+ parameters.extra_space=parameters.extra_space or parameters[7] or 0
+ constructors.enhanceparameters(parameters)
+ if newtfmdata then
+ elseif constructors.resolvevirtualtoo then
+ fonts.loggers.register(tfmdata,file.suffix(filename),specification)
+ local vfname=findbinfile(specification.name,'ovf')
+ if vfname and vfname~="" then
+ local vfdata=font.read_vf(vfname,size)
+ if vfdata then
+ local chars=tfmdata.characters
+ for k,v in next,vfdata.characters do
+ chars[k].commands=v.commands
+ end
+ properties.virtualized=true
+ tfmdata.fonts=vfdata.fonts
+ tfmdata.type="virtual"
+ local fontlist=vfdata.fonts
+ local name=file.nameonly(filename)
+ for i=1,#fontlist do
+ local n=fontlist[i].name
+ local s=fontlist[i].size
+ local d=depth[filename]
+ s=constructors.scaled(s,vfdata.designsize)
+ if d>tfm.maxnestingdepth then
+ report_defining("too deeply nested virtual font %a with size %a, max nesting depth %s",n,s,tfm.maxnestingdepth)
+ fontlist[i]={ id=0 }
+ elseif (d>1) and (s>tfm.maxnestingsize) then
+ report_defining("virtual font %a exceeds size %s",n,s)
+ fontlist[i]={ id=0 }
+ else
+ local t,id=fonts.constructors.readanddefine(n,s)
+ fontlist[i]={ id=id }
+ end
+ end
+ end
+ end
+ end
+ properties.haskerns=true
+ properties.hasligatures=true
+ resources.unicodes={}
+ resources.lookuptags={}
+ depth[filename]=depth[filename]-1
+ return tfmdata
+ else
+ depth[filename]=depth[filename]-1
+ end
+end
+local function check_tfm(specification,fullname)
+ local foundname=findbinfile(fullname,'tfm') or ""
+ if foundname=="" then
+ foundname=findbinfile(fullname,'ofm') or ""
+ end
+ if foundname=="" then
+ foundname=fonts.names.getfilename(fullname,"tfm") or ""
+ end
+ if foundname~="" then
+ specification.filename=foundname
+ specification.format="ofm"
+ return read_from_tfm(specification)
+ elseif trace_defining then
+ report_defining("loading tfm with name %a fails",specification.name)
+ end
+end
+readers.check_tfm=check_tfm
+function readers.tfm(specification)
+ local fullname=specification.filename or ""
+ if fullname=="" then
+ local forced=specification.forced or ""
+ if forced~="" then
+ fullname=specification.name.."."..forced
+ else
+ fullname=specification.name
+ end
+ end
+ return check_tfm(specification,fullname)
+end
+readers.ofm=readers.tfm
+do
+ local outfiles={}
+ local tfmcache=table.setmetatableindex(function(t,tfmdata)
+ local id=font.define(tfmdata)
+ t[tfmdata]=id
+ return id
+ end)
+ local encdone=table.setmetatableindex("table")
+ function tfm.reencode(tfmdata,specification)
+ local features=specification.features
+ if not features then
+ return
+ end
+ local features=features.normal
+ if not features then
+ return
+ end
+ local tfmfile=file.basename(tfmdata.name)
+ local encfile=features.reencode
+ local pfbfile=features.pfbfile
+ local bitmap=features.bitmap
+ if not encfile then
+ return
+ end
+ local pfbfile=outfiles[tfmfile]
+ if pfbfile==nil then
+ if bitmap then
+ pfbfile=false
+ elseif type(pfbfile)~="string" then
+ pfbfile=tfmfile
+ end
+ if type(pfbfile)=="string" then
+ pfbfile=file.addsuffix(pfbfile,"pfb")
+ report_tfm("using type1 shapes from %a for %a",pfbfile,tfmfile)
+ else
+ report_tfm("using bitmap shapes for %a",tfmfile)
+ pfbfile=false
+ end
+ outfiles[tfmfile]=pfbfile
+ end
+ local encoding=false
+ local vector=false
+ if type(pfbfile)=="string" then
+ local pfb=fonts.constructors.handlers.pfb
+ if pfb and pfb.loadvector then
+ local v,e=pfb.loadvector(pfbfile)
+ if v then
+ vector=v
+ end
+ if e then
+ encoding=e
+ end
+ end
+ end
+ if type(encfile)=="string" and encfile~="auto" then
+ encoding=fonts.encodings.load(file.addsuffix(encfile,"enc"))
+ if encoding then
+ encoding=encoding.vector
+ end
+ end
+ if not encoding then
+ report_tfm("bad encoding for %a, quitting",tfmfile)
+ return
+ end
+ local unicoding=fonts.encodings.agl and fonts.encodings.agl.unicodes
+ local virtualid=tfmcache[tfmdata]
+ local tfmdata=table.copy(tfmdata)
+ local characters={}
+ local originals=tfmdata.characters
+ local indices={}
+ local parentfont={ "font",1 }
+ local private=fonts.constructors.privateoffset
+ local reported=encdone[tfmfile][encfile]
+ local backmap=vector and table.swapped(vector)
+ local done={}
+ for index,name in sortedhash(encoding) do
+ local unicode=unicoding[name]
+ local original=originals[index]
+ if original then
+ if unicode then
+ original.unicode=unicode
+ else
+ unicode=private
+ private=private+1
+ if not reported then
+ report_tfm("glyph %a in font %a with encoding %a gets unicode %U",name,tfmfile,encfile,unicode)
+ end
+ end
+ characters[unicode]=original
+ indices[index]=unicode
+ original.name=name
+ if backmap then
+ original.index=backmap[name]
+ else
+ original.commands={ parentfont,{ "char",index } }
+ original.oindex=index
+ end
+ done[name]=true
+ elseif not done[name] then
+ report_tfm("bad index %a in font %a with name %a",index,tfmfile,name)
+ end
+ end
+ encdone[tfmfile][encfile]=true
+ for k,v in next,characters do
+ local kerns=v.kerns
+ if kerns then
+ local t={}
+ for k,v in next,kerns do
+ local i=indices[k]
+ if i then
+ t[i]=v
+ end
+ end
+ v.kerns=next(t) and t or nil
+ end
+ local ligatures=v.ligatures
+ if ligatures then
+ local t={}
+ for k,v in next,ligatures do
+ local i=indices[k]
+ if i then
+ t[i]=v
+ v.char=indices[v.char]
+ end
+ end
+ v.ligatures=next(t) and t or nil
+ end
+ end
+ tfmdata.fonts={ { id=virtualid } }
+ tfmdata.characters=characters
+ tfmdata.fullname=tfmdata.fullname or tfmdata.name
+ tfmdata.psname=file.nameonly(pfbfile or tfmdata.name)
+ tfmdata.filename=pfbfile
+ tfmdata.encodingbytes=2
+ tfmdata.format="type1"
+ tfmdata.tounicode=1
+ tfmdata.embedding="subset"
+ tfmdata.usedbitmap=bitmap and virtualid
+ return tfmdata
+ end
+end
+do
+ local template=[[
+/CIDInit /ProcSet findresource begin
+ 12 dict begin
+ begincmap
+ /CIDSystemInfo << /Registry (TeX) /Ordering (bitmap-%s) /Supplement 0 >> def
+ /CMapName /TeX-bitmap-%s def
+ /CMapType 2 def
+ 1 begincodespacerange
+ <00> <FF>
+ endcodespacerange
+ %s beginbfchar
+%s
+ endbfchar
+ endcmap
+CMapName currentdict /CMap defineresource pop end
+end
+end
+]]
+ local flushstreamobject=lpdf and lpdf.flushstreamobject
+ local setfontattributes=pdf.setfontattributes
+ if not flushstreamobject then
+ flushstreamobject=function(data)
+ return pdf.obj {
+ immediate=true,
+ type="stream",
+ string=data,
+ }
+ end
+ end
+ if not setfontattributes then
+ setfontattributes=function(id,data)
+ print(format("your luatex is too old so no tounicode bitmap font%i",id))
+ end
+ end
+ function tfm.addtounicode(tfmdata)
+ local id=tfmdata.usedbitmap
+ local map={}
+ local char={}
+ for k,v in next,tfmdata.characters do
+ local index=v.oindex
+ local tounicode=v.tounicode
+ if index and tounicode then
+ map[index]=tounicode
+ end
+ end
+ for k,v in sortedhash(map) do
+ char[#char+1]=format("<%02X> <%s>",k,v)
+ end
+ char=concat(char,"\n")
+ local stream=format(template,id,id,#char,char)
+ local reference=flushstreamobject(stream,nil,true)
+ setfontattributes(id,format("/ToUnicode %i 0 R",reference))
+ end
+end
+do
+ local everywhere={ ["*"]={ ["*"]=true } }
+ local noflags={ false,false,false,false }
+ local function enhance_normalize_features(data)
+ local ligatures=setmetatableindex("table")
+ local kerns=setmetatableindex("table")
+ local characters=data.characters
+ for u,c in next,characters do
+ local l=c.ligatures
+ local k=c.kerns
+ if l then
+ ligatures[u]=l
+ for u,v in next,l do
+ l[u]={ ligature=v.char }
+ end
+ c.ligatures=nil
+ end
+ if k then
+ kerns[u]=k
+ for u,v in next,k do
+ k[u]=v
+ end
+ c.kerns=nil
+ end
+ end
+ for u,l in next,ligatures do
+ for k,v in next,l do
+ local vl=v.ligature
+ local dl=ligatures[vl]
+ if dl then
+ for kk,vv in next,dl do
+ v[kk]=vv
+ end
+ end
+ end
+ end
+ local features={
+ gpos={},
+ gsub={},
+ }
+ local sequences={
+ }
+ if next(ligatures) then
+ features.gsub.liga=everywhere
+ data.properties.hasligatures=true
+ sequences[#sequences+1]={
+ features={
+ liga=everywhere,
+ },
+ flags=noflags,
+ name="s_s_0",
+ nofsteps=1,
+ order={ "liga" },
+ type="gsub_ligature",
+ steps={
+ {
+ coverage=ligatures,
+ },
+ },
+ }
+ end
+ if next(kerns) then
+ features.gpos.kern=everywhere
+ data.properties.haskerns=true
+ sequences[#sequences+1]={
+ features={
+ kern=everywhere,
+ },
+ flags=noflags,
+ name="p_s_0",
+ nofsteps=1,
+ order={ "kern" },
+ type="gpos_pair",
+ steps={
+ {
+ format="kern",
+ coverage=kerns,
+ },
+ },
+ }
+ end
+ data.resources.features=features
+ data.resources.sequences=sequences
+ data.shared.resources=data.shared.resources or resources
+ end
+ registertfmenhancer("normalize features",enhance_normalize_features)
+ registertfmenhancer("check extra features",otfenhancers.enhance)
+end
+registertfmfeature {
+ name="mode",
+ description="mode",
+ initializers={
+ base=otf.modeinitializer,
+ node=otf.modeinitializer,
+ }
+}
+registertfmfeature {
+ name="features",
+ description="features",
+ default=true,
+ initializers={
+ base=otf.basemodeinitializer,
+ node=otf.nodemodeinitializer,
+ },
+ processors={
+ node=otf.featuresprocessor,
+ }
+}
+
+end -- closure
+
+do -- begin closure to overcome local limits and interference
+
if not modules then modules={} end modules ['font-lua']={
version=1.001,
comment="companion to font-ini.mkiv",
@@ -24582,10 +26383,11 @@ if not modules then modules={} end modules ['font-def']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local format,gmatch,match,find,lower,gsub=string.format,string.gmatch,string.match,string.find,string.lower,string.gsub
+local lower,gsub=string.lower,string.gsub
local tostring,next=tostring,next
local lpegmatch=lpeg.match
local suffixonly,removesuffix=file.suffix,file.removesuffix
+local formatters=string.formatters
local allocate=utilities.storage.allocate
local trace_defining=false trackers .register("fonts.defining",function(v) trace_defining=v end)
local directive_embedall=false directives.register("fonts.embedall",function(v) directive_embedall=v end)
@@ -24746,7 +26548,7 @@ function definers.applypostprocessors(tfmdata)
local extrahash=postprocessors[i](tfmdata)
if type(extrahash)=="string" and extrahash~="" then
extrahash=gsub(lower(extrahash),"[^a-z]","-")
- properties.fullname=format("%s-%s",properties.fullname,extrahash)
+ properties.fullname=formatters["%s-%s"](properties.fullname,extrahash)
end
end
end
@@ -25204,6 +27006,19 @@ otffeatures.register {
node=reencode,
}
}
+local function ignore(tfmdata,key,value)
+ if value then
+ tfmdata.mathparameters=nil
+ end
+end
+otffeatures.register {
+ name="ignoremathconstants",
+ description="ignore math constants table",
+ initializers={
+ base=ignore,
+ node=ignore,
+ }
+}
end -- closure
@@ -25224,7 +27039,7 @@ local fonts=fonts
local nodes=nodes
local nuts=nodes.nuts
local traverse_id=nuts.traverse_id
-local free_node=nuts.free
+local flush_node=nuts.flush_node
local glyph_code=nodes.nodecodes.glyph
local disc_code=nodes.nodecodes.disc
local tonode=nuts.tonode
@@ -25348,7 +27163,7 @@ function nodes.handlers.nodepass(head)
end
end
end
- free_node(r)
+ flush_node(r)
end
end
for d in traverse_id(disc_code,nuthead) do
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-swiglib-test.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-swiglib-test.lua
index db6a729098d..00d7c5a4efe 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-swiglib-test.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-swiglib-test.lua
@@ -1,25 +1,743 @@
-local gm = swiglib("gmwand.core")
-gm.InitializeMagick(".")
-local magick_wand = gm.NewMagickWand()
-local drawing_wand = gm.NewDrawingWand()
+-- local gm = require("swiglib.gmwand.core") -- local gm = swiglib("gmwand.core")
+--
+-- gm.InitializeMagick(".")
+--
+-- local magick_wand = gm.NewMagickWand()
+-- local drawing_wand = gm.NewDrawingWand()
+--
+-- gm.MagickSetSize(magick_wand,800,600)
+-- gm.MagickReadImage(magick_wand,"xc:red")
+--
+-- gm.DrawPushGraphicContext(drawing_wand)
+--
+-- gm.DrawSetFillColor(drawing_wand,gm.NewPixelWand())
+--
+-- -- gm.DrawSetFont(drawing_wand, kpse.findfile("DejaVuSerifBold.ttf"))
+-- -- gm.DrawSetFontSize(drawing_wand, 96)
+-- -- gm.DrawAnnotation(drawing_wand,300,200, "LuaTeX")
+--
+-- gm.DrawPopGraphicContext(drawing_wand)
+-- gm.MagickDrawImage(magick_wand,drawing_wand)
+--
+-- gm.MagickWriteImages(magick_wand,"./luatex-swiglib-test.jpg",1)
+--
+-- gm.DestroyDrawingWand(drawing_wand)
+-- gm.DestroyMagickWand(magick_wand)
-gm.MagickSetSize(magick_wand,800,600)
-gm.MagickReadImage(magick_wand,"xc:red")
+local swighelpers = require("swiglib.helpers.core")
+local sqlite = require("swiglib.sqlite.core")
-gm.DrawPushGraphicContext(drawing_wand)
+-- s.sqlite3_create_function_v2_lua_callback(function() end)
-gm.DrawSetFillColor(drawing_wand,gm.NewPixelWand())
--- gm.DrawSetFont(drawing_wand, kpse.findfile("DejaVuSerifBold.ttf"))
--- gm.DrawSetFontSize(drawing_wand, 96)
--- gm.DrawAnnotation(drawing_wand,300,200, "LuaTeX")
+local t = [[
+ CREATE TABLE IF NOT EXISTS loggers (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `time` int(11) NOT NULL,
+ `type` int(11) NOT NULL,
+ `action` varchar(15) NOT NULL,
+ `data` longtext,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `id_unique_key` (`id`)
+ )
+ DEFAULT CHARSET = utf8 ;
+]]
-gm.DrawPopGraphicContext(drawing_wand)
-gm.MagickDrawImage(magick_wand,drawing_wand)
+local t = [[
+CREATE TABLE IF NOT EXISTS loggers (
+ `id` INTEGER PRIMARY KEY AUTOINCREMENT,
+ `time` int(11) NOT NULL,
+ `type` int(11) NOT NULL,
+ `action` varchar(15) NOT NULL,
+ `data` longtext
+ );
+]]
-gm.MagickWriteImages(magick_wand,"./luatex-swiglib-test.jpg",1)
+local function execute(name,query)
+ local db = sqlite.new_sqlite3_p_array(1)
+ local okay = sqlite.sqlite3_open(name,db)
+ local dbh = sqlite.sqlite3_p_array_getitem(db,0)
+ if okay ~= sqlite.SQLITE_OK then
+ return false, sqlite.sqlite3_errmsg(dbh)
+ end
+ local result = { }
+ local callback = function(data,nofcolumns,values,fields)
+ local r = { }
+ for i=0,nofcolumns-1 do
+ local field = sqlite.char_p_array_getitem(fields,i)
+ local value = sqlite.char_p_array_getitem(values,i)
+ r[field] = value
+ end
+ result[#result+1] = r
+ return sqlite.SQLITE_OK
+ end
+ local data = nil
+ local message = nil
+ local okay = sqlite.sqlite3_exec_lua_callback(dbh,query,callback,data,message)
+ if okay ~= sqlite.SQLITE_OK then
+ return false, sqlite.sqlite3_errmsg(dbh)
+ end
+ sqlite.sqlite3_close(dbh)
+ sqlite.delete_sqlite3_p_array(db)
+ return result
+end
-gm.DestroyDrawingWand(drawing_wand)
-gm.DestroyMagickWand(magick_wand)
+execute("foo.db",t)
+-- execute("test.db",t)
+
+local template =[[
+ INSERT INTO loggers (
+ `time`,
+ `type`,
+ `action`,
+ `data`
+ ) VALUES (
+ %s,
+ %s,
+ '%s',
+ '%s'
+ ) ;
+]]
+
+-- for i=1,100 do
+-- local t = string.format(template,os.time(),1,"oeps " .. i,"more")
+-- execute("foo.db",t)
+-- end
+
+
+local r = execute("foo.db","select * from loggers;")
+inspect(r)
+
+
+-- inspect(table.sortedkeys(sqlite))
+-- inspect(table.sortedkeys(swighelpers))
+
+
+
+t={
+ "FULLY_WITHIN",
+ "NOT_WITHIN",
+ "PARTLY_WITHIN",
+ "SQLITE3_TEXT",
+ "SQLITE_ABORT",
+ "SQLITE_ABORT_ROLLBACK",
+ "SQLITE_ACCESS_EXISTS",
+ "SQLITE_ACCESS_READ",
+ "SQLITE_ACCESS_READWRITE",
+ "SQLITE_ALTER_TABLE",
+ "SQLITE_ANALYZE",
+ "SQLITE_ANY",
+ "SQLITE_ATTACH",
+ "SQLITE_AUTH",
+ "SQLITE_AUTH_USER",
+ "SQLITE_BLOB",
+ "SQLITE_BUSY",
+ "SQLITE_BUSY_RECOVERY",
+ "SQLITE_BUSY_SNAPSHOT",
+ "SQLITE_CANTOPEN",
+ "SQLITE_CANTOPEN_CONVPATH",
+ "SQLITE_CANTOPEN_FULLPATH",
+ "SQLITE_CANTOPEN_ISDIR",
+ "SQLITE_CANTOPEN_NOTEMPDIR",
+ "SQLITE_CHECKPOINT_FULL",
+ "SQLITE_CHECKPOINT_PASSIVE",
+ "SQLITE_CHECKPOINT_RESTART",
+ "SQLITE_CONFIG_COVERING_INDEX_SCAN",
+ "SQLITE_CONFIG_GETMALLOC",
+ "SQLITE_CONFIG_GETMUTEX",
+ "SQLITE_CONFIG_GETPCACHE",
+ "SQLITE_CONFIG_GETPCACHE2",
+ "SQLITE_CONFIG_HEAP",
+ "SQLITE_CONFIG_LOG",
+ "SQLITE_CONFIG_LOOKASIDE",
+ "SQLITE_CONFIG_MALLOC",
+ "SQLITE_CONFIG_MEMSTATUS",
+ "SQLITE_CONFIG_MMAP_SIZE",
+ "SQLITE_CONFIG_MULTITHREAD",
+ "SQLITE_CONFIG_MUTEX",
+ "SQLITE_CONFIG_PAGECACHE",
+ "SQLITE_CONFIG_PCACHE",
+ "SQLITE_CONFIG_PCACHE2",
+ "SQLITE_CONFIG_SCRATCH",
+ "SQLITE_CONFIG_SERIALIZED",
+ "SQLITE_CONFIG_SINGLETHREAD",
+ "SQLITE_CONFIG_SQLLOG",
+ "SQLITE_CONFIG_URI",
+ "SQLITE_CONFIG_WIN32_HEAPSIZE",
+ "SQLITE_CONSTRAINT",
+ "SQLITE_CONSTRAINT_CHECK",
+ "SQLITE_CONSTRAINT_COMMITHOOK",
+ "SQLITE_CONSTRAINT_FOREIGNKEY",
+ "SQLITE_CONSTRAINT_FUNCTION",
+ "SQLITE_CONSTRAINT_NOTNULL",
+ "SQLITE_CONSTRAINT_PRIMARYKEY",
+ "SQLITE_CONSTRAINT_ROWID",
+ "SQLITE_CONSTRAINT_TRIGGER",
+ "SQLITE_CONSTRAINT_UNIQUE",
+ "SQLITE_CONSTRAINT_VTAB",
+ "SQLITE_COPY",
+ "SQLITE_CORRUPT",
+ "SQLITE_CORRUPT_VTAB",
+ "SQLITE_CREATE_INDEX",
+ "SQLITE_CREATE_TABLE",
+ "SQLITE_CREATE_TEMP_INDEX",
+ "SQLITE_CREATE_TEMP_TABLE",
+ "SQLITE_CREATE_TEMP_TRIGGER",
+ "SQLITE_CREATE_TEMP_VIEW",
+ "SQLITE_CREATE_TRIGGER",
+ "SQLITE_CREATE_VIEW",
+ "SQLITE_CREATE_VTABLE",
+ "SQLITE_DBCONFIG_ENABLE_FKEY",
+ "SQLITE_DBCONFIG_ENABLE_TRIGGER",
+ "SQLITE_DBCONFIG_LOOKASIDE",
+ "SQLITE_DBSTATUS_CACHE_HIT",
+ "SQLITE_DBSTATUS_CACHE_MISS",
+ "SQLITE_DBSTATUS_CACHE_USED",
+ "SQLITE_DBSTATUS_CACHE_WRITE",
+ "SQLITE_DBSTATUS_DEFERRED_FKS",
+ "SQLITE_DBSTATUS_LOOKASIDE_HIT",
+ "SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL",
+ "SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE",
+ "SQLITE_DBSTATUS_LOOKASIDE_USED",
+ "SQLITE_DBSTATUS_MAX",
+ "SQLITE_DBSTATUS_SCHEMA_USED",
+ "SQLITE_DBSTATUS_STMT_USED",
+ "SQLITE_DELETE",
+ "SQLITE_DENY",
+ "SQLITE_DETACH",
+ "SQLITE_DETERMINISTIC",
+ "SQLITE_DONE",
+ "SQLITE_DROP_INDEX",
+ "SQLITE_DROP_TABLE",
+ "SQLITE_DROP_TEMP_INDEX",
+ "SQLITE_DROP_TEMP_TABLE",
+ "SQLITE_DROP_TEMP_TRIGGER",
+ "SQLITE_DROP_TEMP_VIEW",
+ "SQLITE_DROP_TRIGGER",
+ "SQLITE_DROP_VIEW",
+ "SQLITE_DROP_VTABLE",
+ "SQLITE_EMPTY",
+ "SQLITE_ERROR",
+ "SQLITE_FAIL",
+ "SQLITE_FCNTL_BUSYHANDLER",
+ "SQLITE_FCNTL_CHUNK_SIZE",
+ "SQLITE_FCNTL_COMMIT_PHASETWO",
+ "SQLITE_FCNTL_FILE_POINTER",
+ "SQLITE_FCNTL_HAS_MOVED",
+ "SQLITE_FCNTL_LOCKSTATE",
+ "SQLITE_FCNTL_MMAP_SIZE",
+ "SQLITE_FCNTL_OVERWRITE",
+ "SQLITE_FCNTL_PERSIST_WAL",
+ "SQLITE_FCNTL_POWERSAFE_OVERWRITE",
+ "SQLITE_FCNTL_PRAGMA",
+ "SQLITE_FCNTL_SIZE_HINT",
+ "SQLITE_FCNTL_SYNC",
+ "SQLITE_FCNTL_SYNC_OMITTED",
+ "SQLITE_FCNTL_TEMPFILENAME",
+ "SQLITE_FCNTL_TRACE",
+ "SQLITE_FCNTL_VFSNAME",
+ "SQLITE_FCNTL_WIN32_AV_RETRY",
+ "SQLITE_FCNTL_WIN32_SET_HANDLE",
+ "SQLITE_FLOAT",
+ "SQLITE_FORMAT",
+ "SQLITE_FULL",
+ "SQLITE_FUNCTION",
+ "SQLITE_GET_LOCKPROXYFILE",
+ "SQLITE_IGNORE",
+ "SQLITE_INDEX_CONSTRAINT_EQ",
+ "SQLITE_INDEX_CONSTRAINT_GE",
+ "SQLITE_INDEX_CONSTRAINT_GT",
+ "SQLITE_INDEX_CONSTRAINT_LE",
+ "SQLITE_INDEX_CONSTRAINT_LT",
+ "SQLITE_INDEX_CONSTRAINT_MATCH",
+ "SQLITE_INSERT",
+ "SQLITE_INTEGER",
+ "SQLITE_INTERNAL",
+ "SQLITE_INTERRUPT",
+ "SQLITE_IOCAP_ATOMIC",
+ "SQLITE_IOCAP_ATOMIC16K",
+ "SQLITE_IOCAP_ATOMIC1K",
+ "SQLITE_IOCAP_ATOMIC2K",
+ "SQLITE_IOCAP_ATOMIC32K",
+ "SQLITE_IOCAP_ATOMIC4K",
+ "SQLITE_IOCAP_ATOMIC512",
+ "SQLITE_IOCAP_ATOMIC64K",
+ "SQLITE_IOCAP_ATOMIC8K",
+ "SQLITE_IOCAP_IMMUTABLE",
+ "SQLITE_IOCAP_POWERSAFE_OVERWRITE",
+ "SQLITE_IOCAP_SAFE_APPEND",
+ "SQLITE_IOCAP_SEQUENTIAL",
+ "SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN",
+ "SQLITE_IOERR",
+ "SQLITE_IOERR_ACCESS",
+ "SQLITE_IOERR_BLOCKED",
+ "SQLITE_IOERR_CHECKRESERVEDLOCK",
+ "SQLITE_IOERR_CLOSE",
+ "SQLITE_IOERR_CONVPATH",
+ "SQLITE_IOERR_DELETE",
+ "SQLITE_IOERR_DELETE_NOENT",
+ "SQLITE_IOERR_DIR_CLOSE",
+ "SQLITE_IOERR_DIR_FSYNC",
+ "SQLITE_IOERR_FSTAT",
+ "SQLITE_IOERR_FSYNC",
+ "SQLITE_IOERR_GETTEMPPATH",
+ "SQLITE_IOERR_LOCK",
+ "SQLITE_IOERR_MMAP",
+ "SQLITE_IOERR_NOMEM",
+ "SQLITE_IOERR_RDLOCK",
+ "SQLITE_IOERR_READ",
+ "SQLITE_IOERR_SEEK",
+ "SQLITE_IOERR_SHMLOCK",
+ "SQLITE_IOERR_SHMMAP",
+ "SQLITE_IOERR_SHMOPEN",
+ "SQLITE_IOERR_SHMSIZE",
+ "SQLITE_IOERR_SHORT_READ",
+ "SQLITE_IOERR_TRUNCATE",
+ "SQLITE_IOERR_UNLOCK",
+ "SQLITE_IOERR_WRITE",
+ "SQLITE_LAST_ERRNO",
+ "SQLITE_LIMIT_ATTACHED",
+ "SQLITE_LIMIT_COLUMN",
+ "SQLITE_LIMIT_COMPOUND_SELECT",
+ "SQLITE_LIMIT_EXPR_DEPTH",
+ "SQLITE_LIMIT_FUNCTION_ARG",
+ "SQLITE_LIMIT_LENGTH",
+ "SQLITE_LIMIT_LIKE_PATTERN_LENGTH",
+ "SQLITE_LIMIT_SQL_LENGTH",
+ "SQLITE_LIMIT_TRIGGER_DEPTH",
+ "SQLITE_LIMIT_VARIABLE_NUMBER",
+ "SQLITE_LIMIT_VDBE_OP",
+ "SQLITE_LIMIT_WORKER_THREADS",
+ "SQLITE_LOCKED",
+ "SQLITE_LOCKED_SHAREDCACHE",
+ "SQLITE_LOCK_EXCLUSIVE",
+ "SQLITE_LOCK_NONE",
+ "SQLITE_LOCK_PENDING",
+ "SQLITE_LOCK_RESERVED",
+ "SQLITE_LOCK_SHARED",
+ "SQLITE_MISMATCH",
+ "SQLITE_MISUSE",
+ "SQLITE_MUTEX_FAST",
+ "SQLITE_MUTEX_RECURSIVE",
+ "SQLITE_MUTEX_STATIC_APP1",
+ "SQLITE_MUTEX_STATIC_APP2",
+ "SQLITE_MUTEX_STATIC_APP3",
+ "SQLITE_MUTEX_STATIC_LRU",
+ "SQLITE_MUTEX_STATIC_LRU2",
+ "SQLITE_MUTEX_STATIC_MASTER",
+ "SQLITE_MUTEX_STATIC_MEM",
+ "SQLITE_MUTEX_STATIC_MEM2",
+ "SQLITE_MUTEX_STATIC_OPEN",
+ "SQLITE_MUTEX_STATIC_PMEM",
+ "SQLITE_MUTEX_STATIC_PRNG",
+ "SQLITE_NOLFS",
+ "SQLITE_NOMEM",
+ "SQLITE_NOTADB",
+ "SQLITE_NOTFOUND",
+ "SQLITE_NOTICE",
+ "SQLITE_NOTICE_RECOVER_ROLLBACK",
+ "SQLITE_NOTICE_RECOVER_WAL",
+ "SQLITE_NULL",
+ "SQLITE_OK",
+ "SQLITE_OPEN_AUTOPROXY",
+ "SQLITE_OPEN_CREATE",
+ "SQLITE_OPEN_DELETEONCLOSE",
+ "SQLITE_OPEN_EXCLUSIVE",
+ "SQLITE_OPEN_FULLMUTEX",
+ "SQLITE_OPEN_MAIN_DB",
+ "SQLITE_OPEN_MAIN_JOURNAL",
+ "SQLITE_OPEN_MASTER_JOURNAL",
+ "SQLITE_OPEN_MEMORY",
+ "SQLITE_OPEN_NOMUTEX",
+ "SQLITE_OPEN_PRIVATECACHE",
+ "SQLITE_OPEN_READONLY",
+ "SQLITE_OPEN_READWRITE",
+ "SQLITE_OPEN_SHAREDCACHE",
+ "SQLITE_OPEN_SUBJOURNAL",
+ "SQLITE_OPEN_TEMP_DB",
+ "SQLITE_OPEN_TEMP_JOURNAL",
+ "SQLITE_OPEN_TRANSIENT_DB",
+ "SQLITE_OPEN_URI",
+ "SQLITE_OPEN_WAL",
+ "SQLITE_PERM",
+ "SQLITE_PRAGMA",
+ "SQLITE_PROTOCOL",
+ "SQLITE_RANGE",
+ "SQLITE_READ",
+ "SQLITE_READONLY",
+ "SQLITE_READONLY_CANTLOCK",
+ "SQLITE_READONLY_DBMOVED",
+ "SQLITE_READONLY_RECOVERY",
+ "SQLITE_READONLY_ROLLBACK",
+ "SQLITE_RECURSIVE",
+ "SQLITE_REINDEX",
+ "SQLITE_REPLACE",
+ "SQLITE_ROLLBACK",
+ "SQLITE_ROW",
+ "SQLITE_SAVEPOINT",
+ "SQLITE_SCHEMA",
+ "SQLITE_SELECT",
+ "SQLITE_SET_LOCKPROXYFILE",
+ "SQLITE_SHM_EXCLUSIVE",
+ "SQLITE_SHM_LOCK",
+ "SQLITE_SHM_NLOCK",
+ "SQLITE_SHM_SHARED",
+ "SQLITE_SHM_UNLOCK",
+ "SQLITE_SOURCE_ID",
+ "SQLITE_STATUS_MALLOC_COUNT",
+ "SQLITE_STATUS_MALLOC_SIZE",
+ "SQLITE_STATUS_MEMORY_USED",
+ "SQLITE_STATUS_PAGECACHE_OVERFLOW",
+ "SQLITE_STATUS_PAGECACHE_SIZE",
+ "SQLITE_STATUS_PAGECACHE_USED",
+ "SQLITE_STATUS_PARSER_STACK",
+ "SQLITE_STATUS_SCRATCH_OVERFLOW",
+ "SQLITE_STATUS_SCRATCH_SIZE",
+ "SQLITE_STATUS_SCRATCH_USED",
+ "SQLITE_STMTSTATUS_AUTOINDEX",
+ "SQLITE_STMTSTATUS_FULLSCAN_STEP",
+ "SQLITE_STMTSTATUS_SORT",
+ "SQLITE_STMTSTATUS_VM_STEP",
+ "SQLITE_SYNC_DATAONLY",
+ "SQLITE_SYNC_FULL",
+ "SQLITE_SYNC_NORMAL",
+ "SQLITE_TESTCTRL_ALWAYS",
+ "SQLITE_TESTCTRL_ASSERT",
+ "SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS",
+ "SQLITE_TESTCTRL_BITVEC_TEST",
+ "SQLITE_TESTCTRL_BYTEORDER",
+ "SQLITE_TESTCTRL_EXPLAIN_STMT",
+ "SQLITE_TESTCTRL_FAULT_INSTALL",
+ "SQLITE_TESTCTRL_FIRST",
+ "SQLITE_TESTCTRL_ISINIT",
+ "SQLITE_TESTCTRL_ISKEYWORD",
+ "SQLITE_TESTCTRL_LAST",
+ "SQLITE_TESTCTRL_LOCALTIME_FAULT",
+ "SQLITE_TESTCTRL_NEVER_CORRUPT",
+ "SQLITE_TESTCTRL_OPTIMIZATIONS",
+ "SQLITE_TESTCTRL_PENDING_BYTE",
+ "SQLITE_TESTCTRL_PRNG_RESET",
+ "SQLITE_TESTCTRL_PRNG_RESTORE",
+ "SQLITE_TESTCTRL_PRNG_SAVE",
+ "SQLITE_TESTCTRL_RESERVE",
+ "SQLITE_TESTCTRL_SCRATCHMALLOC",
+ "SQLITE_TESTCTRL_SORTER_MMAP",
+ "SQLITE_TESTCTRL_VDBE_COVERAGE",
+ "SQLITE_TEXT",
+ "SQLITE_TOOBIG",
+ "SQLITE_TRANSACTION",
+ "SQLITE_UPDATE",
+ "SQLITE_UTF16",
+ "SQLITE_UTF16BE",
+ "SQLITE_UTF16LE",
+ "SQLITE_UTF16_ALIGNED",
+ "SQLITE_UTF8",
+ "SQLITE_VERSION",
+ "SQLITE_VERSION_NUMBER",
+ "SQLITE_VTAB_CONSTRAINT_SUPPORT",
+ "SQLITE_WARNING",
+ "SQLITE_WARNING_AUTOINDEX",
+ "call_callback_sqlite3_create_collation_v2_1",
+ "call_callback_sqlite3_create_collation_v2_2",
+ "call_callback_sqlite3_create_function16_1",
+ "call_callback_sqlite3_create_function16_2",
+ "call_callback_sqlite3_create_function16_3",
+ "call_callback_sqlite3_create_function_1",
+ "call_callback_sqlite3_create_function_2",
+ "call_callback_sqlite3_create_function_3",
+ "call_callback_sqlite3_create_function_v2_1",
+ "call_callback_sqlite3_create_function_v2_2",
+ "call_callback_sqlite3_create_function_v2_3",
+ "call_callback_sqlite3_create_function_v2_4",
+ "call_callback_sqlite3_rtree_query_callback_1",
+ "call_callback_sqlite3_rtree_query_callback_2",
+ "char_p_array_getitem",
+ "char_p_array_setitem",
+ "delete_char_p_array",
+ "delete_sqlite3_p_array",
+ "delete_sqlite3_rtree_dbl_array",
+ "delete_sqlite3_stmt_p_array",
+ "delete_sqlite3_value_p_array",
+ "delete_sqlite3_vtab_cursor_p_array",
+ "delete_sqlite3_vtab_p_array",
+ "delete_void_p_array",
+ "new_char_p_array",
+ "new_sqlite3_p_array",
+ "new_sqlite3_rtree_dbl_array",
+ "new_sqlite3_stmt_p_array",
+ "new_sqlite3_value_p_array",
+ "new_sqlite3_vtab_cursor_p_array",
+ "new_sqlite3_vtab_p_array",
+ "new_void_p_array",
+ "sqlite3_aggregate_context",
+ "sqlite3_aggregate_count",
+ "sqlite3_auto_extension",
+ "sqlite3_auto_extension_lua_callback",
+ "sqlite3_backup_finish",
+ "sqlite3_backup_init",
+ "sqlite3_backup_pagecount",
+ "sqlite3_backup_remaining",
+ "sqlite3_backup_step",
+ "sqlite3_bind_blob",
+ "sqlite3_bind_blob64",
+ "sqlite3_bind_blob64_lua_callback",
+ "sqlite3_bind_blob_lua_callback",
+ "sqlite3_bind_double",
+ "sqlite3_bind_int",
+ "sqlite3_bind_int64",
+ "sqlite3_bind_null",
+ "sqlite3_bind_parameter_count",
+ "sqlite3_bind_parameter_index",
+ "sqlite3_bind_parameter_name",
+ "sqlite3_bind_text",
+ "sqlite3_bind_text16",
+ "sqlite3_bind_text16_lua_callback",
+ "sqlite3_bind_text64",
+ "sqlite3_bind_text64_lua_callback",
+ "sqlite3_bind_text_lua_callback",
+ "sqlite3_bind_value",
+ "sqlite3_bind_zeroblob",
+ "sqlite3_blob_bytes",
+ "sqlite3_blob_close",
+ "sqlite3_blob_open",
+ "sqlite3_blob_read",
+ "sqlite3_blob_reopen",
+ "sqlite3_blob_write",
+ "sqlite3_busy_handler",
+ "sqlite3_busy_handler_lua_callback",
+ "sqlite3_busy_timeout",
+ "sqlite3_cancel_auto_extension",
+ "sqlite3_cancel_auto_extension_lua_callback",
+ "sqlite3_changes",
+ "sqlite3_clear_bindings",
+ "sqlite3_close",
+ "sqlite3_close_v2",
+ "sqlite3_collation_needed",
+ "sqlite3_collation_needed16",
+ "sqlite3_collation_needed16_lua_callback",
+ "sqlite3_collation_needed_lua_callback",
+ "sqlite3_column_blob",
+ "sqlite3_column_bytes",
+ "sqlite3_column_bytes16",
+ "sqlite3_column_count",
+ "sqlite3_column_decltype",
+ "sqlite3_column_decltype16",
+ "sqlite3_column_double",
+ "sqlite3_column_int",
+ "sqlite3_column_int64",
+ "sqlite3_column_name",
+ "sqlite3_column_name16",
+ "sqlite3_column_text",
+ "sqlite3_column_text16",
+ "sqlite3_column_type",
+ "sqlite3_column_value",
+ "sqlite3_commit_hook",
+ "sqlite3_commit_hook_lua_callback",
+ "sqlite3_compileoption_get",
+ "sqlite3_compileoption_used",
+ "sqlite3_complete",
+ "sqlite3_complete16",
+ "sqlite3_config",
+ "sqlite3_context_db_handle",
+ "sqlite3_create_collation",
+ "sqlite3_create_collation16",
+ "sqlite3_create_collation16_lua_callback",
+ "sqlite3_create_collation_lua_callback",
+ "sqlite3_create_collation_v2",
+ "sqlite3_create_collation_v2_lua_callback",
+ "sqlite3_create_function",
+ "sqlite3_create_function16",
+ "sqlite3_create_function16_lua_callback",
+ "sqlite3_create_function_lua_callback",
+ "sqlite3_create_function_v2",
+ "sqlite3_create_function_v2_lua_callback",
+ "sqlite3_create_module",
+ "sqlite3_create_module_v2",
+ "sqlite3_create_module_v2_lua_callback",
+ "sqlite3_data_count",
+ "sqlite3_db_config",
+ "sqlite3_db_filename",
+ "sqlite3_db_handle",
+ "sqlite3_db_mutex",
+ "sqlite3_db_readonly",
+ "sqlite3_db_release_memory",
+ "sqlite3_db_status",
+ "sqlite3_declare_vtab",
+ "sqlite3_enable_load_extension",
+ "sqlite3_enable_shared_cache",
+ "sqlite3_errcode",
+ "sqlite3_errmsg",
+ "sqlite3_errmsg16",
+ "sqlite3_errstr",
+ "sqlite3_exec",
+ "sqlite3_exec_lua_callback",
+ "sqlite3_expired",
+ "sqlite3_extended_errcode",
+ "sqlite3_extended_result_codes",
+ "sqlite3_file",
+ "sqlite3_file_control",
+ "sqlite3_finalize",
+ "sqlite3_free",
+ "sqlite3_free_table",
+ "sqlite3_get_autocommit",
+ "sqlite3_get_auxdata",
+ "sqlite3_get_table",
+ "sqlite3_global_recover",
+ "sqlite3_index_info",
+ "sqlite3_index_info_aConstraint",
+ "sqlite3_index_info_aConstraintUsage",
+ "sqlite3_index_info_aOrderBy",
+ "sqlite3_initialize",
+ "sqlite3_interrupt",
+ "sqlite3_io_methods",
+ "sqlite3_last_insert_rowid",
+ "sqlite3_libversion",
+ "sqlite3_libversion_number",
+ "sqlite3_limit",
+ "sqlite3_load_extension",
+ "sqlite3_log",
+ "sqlite3_malloc",
+ "sqlite3_malloc64",
+ "sqlite3_mem_methods",
+ "sqlite3_memory_alarm",
+ "sqlite3_memory_highwater",
+ "sqlite3_memory_used",
+ "sqlite3_module",
+ "sqlite3_mprintf",
+ "sqlite3_msize",
+ "sqlite3_mutex_alloc",
+ "sqlite3_mutex_enter",
+ "sqlite3_mutex_free",
+ "sqlite3_mutex_leave",
+ "sqlite3_mutex_methods",
+ "sqlite3_mutex_try",
+ "sqlite3_next_stmt",
+ "sqlite3_open",
+ "sqlite3_open16",
+ "sqlite3_open_v2",
+ "sqlite3_os_end",
+ "sqlite3_os_init",
+ "sqlite3_overload_function",
+ "sqlite3_p_array_getitem",
+ "sqlite3_p_array_setitem",
+ "sqlite3_pcache_methods",
+ "sqlite3_pcache_methods2",
+ "sqlite3_pcache_page",
+ "sqlite3_prepare",
+ "sqlite3_prepare16",
+ "sqlite3_prepare16_v2",
+ "sqlite3_prepare_v2",
+ "sqlite3_profile",
+ "sqlite3_progress_handler",
+ "sqlite3_progress_handler_lua_callback",
+ "sqlite3_randomness",
+ "sqlite3_realloc",
+ "sqlite3_realloc64",
+ "sqlite3_release_memory",
+ "sqlite3_reset",
+ "sqlite3_reset_auto_extension",
+ "sqlite3_result_blob",
+ "sqlite3_result_blob64",
+ "sqlite3_result_blob64_lua_callback",
+ "sqlite3_result_blob_lua_callback",
+ "sqlite3_result_double",
+ "sqlite3_result_error",
+ "sqlite3_result_error16",
+ "sqlite3_result_error_code",
+ "sqlite3_result_error_nomem",
+ "sqlite3_result_error_toobig",
+ "sqlite3_result_int",
+ "sqlite3_result_int64",
+ "sqlite3_result_null",
+ "sqlite3_result_text",
+ "sqlite3_result_text16",
+ "sqlite3_result_text16_lua_callback",
+ "sqlite3_result_text16be",
+ "sqlite3_result_text16be_lua_callback",
+ "sqlite3_result_text16le",
+ "sqlite3_result_text16le_lua_callback",
+ "sqlite3_result_text64",
+ "sqlite3_result_text64_lua_callback",
+ "sqlite3_result_text_lua_callback",
+ "sqlite3_result_value",
+ "sqlite3_result_zeroblob",
+ "sqlite3_rollback_hook",
+ "sqlite3_rollback_hook_lua_callback",
+ "sqlite3_rtree_dbl_array_getitem",
+ "sqlite3_rtree_dbl_array_setitem",
+ "sqlite3_rtree_geometry",
+ "sqlite3_rtree_geometry_callback",
+ "sqlite3_rtree_geometry_callback_lua_callback",
+ "sqlite3_rtree_query_callback",
+ "sqlite3_rtree_query_callback_lua_callback",
+ "sqlite3_rtree_query_info",
+ "sqlite3_set_authorizer",
+ "sqlite3_set_authorizer_lua_callback",
+ "sqlite3_set_auxdata",
+ "sqlite3_set_auxdata_lua_callback",
+ "sqlite3_shutdown",
+ "sqlite3_sleep",
+ "sqlite3_snprintf",
+ "sqlite3_soft_heap_limit",
+ "sqlite3_soft_heap_limit64",
+ "sqlite3_sourceid",
+ "sqlite3_sql",
+ "sqlite3_status",
+ "sqlite3_step",
+ "sqlite3_stmt_busy",
+ "sqlite3_stmt_p_array_getitem",
+ "sqlite3_stmt_p_array_setitem",
+ "sqlite3_stmt_readonly",
+ "sqlite3_stmt_status",
+ "sqlite3_strglob",
+ "sqlite3_stricmp",
+ "sqlite3_strnicmp",
+ "sqlite3_test_control",
+ "sqlite3_thread_cleanup",
+ "sqlite3_threadsafe",
+ "sqlite3_total_changes",
+ "sqlite3_trace",
+ "sqlite3_trace_lua_callback",
+ "sqlite3_transfer_bindings",
+ "sqlite3_update_hook",
+ "sqlite3_update_hook_lua_callback",
+ "sqlite3_uri_boolean",
+ "sqlite3_uri_int64",
+ "sqlite3_uri_parameter",
+ "sqlite3_user_data",
+ "sqlite3_value_blob",
+ "sqlite3_value_bytes",
+ "sqlite3_value_bytes16",
+ "sqlite3_value_double",
+ "sqlite3_value_int",
+ "sqlite3_value_int64",
+ "sqlite3_value_numeric_type",
+ "sqlite3_value_p_array_getitem",
+ "sqlite3_value_p_array_setitem",
+ "sqlite3_value_text",
+ "sqlite3_value_text16",
+ "sqlite3_value_text16be",
+ "sqlite3_value_text16le",
+ "sqlite3_value_type",
+ "sqlite3_vfs",
+ "sqlite3_vfs_find",
+ "sqlite3_vfs_register",
+ "sqlite3_vfs_unregister",
+ "sqlite3_vtab",
+ "sqlite3_vtab_config",
+ "sqlite3_vtab_cursor",
+ "sqlite3_vtab_cursor_p_array_getitem",
+ "sqlite3_vtab_cursor_p_array_setitem",
+ "sqlite3_vtab_on_conflict",
+ "sqlite3_vtab_p_array_getitem",
+ "sqlite3_vtab_p_array_setitem",
+ "sqlite3_wal_autocheckpoint",
+ "sqlite3_wal_checkpoint",
+ "sqlite3_wal_checkpoint_v2",
+ "sqlite3_wal_hook",
+ "sqlite3_wal_hook_lua_callback",
+ "void_p_array_getitem",
+ "void_p_array_setitem",
+}
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-swiglib.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-swiglib.lua
index 7ffcdc37562..3108dd43fb8 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-swiglib.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-swiglib.lua
@@ -8,7 +8,8 @@ if not modules then modules = { } end modules ['luatex-swiglib'] = {
local savedrequire = require
-local libsuffix = os.type == "windows" and ".dll" or ".so"
+local libsuffix = os.type == "windows" and ".dll" or ".so"
+local pathsplit = "([^" .. io.pathseparator .. "]+)"
function requireswiglib(required,version)
local library = package.loaded[required]
@@ -17,7 +18,7 @@ function requireswiglib(required,version)
else
local name = string.gsub(required,"%.","/") .. libsuffix
local list = kpse.show_path("clua")
- for root in string.gmatch(list,"([^;]+)") do
+ for root in string.gmatch(list,pathsplit) do
local full = false
if type(version) == "string" and version ~= "" then
full = root .. "/" .. version .. "/" .. name
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-test.tex b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-test.tex
index 0bb752b3f84..2aa4f22d975 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-test.tex
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-test.tex
@@ -158,4 +158,16 @@ $\sin{x}$
% \textdir TRT\amiri بِسْمِ اللَّـهِ الرَّ‌حْمَـٰنِ الرَّ‌حِيمِ
% \egroup
+% assumes csr10.tfm csr10.pfb csr.enc to be present
+
+% \font\foo=file:luatex-plain-tfm.lua:tfm=csr10;enc=csr;pfb=csr10 at 12pt
+%
+% \foo áäčďěíĺľňóôŕřšťúýž ff ffi
+
+% \font\foo=file:csr10.tfm:reencode=csr
+% \font\foo=file:csr10.tfm:reencode=csr;bitmap=yes % use map file
+% \font\foo=file:csr10.tfm:reencode=auto
+%
+% \foo áäčďěíĺľňóôŕřšťúýž ff ffi \input tufte\par
+
\end
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-util-fil.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-util-fil.lua
index 28c92c7c3c3..0f9731a2656 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-util-fil.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-util-fil.lua
@@ -6,8 +6,10 @@ if not modules then modules = { } end modules ['util-fil'] = {
license = "see context related readme files"
}
-local byte = string.byte
-local extract = bit32.extract
+local byte = string.byte
+local char = string.char
+local extract = bit32 and bit32.extract
+local floor = math.floor
-- Here are a few helpers (the starting point were old ones I used for parsing
-- flac files). In Lua 5.3 we can probably do this better. Some code will move
@@ -36,6 +38,8 @@ function files.size(f)
return f:seek("end")
end
+files.getsize = files.size
+
function files.setposition(f,n)
if zerobased[f] then
f:seek("set",n)
@@ -90,7 +94,8 @@ end
function files.readinteger1(f) -- one byte
local n = byte(f:read(1))
if n >= 0x80 then
- return n - 0xFF - 1
+ -- return n - 0xFF - 1
+ return n - 0x100
else
return n
end
@@ -104,12 +109,27 @@ function files.readcardinal2(f)
local a, b = byte(f:read(2),1,2)
return 0x100 * a + b
end
+function files.readcardinal2le(f)
+ local b, a = byte(f:read(2),1,2)
+ return 0x100 * a + b
+end
function files.readinteger2(f)
local a, b = byte(f:read(2),1,2)
local n = 0x100 * a + b
if n >= 0x8000 then
- return n - 0xFFFF - 1
+ -- return n - 0xFFFF - 1
+ return n - 0x10000
+ else
+ return n
+ end
+end
+function files.readinteger2le(f)
+ local b, a = byte(f:read(2),1,2)
+ local n = 0x100 * a + b
+ if n >= 0x8000 then
+ -- return n - 0xFFFF - 1
+ return n - 0x10000
else
return n
end
@@ -119,17 +139,57 @@ function files.readcardinal3(f)
local a, b, c = byte(f:read(3),1,3)
return 0x10000 * a + 0x100 * b + c
end
+function files.readcardinal3le(f)
+ local c, b, a = byte(f:read(3),1,3)
+ return 0x10000 * a + 0x100 * b + c
+end
+
+function files.readinteger3(f)
+ local a, b, c = byte(f:read(3),1,3)
+ local n = 0x10000 * a + 0x100 * b + c
+ if n >= 0x80000 then
+ -- return n - 0xFFFFFF - 1
+ return n - 0x1000000
+ else
+ return n
+ end
+end
+function files.readinteger3le(f)
+ local c, b, a = byte(f:read(3),1,3)
+ local n = 0x10000 * a + 0x100 * b + c
+ if n >= 0x80000 then
+ -- return n - 0xFFFFFF - 1
+ return n - 0x1000000
+ else
+ return n
+ end
+end
function files.readcardinal4(f)
local a, b, c, d = byte(f:read(4),1,4)
return 0x1000000 * a + 0x10000 * b + 0x100 * c + d
end
+function files.readcardinal4le(f)
+ local d, c, b, a = byte(f:read(4),1,4)
+ return 0x1000000 * a + 0x10000 * b + 0x100 * c + d
+end
function files.readinteger4(f)
local a, b, c, d = byte(f:read(4),1,4)
local n = 0x1000000 * a + 0x10000 * b + 0x100 * c + d
if n >= 0x8000000 then
- return n - 0xFFFFFFFF - 1
+ -- return n - 0xFFFFFFFF - 1
+ return n - 0x100000000
+ else
+ return n
+ end
+end
+function files.readinteger4le(f)
+ local d, c, b, a = byte(f:read(4),1,4)
+ local n = 0x1000000 * a + 0x10000 * b + 0x100 * c + d
+ if n >= 0x8000000 then
+ -- return n - 0xFFFFFFFF - 1
+ return n - 0x100000000
else
return n
end
@@ -139,23 +199,28 @@ function files.readfixed4(f)
local a, b, c, d = byte(f:read(4),1,4)
local n = 0x100 * a + b
if n >= 0x8000 then
- return n - 0xFFFF - 1 + (0x100 * c + d)/0xFFFF
+ -- return n - 0xFFFF - 1 + (0x100 * c + d)/0xFFFF
+ return n - 0x10000 + (0x100 * c + d)/0xFFFF
else
return n + (0x100 * c + d)/0xFFFF
end
end
-function files.read2dot14(f)
- local a, b = byte(f:read(2),1,2)
- local n = 0x100 * a + b
- local m = extract(n,0,30)
- if n > 0x7FFF then
- n = extract(n,30,2)
- return m/0x4000 - 4
- else
- n = extract(n,30,2)
- return n + m/0x4000
+if extract then
+
+ function files.read2dot14(f)
+ local a, b = byte(f:read(2),1,2)
+ local n = 0x100 * a + b
+ local m = extract(n,0,30)
+ if n > 0x7FFF then
+ n = extract(n,30,2)
+ return m/0x4000 - 4
+ else
+ n = extract(n,30,2)
+ return n + m/0x4000
+ end
end
+
end
function files.skipshort(f,n)
@@ -165,3 +230,32 @@ end
function files.skiplong(f,n)
f:read(4*(n or 1))
end
+
+-- writers (kind of slow)
+
+function files.writecardinal2(f,n)
+ local a = char(n % 256)
+ n = floor(n/256)
+ local b = char(n % 256)
+ f:write(b,a)
+end
+
+function files.writecardinal4(f,n)
+ local a = char(n % 256)
+ n = floor(n/256)
+ local b = char(n % 256)
+ n = floor(n/256)
+ local c = char(n % 256)
+ n = floor(n/256)
+ local d = char(n % 256)
+ f:write(d,c,b,a)
+end
+
+function files.writestring(f,s)
+ f:write(char(byte(s,1,#s)))
+end
+
+function files.writebyte(f,b)
+ f:write(char(b))
+end
+
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-util-str.lua b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-util-str.lua
index 28b75dbc599..fb510257a2f 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/fontloader-util-str.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/fontloader-util-str.lua
@@ -10,7 +10,7 @@ utilities = utilities or { }
utilities.strings = utilities.strings or { }
local strings = utilities.strings
-local format, gsub, rep, sub = string.format, string.gsub, string.rep, string.sub
+local format, gsub, rep, sub, find = string.format, string.gsub, string.rep, string.sub, string.find
local load, dump = load, string.dump
local tonumber, type, tostring = tonumber, type, tostring
local unpack, concat = table.unpack, table.concat
@@ -385,6 +385,43 @@ function number.signed(i)
end
end
+-- maybe to util-num
+
+local digit = patterns.digit
+local period = patterns.period
+local three = digit * digit * digit
+
+local splitter = Cs (
+ (((1 - (three^1 * period))^1 + C(three)) * (Carg(1) * three)^1 + C((1-period)^1))
+ * (P(1)/"" * Carg(2)) * C(2)
+)
+
+patterns.formattednumber = splitter
+
+function number.formatted(n,sep1,sep2)
+ local s = type(s) == "string" and n or format("%0.2f",n)
+ if sep1 == true then
+ return lpegmatch(splitter,s,1,".",",")
+ elseif sep1 == "." then
+ return lpegmatch(splitter,s,1,sep1,sep2 or ",")
+ elseif sep1 == "," then
+ return lpegmatch(splitter,s,1,sep1,sep2 or ".")
+ else
+ return lpegmatch(splitter,s,1,sep1 or ",",sep2 or ".")
+ end
+end
+
+-- print(number.formatted(1))
+-- print(number.formatted(12))
+-- print(number.formatted(123))
+-- print(number.formatted(1234))
+-- print(number.formatted(12345))
+-- print(number.formatted(123456))
+-- print(number.formatted(1234567))
+-- print(number.formatted(12345678))
+-- print(number.formatted(12345678,true))
+-- print(number.formatted(1234.56,"!","?"))
+
local zero = P("0")^1 / ""
local plus = P("+") / ""
local minus = P("-")
@@ -732,43 +769,6 @@ local format_W = function(f) -- handy when doing depth related indent
return format("nspaces[%s]",tonumber(f) or 0)
end
--- maybe to util-num
-
-local digit = patterns.digit
-local period = patterns.period
-local three = digit * digit * digit
-
-local splitter = Cs (
- (((1 - (three^1 * period))^1 + C(three)) * (Carg(1) * three)^1 + C((1-period)^1))
- * (P(1)/"" * Carg(2)) * C(2)
-)
-
-patterns.formattednumber = splitter
-
-function number.formatted(n,sep1,sep2)
- local s = type(s) == "string" and n or format("%0.2f",n)
- if sep1 == true then
- return lpegmatch(splitter,s,1,".",",")
- elseif sep1 == "." then
- return lpegmatch(splitter,s,1,sep1,sep2 or ",")
- elseif sep1 == "," then
- return lpegmatch(splitter,s,1,sep1,sep2 or ".")
- else
- return lpegmatch(splitter,s,1,sep1 or ",",sep2 or ".")
- end
-end
-
--- print(number.formatted(1))
--- print(number.formatted(12))
--- print(number.formatted(123))
--- print(number.formatted(1234))
--- print(number.formatted(12345))
--- print(number.formatted(123456))
--- print(number.formatted(1234567))
--- print(number.formatted(12345678))
--- print(number.formatted(12345678,true))
--- print(number.formatted(1234.56,"!","?"))
-
local format_m = function(f)
n = n + 1
if not f or f == "" then
@@ -801,9 +801,16 @@ end
local format_extension = function(extensions,f,name)
local extension = extensions[name] or "tostring(%s)"
local f = tonumber(f) or 1
+ local w = find(extension,"%.%.%.")
if f == 0 then
+ if w then
+ extension = gsub(extension,"%.%.%.","")
+ end
return extension
elseif f == 1 then
+ if w then
+ extension = gsub(extension,"%.%.%.","%%s")
+ end
n = n + 1
local a = "a" .. n
return format(extension,a,a) -- maybe more times?
@@ -811,10 +818,16 @@ local format_extension = function(extensions,f,name)
local a = "a" .. (n + f + 1)
return format(extension,a,a)
else
+ if w then
+ extension = gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
+ end
+ -- we could fill an array and then n = n + 1 unpack(t,n,n+f) but as we
+ -- cache we don't save much and there are hardly any extensions anyway
local t = { }
for i=1,f do
n = n + 1
- t[#t+1] = "a" .. n
+ -- t[#t+1] = "a" .. n
+ t[i] = "a" .. n
end
return format(extension,unpack(t))
end
@@ -824,6 +837,8 @@ end
-- extensions : %!tag!
+-- can be made faster but not called that often
+
local builder = Cs { "start",
start = (
(
@@ -852,10 +867,10 @@ local builder = Cs { "start",
+ V("a") -- new
+ V("A") -- new
+ V("j") + V("J") -- stripped e E
- + V("m") + V("M") -- new
+ + V("m") + V("M") -- new (formatted number)
+ V("z") -- new
--
- -- + V("?") -- ignores probably messed up %
+ -- + V("?") -- ignored, probably messed up %
)
+ V("*")
)
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-auxiliary.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-auxiliary.lua
index 3c43eb926b9..395f9b5b519 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-auxiliary.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-auxiliary.lua
@@ -2,14 +2,11 @@
-----------------------------------------------------------------------
-- FILE: luaotfload-auxiliary.lua
-- DESCRIPTION: part of luaotfload
--- REQUIREMENTS: luaotfload 2.7
+-- REQUIREMENTS: luaotfload 2.8
-- AUTHOR: Khaled Hosny, Élie Roux, Philipp Gesang
-----------------------------------------------------------------------
--
---- this file addresses issue #24
---- https://github.com/lualatex/luaotfload/issues/24#
-
luaotfload = luaotfload or { }
local log = luaotfload.log
local logreport = log.report
@@ -43,13 +40,11 @@ local luaotfload_callbacks = { }
local rewrite_fontname = function (tfmdata, specification)
local format = tfmdata.format or tfmdata.properties.format
- if format ~= "type1" then
- if stringfind (specification, " ") then
- tfmdata.name = stringformat ("%q", specification)
- else
- --- other specs should parse just fine
- tfmdata.name = specification
- end
+ if stringfind (specification, " ") then
+ tfmdata.name = stringformat ("%q", specification)
+ else
+ --- other specs should parse just fine
+ tfmdata.name = specification
end
end
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-characters.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-characters.lua
index 366ac4d0b08..258a5aee649 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-characters.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-characters.lua
@@ -8399,6 +8399,98 @@ return {
category="lo",
direction="al",
},
+ [0x8B6]={
+ category="lo",
+ direction="al",
+ },
+ [0x8B7]={
+ category="lo",
+ direction="al",
+ },
+ [0x8B8]={
+ category="lo",
+ direction="al",
+ },
+ [0x8B9]={
+ category="lo",
+ direction="al",
+ },
+ [0x8BA]={
+ category="lo",
+ direction="al",
+ },
+ [0x8BB]={
+ category="lo",
+ direction="al",
+ },
+ [0x8BC]={
+ category="lo",
+ direction="al",
+ },
+ [0x8BD]={
+ category="lo",
+ direction="al",
+ },
+ [0x8D4]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x8D5]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x8D6]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x8D7]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x8D8]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x8D9]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x8DA]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x8DB]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x8DC]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x8DD]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x8DE]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x8DF]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x8E0]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x8E1]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x8E2]={
+ category="cf",
+ direction="an",
+ },
[0x8E3]={
category="mn",
direction="nsm",
@@ -11087,6 +11179,10 @@ return {
category="so",
direction="l",
},
+ [0xC80]={
+ category="lo",
+ direction="l",
+ },
[0xC81]={
category="mn",
direction="nsm",
@@ -11719,10 +11815,54 @@ return {
category="lo",
direction="l",
},
+ [0xD4F]={
+ category="so",
+ direction="l",
+ },
+ [0xD54]={
+ category="lo",
+ direction="l",
+ },
+ [0xD55]={
+ category="lo",
+ direction="l",
+ },
+ [0xD56]={
+ category="lo",
+ direction="l",
+ },
[0xD57]={
category="mc",
direction="l",
},
+ [0xD58]={
+ category="no",
+ direction="l",
+ },
+ [0xD59]={
+ category="no",
+ direction="l",
+ },
+ [0xD5A]={
+ category="no",
+ direction="l",
+ },
+ [0xD5B]={
+ category="no",
+ direction="l",
+ },
+ [0xD5C]={
+ category="no",
+ direction="l",
+ },
+ [0xD5D]={
+ category="no",
+ direction="l",
+ },
+ [0xD5E]={
+ category="no",
+ direction="l",
+ },
[0xD5F]={
category="lo",
direction="l",
@@ -11807,6 +11947,18 @@ return {
category="no",
direction="l",
},
+ [0xD76]={
+ category="no",
+ direction="l",
+ },
+ [0xD77]={
+ category="no",
+ direction="l",
+ },
+ [0xD78]={
+ category="no",
+ direction="l",
+ },
[0xD79]={
category="so",
direction="l",
@@ -21867,11 +22019,11 @@ return {
},
[0x1885]={
category="lo",
- direction="l",
+ direction="nsm",
},
[0x1886]={
category="lo",
- direction="l",
+ direction="nsm",
},
[0x1887]={
category="lo",
@@ -25309,6 +25461,42 @@ return {
category="po",
direction="l",
},
+ [0x1C80]={
+ category="ll",
+ direction="l",
+ },
+ [0x1C81]={
+ category="ll",
+ direction="l",
+ },
+ [0x1C82]={
+ category="ll",
+ direction="l",
+ },
+ [0x1C83]={
+ category="ll",
+ direction="l",
+ },
+ [0x1C84]={
+ category="ll",
+ direction="l",
+ },
+ [0x1C85]={
+ category="ll",
+ direction="l",
+ },
+ [0x1C86]={
+ category="ll",
+ direction="l",
+ },
+ [0x1C87]={
+ category="ll",
+ direction="l",
+ },
+ [0x1C88]={
+ category="ll",
+ direction="l",
+ },
[0x1CC0]={
category="po",
direction="l",
@@ -26489,6 +26677,10 @@ return {
category="mn",
direction="nsm",
},
+ [0x1DFB]={
+ category="mn",
+ direction="nsm",
+ },
[0x1DFC]={
category="mn",
direction="nsm",
@@ -32499,6 +32691,22 @@ return {
category="so",
direction="on",
},
+ [0x23FB]={
+ category="so",
+ direction="on",
+ },
+ [0x23FC]={
+ category="so",
+ direction="on",
+ },
+ [0x23FD]={
+ category="so",
+ direction="on",
+ },
+ [0x23FE]={
+ category="so",
+ direction="on",
+ },
[0x2400]={
category="so",
direction="on",
@@ -38103,11 +38311,13 @@ return {
category="ps",
direction="on",
mirror=0x2998,
+ textclass="open",
},
[0x2998]={
category="pe",
direction="on",
mirror=0x2997,
+ textclass="close",
},
[0x2999]={
category="sm",
@@ -42593,6 +42803,14 @@ return {
category="ps",
direction="on",
},
+ [0x2E43]={
+ category="po",
+ direction="on",
+ },
+ [0x2E44]={
+ category="po",
+ direction="on",
+ },
[0x2E80]={
category="so",
direction="on",
@@ -55907,6 +56125,10 @@ return {
category="lu",
direction="l",
},
+ [0xA7AE]={
+ category="lu",
+ direction="l",
+ },
[0xA7B0]={
category="lu",
direction="l",
@@ -56691,6 +56913,10 @@ return {
category="mn",
direction="nsm",
},
+ [0xA8C5]={
+ category="mn",
+ direction="nsm",
+ },
[0xA8CE]={
category="po",
direction="l",
@@ -67655,6 +67881,14 @@ return {
category="so",
direction="on",
},
+ [0x1018D]={
+ category="so",
+ direction="l",
+ },
+ [0x1018E]={
+ category="so",
+ direction="l",
+ },
[0x10190]={
category="so",
direction="on",
@@ -69735,6 +69969,294 @@ return {
category="nd",
direction="l",
},
+ [0x104B0]={
+ category="lu",
+ direction="l",
+ },
+ [0x104B1]={
+ category="lu",
+ direction="l",
+ },
+ [0x104B2]={
+ category="lu",
+ direction="l",
+ },
+ [0x104B3]={
+ category="lu",
+ direction="l",
+ },
+ [0x104B4]={
+ category="lu",
+ direction="l",
+ },
+ [0x104B5]={
+ category="lu",
+ direction="l",
+ },
+ [0x104B6]={
+ category="lu",
+ direction="l",
+ },
+ [0x104B7]={
+ category="lu",
+ direction="l",
+ },
+ [0x104B8]={
+ category="lu",
+ direction="l",
+ },
+ [0x104B9]={
+ category="lu",
+ direction="l",
+ },
+ [0x104BA]={
+ category="lu",
+ direction="l",
+ },
+ [0x104BB]={
+ category="lu",
+ direction="l",
+ },
+ [0x104BC]={
+ category="lu",
+ direction="l",
+ },
+ [0x104BD]={
+ category="lu",
+ direction="l",
+ },
+ [0x104BE]={
+ category="lu",
+ direction="l",
+ },
+ [0x104BF]={
+ category="lu",
+ direction="l",
+ },
+ [0x104C0]={
+ category="lu",
+ direction="l",
+ },
+ [0x104C1]={
+ category="lu",
+ direction="l",
+ },
+ [0x104C2]={
+ category="lu",
+ direction="l",
+ },
+ [0x104C3]={
+ category="lu",
+ direction="l",
+ },
+ [0x104C4]={
+ category="lu",
+ direction="l",
+ },
+ [0x104C5]={
+ category="lu",
+ direction="l",
+ },
+ [0x104C6]={
+ category="lu",
+ direction="l",
+ },
+ [0x104C7]={
+ category="lu",
+ direction="l",
+ },
+ [0x104C8]={
+ category="lu",
+ direction="l",
+ },
+ [0x104C9]={
+ category="lu",
+ direction="l",
+ },
+ [0x104CA]={
+ category="lu",
+ direction="l",
+ },
+ [0x104CB]={
+ category="lu",
+ direction="l",
+ },
+ [0x104CC]={
+ category="lu",
+ direction="l",
+ },
+ [0x104CD]={
+ category="lu",
+ direction="l",
+ },
+ [0x104CE]={
+ category="lu",
+ direction="l",
+ },
+ [0x104CF]={
+ category="lu",
+ direction="l",
+ },
+ [0x104D0]={
+ category="lu",
+ direction="l",
+ },
+ [0x104D1]={
+ category="lu",
+ direction="l",
+ },
+ [0x104D2]={
+ category="lu",
+ direction="l",
+ },
+ [0x104D3]={
+ category="lu",
+ direction="l",
+ },
+ [0x104D8]={
+ category="ll",
+ direction="l",
+ },
+ [0x104D9]={
+ category="ll",
+ direction="l",
+ },
+ [0x104DA]={
+ category="ll",
+ direction="l",
+ },
+ [0x104DB]={
+ category="ll",
+ direction="l",
+ },
+ [0x104DC]={
+ category="ll",
+ direction="l",
+ },
+ [0x104DD]={
+ category="ll",
+ direction="l",
+ },
+ [0x104DE]={
+ category="ll",
+ direction="l",
+ },
+ [0x104DF]={
+ category="ll",
+ direction="l",
+ },
+ [0x104E0]={
+ category="ll",
+ direction="l",
+ },
+ [0x104E1]={
+ category="ll",
+ direction="l",
+ },
+ [0x104E2]={
+ category="ll",
+ direction="l",
+ },
+ [0x104E3]={
+ category="ll",
+ direction="l",
+ },
+ [0x104E4]={
+ category="ll",
+ direction="l",
+ },
+ [0x104E5]={
+ category="ll",
+ direction="l",
+ },
+ [0x104E6]={
+ category="ll",
+ direction="l",
+ },
+ [0x104E7]={
+ category="ll",
+ direction="l",
+ },
+ [0x104E8]={
+ category="ll",
+ direction="l",
+ },
+ [0x104E9]={
+ category="ll",
+ direction="l",
+ },
+ [0x104EA]={
+ category="ll",
+ direction="l",
+ },
+ [0x104EB]={
+ category="ll",
+ direction="l",
+ },
+ [0x104EC]={
+ category="ll",
+ direction="l",
+ },
+ [0x104ED]={
+ category="ll",
+ direction="l",
+ },
+ [0x104EE]={
+ category="ll",
+ direction="l",
+ },
+ [0x104EF]={
+ category="ll",
+ direction="l",
+ },
+ [0x104F0]={
+ category="ll",
+ direction="l",
+ },
+ [0x104F1]={
+ category="ll",
+ direction="l",
+ },
+ [0x104F2]={
+ category="ll",
+ direction="l",
+ },
+ [0x104F3]={
+ category="ll",
+ direction="l",
+ },
+ [0x104F4]={
+ category="ll",
+ direction="l",
+ },
+ [0x104F5]={
+ category="ll",
+ direction="l",
+ },
+ [0x104F6]={
+ category="ll",
+ direction="l",
+ },
+ [0x104F7]={
+ category="ll",
+ direction="l",
+ },
+ [0x104F8]={
+ category="ll",
+ direction="l",
+ },
+ [0x104F9]={
+ category="ll",
+ direction="l",
+ },
+ [0x104FA]={
+ category="ll",
+ direction="l",
+ },
+ [0x104FB]={
+ category="ll",
+ direction="l",
+ },
[0x10500]={
category="lo",
direction="l",
@@ -77039,6 +77561,10 @@ return {
category="po",
direction="l",
},
+ [0x1123E]={
+ category="mn",
+ direction="nsm",
+ },
[0x11280]={
category="lo",
direction="l",
@@ -77807,6 +78333,374 @@ return {
category="mn",
direction="nsm",
},
+ [0x11400]={
+ category="lo",
+ direction="l",
+ },
+ [0x11401]={
+ category="lo",
+ direction="l",
+ },
+ [0x11402]={
+ category="lo",
+ direction="l",
+ },
+ [0x11403]={
+ category="lo",
+ direction="l",
+ },
+ [0x11404]={
+ category="lo",
+ direction="l",
+ },
+ [0x11405]={
+ category="lo",
+ direction="l",
+ },
+ [0x11406]={
+ category="lo",
+ direction="l",
+ },
+ [0x11407]={
+ category="lo",
+ direction="l",
+ },
+ [0x11408]={
+ category="lo",
+ direction="l",
+ },
+ [0x11409]={
+ category="lo",
+ direction="l",
+ },
+ [0x1140A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1140B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1140C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1140D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1140E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1140F]={
+ category="lo",
+ direction="l",
+ },
+ [0x11410]={
+ category="lo",
+ direction="l",
+ },
+ [0x11411]={
+ category="lo",
+ direction="l",
+ },
+ [0x11412]={
+ category="lo",
+ direction="l",
+ },
+ [0x11413]={
+ category="lo",
+ direction="l",
+ },
+ [0x11414]={
+ category="lo",
+ direction="l",
+ },
+ [0x11415]={
+ category="lo",
+ direction="l",
+ },
+ [0x11416]={
+ category="lo",
+ direction="l",
+ },
+ [0x11417]={
+ category="lo",
+ direction="l",
+ },
+ [0x11418]={
+ category="lo",
+ direction="l",
+ },
+ [0x11419]={
+ category="lo",
+ direction="l",
+ },
+ [0x1141A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1141B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1141C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1141D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1141E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1141F]={
+ category="lo",
+ direction="l",
+ },
+ [0x11420]={
+ category="lo",
+ direction="l",
+ },
+ [0x11421]={
+ category="lo",
+ direction="l",
+ },
+ [0x11422]={
+ category="lo",
+ direction="l",
+ },
+ [0x11423]={
+ category="lo",
+ direction="l",
+ },
+ [0x11424]={
+ category="lo",
+ direction="l",
+ },
+ [0x11425]={
+ category="lo",
+ direction="l",
+ },
+ [0x11426]={
+ category="lo",
+ direction="l",
+ },
+ [0x11427]={
+ category="lo",
+ direction="l",
+ },
+ [0x11428]={
+ category="lo",
+ direction="l",
+ },
+ [0x11429]={
+ category="lo",
+ direction="l",
+ },
+ [0x1142A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1142B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1142C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1142D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1142E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1142F]={
+ category="lo",
+ direction="l",
+ },
+ [0x11430]={
+ category="lo",
+ direction="l",
+ },
+ [0x11431]={
+ category="lo",
+ direction="l",
+ },
+ [0x11432]={
+ category="lo",
+ direction="l",
+ },
+ [0x11433]={
+ category="lo",
+ direction="l",
+ },
+ [0x11434]={
+ category="lo",
+ direction="l",
+ },
+ [0x11435]={
+ category="mc",
+ direction="l",
+ },
+ [0x11436]={
+ category="mc",
+ direction="l",
+ },
+ [0x11437]={
+ category="mc",
+ direction="l",
+ },
+ [0x11438]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11439]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1143A]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1143B]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1143C]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1143D]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1143E]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1143F]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11440]={
+ category="mc",
+ direction="l",
+ },
+ [0x11441]={
+ category="mc",
+ direction="l",
+ },
+ [0x11442]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11443]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11444]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11445]={
+ category="mc",
+ direction="l",
+ },
+ [0x11446]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11447]={
+ category="lo",
+ direction="l",
+ },
+ [0x11448]={
+ category="lo",
+ direction="l",
+ },
+ [0x11449]={
+ category="lo",
+ direction="l",
+ },
+ [0x1144A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1144B]={
+ category="po",
+ direction="l",
+ },
+ [0x1144C]={
+ category="po",
+ direction="l",
+ },
+ [0x1144D]={
+ category="po",
+ direction="l",
+ },
+ [0x1144E]={
+ category="po",
+ direction="l",
+ },
+ [0x1144F]={
+ category="po",
+ direction="l",
+ },
+ [0x11450]={
+ category="nd",
+ direction="l",
+ },
+ [0x11451]={
+ category="nd",
+ direction="l",
+ },
+ [0x11452]={
+ category="nd",
+ direction="l",
+ },
+ [0x11453]={
+ category="nd",
+ direction="l",
+ },
+ [0x11454]={
+ category="nd",
+ direction="l",
+ },
+ [0x11455]={
+ category="nd",
+ direction="l",
+ },
+ [0x11456]={
+ category="nd",
+ direction="l",
+ },
+ [0x11457]={
+ category="nd",
+ direction="l",
+ },
+ [0x11458]={
+ category="nd",
+ direction="l",
+ },
+ [0x11459]={
+ category="nd",
+ direction="l",
+ },
+ [0x1145B]={
+ category="po",
+ direction="l",
+ },
+ [0x1145D]={
+ category="po",
+ direction="l",
+ },
[0x11480]={
category="lo",
direction="l",
@@ -78819,6 +79713,58 @@ return {
category="nd",
direction="l",
},
+ [0x11660]={
+ category="po",
+ direction="on",
+ },
+ [0x11661]={
+ category="po",
+ direction="on",
+ },
+ [0x11662]={
+ category="po",
+ direction="on",
+ },
+ [0x11663]={
+ category="po",
+ direction="on",
+ },
+ [0x11664]={
+ category="po",
+ direction="on",
+ },
+ [0x11665]={
+ category="po",
+ direction="on",
+ },
+ [0x11666]={
+ category="po",
+ direction="on",
+ },
+ [0x11667]={
+ category="po",
+ direction="on",
+ },
+ [0x11668]={
+ category="po",
+ direction="on",
+ },
+ [0x11669]={
+ category="po",
+ direction="on",
+ },
+ [0x1166A]={
+ category="po",
+ direction="on",
+ },
+ [0x1166B]={
+ category="po",
+ direction="on",
+ },
+ [0x1166C]={
+ category="po",
+ direction="on",
+ },
[0x11680]={
category="lo",
direction="l",
@@ -79875,6 +80821,666 @@ return {
category="lo",
direction="l",
},
+ [0x11C00]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C01]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C02]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C03]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C04]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C05]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C06]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C07]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C08]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C0A]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C0B]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C0C]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C0D]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C0E]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C0F]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C10]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C11]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C12]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C13]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C14]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C15]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C16]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C17]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C18]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C19]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C1A]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C1B]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C1C]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C1D]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C1E]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C1F]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C20]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C21]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C22]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C23]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C24]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C25]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C26]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C27]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C28]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C29]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C2A]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C2B]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C2C]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C2D]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C2E]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C2F]={
+ category="mc",
+ direction="l",
+ },
+ [0x11C30]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C31]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C32]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C33]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C34]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C35]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C36]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C38]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C39]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C3A]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C3B]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C3C]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C3D]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C3E]={
+ category="mc",
+ direction="l",
+ },
+ [0x11C3F]={
+ category="mn",
+ direction="l",
+ },
+ [0x11C40]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C41]={
+ category="po",
+ direction="l",
+ },
+ [0x11C42]={
+ category="po",
+ direction="l",
+ },
+ [0x11C43]={
+ category="po",
+ direction="l",
+ },
+ [0x11C44]={
+ category="po",
+ direction="l",
+ },
+ [0x11C45]={
+ category="po",
+ direction="l",
+ },
+ [0x11C50]={
+ category="nd",
+ direction="l",
+ },
+ [0x11C51]={
+ category="nd",
+ direction="l",
+ },
+ [0x11C52]={
+ category="nd",
+ direction="l",
+ },
+ [0x11C53]={
+ category="nd",
+ direction="l",
+ },
+ [0x11C54]={
+ category="nd",
+ direction="l",
+ },
+ [0x11C55]={
+ category="nd",
+ direction="l",
+ },
+ [0x11C56]={
+ category="nd",
+ direction="l",
+ },
+ [0x11C57]={
+ category="nd",
+ direction="l",
+ },
+ [0x11C58]={
+ category="nd",
+ direction="l",
+ },
+ [0x11C59]={
+ category="nd",
+ direction="l",
+ },
+ [0x11C5A]={
+ category="no",
+ direction="l",
+ },
+ [0x11C5B]={
+ category="no",
+ direction="l",
+ },
+ [0x11C5C]={
+ category="no",
+ direction="l",
+ },
+ [0x11C5D]={
+ category="no",
+ direction="l",
+ },
+ [0x11C5E]={
+ category="no",
+ direction="l",
+ },
+ [0x11C5F]={
+ category="no",
+ direction="l",
+ },
+ [0x11C60]={
+ category="no",
+ direction="l",
+ },
+ [0x11C61]={
+ category="no",
+ direction="l",
+ },
+ [0x11C62]={
+ category="no",
+ direction="l",
+ },
+ [0x11C63]={
+ category="no",
+ direction="l",
+ },
+ [0x11C64]={
+ category="no",
+ direction="l",
+ },
+ [0x11C65]={
+ category="no",
+ direction="l",
+ },
+ [0x11C66]={
+ category="no",
+ direction="l",
+ },
+ [0x11C67]={
+ category="no",
+ direction="l",
+ },
+ [0x11C68]={
+ category="no",
+ direction="l",
+ },
+ [0x11C69]={
+ category="no",
+ direction="l",
+ },
+ [0x11C6A]={
+ category="no",
+ direction="l",
+ },
+ [0x11C6B]={
+ category="no",
+ direction="l",
+ },
+ [0x11C6C]={
+ category="no",
+ direction="l",
+ },
+ [0x11C70]={
+ category="po",
+ direction="l",
+ },
+ [0x11C71]={
+ category="po",
+ direction="l",
+ },
+ [0x11C72]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C73]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C74]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C75]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C76]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C77]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C78]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C79]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C7A]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C7B]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C7C]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C7D]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C7E]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C7F]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C80]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C81]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C82]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C83]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C84]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C85]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C86]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C87]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C88]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C89]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C8A]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C8B]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C8C]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C8D]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C8E]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C8F]={
+ category="lo",
+ direction="l",
+ },
+ [0x11C92]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C93]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C94]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C95]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C96]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C97]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C98]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C99]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C9A]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C9B]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C9C]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C9D]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C9E]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11C9F]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11CA0]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11CA1]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11CA2]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11CA3]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11CA4]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11CA5]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11CA6]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11CA7]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11CA9]={
+ category="mc",
+ direction="l",
+ },
+ [0x11CAA]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11CAB]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11CAC]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11CAD]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11CAE]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11CAF]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11CB0]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11CB1]={
+ category="mc",
+ direction="l",
+ },
+ [0x11CB2]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11CB3]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11CB4]={
+ category="mc",
+ direction="l",
+ },
+ [0x11CB5]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x11CB6]={
+ category="mn",
+ direction="nsm",
+ },
[0x12000]={
category="lo",
direction="l",
@@ -95059,6 +96665,3030 @@ return {
category="lm",
direction="l",
},
+ [0x16FE0]={
+ category="lm",
+ direction="l",
+ },
+ [0x18800]={
+ category="lo",
+ direction="l",
+ },
+ [0x18801]={
+ category="lo",
+ direction="l",
+ },
+ [0x18802]={
+ category="lo",
+ direction="l",
+ },
+ [0x18803]={
+ category="lo",
+ direction="l",
+ },
+ [0x18804]={
+ category="lo",
+ direction="l",
+ },
+ [0x18805]={
+ category="lo",
+ direction="l",
+ },
+ [0x18806]={
+ category="lo",
+ direction="l",
+ },
+ [0x18807]={
+ category="lo",
+ direction="l",
+ },
+ [0x18808]={
+ category="lo",
+ direction="l",
+ },
+ [0x18809]={
+ category="lo",
+ direction="l",
+ },
+ [0x1880A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1880B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1880C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1880D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1880E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1880F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18810]={
+ category="lo",
+ direction="l",
+ },
+ [0x18811]={
+ category="lo",
+ direction="l",
+ },
+ [0x18812]={
+ category="lo",
+ direction="l",
+ },
+ [0x18813]={
+ category="lo",
+ direction="l",
+ },
+ [0x18814]={
+ category="lo",
+ direction="l",
+ },
+ [0x18815]={
+ category="lo",
+ direction="l",
+ },
+ [0x18816]={
+ category="lo",
+ direction="l",
+ },
+ [0x18817]={
+ category="lo",
+ direction="l",
+ },
+ [0x18818]={
+ category="lo",
+ direction="l",
+ },
+ [0x18819]={
+ category="lo",
+ direction="l",
+ },
+ [0x1881A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1881B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1881C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1881D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1881E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1881F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18820]={
+ category="lo",
+ direction="l",
+ },
+ [0x18821]={
+ category="lo",
+ direction="l",
+ },
+ [0x18822]={
+ category="lo",
+ direction="l",
+ },
+ [0x18823]={
+ category="lo",
+ direction="l",
+ },
+ [0x18824]={
+ category="lo",
+ direction="l",
+ },
+ [0x18825]={
+ category="lo",
+ direction="l",
+ },
+ [0x18826]={
+ category="lo",
+ direction="l",
+ },
+ [0x18827]={
+ category="lo",
+ direction="l",
+ },
+ [0x18828]={
+ category="lo",
+ direction="l",
+ },
+ [0x18829]={
+ category="lo",
+ direction="l",
+ },
+ [0x1882A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1882B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1882C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1882D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1882E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1882F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18830]={
+ category="lo",
+ direction="l",
+ },
+ [0x18831]={
+ category="lo",
+ direction="l",
+ },
+ [0x18832]={
+ category="lo",
+ direction="l",
+ },
+ [0x18833]={
+ category="lo",
+ direction="l",
+ },
+ [0x18834]={
+ category="lo",
+ direction="l",
+ },
+ [0x18835]={
+ category="lo",
+ direction="l",
+ },
+ [0x18836]={
+ category="lo",
+ direction="l",
+ },
+ [0x18837]={
+ category="lo",
+ direction="l",
+ },
+ [0x18838]={
+ category="lo",
+ direction="l",
+ },
+ [0x18839]={
+ category="lo",
+ direction="l",
+ },
+ [0x1883A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1883B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1883C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1883D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1883E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1883F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18840]={
+ category="lo",
+ direction="l",
+ },
+ [0x18841]={
+ category="lo",
+ direction="l",
+ },
+ [0x18842]={
+ category="lo",
+ direction="l",
+ },
+ [0x18843]={
+ category="lo",
+ direction="l",
+ },
+ [0x18844]={
+ category="lo",
+ direction="l",
+ },
+ [0x18845]={
+ category="lo",
+ direction="l",
+ },
+ [0x18846]={
+ category="lo",
+ direction="l",
+ },
+ [0x18847]={
+ category="lo",
+ direction="l",
+ },
+ [0x18848]={
+ category="lo",
+ direction="l",
+ },
+ [0x18849]={
+ category="lo",
+ direction="l",
+ },
+ [0x1884A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1884B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1884C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1884D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1884E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1884F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18850]={
+ category="lo",
+ direction="l",
+ },
+ [0x18851]={
+ category="lo",
+ direction="l",
+ },
+ [0x18852]={
+ category="lo",
+ direction="l",
+ },
+ [0x18853]={
+ category="lo",
+ direction="l",
+ },
+ [0x18854]={
+ category="lo",
+ direction="l",
+ },
+ [0x18855]={
+ category="lo",
+ direction="l",
+ },
+ [0x18856]={
+ category="lo",
+ direction="l",
+ },
+ [0x18857]={
+ category="lo",
+ direction="l",
+ },
+ [0x18858]={
+ category="lo",
+ direction="l",
+ },
+ [0x18859]={
+ category="lo",
+ direction="l",
+ },
+ [0x1885A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1885B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1885C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1885D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1885E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1885F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18860]={
+ category="lo",
+ direction="l",
+ },
+ [0x18861]={
+ category="lo",
+ direction="l",
+ },
+ [0x18862]={
+ category="lo",
+ direction="l",
+ },
+ [0x18863]={
+ category="lo",
+ direction="l",
+ },
+ [0x18864]={
+ category="lo",
+ direction="l",
+ },
+ [0x18865]={
+ category="lo",
+ direction="l",
+ },
+ [0x18866]={
+ category="lo",
+ direction="l",
+ },
+ [0x18867]={
+ category="lo",
+ direction="l",
+ },
+ [0x18868]={
+ category="lo",
+ direction="l",
+ },
+ [0x18869]={
+ category="lo",
+ direction="l",
+ },
+ [0x1886A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1886B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1886C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1886D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1886E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1886F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18870]={
+ category="lo",
+ direction="l",
+ },
+ [0x18871]={
+ category="lo",
+ direction="l",
+ },
+ [0x18872]={
+ category="lo",
+ direction="l",
+ },
+ [0x18873]={
+ category="lo",
+ direction="l",
+ },
+ [0x18874]={
+ category="lo",
+ direction="l",
+ },
+ [0x18875]={
+ category="lo",
+ direction="l",
+ },
+ [0x18876]={
+ category="lo",
+ direction="l",
+ },
+ [0x18877]={
+ category="lo",
+ direction="l",
+ },
+ [0x18878]={
+ category="lo",
+ direction="l",
+ },
+ [0x18879]={
+ category="lo",
+ direction="l",
+ },
+ [0x1887A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1887B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1887C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1887D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1887E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1887F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18880]={
+ category="lo",
+ direction="l",
+ },
+ [0x18881]={
+ category="lo",
+ direction="l",
+ },
+ [0x18882]={
+ category="lo",
+ direction="l",
+ },
+ [0x18883]={
+ category="lo",
+ direction="l",
+ },
+ [0x18884]={
+ category="lo",
+ direction="l",
+ },
+ [0x18885]={
+ category="lo",
+ direction="l",
+ },
+ [0x18886]={
+ category="lo",
+ direction="l",
+ },
+ [0x18887]={
+ category="lo",
+ direction="l",
+ },
+ [0x18888]={
+ category="lo",
+ direction="l",
+ },
+ [0x18889]={
+ category="lo",
+ direction="l",
+ },
+ [0x1888A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1888B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1888C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1888D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1888E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1888F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18890]={
+ category="lo",
+ direction="l",
+ },
+ [0x18891]={
+ category="lo",
+ direction="l",
+ },
+ [0x18892]={
+ category="lo",
+ direction="l",
+ },
+ [0x18893]={
+ category="lo",
+ direction="l",
+ },
+ [0x18894]={
+ category="lo",
+ direction="l",
+ },
+ [0x18895]={
+ category="lo",
+ direction="l",
+ },
+ [0x18896]={
+ category="lo",
+ direction="l",
+ },
+ [0x18897]={
+ category="lo",
+ direction="l",
+ },
+ [0x18898]={
+ category="lo",
+ direction="l",
+ },
+ [0x18899]={
+ category="lo",
+ direction="l",
+ },
+ [0x1889A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1889B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1889C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1889D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1889E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1889F]={
+ category="lo",
+ direction="l",
+ },
+ [0x188A0]={
+ category="lo",
+ direction="l",
+ },
+ [0x188A1]={
+ category="lo",
+ direction="l",
+ },
+ [0x188A2]={
+ category="lo",
+ direction="l",
+ },
+ [0x188A3]={
+ category="lo",
+ direction="l",
+ },
+ [0x188A4]={
+ category="lo",
+ direction="l",
+ },
+ [0x188A5]={
+ category="lo",
+ direction="l",
+ },
+ [0x188A6]={
+ category="lo",
+ direction="l",
+ },
+ [0x188A7]={
+ category="lo",
+ direction="l",
+ },
+ [0x188A8]={
+ category="lo",
+ direction="l",
+ },
+ [0x188A9]={
+ category="lo",
+ direction="l",
+ },
+ [0x188AA]={
+ category="lo",
+ direction="l",
+ },
+ [0x188AB]={
+ category="lo",
+ direction="l",
+ },
+ [0x188AC]={
+ category="lo",
+ direction="l",
+ },
+ [0x188AD]={
+ category="lo",
+ direction="l",
+ },
+ [0x188AE]={
+ category="lo",
+ direction="l",
+ },
+ [0x188AF]={
+ category="lo",
+ direction="l",
+ },
+ [0x188B0]={
+ category="lo",
+ direction="l",
+ },
+ [0x188B1]={
+ category="lo",
+ direction="l",
+ },
+ [0x188B2]={
+ category="lo",
+ direction="l",
+ },
+ [0x188B3]={
+ category="lo",
+ direction="l",
+ },
+ [0x188B4]={
+ category="lo",
+ direction="l",
+ },
+ [0x188B5]={
+ category="lo",
+ direction="l",
+ },
+ [0x188B6]={
+ category="lo",
+ direction="l",
+ },
+ [0x188B7]={
+ category="lo",
+ direction="l",
+ },
+ [0x188B8]={
+ category="lo",
+ direction="l",
+ },
+ [0x188B9]={
+ category="lo",
+ direction="l",
+ },
+ [0x188BA]={
+ category="lo",
+ direction="l",
+ },
+ [0x188BB]={
+ category="lo",
+ direction="l",
+ },
+ [0x188BC]={
+ category="lo",
+ direction="l",
+ },
+ [0x188BD]={
+ category="lo",
+ direction="l",
+ },
+ [0x188BE]={
+ category="lo",
+ direction="l",
+ },
+ [0x188BF]={
+ category="lo",
+ direction="l",
+ },
+ [0x188C0]={
+ category="lo",
+ direction="l",
+ },
+ [0x188C1]={
+ category="lo",
+ direction="l",
+ },
+ [0x188C2]={
+ category="lo",
+ direction="l",
+ },
+ [0x188C3]={
+ category="lo",
+ direction="l",
+ },
+ [0x188C4]={
+ category="lo",
+ direction="l",
+ },
+ [0x188C5]={
+ category="lo",
+ direction="l",
+ },
+ [0x188C6]={
+ category="lo",
+ direction="l",
+ },
+ [0x188C7]={
+ category="lo",
+ direction="l",
+ },
+ [0x188C8]={
+ category="lo",
+ direction="l",
+ },
+ [0x188C9]={
+ category="lo",
+ direction="l",
+ },
+ [0x188CA]={
+ category="lo",
+ direction="l",
+ },
+ [0x188CB]={
+ category="lo",
+ direction="l",
+ },
+ [0x188CC]={
+ category="lo",
+ direction="l",
+ },
+ [0x188CD]={
+ category="lo",
+ direction="l",
+ },
+ [0x188CE]={
+ category="lo",
+ direction="l",
+ },
+ [0x188CF]={
+ category="lo",
+ direction="l",
+ },
+ [0x188D0]={
+ category="lo",
+ direction="l",
+ },
+ [0x188D1]={
+ category="lo",
+ direction="l",
+ },
+ [0x188D2]={
+ category="lo",
+ direction="l",
+ },
+ [0x188D3]={
+ category="lo",
+ direction="l",
+ },
+ [0x188D4]={
+ category="lo",
+ direction="l",
+ },
+ [0x188D5]={
+ category="lo",
+ direction="l",
+ },
+ [0x188D6]={
+ category="lo",
+ direction="l",
+ },
+ [0x188D7]={
+ category="lo",
+ direction="l",
+ },
+ [0x188D8]={
+ category="lo",
+ direction="l",
+ },
+ [0x188D9]={
+ category="lo",
+ direction="l",
+ },
+ [0x188DA]={
+ category="lo",
+ direction="l",
+ },
+ [0x188DB]={
+ category="lo",
+ direction="l",
+ },
+ [0x188DC]={
+ category="lo",
+ direction="l",
+ },
+ [0x188DD]={
+ category="lo",
+ direction="l",
+ },
+ [0x188DE]={
+ category="lo",
+ direction="l",
+ },
+ [0x188DF]={
+ category="lo",
+ direction="l",
+ },
+ [0x188E0]={
+ category="lo",
+ direction="l",
+ },
+ [0x188E1]={
+ category="lo",
+ direction="l",
+ },
+ [0x188E2]={
+ category="lo",
+ direction="l",
+ },
+ [0x188E3]={
+ category="lo",
+ direction="l",
+ },
+ [0x188E4]={
+ category="lo",
+ direction="l",
+ },
+ [0x188E5]={
+ category="lo",
+ direction="l",
+ },
+ [0x188E6]={
+ category="lo",
+ direction="l",
+ },
+ [0x188E7]={
+ category="lo",
+ direction="l",
+ },
+ [0x188E8]={
+ category="lo",
+ direction="l",
+ },
+ [0x188E9]={
+ category="lo",
+ direction="l",
+ },
+ [0x188EA]={
+ category="lo",
+ direction="l",
+ },
+ [0x188EB]={
+ category="lo",
+ direction="l",
+ },
+ [0x188EC]={
+ category="lo",
+ direction="l",
+ },
+ [0x188ED]={
+ category="lo",
+ direction="l",
+ },
+ [0x188EE]={
+ category="lo",
+ direction="l",
+ },
+ [0x188EF]={
+ category="lo",
+ direction="l",
+ },
+ [0x188F0]={
+ category="lo",
+ direction="l",
+ },
+ [0x188F1]={
+ category="lo",
+ direction="l",
+ },
+ [0x188F2]={
+ category="lo",
+ direction="l",
+ },
+ [0x188F3]={
+ category="lo",
+ direction="l",
+ },
+ [0x188F4]={
+ category="lo",
+ direction="l",
+ },
+ [0x188F5]={
+ category="lo",
+ direction="l",
+ },
+ [0x188F6]={
+ category="lo",
+ direction="l",
+ },
+ [0x188F7]={
+ category="lo",
+ direction="l",
+ },
+ [0x188F8]={
+ category="lo",
+ direction="l",
+ },
+ [0x188F9]={
+ category="lo",
+ direction="l",
+ },
+ [0x188FA]={
+ category="lo",
+ direction="l",
+ },
+ [0x188FB]={
+ category="lo",
+ direction="l",
+ },
+ [0x188FC]={
+ category="lo",
+ direction="l",
+ },
+ [0x188FD]={
+ category="lo",
+ direction="l",
+ },
+ [0x188FE]={
+ category="lo",
+ direction="l",
+ },
+ [0x188FF]={
+ category="lo",
+ direction="l",
+ },
+ [0x18900]={
+ category="lo",
+ direction="l",
+ },
+ [0x18901]={
+ category="lo",
+ direction="l",
+ },
+ [0x18902]={
+ category="lo",
+ direction="l",
+ },
+ [0x18903]={
+ category="lo",
+ direction="l",
+ },
+ [0x18904]={
+ category="lo",
+ direction="l",
+ },
+ [0x18905]={
+ category="lo",
+ direction="l",
+ },
+ [0x18906]={
+ category="lo",
+ direction="l",
+ },
+ [0x18907]={
+ category="lo",
+ direction="l",
+ },
+ [0x18908]={
+ category="lo",
+ direction="l",
+ },
+ [0x18909]={
+ category="lo",
+ direction="l",
+ },
+ [0x1890A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1890B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1890C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1890D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1890E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1890F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18910]={
+ category="lo",
+ direction="l",
+ },
+ [0x18911]={
+ category="lo",
+ direction="l",
+ },
+ [0x18912]={
+ category="lo",
+ direction="l",
+ },
+ [0x18913]={
+ category="lo",
+ direction="l",
+ },
+ [0x18914]={
+ category="lo",
+ direction="l",
+ },
+ [0x18915]={
+ category="lo",
+ direction="l",
+ },
+ [0x18916]={
+ category="lo",
+ direction="l",
+ },
+ [0x18917]={
+ category="lo",
+ direction="l",
+ },
+ [0x18918]={
+ category="lo",
+ direction="l",
+ },
+ [0x18919]={
+ category="lo",
+ direction="l",
+ },
+ [0x1891A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1891B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1891C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1891D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1891E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1891F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18920]={
+ category="lo",
+ direction="l",
+ },
+ [0x18921]={
+ category="lo",
+ direction="l",
+ },
+ [0x18922]={
+ category="lo",
+ direction="l",
+ },
+ [0x18923]={
+ category="lo",
+ direction="l",
+ },
+ [0x18924]={
+ category="lo",
+ direction="l",
+ },
+ [0x18925]={
+ category="lo",
+ direction="l",
+ },
+ [0x18926]={
+ category="lo",
+ direction="l",
+ },
+ [0x18927]={
+ category="lo",
+ direction="l",
+ },
+ [0x18928]={
+ category="lo",
+ direction="l",
+ },
+ [0x18929]={
+ category="lo",
+ direction="l",
+ },
+ [0x1892A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1892B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1892C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1892D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1892E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1892F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18930]={
+ category="lo",
+ direction="l",
+ },
+ [0x18931]={
+ category="lo",
+ direction="l",
+ },
+ [0x18932]={
+ category="lo",
+ direction="l",
+ },
+ [0x18933]={
+ category="lo",
+ direction="l",
+ },
+ [0x18934]={
+ category="lo",
+ direction="l",
+ },
+ [0x18935]={
+ category="lo",
+ direction="l",
+ },
+ [0x18936]={
+ category="lo",
+ direction="l",
+ },
+ [0x18937]={
+ category="lo",
+ direction="l",
+ },
+ [0x18938]={
+ category="lo",
+ direction="l",
+ },
+ [0x18939]={
+ category="lo",
+ direction="l",
+ },
+ [0x1893A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1893B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1893C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1893D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1893E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1893F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18940]={
+ category="lo",
+ direction="l",
+ },
+ [0x18941]={
+ category="lo",
+ direction="l",
+ },
+ [0x18942]={
+ category="lo",
+ direction="l",
+ },
+ [0x18943]={
+ category="lo",
+ direction="l",
+ },
+ [0x18944]={
+ category="lo",
+ direction="l",
+ },
+ [0x18945]={
+ category="lo",
+ direction="l",
+ },
+ [0x18946]={
+ category="lo",
+ direction="l",
+ },
+ [0x18947]={
+ category="lo",
+ direction="l",
+ },
+ [0x18948]={
+ category="lo",
+ direction="l",
+ },
+ [0x18949]={
+ category="lo",
+ direction="l",
+ },
+ [0x1894A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1894B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1894C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1894D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1894E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1894F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18950]={
+ category="lo",
+ direction="l",
+ },
+ [0x18951]={
+ category="lo",
+ direction="l",
+ },
+ [0x18952]={
+ category="lo",
+ direction="l",
+ },
+ [0x18953]={
+ category="lo",
+ direction="l",
+ },
+ [0x18954]={
+ category="lo",
+ direction="l",
+ },
+ [0x18955]={
+ category="lo",
+ direction="l",
+ },
+ [0x18956]={
+ category="lo",
+ direction="l",
+ },
+ [0x18957]={
+ category="lo",
+ direction="l",
+ },
+ [0x18958]={
+ category="lo",
+ direction="l",
+ },
+ [0x18959]={
+ category="lo",
+ direction="l",
+ },
+ [0x1895A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1895B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1895C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1895D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1895E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1895F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18960]={
+ category="lo",
+ direction="l",
+ },
+ [0x18961]={
+ category="lo",
+ direction="l",
+ },
+ [0x18962]={
+ category="lo",
+ direction="l",
+ },
+ [0x18963]={
+ category="lo",
+ direction="l",
+ },
+ [0x18964]={
+ category="lo",
+ direction="l",
+ },
+ [0x18965]={
+ category="lo",
+ direction="l",
+ },
+ [0x18966]={
+ category="lo",
+ direction="l",
+ },
+ [0x18967]={
+ category="lo",
+ direction="l",
+ },
+ [0x18968]={
+ category="lo",
+ direction="l",
+ },
+ [0x18969]={
+ category="lo",
+ direction="l",
+ },
+ [0x1896A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1896B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1896C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1896D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1896E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1896F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18970]={
+ category="lo",
+ direction="l",
+ },
+ [0x18971]={
+ category="lo",
+ direction="l",
+ },
+ [0x18972]={
+ category="lo",
+ direction="l",
+ },
+ [0x18973]={
+ category="lo",
+ direction="l",
+ },
+ [0x18974]={
+ category="lo",
+ direction="l",
+ },
+ [0x18975]={
+ category="lo",
+ direction="l",
+ },
+ [0x18976]={
+ category="lo",
+ direction="l",
+ },
+ [0x18977]={
+ category="lo",
+ direction="l",
+ },
+ [0x18978]={
+ category="lo",
+ direction="l",
+ },
+ [0x18979]={
+ category="lo",
+ direction="l",
+ },
+ [0x1897A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1897B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1897C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1897D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1897E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1897F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18980]={
+ category="lo",
+ direction="l",
+ },
+ [0x18981]={
+ category="lo",
+ direction="l",
+ },
+ [0x18982]={
+ category="lo",
+ direction="l",
+ },
+ [0x18983]={
+ category="lo",
+ direction="l",
+ },
+ [0x18984]={
+ category="lo",
+ direction="l",
+ },
+ [0x18985]={
+ category="lo",
+ direction="l",
+ },
+ [0x18986]={
+ category="lo",
+ direction="l",
+ },
+ [0x18987]={
+ category="lo",
+ direction="l",
+ },
+ [0x18988]={
+ category="lo",
+ direction="l",
+ },
+ [0x18989]={
+ category="lo",
+ direction="l",
+ },
+ [0x1898A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1898B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1898C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1898D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1898E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1898F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18990]={
+ category="lo",
+ direction="l",
+ },
+ [0x18991]={
+ category="lo",
+ direction="l",
+ },
+ [0x18992]={
+ category="lo",
+ direction="l",
+ },
+ [0x18993]={
+ category="lo",
+ direction="l",
+ },
+ [0x18994]={
+ category="lo",
+ direction="l",
+ },
+ [0x18995]={
+ category="lo",
+ direction="l",
+ },
+ [0x18996]={
+ category="lo",
+ direction="l",
+ },
+ [0x18997]={
+ category="lo",
+ direction="l",
+ },
+ [0x18998]={
+ category="lo",
+ direction="l",
+ },
+ [0x18999]={
+ category="lo",
+ direction="l",
+ },
+ [0x1899A]={
+ category="lo",
+ direction="l",
+ },
+ [0x1899B]={
+ category="lo",
+ direction="l",
+ },
+ [0x1899C]={
+ category="lo",
+ direction="l",
+ },
+ [0x1899D]={
+ category="lo",
+ direction="l",
+ },
+ [0x1899E]={
+ category="lo",
+ direction="l",
+ },
+ [0x1899F]={
+ category="lo",
+ direction="l",
+ },
+ [0x189A0]={
+ category="lo",
+ direction="l",
+ },
+ [0x189A1]={
+ category="lo",
+ direction="l",
+ },
+ [0x189A2]={
+ category="lo",
+ direction="l",
+ },
+ [0x189A3]={
+ category="lo",
+ direction="l",
+ },
+ [0x189A4]={
+ category="lo",
+ direction="l",
+ },
+ [0x189A5]={
+ category="lo",
+ direction="l",
+ },
+ [0x189A6]={
+ category="lo",
+ direction="l",
+ },
+ [0x189A7]={
+ category="lo",
+ direction="l",
+ },
+ [0x189A8]={
+ category="lo",
+ direction="l",
+ },
+ [0x189A9]={
+ category="lo",
+ direction="l",
+ },
+ [0x189AA]={
+ category="lo",
+ direction="l",
+ },
+ [0x189AB]={
+ category="lo",
+ direction="l",
+ },
+ [0x189AC]={
+ category="lo",
+ direction="l",
+ },
+ [0x189AD]={
+ category="lo",
+ direction="l",
+ },
+ [0x189AE]={
+ category="lo",
+ direction="l",
+ },
+ [0x189AF]={
+ category="lo",
+ direction="l",
+ },
+ [0x189B0]={
+ category="lo",
+ direction="l",
+ },
+ [0x189B1]={
+ category="lo",
+ direction="l",
+ },
+ [0x189B2]={
+ category="lo",
+ direction="l",
+ },
+ [0x189B3]={
+ category="lo",
+ direction="l",
+ },
+ [0x189B4]={
+ category="lo",
+ direction="l",
+ },
+ [0x189B5]={
+ category="lo",
+ direction="l",
+ },
+ [0x189B6]={
+ category="lo",
+ direction="l",
+ },
+ [0x189B7]={
+ category="lo",
+ direction="l",
+ },
+ [0x189B8]={
+ category="lo",
+ direction="l",
+ },
+ [0x189B9]={
+ category="lo",
+ direction="l",
+ },
+ [0x189BA]={
+ category="lo",
+ direction="l",
+ },
+ [0x189BB]={
+ category="lo",
+ direction="l",
+ },
+ [0x189BC]={
+ category="lo",
+ direction="l",
+ },
+ [0x189BD]={
+ category="lo",
+ direction="l",
+ },
+ [0x189BE]={
+ category="lo",
+ direction="l",
+ },
+ [0x189BF]={
+ category="lo",
+ direction="l",
+ },
+ [0x189C0]={
+ category="lo",
+ direction="l",
+ },
+ [0x189C1]={
+ category="lo",
+ direction="l",
+ },
+ [0x189C2]={
+ category="lo",
+ direction="l",
+ },
+ [0x189C3]={
+ category="lo",
+ direction="l",
+ },
+ [0x189C4]={
+ category="lo",
+ direction="l",
+ },
+ [0x189C5]={
+ category="lo",
+ direction="l",
+ },
+ [0x189C6]={
+ category="lo",
+ direction="l",
+ },
+ [0x189C7]={
+ category="lo",
+ direction="l",
+ },
+ [0x189C8]={
+ category="lo",
+ direction="l",
+ },
+ [0x189C9]={
+ category="lo",
+ direction="l",
+ },
+ [0x189CA]={
+ category="lo",
+ direction="l",
+ },
+ [0x189CB]={
+ category="lo",
+ direction="l",
+ },
+ [0x189CC]={
+ category="lo",
+ direction="l",
+ },
+ [0x189CD]={
+ category="lo",
+ direction="l",
+ },
+ [0x189CE]={
+ category="lo",
+ direction="l",
+ },
+ [0x189CF]={
+ category="lo",
+ direction="l",
+ },
+ [0x189D0]={
+ category="lo",
+ direction="l",
+ },
+ [0x189D1]={
+ category="lo",
+ direction="l",
+ },
+ [0x189D2]={
+ category="lo",
+ direction="l",
+ },
+ [0x189D3]={
+ category="lo",
+ direction="l",
+ },
+ [0x189D4]={
+ category="lo",
+ direction="l",
+ },
+ [0x189D5]={
+ category="lo",
+ direction="l",
+ },
+ [0x189D6]={
+ category="lo",
+ direction="l",
+ },
+ [0x189D7]={
+ category="lo",
+ direction="l",
+ },
+ [0x189D8]={
+ category="lo",
+ direction="l",
+ },
+ [0x189D9]={
+ category="lo",
+ direction="l",
+ },
+ [0x189DA]={
+ category="lo",
+ direction="l",
+ },
+ [0x189DB]={
+ category="lo",
+ direction="l",
+ },
+ [0x189DC]={
+ category="lo",
+ direction="l",
+ },
+ [0x189DD]={
+ category="lo",
+ direction="l",
+ },
+ [0x189DE]={
+ category="lo",
+ direction="l",
+ },
+ [0x189DF]={
+ category="lo",
+ direction="l",
+ },
+ [0x189E0]={
+ category="lo",
+ direction="l",
+ },
+ [0x189E1]={
+ category="lo",
+ direction="l",
+ },
+ [0x189E2]={
+ category="lo",
+ direction="l",
+ },
+ [0x189E3]={
+ category="lo",
+ direction="l",
+ },
+ [0x189E4]={
+ category="lo",
+ direction="l",
+ },
+ [0x189E5]={
+ category="lo",
+ direction="l",
+ },
+ [0x189E6]={
+ category="lo",
+ direction="l",
+ },
+ [0x189E7]={
+ category="lo",
+ direction="l",
+ },
+ [0x189E8]={
+ category="lo",
+ direction="l",
+ },
+ [0x189E9]={
+ category="lo",
+ direction="l",
+ },
+ [0x189EA]={
+ category="lo",
+ direction="l",
+ },
+ [0x189EB]={
+ category="lo",
+ direction="l",
+ },
+ [0x189EC]={
+ category="lo",
+ direction="l",
+ },
+ [0x189ED]={
+ category="lo",
+ direction="l",
+ },
+ [0x189EE]={
+ category="lo",
+ direction="l",
+ },
+ [0x189EF]={
+ category="lo",
+ direction="l",
+ },
+ [0x189F0]={
+ category="lo",
+ direction="l",
+ },
+ [0x189F1]={
+ category="lo",
+ direction="l",
+ },
+ [0x189F2]={
+ category="lo",
+ direction="l",
+ },
+ [0x189F3]={
+ category="lo",
+ direction="l",
+ },
+ [0x189F4]={
+ category="lo",
+ direction="l",
+ },
+ [0x189F5]={
+ category="lo",
+ direction="l",
+ },
+ [0x189F6]={
+ category="lo",
+ direction="l",
+ },
+ [0x189F7]={
+ category="lo",
+ direction="l",
+ },
+ [0x189F8]={
+ category="lo",
+ direction="l",
+ },
+ [0x189F9]={
+ category="lo",
+ direction="l",
+ },
+ [0x189FA]={
+ category="lo",
+ direction="l",
+ },
+ [0x189FB]={
+ category="lo",
+ direction="l",
+ },
+ [0x189FC]={
+ category="lo",
+ direction="l",
+ },
+ [0x189FD]={
+ category="lo",
+ direction="l",
+ },
+ [0x189FE]={
+ category="lo",
+ direction="l",
+ },
+ [0x189FF]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A00]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A01]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A02]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A03]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A04]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A05]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A06]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A07]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A08]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A09]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A0A]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A0B]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A0C]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A0D]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A0E]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A0F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A10]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A11]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A12]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A13]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A14]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A15]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A16]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A17]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A18]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A19]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A1A]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A1B]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A1C]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A1D]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A1E]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A1F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A20]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A21]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A22]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A23]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A24]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A25]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A26]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A27]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A28]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A29]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A2A]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A2B]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A2C]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A2D]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A2E]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A2F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A30]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A31]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A32]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A33]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A34]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A35]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A36]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A37]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A38]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A39]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A3A]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A3B]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A3C]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A3D]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A3E]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A3F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A40]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A41]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A42]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A43]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A44]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A45]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A46]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A47]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A48]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A49]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A4A]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A4B]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A4C]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A4D]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A4E]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A4F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A50]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A51]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A52]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A53]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A54]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A55]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A56]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A57]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A58]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A59]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A5A]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A5B]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A5C]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A5D]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A5E]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A5F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A60]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A61]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A62]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A63]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A64]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A65]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A66]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A67]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A68]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A69]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A6A]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A6B]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A6C]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A6D]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A6E]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A6F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A70]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A71]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A72]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A73]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A74]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A75]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A76]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A77]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A78]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A79]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A7A]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A7B]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A7C]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A7D]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A7E]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A7F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A80]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A81]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A82]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A83]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A84]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A85]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A86]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A87]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A88]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A89]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A8A]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A8B]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A8C]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A8D]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A8E]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A8F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A90]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A91]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A92]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A93]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A94]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A95]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A96]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A97]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A98]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A99]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A9A]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A9B]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A9C]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A9D]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A9E]={
+ category="lo",
+ direction="l",
+ },
+ [0x18A9F]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AA0]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AA1]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AA2]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AA3]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AA4]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AA5]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AA6]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AA7]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AA8]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AA9]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AAA]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AAB]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AAC]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AAD]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AAE]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AAF]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AB0]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AB1]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AB2]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AB3]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AB4]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AB5]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AB6]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AB7]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AB8]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AB9]={
+ category="lo",
+ direction="l",
+ },
+ [0x18ABA]={
+ category="lo",
+ direction="l",
+ },
+ [0x18ABB]={
+ category="lo",
+ direction="l",
+ },
+ [0x18ABC]={
+ category="lo",
+ direction="l",
+ },
+ [0x18ABD]={
+ category="lo",
+ direction="l",
+ },
+ [0x18ABE]={
+ category="lo",
+ direction="l",
+ },
+ [0x18ABF]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AC0]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AC1]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AC2]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AC3]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AC4]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AC5]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AC6]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AC7]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AC8]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AC9]={
+ category="lo",
+ direction="l",
+ },
+ [0x18ACA]={
+ category="lo",
+ direction="l",
+ },
+ [0x18ACB]={
+ category="lo",
+ direction="l",
+ },
+ [0x18ACC]={
+ category="lo",
+ direction="l",
+ },
+ [0x18ACD]={
+ category="lo",
+ direction="l",
+ },
+ [0x18ACE]={
+ category="lo",
+ direction="l",
+ },
+ [0x18ACF]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AD0]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AD1]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AD2]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AD3]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AD4]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AD5]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AD6]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AD7]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AD8]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AD9]={
+ category="lo",
+ direction="l",
+ },
+ [0x18ADA]={
+ category="lo",
+ direction="l",
+ },
+ [0x18ADB]={
+ category="lo",
+ direction="l",
+ },
+ [0x18ADC]={
+ category="lo",
+ direction="l",
+ },
+ [0x18ADD]={
+ category="lo",
+ direction="l",
+ },
+ [0x18ADE]={
+ category="lo",
+ direction="l",
+ },
+ [0x18ADF]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AE0]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AE1]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AE2]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AE3]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AE4]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AE5]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AE6]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AE7]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AE8]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AE9]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AEA]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AEB]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AEC]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AED]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AEE]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AEF]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AF0]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AF1]={
+ category="lo",
+ direction="l",
+ },
+ [0x18AF2]={
+ category="lo",
+ direction="l",
+ },
[0x1B000]={
category="lo",
direction="l",
@@ -104935,6 +109565,158 @@ return {
category="mn",
direction="nsm",
},
+ [0x1E000]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E001]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E002]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E003]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E004]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E005]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E006]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E008]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E009]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E00A]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E00B]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E00C]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E00D]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E00E]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E00F]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E010]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E011]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E012]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E013]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E014]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E015]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E016]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E017]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E018]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E01B]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E01C]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E01D]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E01E]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E01F]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E020]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E021]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E023]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E024]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E026]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E027]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E028]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E029]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E02A]={
+ category="mn",
+ direction="nsm",
+ },
[0x1E800]={
category="lo",
direction="r",
@@ -105787,6 +110569,354 @@ return {
category="mn",
direction="nsm",
},
+ [0x1E900]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E901]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E902]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E903]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E904]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E905]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E906]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E907]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E908]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E909]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E90A]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E90B]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E90C]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E90D]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E90E]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E90F]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E910]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E911]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E912]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E913]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E914]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E915]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E916]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E917]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E918]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E919]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E91A]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E91B]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E91C]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E91D]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E91E]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E91F]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E920]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E921]={
+ category="lu",
+ direction="r",
+ },
+ [0x1E922]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E923]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E924]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E925]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E926]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E927]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E928]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E929]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E92A]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E92B]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E92C]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E92D]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E92E]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E92F]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E930]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E931]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E932]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E933]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E934]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E935]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E936]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E937]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E938]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E939]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E93A]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E93B]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E93C]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E93D]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E93E]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E93F]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E940]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E941]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E942]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E943]={
+ category="ll",
+ direction="r",
+ },
+ [0x1E944]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E945]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E946]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E947]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E948]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E949]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E94A]={
+ category="mn",
+ direction="nsm",
+ },
+ [0x1E950]={
+ category="nd",
+ direction="r",
+ },
+ [0x1E951]={
+ category="nd",
+ direction="r",
+ },
+ [0x1E952]={
+ category="nd",
+ direction="r",
+ },
+ [0x1E953]={
+ category="nd",
+ direction="r",
+ },
+ [0x1E954]={
+ category="nd",
+ direction="r",
+ },
+ [0x1E955]={
+ category="nd",
+ direction="r",
+ },
+ [0x1E956]={
+ category="nd",
+ direction="r",
+ },
+ [0x1E957]={
+ category="nd",
+ direction="r",
+ },
+ [0x1E958]={
+ category="nd",
+ direction="r",
+ },
+ [0x1E959]={
+ category="nd",
+ direction="r",
+ },
+ [0x1E95E]={
+ category="po",
+ direction="r",
+ },
+ [0x1E95F]={
+ category="po",
+ direction="r",
+ },
[0x1EE00]={
category="lo",
direction="al",
@@ -107851,6 +112981,78 @@ return {
category="so",
direction="l",
},
+ [0x1F19B]={
+ category="so",
+ direction="l",
+ },
+ [0x1F19C]={
+ category="so",
+ direction="l",
+ },
+ [0x1F19D]={
+ category="so",
+ direction="l",
+ },
+ [0x1F19E]={
+ category="so",
+ direction="l",
+ },
+ [0x1F19F]={
+ category="so",
+ direction="l",
+ },
+ [0x1F1A0]={
+ category="so",
+ direction="l",
+ },
+ [0x1F1A1]={
+ category="so",
+ direction="l",
+ },
+ [0x1F1A2]={
+ category="so",
+ direction="l",
+ },
+ [0x1F1A3]={
+ category="so",
+ direction="l",
+ },
+ [0x1F1A4]={
+ category="so",
+ direction="l",
+ },
+ [0x1F1A5]={
+ category="so",
+ direction="l",
+ },
+ [0x1F1A6]={
+ category="so",
+ direction="l",
+ },
+ [0x1F1A7]={
+ category="so",
+ direction="l",
+ },
+ [0x1F1A8]={
+ category="so",
+ direction="l",
+ },
+ [0x1F1A9]={
+ category="so",
+ direction="l",
+ },
+ [0x1F1AA]={
+ category="so",
+ direction="l",
+ },
+ [0x1F1AB]={
+ category="so",
+ direction="l",
+ },
+ [0x1F1AC]={
+ category="so",
+ direction="l",
+ },
[0x1F1E6]={
category="so",
direction="l",
@@ -108139,6 +113341,10 @@ return {
category="so",
direction="l",
},
+ [0x1F23B]={
+ category="so",
+ direction="l",
+ },
[0x1F240]={
category="so",
direction="l",
@@ -110719,6 +115925,10 @@ return {
category="so",
direction="on",
},
+ [0x1F57A]={
+ category="so",
+ direction="on",
+ },
[0x1F57B]={
category="so",
direction="on",
@@ -110883,6 +116093,10 @@ return {
category="so",
direction="on",
},
+ [0x1F5A4]={
+ category="so",
+ direction="on",
+ },
[0x1F5A5]={
category="so",
direction="on",
@@ -112083,6 +117297,14 @@ return {
category="so",
direction="on",
},
+ [0x1F6D1]={
+ category="so",
+ direction="on",
+ },
+ [0x1F6D2]={
+ category="so",
+ direction="on",
+ },
[0x1F6E0]={
category="so",
direction="on",
@@ -112151,6 +117373,18 @@ return {
category="so",
direction="on",
},
+ [0x1F6F4]={
+ category="so",
+ direction="on",
+ },
+ [0x1F6F5]={
+ category="so",
+ direction="on",
+ },
+ [0x1F6F6]={
+ category="so",
+ direction="on",
+ },
[0x1F700]={
category="so",
direction="on",
@@ -113583,6 +118817,222 @@ return {
category="so",
direction="on",
},
+ [0x1F919]={
+ category="so",
+ direction="on",
+ },
+ [0x1F91A]={
+ category="so",
+ direction="on",
+ },
+ [0x1F91B]={
+ category="so",
+ direction="on",
+ },
+ [0x1F91C]={
+ category="so",
+ direction="on",
+ },
+ [0x1F91D]={
+ category="so",
+ direction="on",
+ },
+ [0x1F91E]={
+ category="so",
+ direction="on",
+ },
+ [0x1F920]={
+ category="so",
+ direction="on",
+ },
+ [0x1F921]={
+ category="so",
+ direction="on",
+ },
+ [0x1F922]={
+ category="so",
+ direction="on",
+ },
+ [0x1F923]={
+ category="so",
+ direction="on",
+ },
+ [0x1F924]={
+ category="so",
+ direction="on",
+ },
+ [0x1F925]={
+ category="so",
+ direction="on",
+ },
+ [0x1F926]={
+ category="so",
+ direction="on",
+ },
+ [0x1F927]={
+ category="so",
+ direction="on",
+ },
+ [0x1F930]={
+ category="so",
+ direction="on",
+ },
+ [0x1F933]={
+ category="so",
+ direction="on",
+ },
+ [0x1F934]={
+ category="so",
+ direction="on",
+ },
+ [0x1F935]={
+ category="so",
+ direction="on",
+ },
+ [0x1F936]={
+ category="so",
+ direction="on",
+ },
+ [0x1F937]={
+ category="so",
+ direction="on",
+ },
+ [0x1F938]={
+ category="so",
+ direction="on",
+ },
+ [0x1F939]={
+ category="so",
+ direction="on",
+ },
+ [0x1F93A]={
+ category="so",
+ direction="on",
+ },
+ [0x1F93B]={
+ category="so",
+ direction="on",
+ },
+ [0x1F93C]={
+ category="so",
+ direction="on",
+ },
+ [0x1F93D]={
+ category="so",
+ direction="on",
+ },
+ [0x1F93E]={
+ category="so",
+ direction="on",
+ },
+ [0x1F940]={
+ category="so",
+ direction="on",
+ },
+ [0x1F941]={
+ category="so",
+ direction="on",
+ },
+ [0x1F942]={
+ category="so",
+ direction="on",
+ },
+ [0x1F943]={
+ category="so",
+ direction="on",
+ },
+ [0x1F944]={
+ category="so",
+ direction="on",
+ },
+ [0x1F945]={
+ category="so",
+ direction="on",
+ },
+ [0x1F946]={
+ category="so",
+ direction="on",
+ },
+ [0x1F947]={
+ category="so",
+ direction="on",
+ },
+ [0x1F948]={
+ category="so",
+ direction="on",
+ },
+ [0x1F949]={
+ category="so",
+ direction="on",
+ },
+ [0x1F94A]={
+ category="so",
+ direction="on",
+ },
+ [0x1F94B]={
+ category="so",
+ direction="on",
+ },
+ [0x1F950]={
+ category="so",
+ direction="on",
+ },
+ [0x1F951]={
+ category="so",
+ direction="on",
+ },
+ [0x1F952]={
+ category="so",
+ direction="on",
+ },
+ [0x1F953]={
+ category="so",
+ direction="on",
+ },
+ [0x1F954]={
+ category="so",
+ direction="on",
+ },
+ [0x1F955]={
+ category="so",
+ direction="on",
+ },
+ [0x1F956]={
+ category="so",
+ direction="on",
+ },
+ [0x1F957]={
+ category="so",
+ direction="on",
+ },
+ [0x1F958]={
+ category="so",
+ direction="on",
+ },
+ [0x1F959]={
+ category="so",
+ direction="on",
+ },
+ [0x1F95A]={
+ category="so",
+ direction="on",
+ },
+ [0x1F95B]={
+ category="so",
+ direction="on",
+ },
+ [0x1F95C]={
+ category="so",
+ direction="on",
+ },
+ [0x1F95D]={
+ category="so",
+ direction="on",
+ },
+ [0x1F95E]={
+ category="so",
+ direction="on",
+ },
[0x1F980]={
category="so",
direction="on",
@@ -113603,6 +119053,58 @@ return {
category="so",
direction="on",
},
+ [0x1F985]={
+ category="so",
+ direction="on",
+ },
+ [0x1F986]={
+ category="so",
+ direction="on",
+ },
+ [0x1F987]={
+ category="so",
+ direction="on",
+ },
+ [0x1F988]={
+ category="so",
+ direction="on",
+ },
+ [0x1F989]={
+ category="so",
+ direction="on",
+ },
+ [0x1F98A]={
+ category="so",
+ direction="on",
+ },
+ [0x1F98B]={
+ category="so",
+ direction="on",
+ },
+ [0x1F98C]={
+ category="so",
+ direction="on",
+ },
+ [0x1F98D]={
+ category="so",
+ direction="on",
+ },
+ [0x1F98E]={
+ category="so",
+ direction="on",
+ },
+ [0x1F98F]={
+ category="so",
+ direction="on",
+ },
+ [0x1F990]={
+ category="so",
+ direction="on",
+ },
+ [0x1F991]={
+ category="so",
+ direction="on",
+ },
[0x1F9C0]={
category="so",
direction="on",
@@ -116650,6 +122152,15 @@ return {
[0x8B2]=0x3,
[0x8B3]=0x2,
[0x8B4]=0x2,
+ [0x8B6]=0x2,
+ [0x8B7]=0x2,
+ [0x8B8]=0x2,
+ [0x8B9]=0x3,
+ [0x8BA]=0x2,
+ [0x8BB]=0x2,
+ [0x8BC]=0x2,
+ [0x8BD]=0x2,
+ [0x8E2]=0x4,
[0x1806]=0x4,
[0x1807]=0x2,
[0x180A]=0x2,
@@ -116747,8 +122258,6 @@ return {
[0x1882]=0x4,
[0x1883]=0x4,
[0x1884]=0x4,
- [0x1885]=0x4,
- [0x1886]=0x4,
[0x1887]=0x2,
[0x1888]=0x2,
[0x1889]=0x2,
@@ -116786,6 +122295,7 @@ return {
[0x18AA]=0x2,
[0x200C]=0x4,
[0x200D]=0x2,
+ [0x202F]=0x4,
[0x2066]=0x4,
[0x2067]=0x4,
[0x2068]=0x4,
@@ -116909,5 +122419,73 @@ return {
[0x10BAD]=0x2,
[0x10BAE]=0x2,
[0x10BAF]=0x4,
+ [0x1E900]=0x2,
+ [0x1E901]=0x2,
+ [0x1E902]=0x2,
+ [0x1E903]=0x2,
+ [0x1E904]=0x2,
+ [0x1E905]=0x2,
+ [0x1E906]=0x2,
+ [0x1E907]=0x2,
+ [0x1E908]=0x2,
+ [0x1E909]=0x2,
+ [0x1E90A]=0x2,
+ [0x1E90B]=0x2,
+ [0x1E90C]=0x2,
+ [0x1E90D]=0x2,
+ [0x1E90E]=0x2,
+ [0x1E90F]=0x2,
+ [0x1E910]=0x2,
+ [0x1E911]=0x2,
+ [0x1E912]=0x2,
+ [0x1E913]=0x2,
+ [0x1E914]=0x2,
+ [0x1E915]=0x2,
+ [0x1E916]=0x2,
+ [0x1E917]=0x2,
+ [0x1E918]=0x2,
+ [0x1E919]=0x2,
+ [0x1E91A]=0x2,
+ [0x1E91B]=0x2,
+ [0x1E91C]=0x2,
+ [0x1E91D]=0x2,
+ [0x1E91E]=0x2,
+ [0x1E91F]=0x2,
+ [0x1E920]=0x2,
+ [0x1E921]=0x2,
+ [0x1E922]=0x2,
+ [0x1E923]=0x2,
+ [0x1E924]=0x2,
+ [0x1E925]=0x2,
+ [0x1E926]=0x2,
+ [0x1E927]=0x2,
+ [0x1E928]=0x2,
+ [0x1E929]=0x2,
+ [0x1E92A]=0x2,
+ [0x1E92B]=0x2,
+ [0x1E92C]=0x2,
+ [0x1E92D]=0x2,
+ [0x1E92E]=0x2,
+ [0x1E92F]=0x2,
+ [0x1E930]=0x2,
+ [0x1E931]=0x2,
+ [0x1E932]=0x2,
+ [0x1E933]=0x2,
+ [0x1E934]=0x2,
+ [0x1E935]=0x2,
+ [0x1E936]=0x2,
+ [0x1E937]=0x2,
+ [0x1E938]=0x2,
+ [0x1E939]=0x2,
+ [0x1E93A]=0x2,
+ [0x1E93B]=0x2,
+ [0x1E93C]=0x2,
+ [0x1E93D]=0x2,
+ [0x1E93E]=0x2,
+ [0x1E93F]=0x2,
+ [0x1E940]=0x2,
+ [0x1E941]=0x2,
+ [0x1E942]=0x2,
+ [0x1E943]=0x2,
},
} \ No newline at end of file
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-colors.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-colors.lua
index 12b490e7591..f2fdceb2c50 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-colors.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-colors.lua
@@ -1,5 +1,5 @@
if not modules then modules = { } end modules ['luaotfload-colors'] = {
- version = "2.7",
+ version = "2.8",
comment = "companion to luaotfload-main.lua (font color)",
author = "Khaled Hosny, Elie Roux, Philipp Gesang, Dohyun Kim, David Carlisle",
copyright = "Luaotfload Development Team",
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-configuration.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-configuration.lua
index c707b63588a..2f4589b10d0 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-configuration.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-configuration.lua
@@ -2,14 +2,14 @@
-------------------------------------------------------------------------------
-- FILE: luaotfload-configuration.lua
-- DESCRIPTION: config file reader
--- REQUIREMENTS: Luaotfload 2.7 or above
+-- REQUIREMENTS: Luaotfload 2.8 or above
-- AUTHOR: Philipp Gesang, <phg@phi-gamma.net>
-- AUTHOR: Dohyun Kim <nomosnomos@gmail.com>
-------------------------------------------------------------------------------
--
if not modules then modules = { } end modules ["luaotfload-configuration"] = {
- version = "2.7",
+ version = "2.8",
comment = "part of Luaotfload",
author = "Philipp Gesang, Dohyun Kim",
copyright = "Luaotfload Development Team",
@@ -203,7 +203,7 @@ local default_config = {
update_live = true,
compress = true,
max_fonts = 2^51,
- use_fontforge = false,
+ designsize_dimen= "bp",
},
run = {
anon_sequence = default_anon_sequence,
@@ -315,6 +315,18 @@ local set_font_filter = function ()
return true
end
+local set_size_dimension = function ()
+ local names = fonts.names
+ if names and names.set_size_dimension then
+ local dim = config.luaotfload.db.designsize_dimen
+ if not dim or dim == "" then
+ dim = default_config.db.designsize_dimen
+ end
+ names.set_size_dimension (dim)
+ end
+ return true
+end
+
local set_name_resolver = function ()
local names = fonts.names
if names and names.resolve_cached then
@@ -378,29 +390,14 @@ local set_default_features = function ()
return true
end
-local set_fontforge = function ()
- local names = fonts.names
- if not names or not names.use_fontforge then
- --- happens normally on the first run
- logreport ("log", 4, "db", "Database not present.")
- return true
- end
- local use_ff = config.luaotfload.db.use_fontforge
- if use_ff == true then
- logreport ("both", 0, "db",
- "Fontforge loader was requested but not supported anymore.")
- end
- return true
-end
-
reconf_tasks = {
{ "Set the log level" , set_loglevel },
{ "Build cache paths" , build_cache_paths },
{ "Check terminal dimensions" , check_termwidth },
{ "Set the font filter" , set_font_filter },
+ { "Set design size dimension" , set_size_dimension },
{ "Install font name resolver", set_name_resolver },
{ "Set default features" , set_default_features },
- { "Set fontforge" , set_fontforge },
}
-------------------------------------------------------------------------------
@@ -499,7 +496,10 @@ local option_spec = {
out_t = number_t, --- TODO int_t from 5.3.x on
transform = tointeger,
},
- use_fontforge = { in_t = boolean_t, },
+ designsize_dimen = {
+ in_t = string_t,
+ out_t = string_t,
+ },
},
run = {
anon_sequence = {
@@ -716,14 +716,14 @@ local conf_footer = [==[
local formatters = {
db = {
- compress = { false, format_boolean },
- formats = { false, format_string },
- max_fonts = { false, format_integer },
- scan_local = { false, format_boolean },
- skip_read = { false, format_boolean },
- strip = { false, format_boolean },
- update_live = { false, format_boolean },
- use_fontforge = { false, format_boolean },
+ compress = { false, format_boolean },
+ designsize_dimen = { false, format_string },
+ formats = { false, format_string },
+ max_fonts = { false, format_integer },
+ scan_local = { false, format_boolean },
+ skip_read = { false, format_boolean },
+ strip = { false, format_boolean },
+ update_live = { false, format_boolean },
},
default_features = {
__default = { true, format_keyval },
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-database.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-database.lua
index 3688c3a73f2..621a24ba11d 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-database.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-database.lua
@@ -1,5 +1,5 @@
if not modules then modules = { } end modules ['luaotfload-database'] = {
- version = "2.7",
+ version = "2.8",
comment = "companion to luaotfload-main.lua",
author = "Khaled Hosny, Elie Roux, Philipp Gesang",
copyright = "Luaotfload Development Team",
@@ -111,7 +111,7 @@ if not modules then modules = { } end modules ['luaotfload-database'] = {
--doc]]--
local lpeg = require "lpeg"
-local P, Cc, lpegmatch = lpeg.P, lpeg.Cc, lpeg.match
+local P, lpegmatch = lpeg.P, lpeg.match
local log = luaotfload.log
local logreport = log and log.report or print -- overriden later on
@@ -162,7 +162,6 @@ local tablesort = table.sort
local utf8gsub = unicode.utf8.gsub
local utf8lower = unicode.utf8.lower
local utf8len = unicode.utf8.len
-local zlibcompress = zlib.compress
--- these come from Lualibs/Context
local filebasename = file.basename
@@ -520,7 +519,7 @@ load_names = function (dry_run, no_rebuild)
names_version = names.version
if db_version ~= names_version then
logreport ("both", 0, "db",
- [[Version mismatch; expected %4.3f, got %4.3f.]],
+ [[Version mismatch; expected %d, got %d.]],
names_version, db_version)
if not fonts_reloaded then
logreport ("both", 0, "db", [[Force rebuild.]])
@@ -891,8 +890,9 @@ end
--[[doc--
- choose_size -- Pick a font face of appropriate size from the list
- of family members with matching style. There are three categories:
+ choose_size -- Pick a font face of appropriate size (in sp) from
+ the list of family members with matching style. There are three
+ categories:
1. exact matches: if there is a face whose design size equals
the asked size, it is returned immediately and no further
@@ -1042,6 +1042,35 @@ local lookup_fontname = function (specification, name, style)
return nil, nil
end
+local design_size_dimension
+local set_size_dimension
+do
+
+ --- cf. TeXbook p. 57
+ local dimens = {
+ pt = function (v) return v end,
+ bp = function (v) return (v * 7200) / 7227 end,
+ dd = function (v) return (v * 1157) / 1238 end,
+ }
+
+ design_size_dimension = dimens.bp
+
+ set_size_dimension = function (dim)
+ local f = dimens [dim]
+ if f then
+ logreport ("both", 4, "db",
+ "Interpreting design sizes as %q, factor %.6f.",
+ dim, f (1.000000))
+ design_size_dimension = f
+ return
+ end
+ logreport ("both", 0, "db",
+ "Invalid dimension %q requested for design sizes; \z
+ ignoring.")
+ end
+end
+
+
--[[doc--
lookup_font_name -- Perform a name: lookup. This first queries the
@@ -1099,15 +1128,14 @@ lookup_font_name = function (specification)
local askedsize = specification.optsize
if askedsize then
- askedsize = tonumber (askedsize)
+ askedsize = tonumber (askedsize) * 65536
else
askedsize = specification.size
- if askedsize and askedsize >= 0 then
- askedsize = askedsize / 65536
- else
+ if not askedsize or askedsize < 0 then
askedsize = 0
end
end
+ askedsize = design_size_dimension (askedsize)
resolved, subfont = lookup_familyname (specification,
name,
@@ -1322,28 +1350,35 @@ local load_font_file = function (filename, subfont)
return ret
end
---- rawdata -> (int * int * int | bool)
+local get_size_info do --- too many upvalues :/
+ --- rawdata -> (int * int * int | bool)
-local get_size_info = function (rawinfo)
- local design_size = rawinfo.design_size
- local design_range_top = rawinfo.design_range_top
- local design_range_bottom = rawinfo.design_range_bottom
+ get_size_info = function (rawinfo)
+ local design_size = rawinfo.design_size
+ local design_range_top = rawinfo.design_range_top
+ local design_range_bottom = rawinfo.design_range_bottom
- local fallback_size = design_size ~= 0 and design_size
- or design_range_bottom ~= 0 and design_range_bottom
- or design_range_top ~= 0 and design_range_top
+ local fallback_size = design_size ~= 0 and design_size
+ or design_range_bottom ~= 0 and design_range_bottom
+ or design_range_top ~= 0 and design_range_top
- if fallback_size then
- design_size = (design_size or fallback_size) / 10
- design_range_top = (design_range_top or fallback_size) / 10
- design_range_bottom = (design_range_bottom or fallback_size) / 10
- return {
- design_size, design_range_top, design_range_bottom,
- }
- end
+ if fallback_size then
+ design_size = ((design_size or fallback_size) * 2^16) / 10
+ design_range_top = ((design_range_top or fallback_size) * 2^16) / 10
+ design_range_bottom = ((design_range_bottom or fallback_size) * 2^16) / 10
- return false
-end
+ design_size = (design_size * 7200) / 7227
+ design_range_top = (design_range_top * 7200) / 7227
+ design_range_bottom = (design_range_bottom * 7200) / 7227
+
+ return {
+ design_size, design_range_top, design_range_bottom,
+ }
+ end
+
+ return false
+ end
+end ---[local get_size_info]
--[[doc--
map_enlish_names -- Names-table for Lua fontloader objects. This
@@ -1511,7 +1546,6 @@ end
local organize_styledata = function (metadata, rawinfo, info)
local pfminfo = metadata.pfminfo
local names = rawinfo.names
-
return {
--- see http://www.microsoft.com/typography/OTSPEC/features_pt.htm#size
size = get_size_info (rawinfo),
@@ -1914,7 +1948,7 @@ local create_blacklist = function (blacklist, whitelist)
if p_blacklist == nil then
--- always return false
- p_blacklist = Cc(false)
+ p_blacklist = lpeg.Cc(false)
end
return result
@@ -2553,6 +2587,7 @@ generate_filedata = function (mappings)
end
local bold_spectrum_low = 501 --- 500 is medium, 900 heavy/black
+local normal_weight = 400
local bold_weight = 700
local normal_width = 5
@@ -2605,13 +2640,19 @@ do
polluting the lookup table. What doesn’t work is, e. g.
treating weights > 500 as bold or allowing synonyms like
“heavy”, “black”.
- --]]--
- if width == normal_width and pfmweight == bold_weight then
- --- bold spectrum matches
- if italicangle == 0 then
- return "b"
+ --]]--
+ if width == normal_width then
+ if pfmweight == bold_weight then
+ --- bold spectrum matches
+ if italicangle == 0 then
+ return "b"
+ end
+ return "bi"
+ elseif pfmweight == normal_weight then
+ if italicangle ~= 0 then
+ return "i"
+ end
end
- return "bi"
end
return false
end
@@ -3506,11 +3547,55 @@ local show_cache = function ( )
end
-----------------------------------------------------------------------
+--- API assumptions of the fontloader
+-----------------------------------------------------------------------
+--- PHG: we need to investigate these, maybe they’re useful as early
+--- hooks
+
+local ignoredfile = function () return false end
+
+local reportmissingbase = function ()
+ logreport ("info", 0, "db", --> bug‽
+ "Font name database not found but expected by fontloader.")
+ fonts.names.reportmissingbase = nil
+end
+
+local reportmissingname = function ()
+ logreport ("info", 0, "db", --> bug‽
+ "Fontloader attempted to lookup name before Luaotfload \z
+ was initialized.")
+ fonts.names.reportmissingname = nil
+end
+
+local getfilename = function (a1, a2)
+ logreport ("info", 6, "db", --> bug‽
+ "Fontloader looked up font file (%s, %s) before Luaotfload \z
+ was initialized.", tostring(a1), tostring(a2))
+ return lookup_fullpath (a1, a2)
+end
+
+local resolve = function (name, subfont)
+ logreport ("info", 6, "db", --> bug‽
+ "Fontloader attempted to resolve name (%s, %s) before \z
+ Luaotfload was initialized.", tostring(name), tostring(subfont))
+ return lookup_font_name { name = name, sub = subfont }
+end
+
+local api = {
+ ignoredfile = ignoredfile,
+ reportmissingbase = reportmissingbase,
+ reportmissingname = reportmissingname,
+ getfilename = getfilename,
+ resolve = resolve,
+}
+
+-----------------------------------------------------------------------
--- export functionality to the namespace “fonts.names”
-----------------------------------------------------------------------
local export = {
set_font_filter = set_font_filter,
+ set_size_dimension = set_size_dimension,
flush_lookup_cache = flush_lookup_cache,
save_lookups = save_lookups,
load = load_names,
@@ -3535,8 +3620,6 @@ local export = {
erase_cache = erase_cache,
show_cache = show_cache,
find_closest = find_closest,
- --- transitionary
- use_fontforge = false,
}
return {
@@ -3552,11 +3635,12 @@ return {
fonts.definers = fonts.definers or { resolvers = { } }
names.blacklist = blacklist
- names.version = 2.9
+ names.version = 4 --- increase monotonically
names.data = nil --- contains the loaded database
names.lookups = nil --- contains the lookup cache
for sym, ref in next, export do names[sym] = ref end
+ for sym, ref in next, api do names[sym] = names[sym] or ref end
return true
end
}
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-features.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-features.lua
index b6e889ec033..a57aac3ea6f 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-features.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-features.lua
@@ -1,5 +1,5 @@
if not modules then modules = { } end modules ["features"] = {
- version = "2.7",
+ version = "2.8",
comment = "companion to luaotfload-main.lua",
author = "Hans Hagen, Khaled Hosny, Elie Roux, Philipp Gesang",
copyright = "PRAGMA ADE / ConTeXt Development Team",
@@ -9,7 +9,6 @@ if not modules then modules = { } end modules ["features"] = {
local type = type
local next = next
local tonumber = tonumber
-local tostring = tostring
local lpeg = require "lpeg"
local lpegmatch = lpeg.match
@@ -20,16 +19,14 @@ local C = lpeg.C
local table = table
local tabletohash = table.tohash
local tablesort = table.sort
-local setmetatableindex = table.setmetatableindex
-local insert = table.insert
----[[ begin included font-ltx.lua ]]
--- this appears to be based in part on luatex-fonts-def.lua
local fonts = fonts
local definers = fonts.definers
local handlers = fonts.handlers
local fontidentifiers = fonts.hashes and fonts.hashes.identifiers
+local otf = handlers.otf
local config = config or { luaotfload = { run = { } } }
@@ -37,35 +34,25 @@ local as_script = true
local normalize = function () end
if config.luaotfload.run.live ~= false then
- normalize = handlers.otf.features.normalize
+ normalize = otf.features.normalize
as_script = false
end
---HH A bit of tuning for definitions.
-
-if fonts.constructors then
- fonts.constructors.namemode = "specification" -- somehow latex needs this (changed name!) => will change into an overload
-end
-
---[[HH--
+--[[HH (font-xtx) --
tricky: we sort of bypass the parser and directly feed all into
the sub parser
--HH]]--
-function fonts.definers.getspecification(str)
+function definers.getspecification(str)
return "", str, "", ":", str
end
local log = luaotfload.log
local report = log.report
-local stringfind = string.find
-local stringlower = string.lower
local stringgsub = string.gsub
-local stringsub = string.sub
local stringformat = string.format
local stringis_empty = string.is_empty
-local mathceil = math.ceil
local cmp_by_idx = function (a, b) return a.idx < b.idx end
@@ -1256,15 +1243,18 @@ local handle_request = function (specification)
specification.features = features
end
features.normal = normalize (request.features)
- local subfont = tonumber (specification.sub)
+ local subfont = tonumber (request.sub)
if subfont and subfont >= 0 then
specification.sub = subfont + 1
+ else
+ specification.sub = false
end
return specification
end
fonts.names.handle_request = handle_request
+
if as_script == true then --- skip the remainder of the file
report ("log", 5, "features",
"Exiting early from luaotfload-features.lua.")
@@ -1275,543 +1265,9 @@ else
registersplit ("", handle_request, "xetex path style") -- catches \font\text=[names]
end
----[[ end included font-ltx.lua ]]
-
-- We assume that the other otf stuff is loaded already; though there’s
-- another check below during the initialization phase.
----[[ begin snippet from font-otc.lua ]]
-local trace_loading = false trackers.register("otf.loading", function(v) trace_loading = v end)
-local report_otf = logs.reporter("fonts","otf loading")
-
---[[HH--
-
- In the userdata interface we can not longer tweak the loaded font as
- conveniently as before. For instance, instead of pushing extra data in
- in the table using the original structure, we now have to operate on
- the mkiv representation. And as the fontloader interface is modelled
- after fontforge we cannot change that one too much either.
-
---HH]]--
-
---- start locals for addfeature()
-
-local utf8 = unicode.utf8
-local utfbyte = utf8.byte
-local utflen = utf8.len
-
-local otf = handlers and handlers.otf --- filled in later during initialization
-
-local normalized = {
- substitution = "substitution",
- single = "substitution",
- ligature = "ligature",
- alternate = "alternate",
- multiple = "multiple",
- kern = "kern",
- pair = "pair",
- chainsubstitution = "chainsubstitution",
- chainposition = "chainposition",
-}
-
-local types = {
- substitution = "gsub_single",
- ligature = "gsub_ligature",
- alternate = "gsub_alternate",
- multiple = "gsub_multiple",
- kern = "gpos_pair",
- pair = "gpos_pair",
- chainsubstitution = "gsub_contextchain",
- chainposition = "gpos_contextchain",
-}
-
-setmetatableindex(types, function(t,k) t[k] = k return k end) -- "key"
-
---- stop locals for addfeature()
-
-local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } }
-local noflags = { false, false, false, false }
-
-local tohash = table.tohash
-
-local function current_addfeature(data,feature,specifications)
- local descriptions = data.descriptions
- local resources = data.resources
- local features = resources.features
- local sequences = resources.sequences
- if not features or not sequences then
- return
- end
- -- feature has to be unique but the name entry wins eventually
-
- local fontfeatures = resources.features or everywhere
- local unicodes = resources.unicodes
- local splitter = lpeg.splitter(" ",unicodes)
- local done = 0
- local skip = 0
- local aglunicodes = false
-
- if not specifications[1] then
- -- so we accept a one entry specification
- specifications = { specifications }
- end
-
- local function tounicode(code)
- if not code then
- return
- end
- if type(code) == "number" then
- return code
- end
- local u = unicodes[code]
- if u then
- return u
- end
- if utflen(code) == 1 then
- u = utfbyte(code)
- if u then
- return u
- end
- end
- if not aglunicodes then
- aglunicodes = fonts.encodings.agl.unicodes -- delayed
- end
- return aglunicodes[code]
- end
-
- local coverup = otf.coverup
- local coveractions = coverup.actions
- local stepkey = coverup.stepkey
- local register = coverup.register
-
- local function prepare_substitution(list,featuretype)
- local coverage = { }
- local cover = coveractions[featuretype]
- for code, replacement in next, list do
- local unicode = tounicode(code)
- local description = descriptions[unicode]
- if description then
- if type(replacement) == "table" then
- replacement = replacement[1]
- end
- replacement = tounicode(replacement)
- if replacement and descriptions[replacement] then
- cover(coverage,unicode,replacement)
- done = done + 1
- else
- skip = skip + 1
- end
- else
- skip = skip + 1
- end
- end
- return coverage
- end
-
- local function prepare_alternate(list,featuretype)
- local coverage = { }
- local cover = coveractions[featuretype]
- for code, replacement in next, list do
- local unicode = tounicode(code)
- local description = descriptions[unicode]
- if not description then
- skip = skip + 1
- elseif type(replacement) == "table" then
- local r = { }
- for i=1,#replacement do
- local u = tounicode(replacement[i])
- r[i] = descriptions[u] and u or unicode
- end
- cover(coverage,unicode,r)
- done = done + 1
- else
- local u = tounicode(replacement)
- if u then
- cover(coverage,unicode,{ u })
- done = done + 1
- else
- skip = skip + 1
- end
- end
- end
- return coverage
- end
-
- local function prepare_multiple(list,featuretype)
- local coverage = { }
- local cover = coveractions[featuretype]
- for code, replacement in next, list do
- local unicode = tounicode(code)
- local description = descriptions[unicode]
- if not description then
- skip = skip + 1
- elseif type(replacement) == "table" then
- local r, n = { }, 0
- for i=1,#replacement do
- local u = tounicode(replacement[i])
- if descriptions[u] then
- n = n + 1
- r[n] = u
- end
- end
- if n > 0 then
- cover(coverage,unicode,r)
- done = done + 1
- else
- skip = skip + 1
- end
- else
- local u = tounicode(replacement)
- if u then
- cover(coverage,unicode,{ u })
- done = done + 1
- else
- skip = skip + 1
- end
- end
- end
- return coverage
- end
-
- local function prepare_ligature(list,featuretype)
- local coverage = { }
- local cover = coveractions[featuretype]
- for code, ligature in next, list do
- local unicode = tounicode(code)
- local description = descriptions[unicode]
- if description then
- if type(ligature) == "string" then
- ligature = { lpegmatch(splitter,ligature) }
- end
- local present = true
- for i=1,#ligature do
- local l = ligature[i]
- local u = tounicode(l)
- if descriptions[u] then
- ligature[i] = u
- else
- present = false
- break
- end
- end
- if present then
- cover(coverage,unicode,ligature)
- done = done + 1
- else
- skip = skip + 1
- end
- else
- skip = skip + 1
- end
- end
- return coverage
- end
-
- local function prepare_kern(list,featuretype)
- local coverage = { }
- local cover = coveractions[featuretype]
- for code, replacement in next, list do
- local unicode = tounicode(code)
- local description = descriptions[unicode]
- if description and type(replacement) == "table" then
- local r = { }
- for k, v in next, replacement do
- local u = tounicode(k)
- if u then
- r[u] = v
- end
- end
- if next(r) then
- cover(coverage,unicode,r)
- done = done + 1
- else
- skip = skip + 1
- end
- else
- skip = skip + 1
- end
- end
- return coverage
- end
-
- local function prepare_pair(list,featuretype)
- local coverage = { }
- local cover = coveractions[featuretype]
- if cover then
- for code, replacement in next, list do
- local unicode = tounicode(code)
- local description = descriptions[unicode]
- if description and type(replacement) == "table" then
- local r = { }
- for k, v in next, replacement do
- local u = tounicode(k)
- if u then
- r[u] = v
- end
- end
- if next(r) then
- cover(coverage,unicode,r)
- done = done + 1
- else
- skip = skip + 1
- end
- else
- skip = skip + 1
- end
- end
- else
- report_otf("unknown cover type %a",featuretype)
- end
- return coverage
- end
-
- local function prepare_chain(list,featuretype,sublookups)
- -- todo: coveractions
- local rules = list.rules
- local coverage = { }
- if rules then
- local rulehash = { }
- local rulesize = 0
- local sequence = { }
- local nofsequences = 0
- local lookuptype = types[featuretype]
- for nofrules=1,#rules do
- local rule = rules[nofrules]
- local current = rule.current
- local before = rule.before
- local after = rule.after
- local replacements = rule.replacements or false
- local sequence = { }
- local nofsequences = 0
- if before then
- for n=1,#before do
- nofsequences = nofsequences + 1
- sequence[nofsequences] = before[n]
- end
- end
- local start = nofsequences + 1
- for n=1,#current do
- nofsequences = nofsequences + 1
- sequence[nofsequences] = current[n]
- end
- local stop = nofsequences
- if after then
- for n=1,#after do
- nofsequences = nofsequences + 1
- sequence[nofsequences] = after[n]
- end
- end
- local lookups = rule.lookups or false
- local subtype = nil
- if lookups and sublookups then
- for k, v in next, lookups do
- local lookup = sublookups[v]
- if lookup then
- lookups[k] = lookup
- if not subtype then
- subtype = lookup.type
- end
- else
- -- already expanded
- end
- end
- end
- if nofsequences > 0 then -- we merge coverage into one
- -- we copy as we can have different fonts
- local hashed = { }
- for i=1,nofsequences do
- local t = { }
- local s = sequence[i]
- for i=1,#s do
- local u = tounicode(s[i])
- if u then
- t[u] = true
- end
- end
- hashed[i] = t
- end
- sequence = hashed
- -- now we create the rule
- rulesize = rulesize + 1
- rulehash[rulesize] = {
- nofrules, -- 1
- lookuptype, -- 2
- sequence, -- 3
- start, -- 4
- stop, -- 5
- lookups, -- 6 (6/7 also signal of what to do)
- replacements, -- 7
- subtype, -- 8
- }
- for unic in next, sequence[start] do
- local cu = coverage[unic]
- if not cu then
- coverage[unic] = rulehash -- can now be done cleaner i think
- end
- end
- end
- end
- end
- return coverage
- end
-
- for s=1,#specifications do
- local specification = specifications[s]
- local valid = specification.valid
- local feature = specification.name or feature
- if not valid or valid(data,specification,feature) then
- local initialize = specification.initialize
- if initialize then
- -- when false is returned we initialize only once
- specification.initialize = initialize(specification,data) and initialize or nil
- end
- local askedfeatures = specification.features or everywhere
- local askedsteps = specification.steps or specification.subtables or { specification.data } or { }
- local featuretype = normalized[specification.type or "substitution"] or "substitution"
- local featureflags = specification.flags or noflags
- local featureorder = specification.order or { feature }
- local featurechain = (featuretype == "chainsubstitution" or featuretype == "chainposition") and 1 or 0
- local nofsteps = 0
- local steps = { }
- local sublookups = specification.lookups
- local category = nil
- if sublookups then
- local s = { }
- for i=1,#sublookups do
- local specification = sublookups[i]
- local askedsteps = specification.steps or specification.subtables or { specification.data } or { }
- local featuretype = normalized[specification.type or "substitution"] or "substitution"
- local featureflags = specification.flags or noflags
- local nofsteps = 0
- local steps = { }
- for i=1,#askedsteps do
- local list = askedsteps[i]
- local coverage = nil
- local format = nil
- if featuretype == "substitution" then
- coverage = prepare_substitution(list,featuretype)
- elseif featuretype == "ligature" then
- coverage = prepare_ligature(list,featuretype)
- elseif featuretype == "alternate" then
- coverage = prepare_alternate(list,featuretype)
- elseif featuretype == "multiple" then
- coverage = prepare_multiple(list,featuretype)
- elseif featuretype == "kern" then
- format = "kern"
- coverage = prepare_kern(list,featuretype)
- elseif featuretype == "pair" then
- format = "pair"
- coverage = prepare_pair(list,featuretype)
- end
- if coverage and next(coverage) then
- nofsteps = nofsteps + 1
- steps[nofsteps] = register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
- end
- end
- s[i] = {
- [stepkey] = steps,
- nofsteps = nofsteps,
- type = types[featuretype],
- }
- end
- sublookups = s
- end
- for i=1,#askedsteps do
- local list = askedsteps[i]
- local coverage = nil
- local format = nil
- if featuretype == "substitution" then
- category = "gsub"
- coverage = prepare_substitution(list,featuretype)
- elseif featuretype == "ligature" then
- category = "gsub"
- coverage = prepare_ligature(list,featuretype)
- elseif featuretype == "alternate" then
- category = "gsub"
- coverage = prepare_alternate(list,featuretype)
- elseif featuretype == "multiple" then
- category = "gsub"
- coverage = prepare_multiple(list,featuretype)
- elseif featuretype == "kern" then
- category = "gpos"
- format = "kern"
- coverage = prepare_kern(list,featuretype)
- elseif featuretype == "pair" then
- category = "gpos"
- format = "pair"
- coverage = prepare_pair(list,featuretype)
- elseif featuretype == "chainsubstitution" then
- category = "gsub"
- coverage = prepare_chain(list,featuretype,sublookups)
- elseif featuretype == "chainposition" then
- category = "gpos"
- coverage = prepare_chain(list,featuretype,sublookups)
- else
- report_otf("not registering feature %a, unknown category",feature)
- return
- end
- if coverage and next(coverage) then
- nofsteps = nofsteps + 1
- steps[nofsteps] = register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
- end
- end
- if nofsteps > 0 then
- -- script = { lang1, lang2, lang3 } or script = { lang1 = true, ... }
- for k, v in next, askedfeatures do
- if v[1] then
- askedfeatures[k] = tohash(v)
- end
- end
- if featureflags[1] then featureflags[1] = "mark" end
- if featureflags[2] then featureflags[2] = "ligature" end
- if featureflags[3] then featureflags[3] = "base" end
- local sequence = {
- chain = featurechain,
- features = { [feature] = askedfeatures },
- flags = featureflags,
- name = feature, -- redundant
- order = featureorder,
- [stepkey] = steps,
- nofsteps = nofsteps,
- type = types[featuretype],
- }
- -- todo : before|after|index
- if specification.prepend then
- insert(sequences,1,sequence)
- else
- insert(sequences,sequence)
- end
- -- register in metadata (merge as there can be a few)
- local features = fontfeatures[category]
- if not features then
- features = { }
- fontfeatures[category] = features
- end
- local k = features[feature]
- if not k then
- k = { }
- features[feature] = k
- end
- --
- for script, languages in next, askedfeatures do
- local kk = k[script]
- if not kk then
- kk = { }
- k[script] = kk
- end
- for language, value in next, languages do
- kk[language] = value
- end
- end
- end
- end
- end
- if trace_loading then
- report_otf("registering feature %a, affected glyphs %a, skipped glyphs %a",feature,done,skip)
- end
-end
-
----[[ end snippet from font-otc.lua ]]
local tlig_specification = {
{
@@ -1861,64 +1317,6 @@ local tlig_specification = {
},
}
-local anum_arabic = { --- these are the same as in font-otc
- [0x0030] = 0x0660,
- [0x0031] = 0x0661,
- [0x0032] = 0x0662,
- [0x0033] = 0x0663,
- [0x0034] = 0x0664,
- [0x0035] = 0x0665,
- [0x0036] = 0x0666,
- [0x0037] = 0x0667,
- [0x0038] = 0x0668,
- [0x0039] = 0x0669,
-}
-
-local anum_persian = {--- these are the same as in font-otc
- [0x0030] = 0x06F0,
- [0x0031] = 0x06F1,
- [0x0032] = 0x06F2,
- [0x0033] = 0x06F3,
- [0x0034] = 0x06F4,
- [0x0035] = 0x06F5,
- [0x0036] = 0x06F6,
- [0x0037] = 0x06F7,
- [0x0038] = 0x06F8,
- [0x0039] = 0x06F9,
-}
-
-local function valid(data)
- local features = data.resources.features
- if features then
- for k, v in next, features do
- for k, v in next, v do
- if v.arab then
- return true
- end
- end
- end
- end
-end
-
-local anum_specification = {
- {
- type = "substitution",
- features = { arab = { far = true, urd = true, snd = true } },
- data = anum_persian,
- flags = noflags,
- order = { "anum" },
- valid = valid,
- },
- {
- type = "substitution",
- features = { arab = { ["*"] = true } },
- data = anum_arabic,
- flags = noflags,
- order = { "anum" },
- valid = valid,
- },
-}
-
local rot13_specification = {
type = "substitution",
features = everywhere,
@@ -1942,50 +1340,27 @@ local rot13_specification = {
prepend = true,
}
-local extrafeatures = {
- tlig = { tlig_specification, "tex ligatures and substitutions" },
- anum = { anum_specification, "arabic numerals" },
- rot13 = { rot13_specification, "rot13" },
+local interrolig_specification = {
+ { type = "ligature", data = { [0x203d] = {0x21, 0x3f}, [0x2e18] = {0xa1, 0xbf}, }, },
+ { type = "ligature", data = { [0x203d] = {0x3f, 0x21}, [0x2e18] = {0xbf, 0xa1}, }, },
}
-function add_otf_feature (name, specification)
- if type (name) == "table" then
- specification = name
- name = specification.name
- end
- if type (name) == "string" then
- extrafeatures[name] = specification
- end
-end
-
-otf.addfeature = add_otf_feature
+local autofeatures = {
+ --- always present with Luaotfload; anum for Arabic and Persian is
+ --- predefined in font-otc.
+ { "tlig" , tlig_specification , "tex ligatures and substitutions" },
+ { "rot13", rot13_specification, "rot13" },
+ { "!!??", interrolig_specification, "interrobang substitutions" },
+}
-local install_extra_features = function (data, filename, raw)
- local metadata = data and data.metadata
- if not metadata then
- logreport ("both", 4, "features",
- "no metadata received from font “%s”; not \z
- installing extra features.", filename)
- return
- end
- local format = data.format
- if not format then
- logreport ("both", 4, "features",
- "no format info for font “%s”/“%s”; not \z
- installing extra features.",
- fontname, filename)
- return
- end
- for feature, specification in next, extrafeatures do
- if not fontname then fontname = "<unknown>" end
- if not subfont then subfont = -1 end
- local fontname = tostring (data.metadata.fontname) or "<unknown>"
- local subfont = tonumber (metadata.subfontindex) or -1
- logreport ("both", 3, "features",
- "register synthetic feature “%s” for %s font “%s”(%d)",
- feature, format, fontname, subfont)
- otf.features.register { name = feature, description = specification[2] }
- otf.enhancers.addfeature (data, feature, specification[1])
+local add_auto_features = function ()
+ local nfeats = #autofeatures
+ logreport ("both", 5, "features",
+ "auto-installing %d feature definitions", nfeats)
+ for i = 1, nfeats do
+ local name, spec, desc = unpack (autofeatures [i])
+ spec.description = desc
+ otf.addfeature (name, spec)
end
end
@@ -2001,10 +1376,7 @@ return {
return false
end
- otf = fonts.handlers.otf
- otf.enhancers.addfeature = current_addfeature
- otf.enhancers.register ("check extra features",
- install_extra_features)
+ add_auto_features ()
return true
end
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-glyphlist.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-glyphlist.lua
index 60afd7230a3..55d629c833e 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-glyphlist.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-glyphlist.lua
@@ -2,7 +2,7 @@ if not modules then modules = { } end modules ["font-age"] = {
version = 2.400,
comment = "part of the luaotfload package",
author = "luaotfload team / mkglyphlist",
- copyright = "derived from http://partners.adobe.com/public/developer/en/opentype/glyphlist.txt",
+ copyright = "derived from https://raw.githubusercontent.com/adobe-type-tools/agl-aglfn/master/glyphlist.txt",
original = "Adobe Glyph List, version 2.0, September 20, 2002",
dataonly = true,
}
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-init.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-init.lua
index c977b498071..ad18b321c5e 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-init.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-init.lua
@@ -251,7 +251,6 @@ local context_modules = {
{ ctx, "font-cid" },
{ ctx, "font-map" },
{ ltx, "luatex-fonts-syn" },
- { ctx, "font-tfm" },
{ ctx, "font-oti" },
{ ctx, "font-otr" },
{ ctx, "font-cff" },
@@ -265,9 +264,11 @@ local context_modules = {
{ ctx, "font-ots" },
{ ctx, "font-osd" },
{ ctx, "font-ocl" },
+ { ctx, "font-otc" },
{ ctx, "font-onr" },
{ ctx, "font-one" },
{ ctx, "font-afk" },
+ { ctx, "font-tfm" },
{ ctx, "font-lua" },
{ ctx, "font-def" },
{ ltx, "luatex-fonts-ext" },
@@ -531,7 +532,6 @@ local init_main = function ()
load_fontloader_module "font-cid"
load_fontloader_module "font-map"
load_fontloader_module "fonts-syn"
- load_fontloader_module "font-tfm"
load_fontloader_module "font-oti"
load_fontloader_module "font-otr"
load_fontloader_module "font-cff"
@@ -548,6 +548,7 @@ local init_main = function ()
load_fontloader_module "font-onr"
load_fontloader_module "font-one"
load_fontloader_module "font-afk"
+ load_fontloader_module "font-tfm"
load_fontloader_module "font-lua"
load_fontloader_module "font-def"
load_fontloader_module "fonts-ext"
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua
index 78df1d79ba1..fd64c90a4b8 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua
@@ -1,5 +1,5 @@
if not modules then modules = { } end modules ['letterspace'] = {
- version = "2.7",
+ version = "2.8",
comment = "companion to luaotfload-main.lua",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL; adapted by Philipp Gesang",
copyright = "PRAGMA ADE / ConTeXt Development Team",
@@ -61,7 +61,11 @@ local todirect = nodedirect.tonut
local tonode = nodedirect.tonode
local insert_node_before = nodedirect.insert_before
-local free_node = nodedirect.free
+local free_node = nodedirect.free -- may cause double free
+local free_node = function (n)
+ logreport ("term", 5, "letterspace", "not calling free_node(%d)", n)
+ -- free_node (n)
+end
local copy_node = nodedirect.copy
local new_node = nodedirect.new
@@ -348,7 +352,7 @@ kerncharacters = function (head)
end
start = c
setfield(s, "components", nil)
- --free_node(s) --> double free with multipart components
+ free_node(s) --> double free with multipart components
c = getfield (start, "components")
end
end
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-loaders.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-loaders.lua
index 68cc50f6204..87275ef2d8e 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-loaders.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-loaders.lua
@@ -49,23 +49,8 @@ local unsupported_reader = function (format)
end
end
-local afm_reader = fonts.readers.afm
-
-local afm_loader = function (specification)
- specification.forced = "afm"
- specification.sub = false
- specification.forcedname = file.addsuffix(specification.name, "afm")
- inspect(specification)
- return afm_reader (specification, "afm")
-end
-
-local afm_compat_message = function (specification)
- logreport ("both", 4, "loaders",
- "PFB format only supported with matching \z
- AFM; redirecting (“%s”, “afm”).",
- tostring (specification.name))
- return afm_loader (specification)
-end
+local type1_reader = fonts.readers.afm
+local tfm_reader = fonts.readers.tfm
local install_formats = function ()
local fonts = fonts
@@ -97,9 +82,10 @@ local install_formats = function ()
return aux ("evl", eval_reader)
and aux ("lua", lua_reader)
and aux ("pfa", unsupported_reader "pfa")
- and aux ("afm", afm_loader)
- and aux ("pfb", afm_compat_message) --- pfb loader is incomplete
- and aux ("ofm", readers.tfm)
+ and aux ("afm", type1_reader)
+ and aux ("pfb", type1_reader)
+ and aux ("tfm", tfm_reader)
+ and aux ("ofm", tfm_reader)
and aux ("dfont", unsupported_reader "dfont")
end
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-log.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-log.lua
index 5b2f1f36776..ab38ffaac14 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-log.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-log.lua
@@ -1,5 +1,5 @@
if not modules then modules = { } end modules ["luaotfload-log"] = {
- version = "2.7",
+ version = "2.8",
comment = "companion to Luaotfload",
author = "Khaled Hosny, Elie Roux, Philipp Gesang",
copyright = "Luaotfload Development Team",
@@ -14,6 +14,7 @@ because we lack a user interface to toggle per-subsystem tracing.
--doc]]--
local module_name = "luaotfload" --- prefix for messages
+local debug = debug
luaotfload = luaotfload or { }
luaotfload.log = luaotfload.log or { }
@@ -132,10 +133,33 @@ end
log.set_logout = set_logout
+local format_error_handler
+if debug then
+ local debugtraceback = debug.traceback
+ format_error_handler = function (err)
+ print ""
+ print (stringformat ("luaotfload error: %q", err))
+ print (stringformat ("Lua interpreter %s", debugtraceback ()))
+ print ""
+ end
+else
+ format_error_handler = function (err)
+ print ""
+ print (stringformat ("luaotfload error: %q", err))
+ print "Lua debug module not available; please enable for a backtrace"
+ print ""
+ end
+end
+
local basic_logger = function (category, fmt, ...)
- local res = { module_name, "|", category, ":" }
+ local res = { module_name, "|", category or "UNKNOWN", ":" }
if fmt then
- res [#res + 1] = stringformat (fmt, ...)
+ local ok, val = xpcall (stringformat, format_error_handler, fmt, ...)
+ if ok then
+ res [#res + 1] = val
+ else
+ res [#res + 1] = stringformat ("ERROR: %q", val)
+ end
end
texiowrite_nl (logout, tableconcat(res, " "))
end
@@ -354,4 +378,4 @@ local texioreporter = function (message)
end
texio.reporter = texioreporter
-
+--- vim:shiftwidth=4:expandtab:ft=lua
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-main.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-main.lua
index 271e4ccf9b0..14d531683a2 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-main.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-main.lua
@@ -1,7 +1,7 @@
-----------------------------------------------------------------------
-- FILE: luaotfload-main.lua
-- DESCRIPTION: Luaotfload entry point
--- REQUIREMENTS: luatex v.0.95 or later; packages lualibs
+-- REQUIREMENTS: luatex v.0.95.0 or later; package lualibs
-- AUTHOR: Élie Roux, Khaled Hosny, Philipp Gesang
-----------------------------------------------------------------------
--
@@ -11,9 +11,9 @@ config = config or { }
luaotfload = luaotfload or { }
local luaotfload = luaotfload
luaotfload.log = luaotfload.log or { }
-luaotfload.version = "2.7"
+luaotfload.version = "2.8"
luaotfload.loaders = { }
-luaotfload.min_luatex_version = { 0, 95, 0 } --- i. e. 0.95.0
+luaotfload.min_luatex_version = { 0, 95, 0 }
luaotfload.fontloader_package = "reference" --- default: from current Context
if not tex or not tex.luatexversion then
@@ -25,8 +25,10 @@ else
local revision = tex.luatexrevision --[[ : string ]]
local revno = tonumber (revision)
local minimum = luaotfload.min_luatex_version
- if major < minimum [1] or minor < minimum [2]
- or revno and revno < minimum [3]
+ local actual = { major, minor, revno or 0 }
+ if actual [1] < minimum [1]
+ or actual == minimum and actual [2] < minimum [2]
+ or actual == minimum and actual [2] == minimum [2] and actual [3] < minimum [3]
then
texio.write_nl ("term and log",
string.format ("\tFATAL ERROR\n\z
@@ -50,8 +52,8 @@ local authors = "\z
luaotfload.module = {
name = "luaotfload-main",
- version = 2.70003,
- date = "2016/06/16",
+ version = 2.80001,
+ date = "2017/01/29",
description = "OpenType layout system.",
author = authors,
copyright = authors,
@@ -244,8 +246,18 @@ local install_loaders = function ()
return loaders
end
+local luaotfload_initialized = false --- prevent multiple invocations
+
luaotfload.main = function ()
+ if luaotfload_initialized then
+ logreport ("log", 0, "load",
+ "Luaotfload initialization requested but is already \z
+ loaded, ignoring.")
+ return
+ end
+ luaotfload_initialized = true
+
luaotfload.loaders = install_loaders ()
local loaders = luaotfload.loaders
local loadmodule = loaders.luaotfload
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-parsers.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-parsers.lua
index 307c35cf524..ffb64010846 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-parsers.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-parsers.lua
@@ -2,7 +2,7 @@
-------------------------------------------------------------------------------
-- FILE: luaotfload-parsers.lua
-- DESCRIPTION: various lpeg-based parsers used in Luaotfload
--- REQUIREMENTS: Luaotfload >= 2.7
+-- REQUIREMENTS: Luaotfload >= 2.8
-- AUTHOR: Philipp Gesang (Phg), <phg@phi-gamma.net>
-------------------------------------------------------------------------------
--
@@ -623,7 +623,7 @@ local unprefixed = Cg(fontname, "anon")
local path_lookup = lbrk * Cg(C((1-rbrk)^1), "path") * rbrk
--- features ----------------------------------------------------------
-local field_char = anum + S"+-." --- sic!
+local field_char = anum + S"+-.!?" --- sic!
local field = field_char^1
--- assignments are “lhs=rhs”
--- or “+lhs=rhs” (Xetex-style)
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-resolvers.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-resolvers.lua
index a1e702b71b5..983d3fc6694 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-resolvers.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-resolvers.lua
@@ -173,6 +173,7 @@ local resolve_tex_format = function (specification)
local usename = suffix == format and fileremovesuffix (name) or name
specification.forcedname = file.addsuffix (usename, format)
specification.forced = format
+---- specification.resolved = name
return true
end
end
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-status.lua b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-status.lua
index 07f7f0b74fc..02c77bd93bc 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-status.lua
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-status.lua
@@ -1,85 +1,85 @@
return {
["hashes"]={
- { "fontloader-2016-06-16.lua", "c7cb6ba065c3c0484a6831afae68a511" },
- { "fontloader-util-fil.lua", "5b05af7415ab0f28cf0f37cb4bfaa0dd" },
- { "fontloader-util-str.lua", "5e01ba9afb7715cbf69aeebaa829e42a" },
- { "fontloader-swiglib-test.lua", "c1cdeff07e5b8896f7aa98ce50c31618" },
- { "fontloader-swiglib.lua", "3a350d89416637073b7f09e281dc7c11" },
+ { "fontloader-2017-01-29.lua", "36658a109ba00bf525c7746196f236c8" },
+ { "fontloader-util-fil.lua", "0573e91847e722ffe0fcdb465ba89e6b" },
+ { "fontloader-util-str.lua", "513836cfea6a8027c1451a95bc74649f" },
+ { "fontloader-swiglib-test.lua", "2f0b431faf53d3e19bfae22035bdc77e" },
+ { "fontloader-swiglib.lua", "c20138e09bfd743dba7de1d5421be4af" },
{ "fontloader-preprocessor.lua", "f87963c22d5523218f1beee7e315bae5" },
- { "fontloader-mplib.lua", "db9d22740880daaaeb10070599847558" },
+ { "fontloader-mplib.lua", "55ad1c7febc72c6700b49692c2384738" },
{ "fontloader-math.lua", "f7eda9d5922e4aa7bb858ba9943fdacd" },
- { "fontloader-l-table.lua", "c44995044ee3ccb00fccf1700881b2fa" },
- { "fontloader-l-string.lua", "64d08350c5083058de7ec3d25ae05047" },
+ { "fontloader-l-table.lua", "92978e5ea9ca13dae04fb606f5be4a1c" },
+ { "fontloader-l-string.lua", "2ca01eeb225c09e73ff4f3a2d101827a" },
{ "fontloader-l-math.lua", "51275e81c652e3fbd7d02b1c383d3049" },
- { "fontloader-l-lua.lua", "4029c8b48604bb8ad658095139d1db9a" },
+ { "fontloader-l-lua.lua", "5466b2db6d8cc3b9786a398bb4230ea1" },
{ "fontloader-l-lpeg.lua", "93b90b22d7d3600ddd9def9f3ad9a7bb" },
- { "fontloader-l-io.lua", "a3292f4dad2705c4eeb1d91c40bd0fde" },
+ { "fontloader-l-io.lua", "ee77e357f5965196f9559b8fcccc6e71" },
{ "fontloader-l-function.lua", "a7e68a9703c35238729da41a474e951b" },
- { "fontloader-l-file.lua", "e0af9d75d170a1f62386ed26eb7ad850" },
+ { "fontloader-l-file.lua", "32d9ba0a5cdd3509a3847bb050bfb800" },
{ "fontloader-l-boolean.lua", "abe28515dd33e8f6c416c09bca351cf8" },
{ "fontloader-languages.lua", "4e5bbdad336fa4969ac21a5242643a40" },
- { "fontloader-font-ocl.lua", "21d4db431ea76de6ca180d89f952616a" },
- { "fontloader-font-osd.lua", "5599b76874f4987032a207e1413ab98b" },
- { "fontloader-font-ots.lua", "e792a7e57659ced225ba311177709463" },
- { "fontloader-font-ota.lua", "9d8f76acfcfad35684429d0bb9006bc0" },
- { "fontloader-font-otj.lua", "eb5afafa4d57c53e2918a8dfcb442a0c" },
- { "fontloader-font-oto.lua", "ea9826b209beb09e82a16ec81404fb86" },
- { "fontloader-font-otl.lua", "eaab42986842ff8963114575dca6a6c6" },
- { "fontloader-font-oup.lua", "6f089eaae576d1dbaa46e134cfeba9c7" },
- { "fontloader-font-dsp.lua", "f9dc5739b0d203d3ed9db87269c13647" },
+ { "fontloader-font-otc.lua", "85d63e257c748c624768aa7c8ec7f0bc" },
+ { "fontloader-font-ocl.lua", "fbc00782e4efb24a7569f99cd1574ffb" },
+ { "fontloader-font-osd.lua", "10ecd4b375680b011e7c6a25e5ad74f7" },
+ { "fontloader-font-ots.lua", "7e1e55f9f728474372665e4a64a43f5a" },
+ { "fontloader-font-ota.lua", "c281d18dfc89a8ca18af64f55e9fa92b" },
+ { "fontloader-font-otj.lua", "5ea70db9f1990dc1459425853c79f663" },
+ { "fontloader-font-oto.lua", "5fbdd899624d4eef639f81b580afe9aa" },
+ { "fontloader-font-otl.lua", "2e7c8d9a331c46826211bd507f8e488a" },
+ { "fontloader-font-oup.lua", "f7237130b648a4c2b477dabedc7f90e8" },
+ { "fontloader-font-dsp.lua", "7eda319c53a28de9d91de4a0cfba79c3" },
{ "fontloader-font-ttf.lua", "e0893de6d0f3f421ee4386fa90429db8" },
- { "fontloader-font-cff.lua", "84590de32a9d3bcd1e3fee0bb667e9c2" },
- { "fontloader-font-otr.lua", "aaf9545b2a5d425489ebbcd3e398c1a0" },
- { "fontloader-font-tfm.lua", "5f60184464be0655620709c332065706" },
- { "fontloader-font-tfm.lua", "5f60184464be0655620709c332065706" },
+ { "fontloader-font-cff.lua", "f3fc74e8629f7a2825c34a34550c790d" },
+ { "fontloader-font-otr.lua", "2bd0085b78027f261218d63034f43474" },
+ { "fontloader-font-tfm.lua", "3d813578dbf6c447e4b859c2bf0618f7" },
{ "fontloader-fonts-syn.lua", "6753dfb9a28aad35266284bb00072dca" },
{ "fontloader-font-lua.lua", "1fbfdf7b689b2bdfd0e3bb9bf74ce136" },
- { "fontloader-fonts.lua", "c41db3c5241c7bf1d917626918b1da03" },
- { "fontloader-fonts-ext.lua", "52e620241ee991a687cf1ca8b8ee8de2" },
- { "fontloader-fonts-enc.lua", "b224fe179312d924ffaf8334cf5ef15b" },
- { "fontloader-fonts-demo-vf-1.lua", "edf37ece9bd112b1b13d9475528ab210" },
- { "fontloader-font-def.lua", "3c71c27300a8cb5c29f5d278d2049fb6" },
- { "fontloader-font-gbn.lua", "f7bc5e7bbc3b6e4f58fc6b0ab61bf77e" },
- { "fontloader-font-oti.lua", "7e7e749e6cb1c802a06397e8bed33b98" },
- { "fontloader-font-map.lua", "692066163d78ed09e7659eae72587b9a" },
+ { "fontloader-fonts.lua", "96e568c9b2ffa8108fb95d886bb2b645" },
+ { "fontloader-fonts-ext.lua", "aff3846f4c1f15de0a9f4fd7081e0c68" },
+ { "fontloader-fonts-enc.lua", "a7ace7c1969cd64a5ca9888838f3edb6" },
+ { "fontloader-fonts-demo-vf-1.lua", "7a4cb26eda4f1090d195114c10a33a75" },
+ { "fontloader-font-def.lua", "49fa2b50d8d2a1bb70b08b72f858ecd0" },
+ { "fontloader-font-gbn.lua", "b65b8a0b19cc1b870e4c0569a94d8825" },
+ { "fontloader-font-oti.lua", "8f48c06a1d632febd7231ad5dfadfc53" },
+ { "fontloader-font-map.lua", "8708bde7467785c4d3b7afdaf2f9333a" },
{ "fontloader-font-ini.lua", "10cb9a563a98e06ff79c35a8751e13dc" },
- { "fontloader-font-def.lua", "3c71c27300a8cb5c29f5d278d2049fb6" },
- { "fontloader-font-con.lua", "a8eafab28257eac082b1a8d184bb93f1" },
+ { "fontloader-font-def.lua", "49fa2b50d8d2a1bb70b08b72f858ecd0" },
+ { "fontloader-font-con.lua", "7575a7b4e6d04816072945e27d7d0b33" },
{ "fontloader-font-cid.lua", "52421d1fdaa07ec4b1d936c6ff5079be" },
- { "fontloader-font-one.lua", "199a7b4720b9931180f289703c4fcb97" },
- { "fontloader-font-onr.lua", "a802cb0b7c5152d7f7f99927131118e9" },
+ { "fontloader-font-one.lua", "6fbf6b9e219a944cd1ad5933d77cc488" },
+ { "fontloader-font-onr.lua", "205c8bc640715aecf3538a33b842f450" },
{ "fontloader-font-afk.lua", "b36a76ceb835f41f8c05b471000ddc14" },
- { "fontloader-data-con.lua", "675f5a0af45ffb3e0d2e2ab5d6c2e47b" },
- { "fontloader-basics-nod.lua", "ecd4eb8a91ac539824a9a72c5b97ded4" },
- { "fontloader-reference.lua", "9c845a0ced6ad34e9300c1987ce8f0af" },
- { "fontloader-basics-gen.lua", "f48046adcf081e027371e2813382afb2" },
+ { "fontloader-data-con.lua", "d8982c834ed9acc6193eee23067b9d5d" },
+ { "fontloader-basics-nod.lua", "9288471b8395bfb683aba0ff3964d950" },
+ { "fontloader-reference.lua", "12efa565c640e8583a8fde380dc0e1a0" },
+ { "fontloader-basics-gen.lua", "b6c8f256b6c6d3350bf5bad2034857a0" },
{ "mktests", "918cb50be9ee8bd645ac1a27dc501e8c" },
- { "mkstatus", "81bd39b7939628e565714bcf98fa5138" },
- { "mkimport", "3cff8fec39c8d1664065288ed6ca804e" },
- { "mkglyphlist", "0acaf0fbc9dce6fda4e717a7ddcfdef6" },
+ { "mkstatus", "d66d9237a9e18e64732f239e49e77633" },
+ { "mkimport", "a90dbe00a99c7e77494b07fbe0e669af" },
+ { "mkglyphlist", "b573c7a7645e5b84e776d7d0bb06c559" },
{ "mkcharacters", "1db01d8172c49c8a405897dc45340917" },
- { "luaotfload-glyphlist.lua", "ff440162d1b8a78a586375ee65630c21" },
- { "luaotfload-characters.lua", "8d22d2cf4a25d066974bb8760819d8a4" },
- { "luaotfload-tool.lua", "8401fe1b72b03013560958937d9b7ac1" },
- { "luaotfload-resolvers.lua", "c05fb5bf7b93803f9462ee0111509aa3" },
- { "luaotfload-parsers.lua", "aac54ef728dfe45a19ab22f4e0e858a6" },
- { "luaotfload-main.lua", "0ea3232c348036a07f86452697d7384a" },
- { "luaotfload-log.lua", "f598e8242030424227f1eb54ec084820" },
- { "luaotfload-loaders.lua", "dd83f37462cfdc5ef3ff90aa79ab32d9" },
- { "luaotfload-letterspace.lua", "37da10d6a7e2f2a24fb4841371aafeb6" },
- { "luaotfload-init.lua", "63a1b9dcccbed6ebbfac659c95a566b7" },
- { "luaotfload-features.lua", "b2beca9b1a171d5b36c27ec2103a4b96" },
+ { "luaotfload-glyphlist.lua", "bcf89e1441be9f4ad29c0cf3a076bcea" },
+ { "luaotfload-characters.lua", "99578c3eff8b68cae3da45a4a7cbfcf2" },
+ { "luaotfload-tool.lua", "e6ca512e0620ccaac968ccc17239ee39" },
+ { "luaotfload-resolvers.lua", "bcdde7940630c4b563f3884b64ae3c84" },
+ { "luaotfload-parsers.lua", "d8820cfe256f9590fb02f54850c1ffff" },
+ { "luaotfload-main.lua", "8411e662c9867c423dc0229b12eb174c" },
+ { "luaotfload-log.lua", "cc79197903756cde068d3c197844be99" },
+ { "luaotfload-loaders.lua", "09883d592a3fe6327654d28b0d880b00" },
+ { "luaotfload-letterspace.lua", "0f4bd9bc0365e96f099e68f4a8114d3e" },
+ { "luaotfload-init.lua", "e5c4c96fc7e3bf150229013fb56e77b5" },
+ { "luaotfload-features.lua", "c523b1137190a2bbc9266f218cade394" },
{ "luaotfload-diagnostics.lua", "7b35c9f91e3e73fc5a61dbfe1f0e7ad9" },
- { "luaotfload-database.lua", "3bbd080c3b8d6585580c46906182d7b1" },
- { "luaotfload-configuration.lua", "b48b7673a975e9e6f2d78290d94c7178" },
- { "luaotfload-colors.lua", "4164cc10b40e87285775ff173efc9417" },
- { "luaotfload-auxiliary.lua", "37bf53e18e0204cd62108dc1526ece3d" },
+ { "luaotfload-database.lua", "d78a5e357374b3753acace6a2032fe37" },
+ { "luaotfload-configuration.lua", "64fa81f2f8fe6815f109873fb27f78aa" },
+ { "luaotfload-colors.lua", "2582a42a68739087a72e5ea6440cf0d8" },
+ { "luaotfload-auxiliary.lua", "a6c092c006660ee6e6fbdcddf104a99b" },
},
["notes"]={
["committer"]="Philipp Gesang <phg@phi-gamma.net>",
- ["description"]="v2.7-fix-3",
- ["loader"]="fontloader-2016-06-16.lua",
- ["revision"]="46415b821010269c820f408162a4441616b28345",
- ["timestamp"]="2016-06-16 21:52:21 +0200",
+ ["description"]="v2.8",
+ ["loader"]="fontloader-2017-01-29.lua",
+ ["revision"]="616b9077567fd670341696cb6ff2bfc71cf691a9",
+ ["timestamp"]="2017-01-29 20:52:03 +0100",
},
} \ No newline at end of file
diff --git a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload.sty b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload.sty
index 112ec239901..45744d15053 100644
--- a/Master/texmf-dist/tex/luatex/luaotfload/luaotfload.sty
+++ b/Master/texmf-dist/tex/luatex/luaotfload/luaotfload.sty
@@ -1,4 +1,4 @@
-%% Copyright (C) 2009-2016
+%% Copyright (C) 2009-2017
%%
%% by Elie Roux <elie.roux@telecom-bretagne.eu>
%% and Khaled Hosny <khaledhosny@eglug.org>
@@ -41,7 +41,7 @@
\ProvidesPackage{luaotfload}%
%% FIXME The date is meaningless, we need to find a way to
%% use the git revision instead.
- [2016/06/16 v2.7 OpenType layout system]
+ [2017/01/29 v2.8 OpenType layout system]
\fi
\directlua{
require('luaotfload-main')