summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scripts/context/lua/mtx-base.lua2
-rw-r--r--scripts/context/lua/mtxrun.lua20
-rw-r--r--scripts/context/stubs/mswin/mtxrun.lua20
-rwxr-xr-xscripts/context/stubs/unix/mtxrun20
-rw-r--r--tex/context/base/back-ini.mkiv16
-rw-r--r--tex/context/base/cont-new.tex2
-rw-r--r--tex/context/base/context.tex2
-rw-r--r--tex/context/base/data-env.lua2
-rw-r--r--tex/context/base/font-ldr.lua70
-rw-r--r--tex/context/base/font-map.lua6
-rw-r--r--tex/context/base/font-mis.lua3
-rw-r--r--tex/context/base/font-otb.lua2
-rw-r--r--tex/context/base/font-otc.lua132
-rw-r--r--tex/context/base/font-otf.lua1504
-rw-r--r--tex/context/base/font-otn.lua2
-rw-r--r--tex/context/base/font-otp.lua17
-rw-r--r--tex/context/base/font-pat.lua61
-rw-r--r--tex/context/base/l-io.lua1
-rw-r--r--tex/context/base/l-table.lua17
-rw-r--r--tex/context/base/lpdf-ano.lua145
-rw-r--r--tex/context/base/pack-box.mkiv4
-rw-r--r--tex/context/base/page-ini.mkiv3
-rw-r--r--tex/context/base/scrn-nav.mkiv9
-rw-r--r--tex/context/base/scrp-cjk.lua3
-rw-r--r--tex/context/base/strc-des.mkiv2
-rw-r--r--tex/context/base/strc-num.lua13
-rw-r--r--tex/context/base/strc-num.mkiv5
-rw-r--r--tex/context/base/strc-pag.mkiv21
-rw-r--r--tex/context/base/strc-ref.lua12
-rw-r--r--tex/context/base/strc-tag.lua10
-rw-r--r--tex/context/base/syst-ini.tex6
-rw-r--r--tex/context/base/util-pck.lua12
-rw-r--r--tex/generic/context/luatex-fonts-merged.lua1676
-rw-r--r--web2c/contextcnf.lua10
34 files changed, 2070 insertions, 1760 deletions
diff --git a/scripts/context/lua/mtx-base.lua b/scripts/context/lua/mtx-base.lua
index 443f653f0..67bde5b79 100644
--- a/scripts/context/lua/mtx-base.lua
+++ b/scripts/context/lua/mtx-base.lua
@@ -130,7 +130,7 @@ elseif environment.arguments["configurations"] or environment.arguments["show-co
resolvers.listers.configurations()
elseif environment.arguments["help"] or (environment.files[1]=='help') or (#environment.files==0) then
logs.help(messages.help)
-elseif environment.files[1]=='texmfcnf.lua' then
+elseif environment.files[1] == 'texmfcnf.lua' then
resolvers.load("nofiles")
resolvers.listers.configurations()
else
diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua
index f792cd942..246d08103 100644
--- a/scripts/context/lua/mtxrun.lua
+++ b/scripts/context/lua/mtxrun.lua
@@ -709,20 +709,22 @@ function table.imerged(...)
return tmp
end
-local function fastcopy(old) -- fast one
+local function fastcopy(old,metatabletoo) -- fast one
if old then
local new = { }
for k,v in next, old do
if type(v) == "table" then
- new[k] = fastcopy(v) -- was just table.copy
+ new[k] = fastcopy(v,metatabletoo) -- was just table.copy
else
new[k] = v
end
end
- -- optional second arg
- local mt = getmetatable(old)
- if mt then
- setmetatable(new,mt)
+ if metatabletoo then
+ -- optional second arg
+ local mt = getmetatable(old)
+ if mt then
+ setmetatable(new,mt)
+ end
end
return new
else
@@ -730,6 +732,8 @@ local function fastcopy(old) -- fast one
end
end
+-- todo : copy without metatable
+
local function copy(t, tables) -- taken from lua wiki, slightly adapted
tables = tables or { }
local tcopy = {}
@@ -1146,6 +1150,7 @@ function table.tofile(filename,root,name,reduce,noquotes,hexify)
serialize(root,name,flush,reduce,noquotes,hexify)
end
f:close()
+ io.flush()
end
end
@@ -1381,6 +1386,7 @@ function io.savedata(filename,data,joiner)
f:write(data or "")
end
f:close()
+ io.flush()
return true
else
return false
@@ -9406,7 +9412,7 @@ function resolvers.variableofformat(str)
return formats[str] or formats[alternatives[str]] or ''
end
-function resolvers.vsriableofformatorsuffix(str)
+function resolvers.variableofformatorsuffix(str)
local v = formats[str]
if v then
return v
diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua
index f792cd942..246d08103 100644
--- a/scripts/context/stubs/mswin/mtxrun.lua
+++ b/scripts/context/stubs/mswin/mtxrun.lua
@@ -709,20 +709,22 @@ function table.imerged(...)
return tmp
end
-local function fastcopy(old) -- fast one
+local function fastcopy(old,metatabletoo) -- fast one
if old then
local new = { }
for k,v in next, old do
if type(v) == "table" then
- new[k] = fastcopy(v) -- was just table.copy
+ new[k] = fastcopy(v,metatabletoo) -- was just table.copy
else
new[k] = v
end
end
- -- optional second arg
- local mt = getmetatable(old)
- if mt then
- setmetatable(new,mt)
+ if metatabletoo then
+ -- optional second arg
+ local mt = getmetatable(old)
+ if mt then
+ setmetatable(new,mt)
+ end
end
return new
else
@@ -730,6 +732,8 @@ local function fastcopy(old) -- fast one
end
end
+-- todo : copy without metatable
+
local function copy(t, tables) -- taken from lua wiki, slightly adapted
tables = tables or { }
local tcopy = {}
@@ -1146,6 +1150,7 @@ function table.tofile(filename,root,name,reduce,noquotes,hexify)
serialize(root,name,flush,reduce,noquotes,hexify)
end
f:close()
+ io.flush()
end
end
@@ -1381,6 +1386,7 @@ function io.savedata(filename,data,joiner)
f:write(data or "")
end
f:close()
+ io.flush()
return true
else
return false
@@ -9406,7 +9412,7 @@ function resolvers.variableofformat(str)
return formats[str] or formats[alternatives[str]] or ''
end
-function resolvers.vsriableofformatorsuffix(str)
+function resolvers.variableofformatorsuffix(str)
local v = formats[str]
if v then
return v
diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun
index f792cd942..246d08103 100755
--- a/scripts/context/stubs/unix/mtxrun
+++ b/scripts/context/stubs/unix/mtxrun
@@ -709,20 +709,22 @@ function table.imerged(...)
return tmp
end
-local function fastcopy(old) -- fast one
+local function fastcopy(old,metatabletoo) -- fast one
if old then
local new = { }
for k,v in next, old do
if type(v) == "table" then
- new[k] = fastcopy(v) -- was just table.copy
+ new[k] = fastcopy(v,metatabletoo) -- was just table.copy
else
new[k] = v
end
end
- -- optional second arg
- local mt = getmetatable(old)
- if mt then
- setmetatable(new,mt)
+ if metatabletoo then
+ -- optional second arg
+ local mt = getmetatable(old)
+ if mt then
+ setmetatable(new,mt)
+ end
end
return new
else
@@ -730,6 +732,8 @@ local function fastcopy(old) -- fast one
end
end
+-- todo : copy without metatable
+
local function copy(t, tables) -- taken from lua wiki, slightly adapted
tables = tables or { }
local tcopy = {}
@@ -1146,6 +1150,7 @@ function table.tofile(filename,root,name,reduce,noquotes,hexify)
serialize(root,name,flush,reduce,noquotes,hexify)
end
f:close()
+ io.flush()
end
end
@@ -1381,6 +1386,7 @@ function io.savedata(filename,data,joiner)
f:write(data or "")
end
f:close()
+ io.flush()
return true
else
return false
@@ -9406,7 +9412,7 @@ function resolvers.variableofformat(str)
return formats[str] or formats[alternatives[str]] or ''
end
-function resolvers.vsriableofformatorsuffix(str)
+function resolvers.variableofformatorsuffix(str)
local v = formats[str]
if v then
return v
diff --git a/tex/context/base/back-ini.mkiv b/tex/context/base/back-ini.mkiv
index db37cf61f..12c41d169 100644
--- a/tex/context/base/back-ini.mkiv
+++ b/tex/context/base/back-ini.mkiv
@@ -128,22 +128,6 @@
\let \doloadmapline \gobbletwoarguments % + - = | fileline
%D \macros
-%D {ifusepagedestinations}
-%D
-%D In \PDF\ version 1.0 only page references were supported,
-%D while in \DVIWINDO\ 1.N only named references were accepted.
-%D Therefore \CONTEXT\ supports both methods of referencing. In
-%D \PDF\ version 1.1 named destinations arrived. Lack of
-%D continuous support of version 1.1 viewers for \MSDOS\
-%D therefore sometimes forces us to prefer page references. As
-%D a bonus, they are faster too and have no limitations. How
-%D fortunate we were having both mechanisms available when the
-%D version 3.0 (\PDF\ version 1.2) viewers proved to be too
-%D bugged to support named destinations.
-
-\newif\ifusepagedestinations % not yet interfaced in mkiv
-
-%D \macros
%D {jobsuffix}
%D
%D By default, \TEX\ produces \DVI\ files which can be
diff --git a/tex/context/base/cont-new.tex b/tex/context/base/cont-new.tex
index 19871222b..6ef0310ec 100644
--- a/tex/context/base/cont-new.tex
+++ b/tex/context/base/cont-new.tex
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2010.09.05 13:23}
+\newcontextversion{2010.09.09 23:45}
%D This file is loaded at runtime, thereby providing an
%D excellent place for hacks, patches, extensions and new
diff --git a/tex/context/base/context.tex b/tex/context/base/context.tex
index c50e3fb7b..23afbe8c8 100644
--- a/tex/context/base/context.tex
+++ b/tex/context/base/context.tex
@@ -20,7 +20,7 @@
%D your styles an modules.
\edef\contextformat {\jobname}
-\edef\contextversion{2010.09.05 13:23}
+\edef\contextversion{2010.09.09 23:45}
%D For those who want to use this:
diff --git a/tex/context/base/data-env.lua b/tex/context/base/data-env.lua
index be596f3bf..19c10fde0 100644
--- a/tex/context/base/data-env.lua
+++ b/tex/context/base/data-env.lua
@@ -151,7 +151,7 @@ function resolvers.variableofformat(str)
return formats[str] or formats[alternatives[str]] or ''
end
-function resolvers.vsriableofformatorsuffix(str)
+function resolvers.variableofformatorsuffix(str)
local v = formats[str]
if v then
return v
diff --git a/tex/context/base/font-ldr.lua b/tex/context/base/font-ldr.lua
new file mode 100644
index 000000000..ca4e3f98a
--- /dev/null
+++ b/tex/context/base/font-ldr.lua
@@ -0,0 +1,70 @@
+if not modules then modules = { } end modules ['font-ldr'] = {
+ 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"
+}
+
+-- This module provides a replacement for fontloader.to_table
+-- and will be loaded in due time.
+
+local fields = fontloader.fields
+
+if fields then
+
+ local glyphfields
+
+ local function get_glyphs(r)
+ local t = { }
+ local g = r.glyphs
+ for i=1,r.glyphmax-1 do
+ local gi = g[i]
+ if gi then
+ if not glyphfields then
+ glyphfields = fields(gi)
+ end
+ local h = { }
+ for i=1,#glyphfields do
+ local s = glyphfields[i]
+ h[s] = gi[s]
+ end
+ t[i] = h
+ end
+ end
+ return t
+ end
+
+ local function to_table(r)
+ local f = fields(r)
+ if f then
+ local t = { }
+ for i=1,#f do
+ local fi = f[i]
+ local ri = r[fi]
+ if not ri then
+ -- skip
+ elseif fi == "glyphs" then
+ t.glyphs = get_glyphs(r)
+ elseif fi == "subfonts" then
+ t[fi] = ri
+ ri.glyphs = get_glyphs(ri)
+ else
+ t[fi] = r[fi]
+ end
+ end
+ return t
+ end
+ end
+
+ -- currently glyphs, subfont-glyphs and the main table are userdata
+
+ function fonts.to_table(raw)
+ return to_table(raw)
+ end
+
+else
+
+ fonts.to_table = fontloader.to_table
+
+end
diff --git a/tex/context/base/font-map.lua b/tex/context/base/font-map.lua
index 5fa4170d7..128e80eb9 100644
--- a/tex/context/base/font-map.lua
+++ b/tex/context/base/font-map.lua
@@ -233,7 +233,11 @@ fonts.map.addtounicode = function(data,filename)
t[#t+1] = u
end
end
- if #t > 0 then -- done then
+ if #t == 0 then -- done then
+ -- nothing
+ elseif #t == 1 then
+ originals[index], tounicode[index], nl, unicode = t[1], tounicode16(t[1]), nl + 1, true
+ else
originals[index], tounicode[index], nl, unicode = t, tounicode16sequence(t), nl + 1, true
end
end
diff --git a/tex/context/base/font-mis.lua b/tex/context/base/font-mis.lua
index 645278837..2ae60e635 100644
--- a/tex/context/base/font-mis.lua
+++ b/tex/context/base/font-mis.lua
@@ -11,8 +11,7 @@ local lower, strip = string.lower, string.strip
fonts.otf = fonts.otf or { }
-fonts.otf.version = fonts.otf.version or 2.653
-fonts.otf.pack = true
+fonts.otf.version = fonts.otf.version or 2.702
fonts.otf.cache = containers.define("fonts", "otf", fonts.otf.version, true)
function fonts.otf.loadcached(filename,format,sub)
diff --git a/tex/context/base/font-otb.lua b/tex/context/base/font-otb.lua
index e4d694ea9..241845f24 100644
--- a/tex/context/base/font-otb.lua
+++ b/tex/context/base/font-otb.lua
@@ -276,7 +276,7 @@ local function preparebasekerns(tfmdata,kind,value) -- todo what kind of kerns,
for u, chr in next, characters do
local d = descriptions[u]
if d then
- local dk = d.mykerns -- shared
+ local dk = d.kerns -- shared
if dk then
local s = sharedkerns[dk]
if s == false then
diff --git a/tex/context/base/font-otc.lua b/tex/context/base/font-otc.lua
index 3280d8161..f9d749123 100644
--- a/tex/context/base/font-otc.lua
+++ b/tex/context/base/font-otc.lua
@@ -24,6 +24,12 @@ local report_otf = logs.new("load otf")
--
-- we could have a tnum variant as well
+-- 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.
+
local extra_lists = {
tlig = {
{
@@ -74,116 +80,120 @@ local extra_lists = {
local extra_features = { -- maybe just 1..n so that we prescribe order
tlig = {
{
- features = { { scripts = { { script = "*", langs = { "*" }, } }, tag = "tlig", comment = "added bij mkiv" }, },
+ features = { ["*"] = { ["*"] = true } },
name = "ctx_tlig_1",
- subtables = { { name = "ctx_tlig_1_s" } },
+ subtables = { "ctx_tlig_1_s" },
type = "gsub_ligature",
flags = { },
},
},
trep = {
{
- features = { { scripts = { { script = "*", langs = { "*" }, } }, tag = "trep", comment = "added bij mkiv" }, },
+ features = { ["*"] = { ["*"] = true } },
name = "ctx_trep_1",
- subtables = { { name = "ctx_trep_1_s" } },
+ subtables = { "ctx_trep_1_s" },
type = "gsub_single",
flags = { },
},
},
anum = {
{
- features = { { scripts = { { script = "arab", langs = { "dflt", "FAR" }, } }, tag = "anum", comment = "added bij mkiv" }, },
+ features = { arab = { URD = true, dflt = true } },
name = "ctx_anum_1",
- subtables = { { name = "ctx_anum_1_s" } },
+ subtables = { "ctx_anum_1_s" },
type = "gsub_single",
flags = { },
},
{
- features = { { scripts = { { script = "arab", langs = { "URD" }, } }, tag = "anum", comment = "added bij mkiv" }, },
+ features = { arab = { URD = true } },
name = "ctx_anum_2",
- subtables = { { name = "ctx_anum_2_s" } },
+ subtables = { "ctx_anum_2_s" },
type = "gsub_single",
flags = { },
},
},
}
-otf.enhancers["add some missing characters"] = function(data,filename)
- -- todo
-end
-
-otf.enhancers["enrich with features"] = function(data,filename)
- -- could be done elsewhere (true can be #)
- local used = { }
- for i=1,#otf.glists do
- local g = data[otf.glists[i]]
- if g then
- for i=1,#g do
- local f = g[i].features
- if f then
- for i=1,#f do
- local t = f[i].tag
- if t then used[t] = true end
- end
- end
- end
- end
- end
- --
+local function enhancedata(data,filename,raw)
+ local luatex = data.luatex
+ local lookups = luatex.lookups
+ local sequences = luatex.sequences
local glyphs = data.glyphs
- local indices = data.map.map
- data.gsub = data.gsub or { }
+ local indices = luatex.indices
+ local gsubfeatures = luatex.features.gsub
for kind, specifications in next, extra_features do
- if not used[kind] then
+ if gsub and gsub[kind] then
+ -- already present
+ else
local done = 0
for s=1,#specifications do
local added = false
local specification = specifications[s]
+ local features, subtables = specification.features, specification.subtables
+ local name, type, flags = specification.name, specification.type, specification.flags
+ local full = subtables[1]
local list = extra_lists[kind][s]
- local name = specification.name .. "_s"
- if specification.type == "gsub_ligature" then
+ if type == "gsub_ligature" then
+ -- inefficient loop
for unicode, index in next, indices do
local glyph = glyphs[index]
local ligature = list[glyph.name]
if ligature then
- local o = glyph.lookups or { }
- -- o[name] = { "ligature", ligature, glyph.name }
- o[name] = {
- {
- ["type"] = "ligature",
- ["specification"] = {
- char = glyph.name,
- components = ligature,
- }
- }
- }
- glyph.lookups, done, added = o, done+1, true
+ if glyph.slookups then
+ glyph.slookups [full] = { "ligature", ligature, glyph.name }
+ else
+ glyph.slookups = { [full] = { "ligature", ligature, glyph.name } }
+ end
+ done, added = done+1, true
end
end
- elseif specification.type == "gsub_single" then
+ elseif type == "gsub_single" then
+ -- inefficient loop
for unicode, index in next, indices do
local glyph = glyphs[index]
local r = list[unicode]
if r then
local replacement = indices[r]
if replacement and glyphs[replacement] then
- local o = glyph.lookups or { }
- -- o[name] = { { "substitution", glyphs[replacement].name } }
- o[name] = {
- {
- ["type"] = "substitution",
- ["specification"] = {
- variant = glyphs[replacement].name,
- }
- }
- }
- glyph.lookups, done, added = o, done+1, true
+ if glyph.slookups then
+ glyph.slookups [full] = { "substitution", glyphs[replacement].name }
+ else
+ glyph.slookups = { [full] = { "substitution", glyphs[replacement].name } }
+ end
+ done, added = done+1, true
end
end
end
end
if added then
- insert(data.gsub,s,table.fastcopy(specification)) -- right order
+ sequences[#sequences+1] = {
+ chain = 0,
+ features = { [kind] = features },
+ flags = flags,
+ name = name,
+ subtables = subtables,
+ type = type,
+ }
+ -- register in metadata (merge as there can be a few)
+ if not gsubfeatures then
+ gsubfeatures = { }
+ luatex.features.gsub = gsubfeatures
+ end
+ local k = gsubfeatures[kind]
+ if not k then
+ k = { }
+ gsubfeatures[kind] = k
+ end
+ for script, languages in next, features 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
if done > 0 then
@@ -195,6 +205,8 @@ otf.enhancers["enrich with features"] = function(data,filename)
end
end
+otf.enhancers.register("check extra features",enhancedata)
+
local features = otf.tables.features
features['tlig'] = 'TeX Ligatures'
diff --git a/tex/context/base/font-otf.lua b/tex/context/base/font-otf.lua
index 1da295eb0..46cc34070 100644
--- a/tex/context/base/font-otf.lua
+++ b/tex/context/base/font-otf.lua
@@ -6,6 +6,11 @@ if not modules then modules = { } end modules ['font-otf'] = {
license = "see context related readme files"
}
+-- langs -> languages enz
+-- anchor_classes vs kernclasses
+-- modification/creationtime in subfont is runtime dus zinloos
+-- to_table -> totable
+
local utf = unicode.utf8
local concat, utfbyte = table.concat, utf.byte
@@ -14,6 +19,8 @@ local type, next, tonumber, tostring = type, next, tonumber, tostring
local abs = math.abs
local getn = table.getn
local lpegmatch = lpeg.match
+local reverse = table.reverse
+local ioflush = io.flush
local allocate = utilities.storage.allocate
@@ -27,42 +34,7 @@ local trace_defining = false trackers.register("fonts.defining", function(v
local report_otf = logs.new("load otf")
---~ trackers.enable("otf.loading")
-
---[[ldx--
-<p>The fontforge table has organized lookups in a certain way. A first implementation
-of this code was organized featurewise: information related to features was
-collected and processing boiled down to a run over the features. The current
-implementation honors the order in the main feature table. Since we can reorder this
-table as we want, we can eventually support several models of processing. We kept
-the static as well as dynamic feature processing, because it had proved to be
-rather useful. The formerly three loop variants have beem discarded but will
-reapear at some time.</p>
-
-<itemize>
-<item>we loop over all lookups</item>
-<item>for each lookup we do a run over the list of glyphs</item>
-<item>but we only process them for features that are enabled</item>
-<item>if we're dealing with a contextual lookup, we loop over all contexts</item>
-<item>in that loop we quit at a match and then process the list of sublookups</item>
-<item>we always continue after the match</item>
-</itemize>
-
-<p>In <l n='context'/> we do this for each font that is used in a list, so in
-practice we have quite some nested loops.</p>
-
-<p>We process the whole list and then consult the glyph nodes. An alternative approach
-is to collect strings of characters using the same font including spaces (because some
-lookups involve spaces). However, we then need to reconstruct the list which is no fun.
-Also, we need to carry quite some information, like attributes, so eventually we don't
-gain much (if we gain something at all).</p>
-
-<p>Another consideration has been to operate on sublists (subhead, subtail) but again
-this would complicate matters as we then neext to keep track of a changing subhead
-and subtail. On the other hand, this might save some runtime. The number of changes
-involved is not that large. This only makes sense when we have many fonts in a list
-and don't change to frequently.</p>
---ldx]]--
+local starttiming, stoptiming, elapsedtime = statistics.starttiming, statistics.stoptiming, statistics.elapsedtime
local fonts = fonts
@@ -72,38 +44,114 @@ local tfm = fonts.tfm
local fontdata = fonts.ids
---~ otf.tables = otf.tables or { } -- defined in font-ott.lua
---~ otf.tables.features = otf.tables.features or { } -- defined in font-ott.lua
---~ otf.tables.languages = otf.tables.languages or { } -- defined in font-ott.lua
---~ otf.tables.scripts = otf.tables.scripts or { } -- defined in font-ott.lua
-
otf.features = otf.features or { }
otf.features.list = otf.features.list or { }
otf.features.default = otf.features.default or { }
otf.enhancers = allocate()
local enhancers = otf.enhancers
+enhancers.patches = { }
local definers = fonts.definers
otf.glists = { "gsub", "gpos" }
-otf.version = 2.653 -- beware: also sync font-mis.lua
-otf.pack = true -- beware: also sync font-mis.lua
-otf.syncspace = true
-otf.notdef = false
+otf.version = 2.702 -- beware: also sync font-mis.lua
otf.cache = containers.define("fonts", "otf", otf.version, true)
-local wildcard = "*"
-local default = "dflt"
+local loadmethod = "table" -- table, mixed, sparse
+local forceload = false
+local cleanup = 0
+local usemetatables = false -- .4 slower on mk but 30 M less mem so we might change the default -- will be directive
+local packdata = true
+local syncspace = true
+local forcenotdef = false
+
+local wildcard = "*"
+local default = "dflt"
+
+local fontloaderfields = fontloader.fields
+local mainfields = nil
+local glyphfields = nil -- not used yet
+
+directives.register("fonts.otf.loader.method", function(v)
+ if v == "sparse" and fontloaderfields then
+ loadmethod = "sparse"
+ elseif v == "mixed" then
+ loadmethod = "mixed"
+ elseif v == "table" then
+ loadmethod = "table"
+ else
+ loadmethod = "table"
+ report_otf("no loader method '%s', using '%s' instead",v,loadmethod)
+ end
+end)
+
+directives.register("fonts.otf.loader.cleanup",function(v)
+ cleanup = tonumber(v) or (v and 1) or 0
+end)
+
+directives.register("fonts.otf.loader.force", function(v) forceload = v end)
+directives.register("fonts.otf.loader.usemetatables", function(v) usemetatables = v end)
+directives.register("fonts.otf.loader.pack", function(v) packdata = v end)
+directives.register("fonts.otf.loader.syncspace", function(v) syncspace = v end)
+directives.register("fonts.otf.loader.forcenotdef", function(v) forcenotdef = v end)
+
+local function load_featurefile(raw,featurefile)
+ if featurefile and featurefile ~= "" then
+ if trace_loading then
+ report_otf("featurefile: %s", featurefile)
+ end
+ fontloader.apply_featurefile(raw, featurefile)
+ end
+end
+
+local function showfeatureorder(otfdata,filename)
+ local sequences = otfdata.luatex.sequences
+ if sequences and #sequences > 0 then
+ if trace_loading then
+ report_otf("font %s has %s sequences",filename,#sequences)
+ report_otf(" ")
+ end
+ for nos=1,#sequences do
+ local sequence = sequences[nos]
+ local typ = sequence.type or "no-type"
+ local name = sequence.name or "no-name"
+ local subtables = sequence.subtables or { "no-subtables" }
+ local features = sequence.features
+ if trace_loading then
+ report_otf("%3i %-15s %-20s [%s]",nos,name,typ,concat(subtables,","))
+ end
+ if features then
+ for feature, scripts in next, features do
+ local tt = { }
+ for script, languages in next, scripts do
+ local ttt = { }
+ for language, _ in next, languages do
+ ttt[#ttt+1] = language
+ end
+ tt[#tt+1] = format("[%s: %s]",script,concat(ttt," "))
+ end
+ if trace_loading then
+ report_otf(" %s: %s",feature,concat(tt," "))
+ end
+ end
+ end
+ end
+ if trace_loading then
+ report_otf("\n")
+ end
+ elseif trace_loading then
+ report_otf("font %s has no sequences",filename)
+ end
+end
--[[ldx--
<p>We start with a lot of tables and related functions.</p>
--ldx]]--
--- we can have more local functions
-
-otf.tables.global_fields = allocate( table.tohash {
+local global_fields = table.tohash {
+ "metadata",
"lookups",
"glyphs",
"subfonts",
@@ -114,20 +162,20 @@ otf.tables.global_fields = allocate( table.tohash {
"names",
"unicodes",
"names",
---~ "math",
+ -- "math",
"anchor_classes",
"kern_classes",
"gpos",
"gsub"
-} )
+}
-otf.tables.valid_fields = allocate( {
- "anchor_classes",
+local valid_fields = table.tohash {
+ -- "anchor_classes",
"ascent",
- "cache_version",
+ -- "cache_version",
"cidinfo",
"copyright",
- "creationtime",
+ -- "creationtime",
"descent",
"design_range_bottom",
"design_range_top",
@@ -139,23 +187,23 @@ otf.tables.valid_fields = allocate( {
"fontstyle_id",
"fontstyle_name",
"fullname",
- "glyphs",
+ -- "glyphs",
"hasvmetrics",
"head_optimized_for_cleartype",
"horiz_base",
"issans",
"isserif",
"italicangle",
- "kerns",
- "lookups",
+ -- "kerns",
+ -- "lookups",
-- "luatex",
"macstyle",
- "modificationtime",
+ -- "modificationtime",
"onlybitmaps",
"origname",
"os2_version",
- "pfminfo",
- "private",
+ -- "pfminfo",
+ -- "private",
"serifcheck",
"sfd_version",
-- "size",
@@ -172,59 +220,111 @@ otf.tables.valid_fields = allocate( {
"upos",
"use_typo_metrics",
"uwidth",
- "validation_state",
+ -- "validation_state",
"verbose",
"version",
"vert_base",
"weight",
"weight_width_slope_only",
- "xuid",
-} )
+ -- "xuid",
+}
+
+local ordered_enhancers = {
+ "prepare tables",
+ "prepare glyphs",
+ "prepare unicodes",
+ "prepare lookups",
+
+ "analyze glyphs",
+ "analyze math",
+
+ "prepare tounicode", -- maybe merge with prepare
+
+ "reorganize lookups",
+ "reorganize mark classes",
+ "reorganize anchor classes",
+
+ "reorganize glyph kerns",
+ "reorganize glyph lookups",
+ "reorganize glyph anchors",
+
+ "reorganize features",
+ "reorganize subtables",
+
+ "check glyphs",
+ "check metadata",
+ "check math parameters",
+ "check extra features", -- after metadata
+}
--[[ldx--
<p>Here we go.</p>
--ldx]]--
-local function load_featurefile(ff,featurefile)
- if featurefile and featurefile ~= "" then
- if trace_loading then
- report_otf("featurefile: %s", featurefile)
+local actions = { }
+
+enhancers.patches.before = allocate()
+enhancers.patches.after = allocate()
+
+local before = enhancers.patches.before
+local after = enhancers.patches.after
+
+local function enhance(name,data,filename,raw,verbose)
+ local enhancer = actions[name]
+ if enhancer then
+ if verbose then
+ report_otf("enhance: %s (%s)",name,filename)
+ ioflush()
end
- fontloader.apply_featurefile(ff, featurefile)
+ enhancer(data,filename,raw)
+ else
+ report_otf("enhance: %s is undefined",name)
end
end
-local function enhance(name,data,filename,verbose)
- local enhancer = enhancers[name]
- if enhancer then
- if (verbose ~= nil and verbose) or trace_loading then
- report_otf("enhance: %s (%s)",name,filename)
+function enhancers.apply(data,filename,raw,verbose)
+ local basename = file.basename(lower(filename))
+ report_otf("start enhancing: %s",filename)
+ 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
- enhancer(data,filename)
+ enhance(enhancer,data,filename,raw,verbose)
+ 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
+ report_otf("stop enhancing")
+ ioflush() -- we want instant messages
end
-local ordered_enhancers = { -- implemented later
- -- pack and unpack are handled separately; they might even be moved
- -- away from the enhancers namespace
- "patch bugs",
- "merge cid fonts", "prepare unicode", "cleanup ttf tables", "compact glyphs", "reverse coverage",
- "cleanup aat", "enrich with features", "add some missing characters",
- "reorganize mark classes",
- "reorganize kerns", -- moved here
- "flatten glyph lookups", "flatten anchor tables", "flatten feature tables",
- "simplify glyph lookups", -- some saving
- "prepare luatex tables",
- "analyze features", "rehash features",
- "analyze anchors", "analyze marks", "analyze unicodes", "analyze subtables",
- "check italic correction","check math",
- "share widths",
- "strip not needed data",
- "migrate metadata",
- "check math parameters",
-}
+-- enhancers.patches.register("before","migrate metadata","cambria",function() end)
-local adddimensions, showfeatureorder -- implemented later
+function enhancers.patches.register(what,where,pattern,action)
+ local ww = what[where]
+ if ww then
+ ww[pattern] = action
+ else
+ ww = { [pattern] = action}
+ end
+end
+
+function enhancers.register(what,action) -- only already registered can be overloaded
+ actions[what] = action
+end
function otf.load(filename,format,sub,featurefile)
local name = file.basename(file.removesuffix(filename))
@@ -261,6 +361,10 @@ function otf.load(filename,format,sub,featurefile)
end
local data = containers.read(otf.cache,hash)
local reload = not data or data.verbose ~= fonts.verbose or data.size ~= size or data.time ~= time
+ if forceload then
+ report_otf("loading: forced reload due to hard coded flag")
+ reload = true
+ end
if not reload then
local featuredata = data.featuredata
if featurefiles then
@@ -284,11 +388,14 @@ function otf.load(filename,format,sub,featurefile)
end
if reload then
report_otf("loading: %s (hash: %s)",filename,hash)
- local ff, messages
+ local fontdata, messages, rawdata
if sub then
- ff, messages = fontloader.open(filename,sub)
+ fontdata, messages = fontloader.open(filename,sub)
else
- ff, messages = fontloader.open(filename)
+ fontdata, messages = fontloader.open(filename)
+ end
+ if fontdata then
+ mainfields = mainfields or (fontloaderfields and fontloaderfields(fontdata))
end
if trace_loading and messages and #messages > 0 then
if type(messages) == "string" then
@@ -301,23 +408,27 @@ function otf.load(filename,format,sub,featurefile)
else
report_otf("font loaded okay")
end
- if ff then
+ if fontdata then
if featurefiles then
for i=1,#featurefiles do
- load_featurefile(ff,featurefiles[i].name)
+ load_featurefile(fontdata,featurefiles[i].name)
end
end
- data = fontloader.to_table(ff)
- fontloader.close(ff)
- if data then
+ report_otf("loading method: %s",loadmethod)
+ if loadmethod == "sparse" then
+ rawdata = fontdata
+ else
+ rawdata = fontloader.to_table(fontdata)
+ fontloader.close(fontdata)
+ end
+ if rawdata then
+ data = { }
+ starttiming(data)
+ local verboseindeed = verbose ~= nil and verbose or trace_loading
report_otf("file size: %s", size)
- report_otf("enhancing ...")
- for e=1,#ordered_enhancers do
- enhance(ordered_enhancers[e],data,filename)
- io.flush() -- we want instant messages
- end
- if otf.pack and not fonts.verbose then
- enhance("pack",data,filename)
+ enhancers.apply(data,filename,rawdata,verboseindeed)
+ if packdata and not fonts.verbose then
+ enhance("pack",data,filename,nil,verboseindeed)
end
data.size = size
data.time = time
@@ -327,13 +438,27 @@ function otf.load(filename,format,sub,featurefile)
data.verbose = fonts.verbose
report_otf("saving in cache: %s",filename)
data = containers.write(otf.cache, hash, data)
- collectgarbage("collect")
+ if cleanup > 0 then
+ collectgarbage("collect")
+ end
+ stoptiming(data)
+ report_otf("preprocessing and caching took %s seconds",elapsedtime(data))
data = containers.read(otf.cache, hash) -- this frees the old table and load the sparse one
- collectgarbage("collect")
+ if cleanup > 1 then
+ collectgarbage("collect")
+ end
else
+ data = nil
report_otf("loading failed (table conversion error)")
end
+ if loadmethod == "sparse" then
+ fontloader.close(fontdata)
+ if cleanup > 2 then
+ -- collectgarbage("collect")
+ end
+ end
else
+ data = nil
report_otf("loading failed (file read error)")
end
end
@@ -341,8 +466,8 @@ function otf.load(filename,format,sub,featurefile)
if trace_defining then
report_otf("loading from cache: %s",hash)
end
- enhance("unpack",data,filename,false) -- no message here
- adddimensions(data)
+ enhance("unpack",data,filename,nil,false)
+ enhance("add dimensions",data,filename,nil,false)
if trace_sequences then
showfeatureorder(data,filename)
end
@@ -350,89 +475,321 @@ function otf.load(filename,format,sub,featurefile)
return data
end
-adddimensions = function(data)
+local mt = {
+ __index = function(t,k) -- maybe set it
+ if k == "height" then
+ local ht = t.boundingbox[4]
+ return ht < 0 and 0 or ht
+ elseif k == "depth" then
+ local dp = -t.boundingbox[2]
+ return dp < 0 and 0 or dp
+ elseif k == "width" then
+ return 0
+ elseif k == "name" then -- or maybe uni*
+ return forcenotdef and ".notdef"
+ end
+ end
+}
+
+actions["add dimensions"] = function(data,filename)
-- todo: forget about the width if it's the defaultwidth (saves mem)
-- we could also build the marks hash here (instead of storing it)
if data then
- local force = otf.notdef
local luatex = data.luatex
local defaultwidth = luatex.defaultwidth or 0
local defaultheight = luatex.defaultheight or 0
local defaultdepth = luatex.defaultdepth or 0
- for _, d in next, data.glyphs do
- local bb, wd = d.boundingbox, d.width
- if not wd then
- d.width = defaultwidth
- elseif wd ~= 0 and d.class == "mark" then
- d.width = -wd
+ if usemetatables then
+ for _, d in next, data.glyphs do
+ local wd = d.width
+ if not wd then
+ d.width = defaultwidth
+ elseif wd ~= 0 and d.class == "mark" then
+ d.width = -wd
+ end
+ setmetatable(d,mt)
end
- if force and not d.name then
- d.name = ".notdef"
+ else
+ for _, d in next, data.glyphs do
+ local bb, wd = d.boundingbox, d.width
+ if not wd then
+ d.width = defaultwidth
+ elseif wd ~= 0 and d.class == "mark" then
+ d.width = -wd
+ end
+ if forcenotdef and not d.name then
+ d.name = ".notdef"
+ end
+ if bb then
+ local ht, dp = bb[4], -bb[2]
+ if ht == 0 or ht < 0 then
+ -- not set
+ else
+ d.height = ht
+ end
+ if dp == 0 or dp < 0 then
+ -- not set
+ else
+ d.depth = dp
+ end
+ end
end
- if bb then
- local ht, dp = bb[4], -bb[2]
- if ht == 0 or ht < 0 then
- -- no need to set it and no negative heights, nil == 0
+ end
+ end
+end
+
+actions["prepare tables"] = function(data,filename,raw)
+ local luatex = {
+ filename = filename,
+ version = otf.version,
+ creator = "context mkiv",
+ }
+ data.luatex = luatex
+ data.metadata = { }
+end
+
+local function somecopy(old) -- fast one
+ if old then
+ local new = { }
+ if type(old) == "table" then
+ for k, v in next, old do
+ if k == "glyphs" then
+ -- skip
+ elseif type(v) == "table" then
+ new[k] = somecopy(v)
else
- d.height = ht
+ new[k] = v
end
- if dp == 0 or dp < 0 then
- -- no negative depths and no negative depths, nil == 0
+ end
+ else
+ for i=1,#mainfields do
+ local k = mainfields[i]
+ local v = old[k]
+ if k == "glyphs" then
+ -- skip
+ elseif type(v) == "table" then
+ new[k] = somecopy(v)
else
- d.depth = dp
+ new[k] = v
end
end
end
+ return new
+ else
+ return { }
end
end
-local function showfeatureorder(otfdata,filename)
- local sequences = otfdata.luatex.sequences
- if sequences and #sequences > 0 then
- if trace_loading then
- report_otf("font %s has %s sequences",filename,#sequences)
- report_otf(" ")
+actions["prepare glyphs"] = function(data,filename,raw)
+ -- we can also move the names to data.luatex.names which might
+ -- save us some more memory (at the cost of harder tracing)
+ local rawglyphs = raw.glyphs
+ local glyphs, udglyphs
+ if loadmethod == "sparse" then
+ glyphs, udglyphs = { }, { }
+ elseif loadmethod == "mixed" then
+ glyphs, udglyphs = { }, rawglyphs
+ else
+ glyphs, udglyphs = rawglyphs, rawglyphs
+ end
+ data.glyphs, data.udglyphs = glyphs, udglyphs
+ local subfonts = raw.subfonts
+ if subfonts then
+ if data.glyphs and next(data.glyphs) then
+ report_otf("replacing existing glyph table due to subfonts")
end
- for nos=1,#sequences do
- local sequence = sequences[nos]
- local typ = sequence.type or "no-type"
- local name = sequence.name or "no-name"
- local subtables = sequence.subtables or { "no-subtables" }
- local features = sequence.features
- if trace_loading then
- report_otf("%3i %-15s %-20s [%s]",nos,name,typ,concat(subtables,","))
- end
- if features then
- for feature, scripts in next, features do
- local tt = { }
- for script, languages in next, scripts do
- local ttt = { }
- for language, _ in next, languages do
- ttt[#ttt+1] = language
+ local cidinfo = raw.cidinfo
+ if cidinfo.registry then
+ local cidmap, cidname = fonts.cid.getmap(cidinfo.registry,cidinfo.ordering,cidinfo.supplement)
+ if cidmap then
+ cidinfo.usedname = cidmap.usedname
+ local uni_to_int, int_to_uni, nofnames, nofunicodes = { }, { }, 0, 0
+ local unicodes, names = cidmap.unicodes, cidmap.names
+ for cidindex=1,#subfonts do
+ local subfont = subfonts[cidindex]
+ if loadmethod == "sparse" then
+ local rawglyphs = subfont.glyphs
+ for index=0,subfont.glyphmax - 1 do
+ local g = rawglyphs[index]
+ if g then
+ local unicode, name = unicodes[index], names[index]
+ if unicode then
+ uni_to_int[unicode] = index
+ int_to_uni[index] = unicode
+ nofunicodes = nofunicodes + 1
+ elseif name then
+ nofnames = nofnames + 1
+ end
+ udglyphs[index] = g
+ glyphs[index] = {
+ width = g.width,
+ italic = g.italic_correction,
+ boundingbox = g.boundingbox,
+ class = g.class,
+ name = g.name or name or "unknown", -- uniXXXX
+ cidindex = cidindex,
+ unicode = unicode,
+ }
+ end
end
- tt[#tt+1] = format("[%s: %s]",script,concat(ttt," "))
- end
- if trace_loading then
- report_otf(" %s: %s",feature,concat(tt," "))
+ -- If we had more userdata, we would need more of this
+ -- and it would start working against us in terms of
+ -- convenience and speed.
+ subfont = somecopy(subfont)
+ subfont.glyphs = nil
+ subfont[cidindex] = subfont
+ elseif loadmethod == "mixed" then
+ for index, g in next, subfont.glyphs do
+ local unicode, name = unicodes[index], names[index]
+ if unicode then
+ uni_to_int[unicode] = index
+ int_to_uni[index] = unicode
+ nofunicodes = nofunicodes + 1
+ elseif name then
+ nofnames = nofnames + 1
+ end
+ udglyphs[index] = g
+ glyphs[index] = {
+ width = g.width,
+ italic = g.italic_correction,
+ boundingbox = g.boundingbox,
+ class = g.class,
+ name = g.name or name or "unknown", -- uniXXXX
+ cidindex = cidindex,
+ unicode = unicode,
+ }
+ end
+ subfont.glyphs = nil
+ else
+ for index, g in next, subfont.glyphs do
+ local unicode, name = unicodes[index], names[index]
+ if unicode then
+ uni_to_int[unicode] = index
+ int_to_uni[index] = unicode
+ nofunicodes = nofunicodes + 1
+ g.unicode = unicode
+ elseif name then
+ nofnames = nofnames + 1
+ end
+ g.cidindex = cidindex
+ glyphs[index] = g
+ end
+ subfont.glyphs = nil
end
end
+ if trace_loading then
+ report_otf("cid font remapped, %s unicode points, %s symbolic names, %s glyphs",nofunicodes, nofnames, nofunicodes+nofnames)
+ end
+ data.map = data.map or { }
+ data.map.map = uni_to_int
+ data.map.backmap = int_to_uni
+ elseif trace_loading then
+ report_otf("unable to remap cid font, missing cid file for %s",filename)
end
+ data.subfonts = subfonts
+ elseif trace_loading then
+ report_otf("font %s has no glyphs",filename)
end
- if trace_loading then
- report_otf("\n")
+ else
+ if loadmethod == "sparse" then
+ -- we get fields from the userdata glyph table and create
+ -- a minimal entry first
+ for index=0,raw.glyphmax - 1 do
+ local g = rawglyphs[index]
+ if g then
+ udglyphs[index] = g
+ glyphs[index] = {
+ width = g.width,
+ italic = g.italic_correction,
+ boundingbox = g.boundingbox,
+ class = g.class,
+ name = g.name,
+ unicode = g.unicode,
+ }
+ end
+ end
+ elseif loadmethod == "mixed" then
+ -- we get fields from the totable glyph table and copy to the
+ -- final glyph table so first we create a minimal entry
+ for index, g in next, rawglyphs do
+ udglyphs[index] = g
+ glyphs[index] = {
+ width = g.width,
+ italic = g.italic_correction,
+ boundingbox = g.boundingbox,
+ class = g.class,
+ name = g.name,
+ unicode = g.unicode,
+ }
+ end
+ else
+ -- we use the totable glyph table directly and manipulate the
+ -- entries in this (also final) table
end
- elseif trace_loading then
- report_otf("font %s has no sequences",filename)
+ data.map = raw.map
end
+ data.cidinfo = raw.cidinfo -- hack
end
--- todo: normalize, design_size => designsize
+-- watch copy of cidinfo: we can best make some more copies to data
-enhancers["reorganize mark classes"] = function(data,filename)
- if data.mark_classes then
- local unicodes = data.luatex.unicodes
+actions["analyze glyphs"] = function(data,filename,raw) -- maybe integrate this in the previous
+ local glyphs = data.glyphs
+ -- collect info
+ local has_italic, widths, marks = false, { }, { }
+ for index, glyph in next, glyphs do
+ local italic = glyph.italic_correction
+ if not italic then
+ -- skip
+ elseif italic == 0 then
+ glyph.italic_correction = nil
+ glyph.italic = nil
+ else
+ glyph.italic_correction = nil
+ glyph.italic = italic
+ has_italic = true
+ end
+ local width = glyph.width
+ widths[width] = (widths[width] or 0) + 1
+ if glyph.class == "mark" then
+ marks[glyph.unicode] = true
+ end
+ local a = glyph.altuni if a then glyph.altuni = nil end
+ local d = glyph.dependents if d then glyph.dependents = nil end
+ local v = glyph.vwidth if v then glyph.vwidth = nil end
+ end
+ -- flag italic
+ data.metadata.has_italic = has_italic
+ -- flag marks
+ data.luatex.marks = marks
+ -- share most common width for cjk fonts
+ local wd, most = 0, 1
+ for k,v in next, widths do
+ if v > most then
+ wd, most = k, v
+ end
+ end
+ if most > 1000 then -- maybe 500
+ if trace_loading then
+ report_otf("most common width: %s (%s times), sharing (cjk font)",wd,most)
+ end
+ for index, glyph in next, glyphs do
+ if glyph.width == wd then
+ glyph.width = nil
+ end
+ end
+ data.luatex.defaultwidth = wd
+ end
+end
+
+actions["reorganize mark classes"] = function(data,filename,raw)
+ local mark_classes = raw.mark_classes
+ if mark_classes then
+ local luatex = data.luatex
+ local unicodes = luatex.unicodes
local reverse = { }
- for name, class in next, data.mark_classes do
+ luatex.markclasses = reverse
+ for name, class in next, mark_classes do
local t = { }
for s in gmatch(class,"[^ ]+") do
local us = unicodes[s]
@@ -446,53 +803,15 @@ enhancers["reorganize mark classes"] = function(data,filename)
end
reverse[name] = t
end
- data.luatex.markclasses = reverse
- data.mark_classes = nil
- end
-end
-
-enhancers["prepare luatex tables"] = function(data,filename)
- data.luatex = data.luatex or { }
- local luatex = data.luatex
- luatex.filename = filename
- luatex.version = otf.version
- luatex.creator = "context mkiv"
-end
-
-local function analyze_features(g, features)
- if g then
- local t, done = { }, { }
- for k=1,#g do
- local f = features or g[k].features
- if f then
- for k=1,#f do
- -- scripts and tag
- local tag = f[k].tag
- if not done[tag] then
- t[#t+1] = tag
- done[tag] = true
- end
- end
- end
- end
- if #t > 0 then
- return t
- end
+ data.mark_classes = nil -- when using table
end
- return nil
-end
-
-enhancers["analyze features"] = function(data,filename)
- -- local luatex = data.luatex
- -- luatex.gposfeatures = analyze_features(data.gpos)
- -- luatex.gsubfeatures = analyze_features(data.gsub)
end
-enhancers["rehash features"] = function(data,filename)
+actions["reorganize features"] = function(data,filename,raw) -- combine with other
local features = { }
data.luatex.features = features
for k, what in next, otf.glists do
- local dw = data[what]
+ local dw = raw[what]
if dw then
local f = { }
features[what] = f
@@ -505,8 +824,10 @@ enhancers["rehash features"] = function(data,filename)
local tag = strip(lower(df.tag))
local ft = f[tag] if not ft then ft = {} f[tag] = ft end
local dscripts = df.scripts
- for script, languages in next, dscripts do
- script = strip(lower(script))
+ for i=1,#dscripts do
+ local d = dscripts[i]
+ local languages = d.langs
+ local script = strip(lower(d.script))
local fts = ft[script] if not fts then fts = {} ft[script] = fts end
for i=1,#languages do
fts[strip(lower(languages[i]))] = true
@@ -519,8 +840,8 @@ enhancers["rehash features"] = function(data,filename)
end
end
-enhancers["analyze anchors"] = function(data,filename)
- local classes = data.anchor_classes
+actions["reorganize anchor classes"] = function(data,filename,raw)
+ local classes = raw.anchor_classes -- anchor classes not in final table
local luatex = data.luatex
local anchor_to_lookup, lookup_to_anchor = { }, { }
luatex.anchor_to_lookup, luatex.lookup_to_anchor = anchor_to_lookup, lookup_to_anchor
@@ -545,148 +866,97 @@ enhancers["analyze anchors"] = function(data,filename)
end
end
-enhancers["analyze marks"] = function(data,filename)
- local glyphs = data.glyphs
- local marks = { }
- data.luatex.marks = marks
- for unicode, index in next, data.luatex.indices do
- local glyph = glyphs[index]
- if glyph.class == "mark" then
- marks[unicode] = true
- end
- end
+actions["prepare tounicode"] = function(data,filename,raw)
+ fonts.map.addtounicode(data,filename)
end
-enhancers["analyze unicodes"] = fonts.map.addtounicode
-
-enhancers["analyze subtables"] = function(data,filename)
- data.luatex = data.luatex or { }
+actions["reorganize subtables"] = function(data,filename,raw)
local luatex = data.luatex
- local sequences = { }
- local lookups = { }
- luatex.sequences = sequences
- luatex.lookups = lookups
- for _, g in next, { data.gsub, data.gpos } do
- for k=1,#g do
- local gk = g[k]
- local typ = gk.type
- if typ == "gsub_contextchain" or typ == "gpos_contextchain" then
- gk.chain = 1
- elseif typ == "gsub_reversecontextchain" or typ == "gpos_reversecontextchain" then
- gk.chain = -1
- else
- gk.chain = 0
- end
- local features = gk.features
- if features then
- sequences[#sequences+1] = gk
- -- scripts, tag, ismac
- local t = { }
- for f=1,#features do
- local feature = features[f]
- local hash = { }
- -- only script and langs matter
- for s, languages in next, feature.scripts do
- s = lower(s)
- local h = hash[s]
- if not h then h = { } hash[s] = h end
- for l=1,#languages do
- h[strip(lower(languages[l]))] = true
- end
+ local sequences, lookups = { }, { }
+ luatex.sequences, luatex.lookups = sequences, lookups
+ for _, what in next, otf.glists do
+ local dw = raw[what]
+ if dw then
+ for k=1,#dw do
+ local gk = dw[k]
+ local typ = gk.type
+ local chain =
+ (typ == "gsub_contextchain" or typ == "gpos_contextchain") and 1 or
+ (typ == "gsub_reversecontextchain" or typ == "gpos_reversecontextchain") and -1 or 0
+ --
+ local subtables = gk.subtables
+ if subtables then
+ local t = { }
+ for s=1,#subtables do
+ local subtable = subtables[s]
+ local name = subtable.name
+ t[#t+1] = name
end
- t[feature.tag] = hash
- end
- gk.features = t
- else
- lookups[gk.name] = gk
- gk.name = nil
- end
- local subtables = gk.subtables
- if subtables then
- local t = { }
- for s=1,#subtables do
- local subtable = subtables[s]
- local name = subtable.name
- t[#t+1] = name
+ subtables = t
end
- gk.subtables = t
- end
- local flags = gk.flags
- if flags then
- gk.flags = { -- forcing false packs nicer
- (flags.ignorecombiningmarks and "mark") or false,
- (flags.ignoreligatures and "ligature") or false,
- (flags.ignorebaseglyphs and "base") or false,
- flags.r2l or false,
- }
- if flags.mark_class then
- gk.markclass = luatex.markclasses[flags.mark_class]
+ local flags, markclass = gk.flags, nil
+ if flags then
+ local t = { -- forcing false packs nicer
+ (flags.ignorecombiningmarks and "mark") or false,
+ (flags.ignoreligatures and "ligature") or false,
+ (flags.ignorebaseglyphs and "base") or false,
+ flags.r2l or false,
+ }
+ markclass = flags.mark_class
+ if markclass then
+ markclass = luatex.markclasses[markclass]
+ end
+ flags = t
end
- end
- end
- end
-end
-
-enhancers["merge cid fonts"] = function(data,filename)
- -- we can also move the names to data.luatex.names which might
- -- save us some more memory (at the cost of harder tracing)
- if data.subfonts then
- if data.glyphs and next(data.glyphs) then
- report_otf("replacing existing glyph table due to subfonts")
- end
- local cidinfo = data.cidinfo
- local verbose = fonts.verbose
- if cidinfo.registry then
- local cidmap, cidname = fonts.cid.getmap(cidinfo.registry,cidinfo.ordering,cidinfo.supplement)
- if cidmap then
- cidinfo.usedname = cidmap.usedname
- local glyphs, uni_to_int, int_to_uni, nofnames, nofunicodes = { }, { }, { }, 0, 0
- local unicodes, names = cidmap.unicodes, cidmap.names
- for n, subfont in next, data.subfonts do
- for index, g in next, subfont.glyphs do
- if not next(g) then
- -- dummy entry
- else
- local unicode, name = unicodes[index], names[index]
- g.cidindex = n
- g.boundingbox = g.boundingbox -- or zerobox
- g.name = g.name or name or "unknown"
- if unicode then
- uni_to_int[unicode] = index
- int_to_uni[index] = unicode
- nofunicodes = nofunicodes + 1
- g.unicode = unicode
- elseif name then
- nofnames = nofnames + 1
- g.unicode = -1
+ --
+ local name = gk.name
+ --
+ local features = gk.features
+ if features then
+ -- scripts, tag, ismac
+ local f = { }
+ for i=1,#features do
+ local df = features[i]
+ local tag = strip(lower(df.tag))
+ local ft = f[tag] if not ft then ft = {} f[tag] = ft end
+ local dscripts = df.scripts
+ for i=1,#dscripts do
+ local d = dscripts[i]
+ local languages = d.langs
+ local script = strip(lower(d.script))
+ local fts = ft[script] if not fts then fts = {} ft[script] = fts end
+ for i=1,#languages do
+ fts[strip(lower(languages[i]))] = true
end
- glyphs[index] = g
end
end
- subfont.glyphs = nil
- end
- if trace_loading then
- report_otf("cid font remapped, %s unicode points, %s symbolic names, %s glyphs",nofunicodes, nofnames, nofunicodes+nofnames)
+ sequences[#sequences+1] = {
+ type = typ,
+ chain = chain,
+ flags = flags,
+ name = name,
+ subtables = subtables,
+ markclass = markclass,
+ features = f,
+ }
+ else
+ lookups[name] = {
+ type = typ,
+ chain = chain,
+ flags = flags,
+ subtables = subtables,
+ markclass = markclass,
+ }
end
- data.glyphs = glyphs
- data.map = data.map or { }
- data.map.map = uni_to_int
- data.map.backmap = int_to_uni
- elseif trace_loading then
- report_otf("unable to remap cid font, missing cid file for %s",filename)
end
- elseif trace_loading then
- report_otf("font %s has no glyphs",filename)
end
end
end
-enhancers["prepare unicode"] = function(data,filename)
+actions["prepare unicodes"] = function(data,filename,raw)
local luatex = data.luatex
- if not luatex then luatex = { } data.luatex = luatex end
local indices, unicodes, multiples, internals = { }, { }, { }, { }
- local glyphs = data.glyphs
- local mapmap = data.map
+ local mapmap = data.map or raw.map
if not mapmap then
report_otf("no map in %s",filename)
mapmap = { }
@@ -700,12 +970,13 @@ enhancers["prepare unicode"] = function(data,filename)
end
local criterium = fonts.privateoffset
local private = criterium
+ local glyphs = data.glyphs
for index, glyph in next, glyphs do
if index > 0 then
- local name = glyph.name
+ local name = glyph.name -- really needed ?
if name then
local unicode = glyph.unicode
- if unicode == -1 or unicode >= criterium then
+ if not unicode or unicode == -1 or unicode >= criterium then
glyph.unicode = private
indices[private] = index
unicodes[name] = private
@@ -718,6 +989,8 @@ enhancers["prepare unicode"] = function(data,filename)
indices[unicode] = index
unicodes[name] = unicode
end
+ else
+ -- message that something is wrong
end
end
end
@@ -729,7 +1002,7 @@ enhancers["prepare unicode"] = function(data,filename)
local un = unicodes[name]
if not un then
unicodes[name] = unicode -- or 0
- elseif type(un) == "number" then
+ elseif type(un) == "number" then -- tonumber(un)
if un ~= unicode then
multiples[#multiples+1] = name
unicodes[name] = { un, unicode }
@@ -754,9 +1027,9 @@ enhancers["prepare unicode"] = function(data,filename)
end
if trace_loading then
if #multiples > 0 then
- report_otf("%s glyph are reused: %s",#multiples, concat(multiples," "))
+ report_otf("%s glyphs are reused: %s",#multiples, concat(multiples," "))
else
- report_otf("no glyph are reused")
+ report_otf("no glyphs are reused")
end
end
luatex.indices = indices
@@ -764,26 +1037,14 @@ enhancers["prepare unicode"] = function(data,filename)
luatex.private = private
end
-enhancers["cleanup ttf tables"] = function(data,filename)
- local ttf_tables = data.ttf_tables
- if ttf_tables then
- for k=1,#ttf_tables do
- if ttf_tables[k].data then ttf_tables[k].data = "deleted" end
- end
+actions["prepare lookups"] = function(data,filename,raw)
+ local lookups = raw.lookups
+ if lookups then
+ data.lookups = lookups
end
- data.ttf_tab_saved = nil
end
-enhancers["compact glyphs"] = function(data,filename)
- table.compact(data.glyphs) -- needed?
- if data.subfonts then
- for _, subfont in next, data.subfonts do
- table.compact(subfont.glyphs) -- needed?
- end
- end
-end
-
-enhancers["reverse coverage"] = function(data,filename)
+actions["reorganize lookups"] = function(data,filename,raw)
-- we prefer the before lookups in a normal order
if data.lookups then
for _, v in next, data.lookups do
@@ -791,7 +1052,7 @@ enhancers["reverse coverage"] = function(data,filename)
for _, vv in next, v.rules do
local c = vv.coverage
if c and c.before then
- c.before = table.reverse(c.before)
+ c.before = reverse(c.before)
end
end
end
@@ -799,35 +1060,18 @@ enhancers["reverse coverage"] = function(data,filename)
end
end
-enhancers["check italic correction"] = function(data,filename)
- local glyphs = data.glyphs
- local ok = false
- for index, glyph in next, glyphs do
- local ic = glyph.italic_correction
- if ic then
- if ic ~= 0 then
- glyph.italic = ic
- end
- glyph.italic_correction = nil
- ok = true
- end
- end
- -- we can use this to avoid calculations
- otf.tables.valid_fields[#otf.tables.valid_fields+1] = "has_italic"
- data.has_italic = true
-end
-
-enhancers["check math"] = function(data,filename)
- if data.math then
+actions["analyze math"] = function(data,filename,raw)
+ if raw.math then
-- we move the math stuff into a math subtable because we then can
-- test faster in the tfm copy
- local glyphs = data.glyphs
+ local glyphs, udglyphs = data.glyphs, data.udglyphs
local unicodes = data.luatex.unicodes
- for index, glyph in next, glyphs do
- local mk = glyph.mathkern
- local hv = glyph.horiz_variants
- local vv = glyph.vert_variants
+ for index, udglyph in next, udglyphs do
+ local mk = udglyph.mathkern
+ local hv = udglyph.horiz_variants
+ local vv = udglyph.vert_variants
if mk or hv or vv then
+ local glyph = glyphs[index]
local math = { }
glyph.math = math
if mk then
@@ -837,7 +1081,6 @@ enhancers["check math"] = function(data,filename)
end
end
math.kerns = mk
- glyph.mathkern = nil
end
if hv then
math.horiz_variants = hv.variants
@@ -853,7 +1096,6 @@ enhancers["check math"] = function(data,filename)
if ic and ic ~= 0 then
math.horiz_italic_correction = ic
end
- glyph.horiz_variants = nil
end
if vv then
local uc = unicodes[index]
@@ -870,221 +1112,48 @@ enhancers["check math"] = function(data,filename)
if ic and ic ~= 0 then
math.vert_italic_correction = ic
end
- glyph.vert_variants = nil
end
local ic = glyph.italic_correction
if ic then
if ic ~= 0 then
math.italic_correction = ic
end
- glyph.italic_correction = nil
end
end
end
end
end
-enhancers["share widths"] = function(data,filename)
- local glyphs = data.glyphs
- local widths = { }
- for index, glyph in next, glyphs do
- local width = glyph.width
- widths[width] = (widths[width] or 0) + 1
- end
- -- share width for cjk fonts
- local wd, most = 0, 1
- for k,v in next, widths do
- if v > most then
- wd, most = k, v
- end
- end
- if most > 1000 then
- if trace_loading then
- report_otf("most common width: %s (%s times), sharing (cjk font)",wd,most)
- end
- for k, v in next, glyphs do
- if v.width == wd then
- v.width = nil
- end
- end
- data.luatex.defaultwidth = wd
- end
-end
-
--- kern: ttf has a table with kerns
-
--- Weird, as maxfirst and maxseconds can have holes, first seems to be indexed, but
--- seconds can start at 2 .. this need to be fixed as getn as well as # are sort of
--- unpredictable alternatively we could force an [1] if not set (maybe I will do that
--- anyway).
-
---~ enhancers["reorganize kerns"] = function(data,filename)
---~ local glyphs, mapmap, unicodes = data.glyphs, data.luatex.indices, data.luatex.unicodes
---~ local mkdone = false
---~ for index, glyph in next, glyphs do
---~ if glyph.kerns then
---~ local mykerns = { }
---~ for k,v in next, glyph.kerns do
---~ local vc, vo, vl = v.char, v.off, v.lookup
---~ if vc and vo and vl then -- brrr, wrong! we miss the non unicode ones
---~ local uvc = unicodes[vc]
---~ if not uvc then
---~ if trace_loading then
---~ report_otf("problems with unicode %s of kern %s at glyph %s",vc,k,index)
---~ end
---~ else
---~ if type(vl) ~= "table" then
---~ vl = { vl }
---~ end
---~ for l=1,#vl do
---~ local vll = vl[l]
---~ local mkl = mykerns[vll]
---~ if not mkl then
---~ mkl = { }
---~ mykerns[vll] = mkl
---~ end
---~ if type(uvc) == "table" then
---~ for u=1,#uvc do
---~ mkl[uvc[u]] = vo
---~ end
---~ else
---~ mkl[uvc] = vo
---~ end
---~ end
---~ end
---~ end
---~ end
---~ glyph.mykerns = mykerns
---~ glyph.kerns = nil -- saves space and time
---~ mkdone = true
---~ end
---~ end
---~ if trace_loading and mkdone then
---~ report_otf("replacing 'kerns' tables by 'mykerns' tables")
---~ end
---~ if data.kerns then
---~ if trace_loading then
---~ report_otf("removing global 'kern' table")
---~ end
---~ data.kerns = nil
---~ end
---~ local dgpos = data.gpos
---~ if dgpos then
---~ local separator = lpeg.P(" ")
---~ local other = ((1 - separator)^0) / unicodes
---~ local splitter = lpeg.Ct(other * (separator * other)^0)
---~ for gp=1,#dgpos do
---~ local gpos = dgpos[gp]
---~ local subtables = gpos.subtables
---~ if subtables then
---~ for s=1,#subtables do
---~ local subtable = subtables[s]
---~ local kernclass = subtable.kernclass -- name is inconsistent with anchor_classes
---~ if kernclass then -- the next one is quite slow
---~ local split = { } -- saves time
---~ for k=1,#kernclass do
---~ local kcl = kernclass[k]
---~ local firsts, seconds, offsets, lookups = kcl.firsts, kcl.seconds, kcl.offsets, kcl.lookup -- singular
---~ if type(lookups) ~= "table" then
---~ lookups = { lookups }
---~ end
---~ local maxfirsts, maxseconds = getn(firsts), getn(seconds)
---~ for _, s in next, firsts do
---~ split[s] = split[s] or lpegmatch(splitter,s)
---~ end
---~ for _, s in next, seconds do
---~ split[s] = split[s] or lpegmatch(splitter,s)
---~ end
---~ for l=1,#lookups do
---~ local lookup = lookups[l]
---~ local function do_it(fk,first_unicode)
---~ local glyph = glyphs[mapmap[first_unicode]]
---~ if glyph then
---~ local mykerns = glyph.mykerns
---~ if not mykerns then
---~ mykerns = { } -- unicode indexed !
---~ glyph.mykerns = mykerns
---~ end
---~ local lookupkerns = mykerns[lookup]
---~ if not lookupkerns then
---~ lookupkerns = { }
---~ mykerns[lookup] = lookupkerns
---~ end
---~ local baseoffset = (fk-1) * maxseconds
---~ for sk=2,maxseconds do -- we can avoid this loop with a table
---~ local sv = seconds[sk]
---~ local splt = split[sv]
---~ if splt then
---~ local offset = offsets[baseoffset + sk]
---~ --~ local offset = offsets[sk] -- (fk-1) * maxseconds + sk]
---~ if offset then
---~ for i=1,#splt do
---~ local second_unicode = splt[i]
---~ if tonumber(second_unicode) then
---~ lookupkerns[second_unicode] = offset
---~ else for s=1,#second_unicode do
---~ lookupkerns[second_unicode[s]] = offset
---~ end end
---~ end
---~ end
---~ end
---~ end
---~ elseif trace_loading then
---~ report_otf("no glyph data for U+%04X", first_unicode)
---~ end
---~ end
---~ for fk=1,#firsts do
---~ local fv = firsts[fk]
---~ local splt = split[fv]
---~ if splt then
---~ for i=1,#splt do
---~ local first_unicode = splt[i]
---~ if tonumber(first_unicode) then
---~ do_it(fk,first_unicode)
---~ else for f=1,#first_unicode do
---~ do_it(fk,first_unicode[f])
---~ end end
---~ end
---~ end
---~ end
---~ end
---~ end
---~ subtable.comment = "The kernclass table is merged into mykerns in the indexed glyph tables."
---~ subtable.kernclass = { }
---~ end
---~ end
---~ end
---~ end
---~ end
---~ end
-
-enhancers["reorganize kerns"] = function(data,filename)
- local glyphs, mapmap, unicodes = data.glyphs, data.luatex.indices, data.luatex.unicodes
+actions["reorganize glyph kerns"] = function(data,filename,raw)
+ local luatex = data.luatex
+ local udglyphs, glyphs, mapmap, unicodes = data.udglyphs, data.glyphs, luatex.indices, luatex.unicodes
local mkdone = false
- local function do_it(lookup,first_unicode,kerns)
+ local function do_it(lookup,first_unicode,extrakerns) -- can be moved inline but seldom used
local glyph = glyphs[mapmap[first_unicode]]
if glyph then
- local mykerns = glyph.mykerns
- if not mykerns then
- mykerns = { } -- unicode indexed !
- glyph.mykerns = mykerns
+ local kerns = glyph.kerns
+ if not kerns then
+ kerns = { } -- unicode indexed !
+ glyph.kerns = kerns
end
- local lookupkerns = mykerns[lookup]
+ local lookupkerns = kerns[lookup]
if not lookupkerns then
lookupkerns = { }
- mykerns[lookup] = lookupkerns
+ kerns[lookup] = lookupkerns
end
- for second_unicode, kern in next, kerns do
+ for second_unicode, kern in next, extrakerns do
lookupkerns[second_unicode] = kern
end
elseif trace_loading then
report_otf("no glyph data for U+%04X", first_unicode)
end
end
- for index, glyph in next, glyphs do
- if glyph.kerns then
- local mykerns = { }
- for k,v in next, glyph.kerns do
+ for index, udglyph in next, data.udglyphs do
+ local kerns = udglyph.kerns
+ if kerns then
+ local glyph = glyphs[index]
+ local newkerns = { }
+ for k,v in next, kerns do
local vc, vo, vl = v.char, v.off, v.lookup
if vc and vo and vl then -- brrr, wrong! we miss the non unicode ones
local uvc = unicodes[vc]
@@ -1098,10 +1167,10 @@ enhancers["reorganize kerns"] = function(data,filename)
end
for l=1,#vl do
local vll = vl[l]
- local mkl = mykerns[vll]
+ local mkl = newkerns[vll]
if not mkl then
mkl = { }
- mykerns[vll] = mkl
+ newkerns[vll] = mkl
end
if type(uvc) == "table" then
for u=1,#uvc do
@@ -1114,21 +1183,14 @@ enhancers["reorganize kerns"] = function(data,filename)
end
end
end
- glyph.mykerns = mykerns
- glyph.kerns = nil -- saves space and time
+ glyph.kerns = newkerns -- udglyph.kerns = nil when in mixed mode
mkdone = true
end
end
if trace_loading and mkdone then
- report_otf("replacing 'kerns' tables by 'mykerns' tables")
+ report_otf("replacing 'kerns' tables by a new 'kerns' tables")
end
- if data.kerns then
- if trace_loading then
- report_otf("removing global 'kern' table")
- end
- data.kerns = nil
- end
- local dgpos = data.gpos
+ local dgpos = raw.gpos
if dgpos then
local separator = lpeg.P(" ")
local other = ((1 - separator)^0) / unicodes
@@ -1193,7 +1255,7 @@ enhancers["reorganize kerns"] = function(data,filename)
end
end
end
- subtable.comment = "The kernclass table is merged into mykerns in the indexed glyph tables."
+ subtable.comment = "The kernclass table is merged into kerns in the indexed glyph tables."
subtable.kernclass = { }
end
end
@@ -1202,14 +1264,10 @@ enhancers["reorganize kerns"] = function(data,filename)
end
end
-enhancers["strip not needed data"] = function(data,filename)
+actions["check glyphs"] = function(data,filename,raw)
local verbose = fonts.verbose
local int_to_uni = data.luatex.unicodes
for k, v in next, data.glyphs do
- local d = v.dependents
- if d then v.dependents = nil end
- local a = v.altuni
- if a then v.altuni = nil end
if verbose then
local code = int_to_uni[k]
-- looks like this is done twice ... bug?
@@ -1232,32 +1290,57 @@ enhancers["strip not needed data"] = function(data,filename)
v.index = nil
end
end
- data.luatex.comment = "Glyph tables have their original index. When present, mykern tables are indexed by unicode."
- data.map = nil
- data.names = nil -- funny names for editors
- data.glyphcnt = nil
- data.glyphmax = nil
- if true then
- data.gpos = nil
- data.gsub = nil
- data.anchor_classes = nil
- end
+ data.luatex.comment = "Glyph tables have their original index. When present, kern tables are indexed by unicode."
end
-enhancers["migrate metadata"] = function(data,filename)
- local global_fields = otf.tables.global_fields
- local metadata = { }
- for k,v in next, data do
- if not global_fields[k] then
- metadata[k] = v
- data[k] = nil
+actions["check metadata"] = function(data,filename,raw)
+ local metadata = data.metadata
+ metadata.method = loadmethod
+ if loadmethod == "sparse" then
+ for _, k in next, mainfields do
+ if valid_fields[k] then
+ local v = raw[k]
+ if global_fields[k] then
+ if not data[k] then
+ data[k] = v
+ end
+ else
+ if not metadata[k] then
+ metadata[k] = v
+ end
+ end
+ end
end
+ else
+ for k, v in next, raw do
+ if valid_fields[k] then
+ if global_fields[k] then
+ if not data[k] then
+ data[v] = v
+ end
+ else
+ if not metadata[k] then
+ metadata[k] = v
+ end
+ end
+ end
+ end
+ end
+ local pfminfo = raw.pfminfo
+ if pfminfo then
+ data.pfminfo = pfminfo
+ metadata.isfixedpitch = metadata.isfixedpitch or (pfminfo.panose and pfminfo.panose.proportion == "Monospaced")
+ metadata.charwidth = pfminfo and pfminfo.avgwidth
end
- data.metadata = metadata
- -- goodies
- local pfminfo = data.pfminfo
- metadata.isfixedpitch = metadata.isfixedpitch or (pfminfo.panose and pfminfo.panose["proportion"] == "Monospaced")
- metadata.charwidth = pfminfo and pfminfo.avgwidth
+ local ttftables = metadata.ttf_tables
+ if ttftables then
+ for i=1,#ttftables do
+ ttftables[i].data = "deleted"
+ end
+ end
+ metadata.xuid = nil
+ data.udglyphs = nil
+ data.map = nil
end
local private_math_parameters = {
@@ -1265,7 +1348,7 @@ local private_math_parameters = {
"FractionDelimiterDisplayStyleSize",
}
-enhancers["check math parameters"] = function(data,filename)
+actions["check math parameters"] = function(data,filename,raw)
local mathdata = data.metadata.math
if mathdata then
for m=1,#private_math_parameters do
@@ -1280,123 +1363,101 @@ enhancers["check math parameters"] = function(data,filename)
end
end
-enhancers["flatten glyph lookups"] = function(data,filename)
- for k, v in next, data.glyphs do
- local lookups = v.lookups
+
+-- kern: ttf has a table with kerns
+--
+-- Weird, as maxfirst and maxseconds can have holes, first seems to be indexed, but
+-- seconds can start at 2 .. this need to be fixed as getn as well as # are sort of
+-- unpredictable alternatively we could force an [1] if not set (maybe I will do that
+-- anyway).
+
+actions["reorganize glyph lookups"] = function(data,filename,raw)
+ local glyphs = data.glyphs
+ for index, udglyph in next, data.udglyphs do
+ local lookups = udglyph.lookups
if lookups then
+ local glyph = glyphs[index]
+ local l = { }
for kk, vv in next, lookups do
+ local aa = { }
+ l[kk] = aa
for kkk=1,#vv do
local vvv = vv[kkk]
local s = vvv.specification
- if s then
- local t = vvv.type
- if t == "ligature" then
- vv[kkk] = { "ligature", s.components, s.char }
- elseif t == "alternate" then
- vv[kkk] = { "alternate", s.components }
- elseif t == "substitution" then
- vv[kkk] = { "substitution", s.variant }
- elseif t == "multiple" then
- vv[kkk] = { "multiple", s.components }
- elseif t == "position" then
- vv[kkk] = { "position", { s.x or 0, s.y or 0, s.h or 0, s.v or 0 } }
- elseif t == "pair" then
- local one, two, paired = s.offsets[1], s.offsets[2], s.paired or ""
- if one then
- if two then
- vv[kkk] = { "pair", paired, { one.x or 0, one.y or 0, one.h or 0, one.v or 0 }, { two.x or 0, two.y or 0, two.h or 0, two.v or 0 } }
- else
- vv[kkk] = { "pair", paired, { one.x or 0, one.y or 0, one.h or 0, one.v or 0 } }
- end
+ local t = vvv.type
+ -- #aa+1
+ if t == "ligature" then
+ aa[kkk] = { "ligature", s.components, s.char }
+ elseif t == "alternate" then
+ aa[kkk] = { "alternate", s.components }
+ elseif t == "substitution" then
+ aa[kkk] = { "substitution", s.variant }
+ elseif t == "multiple" then
+ aa[kkk] = { "multiple", s.components }
+ elseif t == "position" then
+ aa[kkk] = { "position", { s.x or 0, s.y or 0, s.h or 0, s.v or 0 } }
+ elseif t == "pair" then
+ -- maybe flatten this one
+ local one, two, paired = s.offsets[1], s.offsets[2], s.paired or ""
+ if one then
+ if two then
+ aa[kkk] = { "pair", paired, { one.x or 0, one.y or 0, one.h or 0, one.v or 0 }, { two.x or 0, two.y or 0, two.h or 0, two.v or 0 } }
else
- if two then
- vv[kkk] = { "pair", paired, { }, { two.x or 0, two.y or 0, two.h or 0, two.v or 0} } -- maybe nil instead of { }
- else
- vv[kkk] = { "pair", paired }
- end
+ aa[kkk] = { "pair", paired, { one.x or 0, one.y or 0, one.h or 0, one.v or 0 } }
end
else
- if trace_loading then
- report_otf("flattening needed, report to context list")
- end
- for a, b in next, s do
- if trace_loading and vvv[a] then
- report_otf("flattening conflict, report to context list")
- end
- vvv[a] = b
+ if two then
+ aa[kkk] = { "pair", paired, { }, { two.x or 0, two.y or 0, two.h or 0, two.v or 0} } -- maybe nil instead of { }
+ else
+ aa[kkk] = { "pair", paired }
end
- vvv.specification = nil
end
end
end
end
- end
- end
-end
-
-enhancers["simplify glyph lookups"] = function(data,filename)
- for k, v in next, data.glyphs do
- local lookups = v.lookups
- if lookups then
+ -- we could combine this
local slookups, mlookups
- for kk, vv in next, lookups do
+ for kk, vv in next, l do
if #vv == 1 then
if not slookups then
slookups = { }
- v.slookups = slookups
+ glyph.slookups = slookups
end
slookups[kk] = vv[1]
else
if not mlookups then
mlookups = { }
- v.mlookups = mlookups
+ glyph.mlookups = mlookups
end
mlookups[kk] = vv
end
end
- v.lookups = nil
+ glyph.lookups = nil -- when using table
end
end
end
-enhancers["flatten anchor tables"] = function(data,filename)
- for k, v in next, data.glyphs do
- if v.anchors then
- for kk, vv in next, v.anchors do
+actions["reorganize glyph anchors"] = function(data,filename,raw)
+ local glyphs = data.glyphs
+ for index, udglyph in next, data.udglyphs do
+ local anchors = udglyph.anchors
+ if anchors then
+ local glyph = glyphs[index]
+ local a = { }
+ glyph.anchors = a
+ for kk, vv in next, anchors do
+ local aa = { }
+ a[kk] = aa
for kkk, vvv in next, vv do
if vvv.x or vvv.y then
- vv[kkk] = { vvv.x or 0, vvv.y or 0 }
+ aa[kkk] = { vvv.x , vvv.y }
else
+ local aaa = { }
+ aa[kkk] = aaa
for kkkk=1,#vvv do
local vvvv = vvv[kkkk]
- vvv[kkkk] = { vvvv.x or 0, vvvv.y or 0 }
- end
- end
- end
- end
- end
- end
-end
-
-enhancers["flatten feature tables"] = function(data,filename)
- -- is this needed? do we still use them at all?
- for _, tag in next, otf.glists do
- if data[tag] then
- if trace_loading then
- report_otf("flattening %s table", tag)
- end
- for k, v in next, data[tag] do
- local features = v.features
- if features then
- for kk=1,#features do
- local vv = features[kk]
- local t = { }
- local scripts = vv.scripts
- for kkk=1,#scripts do
- local vvv = scripts[kkk]
- t[vvv.script] = vvv.langs
+ aaa[kkkk] = { vvvv.x, vvvv.y }
end
- vv.scripts = t
end
end
end
@@ -1404,22 +1465,12 @@ enhancers["flatten feature tables"] = function(data,filename)
end
end
-enhancers.patches = allocate()
-
-enhancers["patch bugs"] = function(data,filename)
- local basename = file.basename(lower(filename))
- for pattern, action in next, enhancers.patches do
- if find(basename,pattern) then
- action(data,filename)
- end
- end
-end
-
--- tex features
+--~ actions["check extra features"] = function(data,filename,raw)
+--~ -- later, ctx only
+--~ end
-enhancers["enrich with features"] = function(data,filename)
- -- later, ctx only
-end
+-- -- -- -- -- --
+-- -- -- -- -- --
function otf.features.register(name,default)
otf.features.list[#otf.features.list+1] = name
@@ -1496,25 +1547,6 @@ tfmdata.mode = mode
return processes, features
end
---~ {
---~ ['boundingbox']={ 95, -458, 733, 1449 },
---~ ['class']="base",
---~ ['name']="braceleft",
---~ ['unicode']=123,
---~ ['vert_variants']={
---~ ['italic_correction']=0,
---~ ['parts']={
---~ { ['component']="uni23A9", ['endConnectorLength']=1000, ['fullAdvance']=2546, ['is_extender']=0, ['startConnectorLength']=0, }, -- bot
---~ { ['component']="uni23AA", ['endConnectorLength']=2500, ['fullAdvance']=2501, ['is_extender']=1, ['startConnectorLength']=2500, }, -- rep
---~ { ['component']="uni23A8", ['endConnectorLength']=1000, ['fullAdvance']=4688, ['is_extender']=0, ['startConnectorLength']=1000, }, -- mid
---~ { ['component']="uni23AA", ['endConnectorLength']=2500, ['fullAdvance']=2501, ['is_extender']=1, ['startConnectorLength']=2500, }, -- rep
---~ { ['component']="uni23A7", ['endConnectorLength']=0, ['fullAdvance']=2546, ['is_extender']=0, ['startConnectorLength']=1000, }, -- top
---~ },
---~ ['variants']="braceleft braceleft.vsize1 braceleft.vsize2 braceleft.vsize3 braceleft.vsize4 braceleft.vsize5 braceleft.vsize6 braceleft.vsize7",
---~ },
---~ ['width']=793,
---~ },
-
-- the first version made a top/mid/not extensible table, now we just pass on the variants data
-- and deal with it in the tfm scaler (there is no longer an extensible table anyway)
@@ -1622,7 +1654,7 @@ local function copytotfm(data,cache_id) -- we can save a copy when we reorder th
local filename = fonts.tfm.checkedfilename(luatex)
local fontname = metadata.fontname
local fullname = metadata.fullname or fontname
- local cidinfo = data.cidinfo
+ local cidinfo = data.cidinfo -- or { }
local units = metadata.units_per_em or 1000
--
cidinfo.registry = cidinfo and cidinfo.registry or "" -- weird here, fix upstream
@@ -1643,7 +1675,7 @@ local function copytotfm(data,cache_id) -- we can save a copy when we reorder th
if metadata.isfixedpitch then
parameters.space_stretch = 0
parameters.space_shrink = 0
- elseif otf.syncspace then --
+ elseif syncspace then --
parameters.space_stretch = spaceunits/2
parameters.space_shrink = spaceunits/3
end
diff --git a/tex/context/base/font-otn.lua b/tex/context/base/font-otn.lua
index 4109ca2d0..608e42fb3 100644
--- a/tex/context/base/font-otn.lua
+++ b/tex/context/base/font-otn.lua
@@ -2471,7 +2471,7 @@ local function prepare_lookups(tfmdata)
end
end
end
- local list = glyph.mykerns
+ local list = glyph.kerns
if list then
for lookup, krn in next, list do
local k = kerns[lookup]
diff --git a/tex/context/base/font-otp.lua b/tex/context/base/font-otp.lua
index 8df02e135..6453268bf 100644
--- a/tex/context/base/font-otp.lua
+++ b/tex/context/base/font-otp.lua
@@ -39,7 +39,7 @@ local function tabstr(t) -- hashed from core-uti / experiment
return concat(s,",")
end
-function enhancers.pack(data)
+local function packdata(data)
if data then
local h, t, c = { }, { }, { }
local hh, tt, cc = { }, { }, { }
@@ -140,7 +140,7 @@ function enhancers.pack(data)
end
end
end
- local m = v.mykerns
+ local m = v.kerns
if m then
for k,v in next, m do
m[k] = pack(v)
@@ -267,9 +267,9 @@ function enhancers.pack(data)
for pass=1,2 do
local pack = (pass == 1 and pack_1) or pack_2
for k, v in next, data.glyphs do
- local m = v.mykerns
+ local m = v.kerns
if m then
- v.mykerns = pack(m)
+ v.kerns = pack(m)
end
local m = v.math
if m then
@@ -305,7 +305,7 @@ function enhancers.pack(data)
end
end
-function enhancers.unpack(data)
+local function unpackdata(data)
if data then
local t = data.tables
if t then
@@ -344,11 +344,11 @@ function enhancers.unpack(data)
end
end
end
- local m = v.mykerns
+ local m = v.kerns
if m then
local tm = t[m]
if tm then
- v.mykerns = tm
+ v.kerns = tm
if unpacked[tm] then
m = false
else
@@ -508,3 +508,6 @@ function enhancers.unpack(data)
end
end
end
+
+otf.enhancers.register( "pack", packdata)
+otf.enhancers.register("unpack",unpackdata)
diff --git a/tex/context/base/font-pat.lua b/tex/context/base/font-pat.lua
index 9f679f663..20e68489c 100644
--- a/tex/context/base/font-pat.lua
+++ b/tex/context/base/font-pat.lua
@@ -17,7 +17,7 @@ local report_otf = logs.new("load otf")
-- older versions of latin modern didn't have the designsize set
-- so for them we get it from the name
-local patches = fonts.otf.enhancers.patches
+local register = enhancers.patches.register
local function patch(data,filename)
if data.design_size == 0 then
@@ -29,6 +29,13 @@ local function patch(data,filename)
data.design_size = tonumber(ds) * 10
end
end
+end
+
+register("after","migrate metadata","^lmroman", patch)
+register("after","migrate metadata","^lmsans", patch)
+register("after","migrate metadata","^lmtypewriter",patch)
+
+local function patch(data,filename)
local uni_to_ind = data.map.map
if not uni_to_ind[0x391] then
-- beware, this is a hack, features for latin often don't apply to greek
@@ -50,21 +57,11 @@ local function patch(data,filename)
uni_to_ind[0x3A7] = uni_to_ind[0x58]
uni_to_ind[0x396] = uni_to_ind[0x5A]
end
- -- better make this into a feature
- --
- -- local glyphs = data.glyphs
- -- for i=0x300,0x36F do
- -- local c = glyphs[uni_to_ind[i]]
- -- if c and c.width == 0 then
- -- local boundingbox = c.boundingbox
- -- c.width = boundingbox[3] - boundingbox[1]
- -- end
- -- end
end
-patches["^lmroman"] = patch
-patches["^lmsans"] = patch
-patches["^lmtypewriter"] = patch
+register("after","prepare glyphs","^lmroman", patch)
+register("after","prepare glyphs","^lmsans", patch)
+register("after","prepare glyphs","^lmtypewriter",patch)
-- for some reason (either it's a bug in the font, or it's
-- a problem in the library) the palatino arabic fonts don't
@@ -81,12 +78,13 @@ local function patch(data,filename)
end
v.features = {
{
- scripts = {
- {
- langs = { "ARA ", "FAR ", "URD ", "dflt" },
- script = "arab",
- },
- },
+--~ scripts = {
+--~ {
+--~ langs = { "ARA ", "FAR ", "URD ", "dflt" },
+--~ script = "arab",
+--~ },
+--~ },
+ scripts = { arab = { "ARA " = true, "FAR " = true, "URD " = true, "dflt" = true } },
tag = "mkmk"
}
}
@@ -95,10 +93,10 @@ local function patch(data,filename)
end
end
-patches["palatino.*arabic"] = patch
+register("after","rehash features","palatino.*arabic",patch)
local function patch_domh(data,filename,threshold)
- local m = data.math
+ local m = data.metadata.math
if m then
local d = m.DisplayOperatorMinHeight or 0
if d < threshold then
@@ -108,21 +106,8 @@ local function patch_domh(data,filename,threshold)
m.DisplayOperatorMinHeight = threshold
end
end
--- if tex.luatexversion < 48 then
--- for _, g in next, data.glyphs do
--- local name = g.name
--- if find(name,"^integral$") or find(name,"^integral%.vsize") then
--- local width, italic = g.width or 0, g.italic_correction or 0
--- local newwidth = width - italic
--- if trace_loading then
--- report_otf("patching width of %s: %s (width) - %s (italic) = %s",name,width,italic,newwidth)
--- end
--- g.width = newwidth
--- end
--- end
--- end
end
-patches["cambria"] = function(data,filename) patch_domh(data,filename,2800) end
-patches["cambmath"] = function(data,filename) patch_domh(data,filename,2800) end
-patches["asana"] = function(data,filename) patch_domh(data,filename,1350) end
+register("after","check math parameters","cambria", function(data,filename) patch_domh(data,filename,2800) end)
+register("after","check math parameters","cambmath",function(data,filename) patch_domh(data,filename,2800) end)
+register("after","check math parameters","asana", function(data,filename) patch_domh(data,filename,1350) end)
diff --git a/tex/context/base/l-io.lua b/tex/context/base/l-io.lua
index fe988b107..f9a663519 100644
--- a/tex/context/base/l-io.lua
+++ b/tex/context/base/l-io.lua
@@ -38,6 +38,7 @@ function io.savedata(filename,data,joiner)
f:write(data or "")
end
f:close()
+ io.flush()
return true
else
return false
diff --git a/tex/context/base/l-table.lua b/tex/context/base/l-table.lua
index 331bd9ca0..996e36a83 100644
--- a/tex/context/base/l-table.lua
+++ b/tex/context/base/l-table.lua
@@ -193,20 +193,22 @@ function table.imerged(...)
return tmp
end
-local function fastcopy(old) -- fast one
+local function fastcopy(old,metatabletoo) -- fast one
if old then
local new = { }
for k,v in next, old do
if type(v) == "table" then
- new[k] = fastcopy(v) -- was just table.copy
+ new[k] = fastcopy(v,metatabletoo) -- was just table.copy
else
new[k] = v
end
end
- -- optional second arg
- local mt = getmetatable(old)
- if mt then
- setmetatable(new,mt)
+ if metatabletoo then
+ -- optional second arg
+ local mt = getmetatable(old)
+ if mt then
+ setmetatable(new,mt)
+ end
end
return new
else
@@ -214,6 +216,8 @@ local function fastcopy(old) -- fast one
end
end
+-- todo : copy without metatable
+
local function copy(t, tables) -- taken from lua wiki, slightly adapted
tables = tables or { }
local tcopy = {}
@@ -660,6 +664,7 @@ function table.tofile(filename,root,name,reduce,noquotes,hexify)
serialize(root,name,flush,reduce,noquotes,hexify)
end
f:close()
+ io.flush()
end
end
diff --git a/tex/context/base/lpdf-ano.lua b/tex/context/base/lpdf-ano.lua
index a56c8fdeb..5a98a6e81 100644
--- a/tex/context/base/lpdf-ano.lua
+++ b/tex/context/base/lpdf-ano.lua
@@ -245,9 +245,81 @@ function codeinjections.prerollreference(actions) -- share can become option
end
end
-local lln = latelua_node() if not node.has_field(lln,'string') then
-
- function nodeinjections.reference(width,height,depth,prerolled) -- keep this one
+--~ local lln = latelua_node() if not node.has_field(lln,'string') then
+
+--~ function nodeinjections.reference(width,height,depth,prerolled) -- keep this one
+--~ if prerolled then
+--~ if trace_references then
+--~ report_references("w=%s, h=%s, d=%s, a=%s",width,height,depth,prerolled)
+--~ end
+--~ return pdfannotation_node(width,height,depth,prerolled)
+--~ end
+--~ end
+
+--~ function codeinjections.finishreference()
+--~ end
+
+--~ else
+
+--~ report_references("hashing annotations")
+
+--~ local delayed = { }
+--~ local hashed = { }
+--~ local sharing = true -- we can do this for special refs (so we need an extra argument)
+
+--~ local function flush()
+--~ local n = 0
+--~ for k,v in next, delayed do
+--~ pdfimmediateobject(k,v)
+--~ n = n + 1
+--~ end
+--~ if trace_references then
+--~ report_references("%s annotations flushed",n)
+--~ end
+--~ delayed = { }
+--~ end
+
+--~ lpdf.registerpagefinalizer (flush,3,"annotations") -- somehow this lags behind .. I need to look into that some day
+--~ lpdf.registerdocumentfinalizer(flush,3,"annotations") -- so we need a final flush too
+
+--~ local factor = number.dimenfactors.bp
+
+--~ function codeinjections.finishreference(width,height,depth,prerolled)
+--~ local h, v = pdf.h, pdf.v
+--~ local llx, lly = h*factor, (v - depth)*factor
+--~ local urx, ury = (h + width)*factor, (v + height)*factor
+--~ local annot = format("<< /Type /Annot %s /Rect [%s %s %s %s] >>",prerolled,llx,lly,urx,ury)
+--~ local n = sharing and hashed[annot]
+--~ if not n then
+--~ n = pdfreserveobject() -- todo: share
+--~ delayed[n] = annot
+--~ --~ n = pdf.obj(annot)
+--~ --~ pdf.refobj(n)
+--~ if sharing then
+--~ hashed[annot] = n
+--~ end
+--~ end
+--~ pdfregisterannot(n)
+--~ end
+
+--~ _bpnf_ = codeinjections.finishreference
+
+--~ function nodeinjections.reference(width,height,depth,prerolled)
+--~ if prerolled then
+--~ if trace_references then
+--~ report_references("w=%s, h=%s, d=%s, a=%s",width,height,depth,prerolled)
+--~ end
+--~ -- local luacode = format("backends.pdf.codeinjections.finishreference(%s,%s,%s,'%s')",width,height,depth,prerolled)
+--~ local luacode = format("_bpnf_(%s,%s,%s,'%s')",width,height,depth,prerolled)
+--~ return latelua_node(luacode)
+--~ end
+--~ end
+
+--~ end node.free(lln)
+
+local function use_normal_annotations()
+
+ local function reference(width,height,depth,prerolled) -- keep this one
if prerolled then
if trace_references then
report_references("w=%s, h=%s, d=%s, a=%s",width,height,depth,prerolled)
@@ -256,35 +328,35 @@ local lln = latelua_node() if not node.has_field(lln,'string') then
end
end
- function codeinjections.finishreference()
+ local function finishreference()
end
-else
+ return reference, finishreference
- report_references("hashing annotations")
+end
- local delayed = { }
- local hashed = { }
- local sharing = true -- we can do this for special refs (so we need an extra argument)
+local delayed, hashed, sharing = { }, { }, true -- we can do this for special refs (so we need an extra argument)
- local function flush()
- local n = 0
- for k,v in next, delayed do
- pdfimmediateobject(k,v)
- n = n + 1
- end
- if trace_references then
- report_references("%s annotations flushed",n)
- end
- delayed = { }
+local function flush()
+ local n = 0
+ for k,v in next, delayed do
+ pdfimmediateobject(k,v)
+ n = n + 1
end
+ if trace_references then
+ report_references("%s annotations flushed",n)
+ end
+ delayed = { }
+end
+
+lpdf.registerdocumentfinalizer(flush,3,"annotations") -- so we need a final flush too
+lpdf.registerpagefinalizer (flush,3,"annotations") -- somehow this lags behind .. I need to look into that some day
- lpdf.registerpagefinalizer (flush,3,"annotations") -- somehow this lags behind .. I need to look into that some day
- lpdf.registerdocumentfinalizer(flush,3,"annotations") -- so we need a final flush too
+local function use_shared_annotations()
local factor = number.dimenfactors.bp
- function codeinjections.finishreference(width,height,depth,prerolled)
+ local function finishreference(width,height,depth,prerolled)
local h, v = pdf.h, pdf.v
local llx, lly = h*factor, (v - depth)*factor
local urx, ury = (h + width)*factor, (v + height)*factor
@@ -302,9 +374,9 @@ else
pdfregisterannot(n)
end
- _bpnf_ = codeinjections.finishreference
+ _bpnf_ = finishreference
- function nodeinjections.reference(width,height,depth,prerolled)
+ local function reference(width,height,depth,prerolled)
if prerolled then
if trace_references then
report_references("w=%s, h=%s, d=%s, a=%s",width,height,depth,prerolled)
@@ -315,8 +387,33 @@ else
end
end
+ return reference, finishreference
+
+end
+
+local lln = latelua_node() if node.has_field(lln,'string') then
+
+ directives.register("refences.sharelinks", function(v)
+ if v then
+ backends.nodeinjections.reference, backends.codeinjections.finishreference = use_shared_annotations()
+ else
+ backends.nodeinjections.reference, backends.codeinjections.finishreference = use_normal_annotations()
+ end
+ end)
+
+ nodeinjections.reference, codeinjections.finishreference = use_shared_annotations()
+
+else
+
+ nodeinjections.reference, codeinjections.finishreference = use_normal_annotations()
+
end node.free(lln)
+-- -- -- --
+-- -- -- --
+
+
+
function nodeinjections.destination(width,height,depth,name,view)
if trace_destinations then
report_destinations("w=%s, h=%s, d=%s, n=%s, v=%s",width,height,depth,name,view or "no view")
diff --git a/tex/context/base/pack-box.mkiv b/tex/context/base/pack-box.mkiv
index 2c25f5c3a..09af1d633 100644
--- a/tex/context/base/pack-box.mkiv
+++ b/tex/context/base/pack-box.mkiv
@@ -482,7 +482,7 @@
\if!!donea
\advance\scratchdimen\dimexpr \MPx\currentbgposition-\MPx\currentpageposition\relax
\else\if!!doneb
- \scratchdimen\dimexpr\paperwidth-\MPx\currentbgposition-\MPx\currentpageposition\relax % not checked
+ \scratchdimen\dimexpr\paperwidth-\MPx\currentbgposition+\MPx\currentpageposition\relax % not checked
\fi\fi
\fi
\advance\scratchdimen\@@bghoffset
@@ -490,7 +490,7 @@
\scratchdimen\@@bgheight
\ifdone
\if!!donec
- \scratchdimen\dimexpr\paperheight-\MPy\currentbgposition-\MPy\currentpageposition\relax % not checked
+ \scratchdimen\dimexpr\paperheight-\MPy\currentbgposition+\MPy\currentpageposition\relax % not checked
\else\if!!doned
\advance\scratchdimen\dimexpr \MPy\currentbgposition-\MPy\currentpageposition\relax % not checked
\fi\fi
diff --git a/tex/context/base/page-ini.mkiv b/tex/context/base/page-ini.mkiv
index 3cc0778f9..66ab776b9 100644
--- a/tex/context/base/page-ini.mkiv
+++ b/tex/context/base/page-ini.mkiv
@@ -565,8 +565,7 @@
\fi
\fi#1#2%
\resetselectiepagina
- \incrementpagenumber
- \incrementsubpagenumber
+ \doincrementpageboundcounters % should hook into an every
\checkpagedimensions
\ifnum\outputpenalty>\superpenalty \else
\dosupereject
diff --git a/tex/context/base/scrn-nav.mkiv b/tex/context/base/scrn-nav.mkiv
index bc27cd973..7b8fbdfa7 100644
--- a/tex/context/base/scrn-nav.mkiv
+++ b/tex/context/base/scrn-nav.mkiv
@@ -56,11 +56,11 @@
\appendtoks
\doifelse\@@iastate\v!start
{\iflocation\else
- \showmessage\m!interactions2{\ifusepagedestinations\space(PAGE)\fi}%
+ \showmessage\m!interactions2{(page mode: \@@iapage)}%
\global\locationtrue
\fi}%
{\iflocation
- \showmessage\m!interactions3{\ifusepagedestinations\space(PAGE)\fi}%
+ \showmessage\m!interactions3{(page mode: \@@iapage)}%
\global\locationfalse
\fi}%
\iflocation
@@ -73,9 +73,12 @@
\doifelse\@@iastrut \v!yes \settrue \setfalse \uselocationstrut
\doifelse\@@iaclick \v!yes \settrue \setfalse \highlighthyperlinks
\doifelse\@@iadisplay\v!new \settrue \setfalse \gotonewwindow
- \doifelse\@@iapage \v!yes \settrue \setfalse \usepagedestinations
+ \doifnot \@@iapage \v!no \dosetpagedestinations
\to \everysetupinteraction
+\def\dosetpagedestinations
+ {\ctxlua{structures.references.setinnermethod("\@@iapage")}}
+
\def\synchronizebackendidentity
{\ctxlua{backends.codeinjections.setupidentity{
title = \!!bs\@@iatitle\!!es,
diff --git a/tex/context/base/scrp-cjk.lua b/tex/context/base/scrp-cjk.lua
index 7c1310528..44212a098 100644
--- a/tex/context/base/scrp-cjk.lua
+++ b/tex/context/base/scrp-cjk.lua
@@ -553,7 +553,8 @@ local function process(head,first,last)
if not pcjk or not ncjk
or pcjk == "korean" or ncjk == "korean"
or pcjk == "other" or ncjk == "other"
- or pcjk == "jamo_final" or ncjk == "jamo_initial" then
+ -- or pcjk == "jamo_final" or ncjk == "jamo_initial" then
+ or pcjk == "jamo_final" or ncjk == "jamo_initial" or pcjk == "half_width_close" or ncjk == "half_width_open" then
previous = "start"
else -- if head ~= first then
remove_node(head,first,true)
diff --git a/tex/context/base/strc-des.mkiv b/tex/context/base/strc-des.mkiv
index 9929cc1c5..5f25ac60d 100644
--- a/tex/context/base/strc-des.mkiv
+++ b/tex/context/base/strc-des.mkiv
@@ -602,7 +602,7 @@
\def\dosetupenumerationcounter#1%
{\edef\currentenumerationcountername{#1}% only used in the token list
- \edef\currentdiscription{#1}%
+ \edef\currentdescription{#1}%
\the\everysetupenumerationcounter}
\appendtoks
diff --git a/tex/context/base/strc-num.lua b/tex/context/base/strc-num.lua
index 1b26a4a7a..f42b11b32 100644
--- a/tex/context/base/strc-num.lua
+++ b/tex/context/base/strc-num.lua
@@ -161,9 +161,17 @@ local function savevalue(name,i)
local cd = counterdata[name].data[i]
local cs = tobesaved[name][i]
local cc = collected[name]
+ if trace_counters then
+ report_counters("saving value %s of counter named %s",cd.number,name)
+ end
local cr = cd.range
local old = (cc and cc[i] and cc[i][cr]) or 0
- cs[cr] = cd.number
+ local number = cd.number
+ if cd.method == variables.page then
+ -- we can be one page ahead
+ number = number - 1
+ end
+ cs[cr] = (number >= 0) and number or 0
cd.range = cr + 1
return old
else
@@ -171,11 +179,12 @@ local function savevalue(name,i)
end
end
-function counters.define(name, start, counter) -- todo: step
+function counters.define(name, start, counter, method) -- todo: step
local d = allocate(name,1)
d.start = start
if counter ~= "" then
d.counter = counter -- only for special purposes, cannot be false
+ d.method = method -- frozen at define time
end
end
diff --git a/tex/context/base/strc-num.mkiv b/tex/context/base/strc-num.mkiv
index f675e4ac3..d2ed5dad1 100644
--- a/tex/context/base/strc-num.mkiv
+++ b/tex/context/base/strc-num.mkiv
@@ -108,7 +108,10 @@
\def\dododefinestructurecounter[#1][#2]%
{\getparameters[\??nn#1][\s!counter=,#2]% counter is for internal purposes
- \ctxlua{structures.counters.define("#1",tonumber("\structurecounterparameter{#1}\c!start") or 0,"\structurecounterparameter{#1}\s!counter")}%
+ \ctxlua{structures.counters.define("#1",
+ tonumber("\structurecounterparameter{#1}\c!start") or 0,
+ "\structurecounterparameter{#1}\s!counter",
+ "\structurecounterparameter{#1}\c!method")}%
\docheckstructurecountersetup{#1}}
\def\donodefinestructurecounter[#1][#2]% inherit
diff --git a/tex/context/base/strc-pag.mkiv b/tex/context/base/strc-pag.mkiv
index 2d6a6aaf1..8d18b9e56 100644
--- a/tex/context/base/strc-pag.mkiv
+++ b/tex/context/base/strc-pag.mkiv
@@ -71,9 +71,9 @@
% \stopbodymatter
% \stoptext
-\definestructurecounter[\s!realpage][\c!prefix=\v!no,\c!start=1,\c!prefixsegments=,\s!counter=realpageno]
-\definestructurecounter[\s!userpage][\c!prefix=\v!no,\c!start=1,\c!prefixsegments=,\s!counter=userpageno]
-\definestructurecounter[\s!subpage] [\c!prefix=\v!no,\c!start=1,\c!prefixsegments=,\s!counter=subpageno]
+\definestructurecounter[\s!realpage][\c!prefix=\v!no,\c!start=1,\c!prefixsegments=,\s!counter=realpageno,\c!method=\v!page]
+\definestructurecounter[\s!userpage][\c!prefix=\v!no,\c!start=1,\c!prefixsegments=,\s!counter=userpageno,\c!method=\v!page]
+\definestructurecounter[\s!subpage] [\c!prefix=\v!no,\c!start=1,\c!prefixsegments=,\s!counter=subpageno, \c!method=\v!page]
\newtoks\everysetuprealpagenumber % todo: set state: none, start, stop, reset
\newtoks\everysetupuserpagenumber % todo: set state: none, start, stop, reset
@@ -221,11 +221,18 @@
\def\nextuserpagenumber {\directconvertedstructurecounter\s!userpage\v!next}
\def\nextsubpagenumber {\directconvertedstructurecounter\s!subpage \v!next}
-\appendtoks
- \decrementstructurecounter[\s!realpage]%
+\def\dodeincrementpageboundcounters % only at the end
+ {\decrementstructurecounter[\s!realpage]%
\decrementstructurecounter[\s!userpage]%
- \decrementstructurecounter[\s!subpage ]%
-\to\everygoodbye
+ \decrementstructurecounter[\s!subpage ]}
+
+\def\doincrementpageboundcounters
+ {\incrementpagenumber
+ \incrementsubpagenumber}
+
+\appendtoks
+ \dodeincrementpageboundcounters
+\to \everygoodbye
% Equivalents (compatibility):
%
diff --git a/tex/context/base/strc-ref.lua b/tex/context/base/strc-ref.lua
index 1d7a94c44..67436e0e3 100644
--- a/tex/context/base/strc-ref.lua
+++ b/tex/context/base/strc-ref.lua
@@ -957,7 +957,13 @@ end
local innermethod = "names"
function references.setinnermethod(m)
- innermethod = m -- page names mixed
+ if m then
+ if m == "page" or m == "mixed" or m == "names" then
+ innermethod = m
+ elseif m == true or m == variables.yes then
+ innermethod = "page"
+ end
+ end
function references.setinnermethod()
report_references("inner method is already set and frozen to '%s'",innermethod)
end
@@ -967,6 +973,10 @@ function references.getinnermethod()
return innermethod or "names"
end
+directives.register("references.linkmethod", function(v) -- page mixed names
+ references.setinnermethod(v)
+end)
+
function references.setinternalreference(prefix,tag,internal,view)
if innermethod == "page" then
return unsetvalue
diff --git a/tex/context/base/strc-tag.lua b/tex/context/base/strc-tag.lua
index 7701cc57e..d6dcab81f 100644
--- a/tex/context/base/strc-tag.lua
+++ b/tex/context/base/strc-tag.lua
@@ -55,9 +55,9 @@ local properties = allocate {
itemtag = { pdf = "Lbl", nature = "mixed" },
itemcontent = { pdf = "LBody", nature = "mixed" },
- description = { pdf = "Li", nature = "display" },
- descriptiontag = { pdf = "Lbl", nature = "mixed" },
- descriptioncontent = { pdf = "LBody", nature = "mixed" },
+ description = { pdf = "Div", nature = "display" },
+ descriptiontag = { pdf = "Div", nature = "mixed" },
+ descriptioncontent = { pdf = "Div", nature = "mixed" },
descriptionsymbol = { pdf = "Span", nature = "inline" }, -- note reference
verbatimblock = { pdf = "Code", nature = "display" },
@@ -91,7 +91,7 @@ local properties = allocate {
delimited = { pdf = "Quote", nature = "inline" },
subsentence = { pdf = "Span", nature = "inline" },
- float = { pdf = "Div", nature = "display" },
+ float = { pdf = "Div", nature = "display" }, -- Figure
floatcaption = { pdf = "Caption", nature = "display" },
floattag = { pdf = "Span", nature = "mixed" },
floattext = { pdf = "Span", nature = "mixed" },
@@ -101,7 +101,7 @@ local properties = allocate {
mpgraphic = { pdf = "P", nature = "mixed" },
formulaset = { pdf = "Div", nature = "display" },
- formula = { pdf = "Div", nature = "display" },
+ formula = { pdf = "Div", nature = "display" }, -- Formula
formulatag = { pdf = "Span", nature = "mixed" },
formulacontent = { pdf = "P", nature = "display" },
subformula = { pdf = "Div", nature = "display" },
diff --git a/tex/context/base/syst-ini.tex b/tex/context/base/syst-ini.tex
index d4b024c30..c4b326d96 100644
--- a/tex/context/base/syst-ini.tex
+++ b/tex/context/base/syst-ini.tex
@@ -235,13 +235,13 @@
\let\newfam\newfamily
-% watch out, for the moment we disable the check for already being defined
-% later we will revert this but first all chardefs must be replaced
+% Watch out, for the moment we disable the check for already being defined
+% later we will revert this but first all chardefs must be replaced.
\def\newconstant #1{\ifdefined#1\let#1\undefined\fi\newcount#1}
\def\setnewconstant#1{\ifdefined#1\let#1\undefined\fi\newcount#1#1} % just a number
-% matbe setconstant with check
+% maybe setconstant with check
% %D The next definitions are really needed (in \CONTEXT):
diff --git a/tex/context/base/util-pck.lua b/tex/context/base/util-pck.lua
index 835c70800..585123b5c 100644
--- a/tex/context/base/util-pck.lua
+++ b/tex/context/base/util-pck.lua
@@ -29,6 +29,18 @@ local function hashed(t)
return concat(s,",")
end
+local function simplehashed(t)
+ local s = { }
+ for k, v in next, t do
+ s[#s+1] = k.."="..v
+ end
+ sort(s)
+ return concat(s,",")
+end
+
+packers.hashed = hashed
+packers.simplehashed = simplehashed
+
local function pack(t,keys,hash,index)
for k,v in next, t do
if type(v) == "table" then
diff --git a/tex/generic/context/luatex-fonts-merged.lua b/tex/generic/context/luatex-fonts-merged.lua
index 3e64855a8..25c0f2d9d 100644
--- a/tex/generic/context/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
-- merged file : luatex-fonts-merged.lua
-- parent file : luatex-fonts.lua
--- merge date : 09/05/10 13:23:12
+-- merge date : 09/09/10 23:45:11
do -- begin closure to overcome local limits and interference
@@ -830,20 +830,22 @@ function table.imerged(...)
return tmp
end
-local function fastcopy(old) -- fast one
+local function fastcopy(old,metatabletoo) -- fast one
if old then
local new = { }
for k,v in next, old do
if type(v) == "table" then
- new[k] = fastcopy(v) -- was just table.copy
+ new[k] = fastcopy(v,metatabletoo) -- was just table.copy
else
new[k] = v
end
end
- -- optional second arg
- local mt = getmetatable(old)
- if mt then
- setmetatable(new,mt)
+ if metatabletoo then
+ -- optional second arg
+ local mt = getmetatable(old)
+ if mt then
+ setmetatable(new,mt)
+ end
end
return new
else
@@ -851,6 +853,8 @@ local function fastcopy(old) -- fast one
end
end
+-- todo : copy without metatable
+
local function copy(t, tables) -- taken from lua wiki, slightly adapted
tables = tables or { }
local tcopy = {}
@@ -1297,6 +1301,7 @@ function table.tofile(filename,root,name,reduce,noquotes,hexify)
serialize(root,name,flush,reduce,noquotes,hexify)
end
f:close()
+ io.flush()
end
end
@@ -1961,6 +1966,7 @@ function io.savedata(filename,data,joiner)
f:write(data or "")
end
f:close()
+ io.flush()
return true
else
return false
@@ -5283,7 +5289,11 @@ fonts.map.addtounicode = function(data,filename)
t[#t+1] = u
end
end
- if #t > 0 then -- done then
+ if #t == 0 then -- done then
+ -- nothing
+ elseif #t == 1 then
+ originals[index], tounicode[index], nl, unicode = t[1], tounicode16(t[1]), nl + 1, true
+ else
originals[index], tounicode[index], nl, unicode = t, tounicode16sequence(t), nl + 1, true
end
end
@@ -5434,6 +5444,11 @@ if not modules then modules = { } end modules ['font-otf'] = {
license = "see context related readme files"
}
+-- langs -> languages enz
+-- anchor_classes vs kernclasses
+-- modification/creationtime in subfont is runtime dus zinloos
+-- to_table -> totable
+
local utf = unicode.utf8
local concat, utfbyte = table.concat, utf.byte
@@ -5442,6 +5457,8 @@ local type, next, tonumber, tostring = type, next, tonumber, tostring
local abs = math.abs
local getn = table.getn
local lpegmatch = lpeg.match
+local reverse = table.reverse
+local ioflush = io.flush
local allocate = utilities.storage.allocate
@@ -5455,42 +5472,7 @@ local trace_defining = false trackers.register("fonts.defining", function(v
local report_otf = logs.new("load otf")
---~ trackers.enable("otf.loading")
-
---[[ldx--
-<p>The fontforge table has organized lookups in a certain way. A first implementation
-of this code was organized featurewise: information related to features was
-collected and processing boiled down to a run over the features. The current
-implementation honors the order in the main feature table. Since we can reorder this
-table as we want, we can eventually support several models of processing. We kept
-the static as well as dynamic feature processing, because it had proved to be
-rather useful. The formerly three loop variants have beem discarded but will
-reapear at some time.</p>
-
-<itemize>
-<item>we loop over all lookups</item>
-<item>for each lookup we do a run over the list of glyphs</item>
-<item>but we only process them for features that are enabled</item>
-<item>if we're dealing with a contextual lookup, we loop over all contexts</item>
-<item>in that loop we quit at a match and then process the list of sublookups</item>
-<item>we always continue after the match</item>
-</itemize>
-
-<p>In <l n='context'/> we do this for each font that is used in a list, so in
-practice we have quite some nested loops.</p>
-
-<p>We process the whole list and then consult the glyph nodes. An alternative approach
-is to collect strings of characters using the same font including spaces (because some
-lookups involve spaces). However, we then need to reconstruct the list which is no fun.
-Also, we need to carry quite some information, like attributes, so eventually we don't
-gain much (if we gain something at all).</p>
-
-<p>Another consideration has been to operate on sublists (subhead, subtail) but again
-this would complicate matters as we then neext to keep track of a changing subhead
-and subtail. On the other hand, this might save some runtime. The number of changes
-involved is not that large. This only makes sense when we have many fonts in a list
-and don't change to frequently.</p>
---ldx]]--
+local starttiming, stoptiming, elapsedtime = statistics.starttiming, statistics.stoptiming, statistics.elapsedtime
local fonts = fonts
@@ -5500,38 +5482,114 @@ local tfm = fonts.tfm
local fontdata = fonts.ids
---~ otf.tables = otf.tables or { } -- defined in font-ott.lua
---~ otf.tables.features = otf.tables.features or { } -- defined in font-ott.lua
---~ otf.tables.languages = otf.tables.languages or { } -- defined in font-ott.lua
---~ otf.tables.scripts = otf.tables.scripts or { } -- defined in font-ott.lua
-
otf.features = otf.features or { }
otf.features.list = otf.features.list or { }
otf.features.default = otf.features.default or { }
otf.enhancers = allocate()
local enhancers = otf.enhancers
+enhancers.patches = { }
local definers = fonts.definers
otf.glists = { "gsub", "gpos" }
-otf.version = 2.653 -- beware: also sync font-mis.lua
-otf.pack = true -- beware: also sync font-mis.lua
-otf.syncspace = true
-otf.notdef = false
+otf.version = 2.702 -- beware: also sync font-mis.lua
otf.cache = containers.define("fonts", "otf", otf.version, true)
-local wildcard = "*"
-local default = "dflt"
+local loadmethod = "table" -- table, mixed, sparse
+local forceload = false
+local cleanup = 0
+local usemetatables = false -- .4 slower on mk but 30 M less mem so we might change the default -- will be directive
+local packdata = true
+local syncspace = true
+local forcenotdef = false
+
+local wildcard = "*"
+local default = "dflt"
+
+local fontloaderfields = fontloader.fields
+local mainfields = nil
+local glyphfields = nil -- not used yet
+
+directives.register("fonts.otf.loader.method", function(v)
+ if v == "sparse" and fontloaderfields then
+ loadmethod = "sparse"
+ elseif v == "mixed" then
+ loadmethod = "mixed"
+ elseif v == "table" then
+ loadmethod = "table"
+ else
+ loadmethod = "table"
+ report_otf("no loader method '%s', using '%s' instead",v,loadmethod)
+ end
+end)
+
+directives.register("fonts.otf.loader.cleanup",function(v)
+ cleanup = tonumber(v) or (v and 1) or 0
+end)
+
+directives.register("fonts.otf.loader.force", function(v) forceload = v end)
+directives.register("fonts.otf.loader.usemetatables", function(v) usemetatables = v end)
+directives.register("fonts.otf.loader.pack", function(v) packdata = v end)
+directives.register("fonts.otf.loader.syncspace", function(v) syncspace = v end)
+directives.register("fonts.otf.loader.forcenotdef", function(v) forcenotdef = v end)
+
+local function load_featurefile(raw,featurefile)
+ if featurefile and featurefile ~= "" then
+ if trace_loading then
+ report_otf("featurefile: %s", featurefile)
+ end
+ fontloader.apply_featurefile(raw, featurefile)
+ end
+end
+
+local function showfeatureorder(otfdata,filename)
+ local sequences = otfdata.luatex.sequences
+ if sequences and #sequences > 0 then
+ if trace_loading then
+ report_otf("font %s has %s sequences",filename,#sequences)
+ report_otf(" ")
+ end
+ for nos=1,#sequences do
+ local sequence = sequences[nos]
+ local typ = sequence.type or "no-type"
+ local name = sequence.name or "no-name"
+ local subtables = sequence.subtables or { "no-subtables" }
+ local features = sequence.features
+ if trace_loading then
+ report_otf("%3i %-15s %-20s [%s]",nos,name,typ,concat(subtables,","))
+ end
+ if features then
+ for feature, scripts in next, features do
+ local tt = { }
+ for script, languages in next, scripts do
+ local ttt = { }
+ for language, _ in next, languages do
+ ttt[#ttt+1] = language
+ end
+ tt[#tt+1] = format("[%s: %s]",script,concat(ttt," "))
+ end
+ if trace_loading then
+ report_otf(" %s: %s",feature,concat(tt," "))
+ end
+ end
+ end
+ end
+ if trace_loading then
+ report_otf("\n")
+ end
+ elseif trace_loading then
+ report_otf("font %s has no sequences",filename)
+ end
+end
--[[ldx--
<p>We start with a lot of tables and related functions.</p>
--ldx]]--
--- we can have more local functions
-
-otf.tables.global_fields = allocate( table.tohash {
+local global_fields = table.tohash {
+ "metadata",
"lookups",
"glyphs",
"subfonts",
@@ -5542,20 +5600,20 @@ otf.tables.global_fields = allocate( table.tohash {
"names",
"unicodes",
"names",
---~ "math",
+ -- "math",
"anchor_classes",
"kern_classes",
"gpos",
"gsub"
-} )
+}
-otf.tables.valid_fields = allocate( {
- "anchor_classes",
+local valid_fields = table.tohash {
+ -- "anchor_classes",
"ascent",
- "cache_version",
+ -- "cache_version",
"cidinfo",
"copyright",
- "creationtime",
+ -- "creationtime",
"descent",
"design_range_bottom",
"design_range_top",
@@ -5567,23 +5625,23 @@ otf.tables.valid_fields = allocate( {
"fontstyle_id",
"fontstyle_name",
"fullname",
- "glyphs",
+ -- "glyphs",
"hasvmetrics",
"head_optimized_for_cleartype",
"horiz_base",
"issans",
"isserif",
"italicangle",
- "kerns",
- "lookups",
+ -- "kerns",
+ -- "lookups",
-- "luatex",
"macstyle",
- "modificationtime",
+ -- "modificationtime",
"onlybitmaps",
"origname",
"os2_version",
- "pfminfo",
- "private",
+ -- "pfminfo",
+ -- "private",
"serifcheck",
"sfd_version",
-- "size",
@@ -5600,59 +5658,111 @@ otf.tables.valid_fields = allocate( {
"upos",
"use_typo_metrics",
"uwidth",
- "validation_state",
+ -- "validation_state",
"verbose",
"version",
"vert_base",
"weight",
"weight_width_slope_only",
- "xuid",
-} )
+ -- "xuid",
+}
+
+local ordered_enhancers = {
+ "prepare tables",
+ "prepare glyphs",
+ "prepare unicodes",
+ "prepare lookups",
+
+ "analyze glyphs",
+ "analyze math",
+
+ "prepare tounicode", -- maybe merge with prepare
+
+ "reorganize lookups",
+ "reorganize mark classes",
+ "reorganize anchor classes",
+
+ "reorganize glyph kerns",
+ "reorganize glyph lookups",
+ "reorganize glyph anchors",
+
+ "reorganize features",
+ "reorganize subtables",
+
+ "check glyphs",
+ "check metadata",
+ "check math parameters",
+ "check extra features", -- after metadata
+}
--[[ldx--
<p>Here we go.</p>
--ldx]]--
-local function load_featurefile(ff,featurefile)
- if featurefile and featurefile ~= "" then
- if trace_loading then
- report_otf("featurefile: %s", featurefile)
+local actions = { }
+
+enhancers.patches.before = allocate()
+enhancers.patches.after = allocate()
+
+local before = enhancers.patches.before
+local after = enhancers.patches.after
+
+local function enhance(name,data,filename,raw,verbose)
+ local enhancer = actions[name]
+ if enhancer then
+ if verbose then
+ report_otf("enhance: %s (%s)",name,filename)
+ ioflush()
end
- fontloader.apply_featurefile(ff, featurefile)
+ enhancer(data,filename,raw)
+ else
+ report_otf("enhance: %s is undefined",name)
end
end
-local function enhance(name,data,filename,verbose)
- local enhancer = enhancers[name]
- if enhancer then
- if (verbose ~= nil and verbose) or trace_loading then
- report_otf("enhance: %s (%s)",name,filename)
+function enhancers.apply(data,filename,raw,verbose)
+ local basename = file.basename(lower(filename))
+ report_otf("start enhancing: %s",filename)
+ 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
- enhancer(data,filename)
+ enhance(enhancer,data,filename,raw,verbose)
+ 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
+ report_otf("stop enhancing")
+ ioflush() -- we want instant messages
end
-local ordered_enhancers = { -- implemented later
- -- pack and unpack are handled separately; they might even be moved
- -- away from the enhancers namespace
- "patch bugs",
- "merge cid fonts", "prepare unicode", "cleanup ttf tables", "compact glyphs", "reverse coverage",
- "cleanup aat", "enrich with features", "add some missing characters",
- "reorganize mark classes",
- "reorganize kerns", -- moved here
- "flatten glyph lookups", "flatten anchor tables", "flatten feature tables",
- "simplify glyph lookups", -- some saving
- "prepare luatex tables",
- "analyze features", "rehash features",
- "analyze anchors", "analyze marks", "analyze unicodes", "analyze subtables",
- "check italic correction","check math",
- "share widths",
- "strip not needed data",
- "migrate metadata",
- "check math parameters",
-}
+-- enhancers.patches.register("before","migrate metadata","cambria",function() end)
+
+function enhancers.patches.register(what,where,pattern,action)
+ local ww = what[where]
+ if ww then
+ ww[pattern] = action
+ else
+ ww = { [pattern] = action}
+ end
+end
-local adddimensions, showfeatureorder -- implemented later
+function enhancers.register(what,action) -- only already registered can be overloaded
+ actions[what] = action
+end
function otf.load(filename,format,sub,featurefile)
local name = file.basename(file.removesuffix(filename))
@@ -5689,6 +5799,10 @@ function otf.load(filename,format,sub,featurefile)
end
local data = containers.read(otf.cache,hash)
local reload = not data or data.verbose ~= fonts.verbose or data.size ~= size or data.time ~= time
+ if forceload then
+ report_otf("loading: forced reload due to hard coded flag")
+ reload = true
+ end
if not reload then
local featuredata = data.featuredata
if featurefiles then
@@ -5712,11 +5826,14 @@ function otf.load(filename,format,sub,featurefile)
end
if reload then
report_otf("loading: %s (hash: %s)",filename,hash)
- local ff, messages
+ local fontdata, messages, rawdata
if sub then
- ff, messages = fontloader.open(filename,sub)
+ fontdata, messages = fontloader.open(filename,sub)
else
- ff, messages = fontloader.open(filename)
+ fontdata, messages = fontloader.open(filename)
+ end
+ if fontdata then
+ mainfields = mainfields or (fontloaderfields and fontloaderfields(fontdata))
end
if trace_loading and messages and #messages > 0 then
if type(messages) == "string" then
@@ -5729,23 +5846,27 @@ function otf.load(filename,format,sub,featurefile)
else
report_otf("font loaded okay")
end
- if ff then
+ if fontdata then
if featurefiles then
for i=1,#featurefiles do
- load_featurefile(ff,featurefiles[i].name)
+ load_featurefile(fontdata,featurefiles[i].name)
end
end
- data = fontloader.to_table(ff)
- fontloader.close(ff)
- if data then
+ report_otf("loading method: %s",loadmethod)
+ if loadmethod == "sparse" then
+ rawdata = fontdata
+ else
+ rawdata = fontloader.to_table(fontdata)
+ fontloader.close(fontdata)
+ end
+ if rawdata then
+ data = { }
+ starttiming(data)
+ local verboseindeed = verbose ~= nil and verbose or trace_loading
report_otf("file size: %s", size)
- report_otf("enhancing ...")
- for e=1,#ordered_enhancers do
- enhance(ordered_enhancers[e],data,filename)
- io.flush() -- we want instant messages
- end
- if otf.pack and not fonts.verbose then
- enhance("pack",data,filename)
+ enhancers.apply(data,filename,rawdata,verboseindeed)
+ if packdata and not fonts.verbose then
+ enhance("pack",data,filename,nil,verboseindeed)
end
data.size = size
data.time = time
@@ -5755,13 +5876,27 @@ function otf.load(filename,format,sub,featurefile)
data.verbose = fonts.verbose
report_otf("saving in cache: %s",filename)
data = containers.write(otf.cache, hash, data)
- collectgarbage("collect")
+ if cleanup > 0 then
+ collectgarbage("collect")
+ end
+ stoptiming(data)
+ report_otf("preprocessing and caching took %s seconds",elapsedtime(data))
data = containers.read(otf.cache, hash) -- this frees the old table and load the sparse one
- collectgarbage("collect")
+ if cleanup > 1 then
+ collectgarbage("collect")
+ end
else
+ data = nil
report_otf("loading failed (table conversion error)")
end
+ if loadmethod == "sparse" then
+ fontloader.close(fontdata)
+ if cleanup > 2 then
+ -- collectgarbage("collect")
+ end
+ end
else
+ data = nil
report_otf("loading failed (file read error)")
end
end
@@ -5769,8 +5904,8 @@ function otf.load(filename,format,sub,featurefile)
if trace_defining then
report_otf("loading from cache: %s",hash)
end
- enhance("unpack",data,filename,false) -- no message here
- adddimensions(data)
+ enhance("unpack",data,filename,nil,false)
+ enhance("add dimensions",data,filename,nil,false)
if trace_sequences then
showfeatureorder(data,filename)
end
@@ -5778,89 +5913,321 @@ function otf.load(filename,format,sub,featurefile)
return data
end
-adddimensions = function(data)
+local mt = {
+ __index = function(t,k) -- maybe set it
+ if k == "height" then
+ local ht = t.boundingbox[4]
+ return ht < 0 and 0 or ht
+ elseif k == "depth" then
+ local dp = -t.boundingbox[2]
+ return dp < 0 and 0 or dp
+ elseif k == "width" then
+ return 0
+ elseif k == "name" then -- or maybe uni*
+ return forcenotdef and ".notdef"
+ end
+ end
+}
+
+actions["add dimensions"] = function(data,filename)
-- todo: forget about the width if it's the defaultwidth (saves mem)
-- we could also build the marks hash here (instead of storing it)
if data then
- local force = otf.notdef
local luatex = data.luatex
local defaultwidth = luatex.defaultwidth or 0
local defaultheight = luatex.defaultheight or 0
local defaultdepth = luatex.defaultdepth or 0
- for _, d in next, data.glyphs do
- local bb, wd = d.boundingbox, d.width
- if not wd then
- d.width = defaultwidth
- elseif wd ~= 0 and d.class == "mark" then
- d.width = -wd
- end
- if force and not d.name then
- d.name = ".notdef"
- end
- if bb then
- local ht, dp = bb[4], -bb[2]
- if ht == 0 or ht < 0 then
- -- no need to set it and no negative heights, nil == 0
+ if usemetatables then
+ for _, d in next, data.glyphs do
+ local wd = d.width
+ if not wd then
+ d.width = defaultwidth
+ elseif wd ~= 0 and d.class == "mark" then
+ d.width = -wd
+ end
+ setmetatable(d,mt)
+ end
+ else
+ for _, d in next, data.glyphs do
+ local bb, wd = d.boundingbox, d.width
+ if not wd then
+ d.width = defaultwidth
+ elseif wd ~= 0 and d.class == "mark" then
+ d.width = -wd
+ end
+ if forcenotdef and not d.name then
+ d.name = ".notdef"
+ end
+ if bb then
+ local ht, dp = bb[4], -bb[2]
+ if ht == 0 or ht < 0 then
+ -- not set
+ else
+ d.height = ht
+ end
+ if dp == 0 or dp < 0 then
+ -- not set
+ else
+ d.depth = dp
+ end
+ end
+ end
+ end
+ end
+end
+
+actions["prepare tables"] = function(data,filename,raw)
+ local luatex = {
+ filename = filename,
+ version = otf.version,
+ creator = "context mkiv",
+ }
+ data.luatex = luatex
+ data.metadata = { }
+end
+
+local function somecopy(old) -- fast one
+ if old then
+ local new = { }
+ if type(old) == "table" then
+ for k, v in next, old do
+ if k == "glyphs" then
+ -- skip
+ elseif type(v) == "table" then
+ new[k] = somecopy(v)
else
- d.height = ht
+ new[k] = v
end
- if dp == 0 or dp < 0 then
- -- no negative depths and no negative depths, nil == 0
+ end
+ else
+ for i=1,#mainfields do
+ local k = mainfields[i]
+ local v = old[k]
+ if k == "glyphs" then
+ -- skip
+ elseif type(v) == "table" then
+ new[k] = somecopy(v)
else
- d.depth = dp
+ new[k] = v
end
end
end
+ return new
+ else
+ return { }
end
end
-local function showfeatureorder(otfdata,filename)
- local sequences = otfdata.luatex.sequences
- if sequences and #sequences > 0 then
- if trace_loading then
- report_otf("font %s has %s sequences",filename,#sequences)
- report_otf(" ")
+actions["prepare glyphs"] = function(data,filename,raw)
+ -- we can also move the names to data.luatex.names which might
+ -- save us some more memory (at the cost of harder tracing)
+ local rawglyphs = raw.glyphs
+ local glyphs, udglyphs
+ if loadmethod == "sparse" then
+ glyphs, udglyphs = { }, { }
+ elseif loadmethod == "mixed" then
+ glyphs, udglyphs = { }, rawglyphs
+ else
+ glyphs, udglyphs = rawglyphs, rawglyphs
+ end
+ data.glyphs, data.udglyphs = glyphs, udglyphs
+ local subfonts = raw.subfonts
+ if subfonts then
+ if data.glyphs and next(data.glyphs) then
+ report_otf("replacing existing glyph table due to subfonts")
end
- for nos=1,#sequences do
- local sequence = sequences[nos]
- local typ = sequence.type or "no-type"
- local name = sequence.name or "no-name"
- local subtables = sequence.subtables or { "no-subtables" }
- local features = sequence.features
- if trace_loading then
- report_otf("%3i %-15s %-20s [%s]",nos,name,typ,concat(subtables,","))
- end
- if features then
- for feature, scripts in next, features do
- local tt = { }
- for script, languages in next, scripts do
- local ttt = { }
- for language, _ in next, languages do
- ttt[#ttt+1] = language
+ local cidinfo = raw.cidinfo
+ if cidinfo.registry then
+ local cidmap, cidname = fonts.cid.getmap(cidinfo.registry,cidinfo.ordering,cidinfo.supplement)
+ if cidmap then
+ cidinfo.usedname = cidmap.usedname
+ local uni_to_int, int_to_uni, nofnames, nofunicodes = { }, { }, 0, 0
+ local unicodes, names = cidmap.unicodes, cidmap.names
+ for cidindex=1,#subfonts do
+ local subfont = subfonts[cidindex]
+ if loadmethod == "sparse" then
+ local rawglyphs = subfont.glyphs
+ for index=0,subfont.glyphmax - 1 do
+ local g = rawglyphs[index]
+ if g then
+ local unicode, name = unicodes[index], names[index]
+ if unicode then
+ uni_to_int[unicode] = index
+ int_to_uni[index] = unicode
+ nofunicodes = nofunicodes + 1
+ elseif name then
+ nofnames = nofnames + 1
+ end
+ udglyphs[index] = g
+ glyphs[index] = {
+ width = g.width,
+ italic = g.italic_correction,
+ boundingbox = g.boundingbox,
+ class = g.class,
+ name = g.name or name or "unknown", -- uniXXXX
+ cidindex = cidindex,
+ unicode = unicode,
+ }
+ end
end
- tt[#tt+1] = format("[%s: %s]",script,concat(ttt," "))
- end
- if trace_loading then
- report_otf(" %s: %s",feature,concat(tt," "))
+ -- If we had more userdata, we would need more of this
+ -- and it would start working against us in terms of
+ -- convenience and speed.
+ subfont = somecopy(subfont)
+ subfont.glyphs = nil
+ subfont[cidindex] = subfont
+ elseif loadmethod == "mixed" then
+ for index, g in next, subfont.glyphs do
+ local unicode, name = unicodes[index], names[index]
+ if unicode then
+ uni_to_int[unicode] = index
+ int_to_uni[index] = unicode
+ nofunicodes = nofunicodes + 1
+ elseif name then
+ nofnames = nofnames + 1
+ end
+ udglyphs[index] = g
+ glyphs[index] = {
+ width = g.width,
+ italic = g.italic_correction,
+ boundingbox = g.boundingbox,
+ class = g.class,
+ name = g.name or name or "unknown", -- uniXXXX
+ cidindex = cidindex,
+ unicode = unicode,
+ }
+ end
+ subfont.glyphs = nil
+ else
+ for index, g in next, subfont.glyphs do
+ local unicode, name = unicodes[index], names[index]
+ if unicode then
+ uni_to_int[unicode] = index
+ int_to_uni[index] = unicode
+ nofunicodes = nofunicodes + 1
+ g.unicode = unicode
+ elseif name then
+ nofnames = nofnames + 1
+ end
+ g.cidindex = cidindex
+ glyphs[index] = g
+ end
+ subfont.glyphs = nil
end
end
+ if trace_loading then
+ report_otf("cid font remapped, %s unicode points, %s symbolic names, %s glyphs",nofunicodes, nofnames, nofunicodes+nofnames)
+ end
+ data.map = data.map or { }
+ data.map.map = uni_to_int
+ data.map.backmap = int_to_uni
+ elseif trace_loading then
+ report_otf("unable to remap cid font, missing cid file for %s",filename)
end
+ data.subfonts = subfonts
+ elseif trace_loading then
+ report_otf("font %s has no glyphs",filename)
end
- if trace_loading then
- report_otf("\n")
+ else
+ if loadmethod == "sparse" then
+ -- we get fields from the userdata glyph table and create
+ -- a minimal entry first
+ for index=0,raw.glyphmax - 1 do
+ local g = rawglyphs[index]
+ if g then
+ udglyphs[index] = g
+ glyphs[index] = {
+ width = g.width,
+ italic = g.italic_correction,
+ boundingbox = g.boundingbox,
+ class = g.class,
+ name = g.name,
+ unicode = g.unicode,
+ }
+ end
+ end
+ elseif loadmethod == "mixed" then
+ -- we get fields from the totable glyph table and copy to the
+ -- final glyph table so first we create a minimal entry
+ for index, g in next, rawglyphs do
+ udglyphs[index] = g
+ glyphs[index] = {
+ width = g.width,
+ italic = g.italic_correction,
+ boundingbox = g.boundingbox,
+ class = g.class,
+ name = g.name,
+ unicode = g.unicode,
+ }
+ end
+ else
+ -- we use the totable glyph table directly and manipulate the
+ -- entries in this (also final) table
end
- elseif trace_loading then
- report_otf("font %s has no sequences",filename)
+ data.map = raw.map
end
+ data.cidinfo = raw.cidinfo -- hack
end
--- todo: normalize, design_size => designsize
+-- watch copy of cidinfo: we can best make some more copies to data
-enhancers["reorganize mark classes"] = function(data,filename)
- if data.mark_classes then
- local unicodes = data.luatex.unicodes
+actions["analyze glyphs"] = function(data,filename,raw) -- maybe integrate this in the previous
+ local glyphs = data.glyphs
+ -- collect info
+ local has_italic, widths, marks = false, { }, { }
+ for index, glyph in next, glyphs do
+ local italic = glyph.italic_correction
+ if not italic then
+ -- skip
+ elseif italic == 0 then
+ glyph.italic_correction = nil
+ glyph.italic = nil
+ else
+ glyph.italic_correction = nil
+ glyph.italic = italic
+ has_italic = true
+ end
+ local width = glyph.width
+ widths[width] = (widths[width] or 0) + 1
+ if glyph.class == "mark" then
+ marks[glyph.unicode] = true
+ end
+ local a = glyph.altuni if a then glyph.altuni = nil end
+ local d = glyph.dependents if d then glyph.dependents = nil end
+ local v = glyph.vwidth if v then glyph.vwidth = nil end
+ end
+ -- flag italic
+ data.metadata.has_italic = has_italic
+ -- flag marks
+ data.luatex.marks = marks
+ -- share most common width for cjk fonts
+ local wd, most = 0, 1
+ for k,v in next, widths do
+ if v > most then
+ wd, most = k, v
+ end
+ end
+ if most > 1000 then -- maybe 500
+ if trace_loading then
+ report_otf("most common width: %s (%s times), sharing (cjk font)",wd,most)
+ end
+ for index, glyph in next, glyphs do
+ if glyph.width == wd then
+ glyph.width = nil
+ end
+ end
+ data.luatex.defaultwidth = wd
+ end
+end
+
+actions["reorganize mark classes"] = function(data,filename,raw)
+ local mark_classes = raw.mark_classes
+ if mark_classes then
+ local luatex = data.luatex
+ local unicodes = luatex.unicodes
local reverse = { }
- for name, class in next, data.mark_classes do
+ luatex.markclasses = reverse
+ for name, class in next, mark_classes do
local t = { }
for s in gmatch(class,"[^ ]+") do
local us = unicodes[s]
@@ -5874,53 +6241,15 @@ enhancers["reorganize mark classes"] = function(data,filename)
end
reverse[name] = t
end
- data.luatex.markclasses = reverse
- data.mark_classes = nil
- end
-end
-
-enhancers["prepare luatex tables"] = function(data,filename)
- data.luatex = data.luatex or { }
- local luatex = data.luatex
- luatex.filename = filename
- luatex.version = otf.version
- luatex.creator = "context mkiv"
-end
-
-local function analyze_features(g, features)
- if g then
- local t, done = { }, { }
- for k=1,#g do
- local f = features or g[k].features
- if f then
- for k=1,#f do
- -- scripts and tag
- local tag = f[k].tag
- if not done[tag] then
- t[#t+1] = tag
- done[tag] = true
- end
- end
- end
- end
- if #t > 0 then
- return t
- end
+ data.mark_classes = nil -- when using table
end
- return nil
-end
-
-enhancers["analyze features"] = function(data,filename)
- -- local luatex = data.luatex
- -- luatex.gposfeatures = analyze_features(data.gpos)
- -- luatex.gsubfeatures = analyze_features(data.gsub)
end
-enhancers["rehash features"] = function(data,filename)
+actions["reorganize features"] = function(data,filename,raw) -- combine with other
local features = { }
data.luatex.features = features
for k, what in next, otf.glists do
- local dw = data[what]
+ local dw = raw[what]
if dw then
local f = { }
features[what] = f
@@ -5933,8 +6262,10 @@ enhancers["rehash features"] = function(data,filename)
local tag = strip(lower(df.tag))
local ft = f[tag] if not ft then ft = {} f[tag] = ft end
local dscripts = df.scripts
- for script, languages in next, dscripts do
- script = strip(lower(script))
+ for i=1,#dscripts do
+ local d = dscripts[i]
+ local languages = d.langs
+ local script = strip(lower(d.script))
local fts = ft[script] if not fts then fts = {} ft[script] = fts end
for i=1,#languages do
fts[strip(lower(languages[i]))] = true
@@ -5947,8 +6278,8 @@ enhancers["rehash features"] = function(data,filename)
end
end
-enhancers["analyze anchors"] = function(data,filename)
- local classes = data.anchor_classes
+actions["reorganize anchor classes"] = function(data,filename,raw)
+ local classes = raw.anchor_classes -- anchor classes not in final table
local luatex = data.luatex
local anchor_to_lookup, lookup_to_anchor = { }, { }
luatex.anchor_to_lookup, luatex.lookup_to_anchor = anchor_to_lookup, lookup_to_anchor
@@ -5973,148 +6304,97 @@ enhancers["analyze anchors"] = function(data,filename)
end
end
-enhancers["analyze marks"] = function(data,filename)
- local glyphs = data.glyphs
- local marks = { }
- data.luatex.marks = marks
- for unicode, index in next, data.luatex.indices do
- local glyph = glyphs[index]
- if glyph.class == "mark" then
- marks[unicode] = true
- end
- end
+actions["prepare tounicode"] = function(data,filename,raw)
+ fonts.map.addtounicode(data,filename)
end
-enhancers["analyze unicodes"] = fonts.map.addtounicode
-
-enhancers["analyze subtables"] = function(data,filename)
- data.luatex = data.luatex or { }
+actions["reorganize subtables"] = function(data,filename,raw)
local luatex = data.luatex
- local sequences = { }
- local lookups = { }
- luatex.sequences = sequences
- luatex.lookups = lookups
- for _, g in next, { data.gsub, data.gpos } do
- for k=1,#g do
- local gk = g[k]
- local typ = gk.type
- if typ == "gsub_contextchain" or typ == "gpos_contextchain" then
- gk.chain = 1
- elseif typ == "gsub_reversecontextchain" or typ == "gpos_reversecontextchain" then
- gk.chain = -1
- else
- gk.chain = 0
- end
- local features = gk.features
- if features then
- sequences[#sequences+1] = gk
- -- scripts, tag, ismac
- local t = { }
- for f=1,#features do
- local feature = features[f]
- local hash = { }
- -- only script and langs matter
- for s, languages in next, feature.scripts do
- s = lower(s)
- local h = hash[s]
- if not h then h = { } hash[s] = h end
- for l=1,#languages do
- h[strip(lower(languages[l]))] = true
- end
- end
- t[feature.tag] = hash
- end
- gk.features = t
- else
- lookups[gk.name] = gk
- gk.name = nil
- end
- local subtables = gk.subtables
- if subtables then
- local t = { }
- for s=1,#subtables do
- local subtable = subtables[s]
- local name = subtable.name
- t[#t+1] = name
- end
- gk.subtables = t
- end
- local flags = gk.flags
- if flags then
- gk.flags = { -- forcing false packs nicer
- (flags.ignorecombiningmarks and "mark") or false,
- (flags.ignoreligatures and "ligature") or false,
- (flags.ignorebaseglyphs and "base") or false,
- flags.r2l or false,
- }
- if flags.mark_class then
- gk.markclass = luatex.markclasses[flags.mark_class]
- end
- end
- end
- end
-end
-
-enhancers["merge cid fonts"] = function(data,filename)
- -- we can also move the names to data.luatex.names which might
- -- save us some more memory (at the cost of harder tracing)
- if data.subfonts then
- if data.glyphs and next(data.glyphs) then
- report_otf("replacing existing glyph table due to subfonts")
- end
- local cidinfo = data.cidinfo
- local verbose = fonts.verbose
- if cidinfo.registry then
- local cidmap, cidname = fonts.cid.getmap(cidinfo.registry,cidinfo.ordering,cidinfo.supplement)
- if cidmap then
- cidinfo.usedname = cidmap.usedname
- local glyphs, uni_to_int, int_to_uni, nofnames, nofunicodes = { }, { }, { }, 0, 0
- local unicodes, names = cidmap.unicodes, cidmap.names
- for n, subfont in next, data.subfonts do
- for index, g in next, subfont.glyphs do
- if not next(g) then
- -- dummy entry
- else
- local unicode, name = unicodes[index], names[index]
- g.cidindex = n
- g.boundingbox = g.boundingbox -- or zerobox
- g.name = g.name or name or "unknown"
- if unicode then
- uni_to_int[unicode] = index
- int_to_uni[index] = unicode
- nofunicodes = nofunicodes + 1
- g.unicode = unicode
- elseif name then
- nofnames = nofnames + 1
- g.unicode = -1
+ local sequences, lookups = { }, { }
+ luatex.sequences, luatex.lookups = sequences, lookups
+ for _, what in next, otf.glists do
+ local dw = raw[what]
+ if dw then
+ for k=1,#dw do
+ local gk = dw[k]
+ local typ = gk.type
+ local chain =
+ (typ == "gsub_contextchain" or typ == "gpos_contextchain") and 1 or
+ (typ == "gsub_reversecontextchain" or typ == "gpos_reversecontextchain") and -1 or 0
+ --
+ local subtables = gk.subtables
+ if subtables then
+ local t = { }
+ for s=1,#subtables do
+ local subtable = subtables[s]
+ local name = subtable.name
+ t[#t+1] = name
+ end
+ subtables = t
+ end
+ local flags, markclass = gk.flags, nil
+ if flags then
+ local t = { -- forcing false packs nicer
+ (flags.ignorecombiningmarks and "mark") or false,
+ (flags.ignoreligatures and "ligature") or false,
+ (flags.ignorebaseglyphs and "base") or false,
+ flags.r2l or false,
+ }
+ markclass = flags.mark_class
+ if markclass then
+ markclass = luatex.markclasses[markclass]
+ end
+ flags = t
+ end
+ --
+ local name = gk.name
+ --
+ local features = gk.features
+ if features then
+ -- scripts, tag, ismac
+ local f = { }
+ for i=1,#features do
+ local df = features[i]
+ local tag = strip(lower(df.tag))
+ local ft = f[tag] if not ft then ft = {} f[tag] = ft end
+ local dscripts = df.scripts
+ for i=1,#dscripts do
+ local d = dscripts[i]
+ local languages = d.langs
+ local script = strip(lower(d.script))
+ local fts = ft[script] if not fts then fts = {} ft[script] = fts end
+ for i=1,#languages do
+ fts[strip(lower(languages[i]))] = true
end
- glyphs[index] = g
end
end
- subfont.glyphs = nil
- end
- if trace_loading then
- report_otf("cid font remapped, %s unicode points, %s symbolic names, %s glyphs",nofunicodes, nofnames, nofunicodes+nofnames)
+ sequences[#sequences+1] = {
+ type = typ,
+ chain = chain,
+ flags = flags,
+ name = name,
+ subtables = subtables,
+ markclass = markclass,
+ features = f,
+ }
+ else
+ lookups[name] = {
+ type = typ,
+ chain = chain,
+ flags = flags,
+ subtables = subtables,
+ markclass = markclass,
+ }
end
- data.glyphs = glyphs
- data.map = data.map or { }
- data.map.map = uni_to_int
- data.map.backmap = int_to_uni
- elseif trace_loading then
- report_otf("unable to remap cid font, missing cid file for %s",filename)
end
- elseif trace_loading then
- report_otf("font %s has no glyphs",filename)
end
end
end
-enhancers["prepare unicode"] = function(data,filename)
+actions["prepare unicodes"] = function(data,filename,raw)
local luatex = data.luatex
- if not luatex then luatex = { } data.luatex = luatex end
local indices, unicodes, multiples, internals = { }, { }, { }, { }
- local glyphs = data.glyphs
- local mapmap = data.map
+ local mapmap = data.map or raw.map
if not mapmap then
report_otf("no map in %s",filename)
mapmap = { }
@@ -6128,12 +6408,13 @@ enhancers["prepare unicode"] = function(data,filename)
end
local criterium = fonts.privateoffset
local private = criterium
+ local glyphs = data.glyphs
for index, glyph in next, glyphs do
if index > 0 then
- local name = glyph.name
+ local name = glyph.name -- really needed ?
if name then
local unicode = glyph.unicode
- if unicode == -1 or unicode >= criterium then
+ if not unicode or unicode == -1 or unicode >= criterium then
glyph.unicode = private
indices[private] = index
unicodes[name] = private
@@ -6146,6 +6427,8 @@ enhancers["prepare unicode"] = function(data,filename)
indices[unicode] = index
unicodes[name] = unicode
end
+ else
+ -- message that something is wrong
end
end
end
@@ -6157,7 +6440,7 @@ enhancers["prepare unicode"] = function(data,filename)
local un = unicodes[name]
if not un then
unicodes[name] = unicode -- or 0
- elseif type(un) == "number" then
+ elseif type(un) == "number" then -- tonumber(un)
if un ~= unicode then
multiples[#multiples+1] = name
unicodes[name] = { un, unicode }
@@ -6182,9 +6465,9 @@ enhancers["prepare unicode"] = function(data,filename)
end
if trace_loading then
if #multiples > 0 then
- report_otf("%s glyph are reused: %s",#multiples, concat(multiples," "))
+ report_otf("%s glyphs are reused: %s",#multiples, concat(multiples," "))
else
- report_otf("no glyph are reused")
+ report_otf("no glyphs are reused")
end
end
luatex.indices = indices
@@ -6192,26 +6475,14 @@ enhancers["prepare unicode"] = function(data,filename)
luatex.private = private
end
-enhancers["cleanup ttf tables"] = function(data,filename)
- local ttf_tables = data.ttf_tables
- if ttf_tables then
- for k=1,#ttf_tables do
- if ttf_tables[k].data then ttf_tables[k].data = "deleted" end
- end
- end
- data.ttf_tab_saved = nil
-end
-
-enhancers["compact glyphs"] = function(data,filename)
- table.compact(data.glyphs) -- needed?
- if data.subfonts then
- for _, subfont in next, data.subfonts do
- table.compact(subfont.glyphs) -- needed?
- end
+actions["prepare lookups"] = function(data,filename,raw)
+ local lookups = raw.lookups
+ if lookups then
+ data.lookups = lookups
end
end
-enhancers["reverse coverage"] = function(data,filename)
+actions["reorganize lookups"] = function(data,filename,raw)
-- we prefer the before lookups in a normal order
if data.lookups then
for _, v in next, data.lookups do
@@ -6219,7 +6490,7 @@ enhancers["reverse coverage"] = function(data,filename)
for _, vv in next, v.rules do
local c = vv.coverage
if c and c.before then
- c.before = table.reverse(c.before)
+ c.before = reverse(c.before)
end
end
end
@@ -6227,35 +6498,18 @@ enhancers["reverse coverage"] = function(data,filename)
end
end
-enhancers["check italic correction"] = function(data,filename)
- local glyphs = data.glyphs
- local ok = false
- for index, glyph in next, glyphs do
- local ic = glyph.italic_correction
- if ic then
- if ic ~= 0 then
- glyph.italic = ic
- end
- glyph.italic_correction = nil
- ok = true
- end
- end
- -- we can use this to avoid calculations
- otf.tables.valid_fields[#otf.tables.valid_fields+1] = "has_italic"
- data.has_italic = true
-end
-
-enhancers["check math"] = function(data,filename)
- if data.math then
+actions["analyze math"] = function(data,filename,raw)
+ if raw.math then
-- we move the math stuff into a math subtable because we then can
-- test faster in the tfm copy
- local glyphs = data.glyphs
+ local glyphs, udglyphs = data.glyphs, data.udglyphs
local unicodes = data.luatex.unicodes
- for index, glyph in next, glyphs do
- local mk = glyph.mathkern
- local hv = glyph.horiz_variants
- local vv = glyph.vert_variants
+ for index, udglyph in next, udglyphs do
+ local mk = udglyph.mathkern
+ local hv = udglyph.horiz_variants
+ local vv = udglyph.vert_variants
if mk or hv or vv then
+ local glyph = glyphs[index]
local math = { }
glyph.math = math
if mk then
@@ -6265,7 +6519,6 @@ enhancers["check math"] = function(data,filename)
end
end
math.kerns = mk
- glyph.mathkern = nil
end
if hv then
math.horiz_variants = hv.variants
@@ -6281,7 +6534,6 @@ enhancers["check math"] = function(data,filename)
if ic and ic ~= 0 then
math.horiz_italic_correction = ic
end
- glyph.horiz_variants = nil
end
if vv then
local uc = unicodes[index]
@@ -6298,221 +6550,48 @@ enhancers["check math"] = function(data,filename)
if ic and ic ~= 0 then
math.vert_italic_correction = ic
end
- glyph.vert_variants = nil
end
local ic = glyph.italic_correction
if ic then
if ic ~= 0 then
math.italic_correction = ic
end
- glyph.italic_correction = nil
end
end
end
end
end
-enhancers["share widths"] = function(data,filename)
- local glyphs = data.glyphs
- local widths = { }
- for index, glyph in next, glyphs do
- local width = glyph.width
- widths[width] = (widths[width] or 0) + 1
- end
- -- share width for cjk fonts
- local wd, most = 0, 1
- for k,v in next, widths do
- if v > most then
- wd, most = k, v
- end
- end
- if most > 1000 then
- if trace_loading then
- report_otf("most common width: %s (%s times), sharing (cjk font)",wd,most)
- end
- for k, v in next, glyphs do
- if v.width == wd then
- v.width = nil
- end
- end
- data.luatex.defaultwidth = wd
- end
-end
-
--- kern: ttf has a table with kerns
-
--- Weird, as maxfirst and maxseconds can have holes, first seems to be indexed, but
--- seconds can start at 2 .. this need to be fixed as getn as well as # are sort of
--- unpredictable alternatively we could force an [1] if not set (maybe I will do that
--- anyway).
-
---~ enhancers["reorganize kerns"] = function(data,filename)
---~ local glyphs, mapmap, unicodes = data.glyphs, data.luatex.indices, data.luatex.unicodes
---~ local mkdone = false
---~ for index, glyph in next, glyphs do
---~ if glyph.kerns then
---~ local mykerns = { }
---~ for k,v in next, glyph.kerns do
---~ local vc, vo, vl = v.char, v.off, v.lookup
---~ if vc and vo and vl then -- brrr, wrong! we miss the non unicode ones
---~ local uvc = unicodes[vc]
---~ if not uvc then
---~ if trace_loading then
---~ report_otf("problems with unicode %s of kern %s at glyph %s",vc,k,index)
---~ end
---~ else
---~ if type(vl) ~= "table" then
---~ vl = { vl }
---~ end
---~ for l=1,#vl do
---~ local vll = vl[l]
---~ local mkl = mykerns[vll]
---~ if not mkl then
---~ mkl = { }
---~ mykerns[vll] = mkl
---~ end
---~ if type(uvc) == "table" then
---~ for u=1,#uvc do
---~ mkl[uvc[u]] = vo
---~ end
---~ else
---~ mkl[uvc] = vo
---~ end
---~ end
---~ end
---~ end
---~ end
---~ glyph.mykerns = mykerns
---~ glyph.kerns = nil -- saves space and time
---~ mkdone = true
---~ end
---~ end
---~ if trace_loading and mkdone then
---~ report_otf("replacing 'kerns' tables by 'mykerns' tables")
---~ end
---~ if data.kerns then
---~ if trace_loading then
---~ report_otf("removing global 'kern' table")
---~ end
---~ data.kerns = nil
---~ end
---~ local dgpos = data.gpos
---~ if dgpos then
---~ local separator = lpeg.P(" ")
---~ local other = ((1 - separator)^0) / unicodes
---~ local splitter = lpeg.Ct(other * (separator * other)^0)
---~ for gp=1,#dgpos do
---~ local gpos = dgpos[gp]
---~ local subtables = gpos.subtables
---~ if subtables then
---~ for s=1,#subtables do
---~ local subtable = subtables[s]
---~ local kernclass = subtable.kernclass -- name is inconsistent with anchor_classes
---~ if kernclass then -- the next one is quite slow
---~ local split = { } -- saves time
---~ for k=1,#kernclass do
---~ local kcl = kernclass[k]
---~ local firsts, seconds, offsets, lookups = kcl.firsts, kcl.seconds, kcl.offsets, kcl.lookup -- singular
---~ if type(lookups) ~= "table" then
---~ lookups = { lookups }
---~ end
---~ local maxfirsts, maxseconds = getn(firsts), getn(seconds)
---~ for _, s in next, firsts do
---~ split[s] = split[s] or lpegmatch(splitter,s)
---~ end
---~ for _, s in next, seconds do
---~ split[s] = split[s] or lpegmatch(splitter,s)
---~ end
---~ for l=1,#lookups do
---~ local lookup = lookups[l]
---~ local function do_it(fk,first_unicode)
---~ local glyph = glyphs[mapmap[first_unicode]]
---~ if glyph then
---~ local mykerns = glyph.mykerns
---~ if not mykerns then
---~ mykerns = { } -- unicode indexed !
---~ glyph.mykerns = mykerns
---~ end
---~ local lookupkerns = mykerns[lookup]
---~ if not lookupkerns then
---~ lookupkerns = { }
---~ mykerns[lookup] = lookupkerns
---~ end
---~ local baseoffset = (fk-1) * maxseconds
---~ for sk=2,maxseconds do -- we can avoid this loop with a table
---~ local sv = seconds[sk]
---~ local splt = split[sv]
---~ if splt then
---~ local offset = offsets[baseoffset + sk]
---~ --~ local offset = offsets[sk] -- (fk-1) * maxseconds + sk]
---~ if offset then
---~ for i=1,#splt do
---~ local second_unicode = splt[i]
---~ if tonumber(second_unicode) then
---~ lookupkerns[second_unicode] = offset
---~ else for s=1,#second_unicode do
---~ lookupkerns[second_unicode[s]] = offset
---~ end end
---~ end
---~ end
---~ end
---~ end
---~ elseif trace_loading then
---~ report_otf("no glyph data for U+%04X", first_unicode)
---~ end
---~ end
---~ for fk=1,#firsts do
---~ local fv = firsts[fk]
---~ local splt = split[fv]
---~ if splt then
---~ for i=1,#splt do
---~ local first_unicode = splt[i]
---~ if tonumber(first_unicode) then
---~ do_it(fk,first_unicode)
---~ else for f=1,#first_unicode do
---~ do_it(fk,first_unicode[f])
---~ end end
---~ end
---~ end
---~ end
---~ end
---~ end
---~ subtable.comment = "The kernclass table is merged into mykerns in the indexed glyph tables."
---~ subtable.kernclass = { }
---~ end
---~ end
---~ end
---~ end
---~ end
---~ end
-
-enhancers["reorganize kerns"] = function(data,filename)
- local glyphs, mapmap, unicodes = data.glyphs, data.luatex.indices, data.luatex.unicodes
+actions["reorganize glyph kerns"] = function(data,filename,raw)
+ local luatex = data.luatex
+ local udglyphs, glyphs, mapmap, unicodes = data.udglyphs, data.glyphs, luatex.indices, luatex.unicodes
local mkdone = false
- local function do_it(lookup,first_unicode,kerns)
+ local function do_it(lookup,first_unicode,extrakerns) -- can be moved inline but seldom used
local glyph = glyphs[mapmap[first_unicode]]
if glyph then
- local mykerns = glyph.mykerns
- if not mykerns then
- mykerns = { } -- unicode indexed !
- glyph.mykerns = mykerns
+ local kerns = glyph.kerns
+ if not kerns then
+ kerns = { } -- unicode indexed !
+ glyph.kerns = kerns
end
- local lookupkerns = mykerns[lookup]
+ local lookupkerns = kerns[lookup]
if not lookupkerns then
lookupkerns = { }
- mykerns[lookup] = lookupkerns
+ kerns[lookup] = lookupkerns
end
- for second_unicode, kern in next, kerns do
+ for second_unicode, kern in next, extrakerns do
lookupkerns[second_unicode] = kern
end
elseif trace_loading then
report_otf("no glyph data for U+%04X", first_unicode)
end
end
- for index, glyph in next, glyphs do
- if glyph.kerns then
- local mykerns = { }
- for k,v in next, glyph.kerns do
+ for index, udglyph in next, data.udglyphs do
+ local kerns = udglyph.kerns
+ if kerns then
+ local glyph = glyphs[index]
+ local newkerns = { }
+ for k,v in next, kerns do
local vc, vo, vl = v.char, v.off, v.lookup
if vc and vo and vl then -- brrr, wrong! we miss the non unicode ones
local uvc = unicodes[vc]
@@ -6526,10 +6605,10 @@ enhancers["reorganize kerns"] = function(data,filename)
end
for l=1,#vl do
local vll = vl[l]
- local mkl = mykerns[vll]
+ local mkl = newkerns[vll]
if not mkl then
mkl = { }
- mykerns[vll] = mkl
+ newkerns[vll] = mkl
end
if type(uvc) == "table" then
for u=1,#uvc do
@@ -6542,21 +6621,14 @@ enhancers["reorganize kerns"] = function(data,filename)
end
end
end
- glyph.mykerns = mykerns
- glyph.kerns = nil -- saves space and time
+ glyph.kerns = newkerns -- udglyph.kerns = nil when in mixed mode
mkdone = true
end
end
if trace_loading and mkdone then
- report_otf("replacing 'kerns' tables by 'mykerns' tables")
+ report_otf("replacing 'kerns' tables by a new 'kerns' tables")
end
- if data.kerns then
- if trace_loading then
- report_otf("removing global 'kern' table")
- end
- data.kerns = nil
- end
- local dgpos = data.gpos
+ local dgpos = raw.gpos
if dgpos then
local separator = lpeg.P(" ")
local other = ((1 - separator)^0) / unicodes
@@ -6621,7 +6693,7 @@ enhancers["reorganize kerns"] = function(data,filename)
end
end
end
- subtable.comment = "The kernclass table is merged into mykerns in the indexed glyph tables."
+ subtable.comment = "The kernclass table is merged into kerns in the indexed glyph tables."
subtable.kernclass = { }
end
end
@@ -6630,14 +6702,10 @@ enhancers["reorganize kerns"] = function(data,filename)
end
end
-enhancers["strip not needed data"] = function(data,filename)
+actions["check glyphs"] = function(data,filename,raw)
local verbose = fonts.verbose
local int_to_uni = data.luatex.unicodes
for k, v in next, data.glyphs do
- local d = v.dependents
- if d then v.dependents = nil end
- local a = v.altuni
- if a then v.altuni = nil end
if verbose then
local code = int_to_uni[k]
-- looks like this is done twice ... bug?
@@ -6660,32 +6728,57 @@ enhancers["strip not needed data"] = function(data,filename)
v.index = nil
end
end
- data.luatex.comment = "Glyph tables have their original index. When present, mykern tables are indexed by unicode."
- data.map = nil
- data.names = nil -- funny names for editors
- data.glyphcnt = nil
- data.glyphmax = nil
- if true then
- data.gpos = nil
- data.gsub = nil
- data.anchor_classes = nil
- end
+ data.luatex.comment = "Glyph tables have their original index. When present, kern tables are indexed by unicode."
end
-enhancers["migrate metadata"] = function(data,filename)
- local global_fields = otf.tables.global_fields
- local metadata = { }
- for k,v in next, data do
- if not global_fields[k] then
- metadata[k] = v
- data[k] = nil
+actions["check metadata"] = function(data,filename,raw)
+ local metadata = data.metadata
+ metadata.method = loadmethod
+ if loadmethod == "sparse" then
+ for _, k in next, mainfields do
+ if valid_fields[k] then
+ local v = raw[k]
+ if global_fields[k] then
+ if not data[k] then
+ data[k] = v
+ end
+ else
+ if not metadata[k] then
+ metadata[k] = v
+ end
+ end
+ end
+ end
+ else
+ for k, v in next, raw do
+ if valid_fields[k] then
+ if global_fields[k] then
+ if not data[k] then
+ data[v] = v
+ end
+ else
+ if not metadata[k] then
+ metadata[k] = v
+ end
+ end
+ end
+ end
+ end
+ local pfminfo = raw.pfminfo
+ if pfminfo then
+ data.pfminfo = pfminfo
+ metadata.isfixedpitch = metadata.isfixedpitch or (pfminfo.panose and pfminfo.panose.proportion == "Monospaced")
+ metadata.charwidth = pfminfo and pfminfo.avgwidth
+ end
+ local ttftables = metadata.ttf_tables
+ if ttftables then
+ for i=1,#ttftables do
+ ttftables[i].data = "deleted"
end
end
- data.metadata = metadata
- -- goodies
- local pfminfo = data.pfminfo
- metadata.isfixedpitch = metadata.isfixedpitch or (pfminfo.panose and pfminfo.panose["proportion"] == "Monospaced")
- metadata.charwidth = pfminfo and pfminfo.avgwidth
+ metadata.xuid = nil
+ data.udglyphs = nil
+ data.map = nil
end
local private_math_parameters = {
@@ -6693,7 +6786,7 @@ local private_math_parameters = {
"FractionDelimiterDisplayStyleSize",
}
-enhancers["check math parameters"] = function(data,filename)
+actions["check math parameters"] = function(data,filename,raw)
local mathdata = data.metadata.math
if mathdata then
for m=1,#private_math_parameters do
@@ -6708,123 +6801,101 @@ enhancers["check math parameters"] = function(data,filename)
end
end
-enhancers["flatten glyph lookups"] = function(data,filename)
- for k, v in next, data.glyphs do
- local lookups = v.lookups
+
+-- kern: ttf has a table with kerns
+--
+-- Weird, as maxfirst and maxseconds can have holes, first seems to be indexed, but
+-- seconds can start at 2 .. this need to be fixed as getn as well as # are sort of
+-- unpredictable alternatively we could force an [1] if not set (maybe I will do that
+-- anyway).
+
+actions["reorganize glyph lookups"] = function(data,filename,raw)
+ local glyphs = data.glyphs
+ for index, udglyph in next, data.udglyphs do
+ local lookups = udglyph.lookups
if lookups then
+ local glyph = glyphs[index]
+ local l = { }
for kk, vv in next, lookups do
+ local aa = { }
+ l[kk] = aa
for kkk=1,#vv do
local vvv = vv[kkk]
local s = vvv.specification
- if s then
- local t = vvv.type
- if t == "ligature" then
- vv[kkk] = { "ligature", s.components, s.char }
- elseif t == "alternate" then
- vv[kkk] = { "alternate", s.components }
- elseif t == "substitution" then
- vv[kkk] = { "substitution", s.variant }
- elseif t == "multiple" then
- vv[kkk] = { "multiple", s.components }
- elseif t == "position" then
- vv[kkk] = { "position", { s.x or 0, s.y or 0, s.h or 0, s.v or 0 } }
- elseif t == "pair" then
- local one, two, paired = s.offsets[1], s.offsets[2], s.paired or ""
- if one then
- if two then
- vv[kkk] = { "pair", paired, { one.x or 0, one.y or 0, one.h or 0, one.v or 0 }, { two.x or 0, two.y or 0, two.h or 0, two.v or 0 } }
- else
- vv[kkk] = { "pair", paired, { one.x or 0, one.y or 0, one.h or 0, one.v or 0 } }
- end
+ local t = vvv.type
+ -- #aa+1
+ if t == "ligature" then
+ aa[kkk] = { "ligature", s.components, s.char }
+ elseif t == "alternate" then
+ aa[kkk] = { "alternate", s.components }
+ elseif t == "substitution" then
+ aa[kkk] = { "substitution", s.variant }
+ elseif t == "multiple" then
+ aa[kkk] = { "multiple", s.components }
+ elseif t == "position" then
+ aa[kkk] = { "position", { s.x or 0, s.y or 0, s.h or 0, s.v or 0 } }
+ elseif t == "pair" then
+ -- maybe flatten this one
+ local one, two, paired = s.offsets[1], s.offsets[2], s.paired or ""
+ if one then
+ if two then
+ aa[kkk] = { "pair", paired, { one.x or 0, one.y or 0, one.h or 0, one.v or 0 }, { two.x or 0, two.y or 0, two.h or 0, two.v or 0 } }
else
- if two then
- vv[kkk] = { "pair", paired, { }, { two.x or 0, two.y or 0, two.h or 0, two.v or 0} } -- maybe nil instead of { }
- else
- vv[kkk] = { "pair", paired }
- end
+ aa[kkk] = { "pair", paired, { one.x or 0, one.y or 0, one.h or 0, one.v or 0 } }
end
else
- if trace_loading then
- report_otf("flattening needed, report to context list")
- end
- for a, b in next, s do
- if trace_loading and vvv[a] then
- report_otf("flattening conflict, report to context list")
- end
- vvv[a] = b
+ if two then
+ aa[kkk] = { "pair", paired, { }, { two.x or 0, two.y or 0, two.h or 0, two.v or 0} } -- maybe nil instead of { }
+ else
+ aa[kkk] = { "pair", paired }
end
- vvv.specification = nil
end
end
end
end
- end
- end
-end
-
-enhancers["simplify glyph lookups"] = function(data,filename)
- for k, v in next, data.glyphs do
- local lookups = v.lookups
- if lookups then
+ -- we could combine this
local slookups, mlookups
- for kk, vv in next, lookups do
+ for kk, vv in next, l do
if #vv == 1 then
if not slookups then
slookups = { }
- v.slookups = slookups
+ glyph.slookups = slookups
end
slookups[kk] = vv[1]
else
if not mlookups then
mlookups = { }
- v.mlookups = mlookups
+ glyph.mlookups = mlookups
end
mlookups[kk] = vv
end
end
- v.lookups = nil
+ glyph.lookups = nil -- when using table
end
end
end
-enhancers["flatten anchor tables"] = function(data,filename)
- for k, v in next, data.glyphs do
- if v.anchors then
- for kk, vv in next, v.anchors do
+actions["reorganize glyph anchors"] = function(data,filename,raw)
+ local glyphs = data.glyphs
+ for index, udglyph in next, data.udglyphs do
+ local anchors = udglyph.anchors
+ if anchors then
+ local glyph = glyphs[index]
+ local a = { }
+ glyph.anchors = a
+ for kk, vv in next, anchors do
+ local aa = { }
+ a[kk] = aa
for kkk, vvv in next, vv do
if vvv.x or vvv.y then
- vv[kkk] = { vvv.x or 0, vvv.y or 0 }
+ aa[kkk] = { vvv.x , vvv.y }
else
+ local aaa = { }
+ aa[kkk] = aaa
for kkkk=1,#vvv do
local vvvv = vvv[kkkk]
- vvv[kkkk] = { vvvv.x or 0, vvvv.y or 0 }
- end
- end
- end
- end
- end
- end
-end
-
-enhancers["flatten feature tables"] = function(data,filename)
- -- is this needed? do we still use them at all?
- for _, tag in next, otf.glists do
- if data[tag] then
- if trace_loading then
- report_otf("flattening %s table", tag)
- end
- for k, v in next, data[tag] do
- local features = v.features
- if features then
- for kk=1,#features do
- local vv = features[kk]
- local t = { }
- local scripts = vv.scripts
- for kkk=1,#scripts do
- local vvv = scripts[kkk]
- t[vvv.script] = vvv.langs
+ aaa[kkkk] = { vvvv.x, vvvv.y }
end
- vv.scripts = t
end
end
end
@@ -6832,22 +6903,12 @@ enhancers["flatten feature tables"] = function(data,filename)
end
end
-enhancers.patches = allocate()
-
-enhancers["patch bugs"] = function(data,filename)
- local basename = file.basename(lower(filename))
- for pattern, action in next, enhancers.patches do
- if find(basename,pattern) then
- action(data,filename)
- end
- end
-end
-
--- tex features
+--~ actions["check extra features"] = function(data,filename,raw)
+--~ -- later, ctx only
+--~ end
-enhancers["enrich with features"] = function(data,filename)
- -- later, ctx only
-end
+-- -- -- -- -- --
+-- -- -- -- -- --
function otf.features.register(name,default)
otf.features.list[#otf.features.list+1] = name
@@ -6924,25 +6985,6 @@ tfmdata.mode = mode
return processes, features
end
---~ {
---~ ['boundingbox']={ 95, -458, 733, 1449 },
---~ ['class']="base",
---~ ['name']="braceleft",
---~ ['unicode']=123,
---~ ['vert_variants']={
---~ ['italic_correction']=0,
---~ ['parts']={
---~ { ['component']="uni23A9", ['endConnectorLength']=1000, ['fullAdvance']=2546, ['is_extender']=0, ['startConnectorLength']=0, }, -- bot
---~ { ['component']="uni23AA", ['endConnectorLength']=2500, ['fullAdvance']=2501, ['is_extender']=1, ['startConnectorLength']=2500, }, -- rep
---~ { ['component']="uni23A8", ['endConnectorLength']=1000, ['fullAdvance']=4688, ['is_extender']=0, ['startConnectorLength']=1000, }, -- mid
---~ { ['component']="uni23AA", ['endConnectorLength']=2500, ['fullAdvance']=2501, ['is_extender']=1, ['startConnectorLength']=2500, }, -- rep
---~ { ['component']="uni23A7", ['endConnectorLength']=0, ['fullAdvance']=2546, ['is_extender']=0, ['startConnectorLength']=1000, }, -- top
---~ },
---~ ['variants']="braceleft braceleft.vsize1 braceleft.vsize2 braceleft.vsize3 braceleft.vsize4 braceleft.vsize5 braceleft.vsize6 braceleft.vsize7",
---~ },
---~ ['width']=793,
---~ },
-
-- the first version made a top/mid/not extensible table, now we just pass on the variants data
-- and deal with it in the tfm scaler (there is no longer an extensible table anyway)
@@ -7050,7 +7092,7 @@ local function copytotfm(data,cache_id) -- we can save a copy when we reorder th
local filename = fonts.tfm.checkedfilename(luatex)
local fontname = metadata.fontname
local fullname = metadata.fullname or fontname
- local cidinfo = data.cidinfo
+ local cidinfo = data.cidinfo -- or { }
local units = metadata.units_per_em or 1000
--
cidinfo.registry = cidinfo and cidinfo.registry or "" -- weird here, fix upstream
@@ -7071,7 +7113,7 @@ local function copytotfm(data,cache_id) -- we can save a copy when we reorder th
if metadata.isfixedpitch then
parameters.space_stretch = 0
parameters.space_shrink = 0
- elseif otf.syncspace then --
+ elseif syncspace then --
parameters.space_stretch = spaceunits/2
parameters.space_shrink = spaceunits/3
end
@@ -7697,7 +7739,7 @@ local function preparebasekerns(tfmdata,kind,value) -- todo what kind of kerns,
for u, chr in next, characters do
local d = descriptions[u]
if d then
- local dk = d.mykerns -- shared
+ local dk = d.kerns -- shared
if dk then
local s = sharedkerns[dk]
if s == false then
@@ -10285,7 +10327,7 @@ local function prepare_lookups(tfmdata)
end
end
end
- local list = glyph.mykerns
+ local list = glyph.kerns
if list then
for lookup, krn in next, list do
local k = kerns[lookup]
@@ -10831,6 +10873,12 @@ local report_otf = logs.new("load otf")
--
-- we could have a tnum variant as well
+-- 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.
+
local extra_lists = {
tlig = {
{
@@ -10881,116 +10929,120 @@ local extra_lists = {
local extra_features = { -- maybe just 1..n so that we prescribe order
tlig = {
{
- features = { { scripts = { { script = "*", langs = { "*" }, } }, tag = "tlig", comment = "added bij mkiv" }, },
+ features = { ["*"] = { ["*"] = true } },
name = "ctx_tlig_1",
- subtables = { { name = "ctx_tlig_1_s" } },
+ subtables = { "ctx_tlig_1_s" },
type = "gsub_ligature",
flags = { },
},
},
trep = {
{
- features = { { scripts = { { script = "*", langs = { "*" }, } }, tag = "trep", comment = "added bij mkiv" }, },
+ features = { ["*"] = { ["*"] = true } },
name = "ctx_trep_1",
- subtables = { { name = "ctx_trep_1_s" } },
+ subtables = { "ctx_trep_1_s" },
type = "gsub_single",
flags = { },
},
},
anum = {
{
- features = { { scripts = { { script = "arab", langs = { "dflt", "FAR" }, } }, tag = "anum", comment = "added bij mkiv" }, },
+ features = { arab = { URD = true, dflt = true } },
name = "ctx_anum_1",
- subtables = { { name = "ctx_anum_1_s" } },
+ subtables = { "ctx_anum_1_s" },
type = "gsub_single",
flags = { },
},
{
- features = { { scripts = { { script = "arab", langs = { "URD" }, } }, tag = "anum", comment = "added bij mkiv" }, },
+ features = { arab = { URD = true } },
name = "ctx_anum_2",
- subtables = { { name = "ctx_anum_2_s" } },
+ subtables = { "ctx_anum_2_s" },
type = "gsub_single",
flags = { },
},
},
}
-otf.enhancers["add some missing characters"] = function(data,filename)
- -- todo
-end
-
-otf.enhancers["enrich with features"] = function(data,filename)
- -- could be done elsewhere (true can be #)
- local used = { }
- for i=1,#otf.glists do
- local g = data[otf.glists[i]]
- if g then
- for i=1,#g do
- local f = g[i].features
- if f then
- for i=1,#f do
- local t = f[i].tag
- if t then used[t] = true end
- end
- end
- end
- end
- end
- --
+local function enhancedata(data,filename,raw)
+ local luatex = data.luatex
+ local lookups = luatex.lookups
+ local sequences = luatex.sequences
local glyphs = data.glyphs
- local indices = data.map.map
- data.gsub = data.gsub or { }
+ local indices = luatex.indices
+ local gsubfeatures = luatex.features.gsub
for kind, specifications in next, extra_features do
- if not used[kind] then
+ if gsub and gsub[kind] then
+ -- already present
+ else
local done = 0
for s=1,#specifications do
local added = false
local specification = specifications[s]
+ local features, subtables = specification.features, specification.subtables
+ local name, type, flags = specification.name, specification.type, specification.flags
+ local full = subtables[1]
local list = extra_lists[kind][s]
- local name = specification.name .. "_s"
- if specification.type == "gsub_ligature" then
+ if type == "gsub_ligature" then
+ -- inefficient loop
for unicode, index in next, indices do
local glyph = glyphs[index]
local ligature = list[glyph.name]
if ligature then
- local o = glyph.lookups or { }
- -- o[name] = { "ligature", ligature, glyph.name }
- o[name] = {
- {
- ["type"] = "ligature",
- ["specification"] = {
- char = glyph.name,
- components = ligature,
- }
- }
- }
- glyph.lookups, done, added = o, done+1, true
+ if glyph.slookups then
+ glyph.slookups [full] = { "ligature", ligature, glyph.name }
+ else
+ glyph.slookups = { [full] = { "ligature", ligature, glyph.name } }
+ end
+ done, added = done+1, true
end
end
- elseif specification.type == "gsub_single" then
+ elseif type == "gsub_single" then
+ -- inefficient loop
for unicode, index in next, indices do
local glyph = glyphs[index]
local r = list[unicode]
if r then
local replacement = indices[r]
if replacement and glyphs[replacement] then
- local o = glyph.lookups or { }
- -- o[name] = { { "substitution", glyphs[replacement].name } }
- o[name] = {
- {
- ["type"] = "substitution",
- ["specification"] = {
- variant = glyphs[replacement].name,
- }
- }
- }
- glyph.lookups, done, added = o, done+1, true
+ if glyph.slookups then
+ glyph.slookups [full] = { "substitution", glyphs[replacement].name }
+ else
+ glyph.slookups = { [full] = { "substitution", glyphs[replacement].name } }
+ end
+ done, added = done+1, true
end
end
end
end
if added then
- insert(data.gsub,s,table.fastcopy(specification)) -- right order
+ sequences[#sequences+1] = {
+ chain = 0,
+ features = { [kind] = features },
+ flags = flags,
+ name = name,
+ subtables = subtables,
+ type = type,
+ }
+ -- register in metadata (merge as there can be a few)
+ if not gsubfeatures then
+ gsubfeatures = { }
+ luatex.features.gsub = gsubfeatures
+ end
+ local k = gsubfeatures[kind]
+ if not k then
+ k = { }
+ gsubfeatures[kind] = k
+ end
+ for script, languages in next, features 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
if done > 0 then
@@ -11002,6 +11054,8 @@ otf.enhancers["enrich with features"] = function(data,filename)
end
end
+otf.enhancers.register("check extra features",enhancedata)
+
local features = otf.tables.features
features['tlig'] = 'TeX Ligatures'
diff --git a/web2c/contextcnf.lua b/web2c/contextcnf.lua
index 03a7d4b51..7d2edb6fd 100644
--- a/web2c/contextcnf.lua
+++ b/web2c/contextcnf.lua
@@ -107,10 +107,12 @@ return {
-- like ['foo.bar'] so for convenience we also support 'foo_bar'.
directives = {
- -- system_checkglobals = "10",
- -- system.nostatistics = "yes",
- system_errorcontext = "10",
- mplib_texerrors = "yes",
+ -- system_checkglobals = "10",
+ -- system_nostatistics = "yes",
+ system_errorcontext = "10",
+ mplib_texerrors = "yes",
+ -- fonts_otf_loader_method = "table", -- table mixed sparse
+ -- fonts_otf_loader_cleanup = "0", -- 0 1 2 3
},
experiments = {