summaryrefslogtreecommitdiff
path: root/src/fontloader
diff options
context:
space:
mode:
authorPhilipp Gesang <phg@phi-gamma.net>2016-06-12 18:14:33 +0200
committerPhilipp Gesang <phg@phi-gamma.net>2016-06-12 18:14:33 +0200
commitd8ba9c36eaf49c1f28b8e8f11c969b77ece32db4 (patch)
treed4cdef7062d4d75734c9a170afc861ae14858a32 /src/fontloader
parent3bbb743eb16f83c118776a7689b4826911c41bb1 (diff)
downloadluaotfload-d8ba9c36eaf49c1f28b8e8f11c969b77ece32db4.tar.gz
[fontloader] sync with Context as of 2016-06-12
Diffstat (limited to 'src/fontloader')
-rw-r--r--src/fontloader/misc/fontloader-font-con.lua51
-rw-r--r--src/fontloader/misc/fontloader-font-dsp.lua144
-rw-r--r--src/fontloader/misc/fontloader-font-map.lua4
-rw-r--r--src/fontloader/misc/fontloader-font-one.lua6
-rw-r--r--src/fontloader/misc/fontloader-font-osd.lua2
-rw-r--r--src/fontloader/misc/fontloader-font-ota.lua2
-rw-r--r--src/fontloader/misc/fontloader-font-otd.lua48
-rw-r--r--src/fontloader/misc/fontloader-font-oti.lua4
-rw-r--r--src/fontloader/misc/fontloader-font-otj.lua2
-rw-r--r--src/fontloader/misc/fontloader-font-otl.lua28
-rw-r--r--src/fontloader/misc/fontloader-font-otr.lua37
-rw-r--r--src/fontloader/misc/fontloader-font-ots.lua15
-rw-r--r--src/fontloader/misc/fontloader-font-oup.lua56
-rw-r--r--src/fontloader/misc/fontloader-font-tfm.lua4
-rw-r--r--src/fontloader/misc/fontloader-fonts-ext.lua2
-rw-r--r--src/fontloader/misc/fontloader-fonts.lua2
-rw-r--r--src/fontloader/misc/fontloader-math.tex12
-rw-r--r--src/fontloader/runtime/fontloader-reference.lua1131
18 files changed, 1464 insertions, 86 deletions
diff --git a/src/fontloader/misc/fontloader-font-con.lua b/src/fontloader/misc/fontloader-font-con.lua
index 367f807..1a0daff 100644
--- a/src/fontloader/misc/fontloader-font-con.lua
+++ b/src/fontloader/misc/fontloader-font-con.lua
@@ -1049,6 +1049,29 @@ function constructors.hashfeatures(specification) -- will be overloaded
return "unknown"
end
+-- hashmethods.normal = function(list)
+-- local s = { }
+-- local n = 0
+-- for k, v in next, list do
+-- if not k then
+-- -- no need to add to hash
+-- elseif k == "number" or k == "features" then
+-- -- no need to add to hash (maybe we need a skip list)
+-- else
+-- n = n + 1
+-- s[n] = k
+-- end
+-- end
+-- if n > 0 then
+-- sort(s)
+-- for i=1,n do
+-- local k = s[i]
+-- s[i] = k .. '=' .. tostring(list[k])
+-- end
+-- return concat(s,"+")
+-- end
+-- end
+
hashmethods.normal = function(list)
local s = { }
local n = 0
@@ -1059,15 +1082,11 @@ hashmethods.normal = function(list)
-- no need to add to hash (maybe we need a skip list)
else
n = n + 1
- s[n] = k
+ s[n] = k .. '=' .. tostring(v)
end
end
if n > 0 then
sort(s)
- for i=1,n do
- local k = s[i]
- s[i] = k .. '=' .. tostring(list[k])
- end
return concat(s,"+")
end
end
@@ -1236,7 +1255,11 @@ function constructors.getfeatureaction(what,where,mode,name)
end
end
-function constructors.newhandler(what) -- could be a metatable newindex
+local newhandler = { }
+constructors.handlers = newhandler -- downward compatible
+constructors.newhandler = newhandler
+
+local function setnewhandler(what) -- could be a metatable newindex
local handler = handlers[what]
if not handler then
handler = { }
@@ -1245,7 +1268,16 @@ function constructors.newhandler(what) -- could be a metatable newindex
return handler
end
-function constructors.newfeatures(what) -- could be a metatable newindex
+setmetatable(newhandler, {
+ __call = function(t,k) local v = t[k] return v end,
+ __index = function(t,k) local v = setnewhandler(k) t[k] = v return v end,
+})
+
+local newfeatures = { }
+constructors.newfeatures = newfeatures -- downward compatible
+constructors.features = newfeatures
+
+local function setnewfeatures(what)
local handler = handlers[what]
local features = handler.features
if not features then
@@ -1265,6 +1297,11 @@ function constructors.newfeatures(what) -- could be a metatable newindex
return features
end
+setmetatable(newfeatures, {
+ __call = function(t,k) local v = t[k] return v end,
+ __index = function(t,k) local v = setnewfeatures(k) t[k] = v return v end,
+})
+
--[[ldx--
<p>We need to check for default features. For this we provide
a helper function.</p>
diff --git a/src/fontloader/misc/fontloader-font-dsp.lua b/src/fontloader/misc/fontloader-font-dsp.lua
index 37ae166..9726c51 100644
--- a/src/fontloader/misc/fontloader-font-dsp.lua
+++ b/src/fontloader/misc/fontloader-font-dsp.lua
@@ -76,6 +76,7 @@ local readshort = streamreader.readinteger2 -- 16-bit signed integer
local readfword = readshort
local readstring = streamreader.readstring
local readtag = streamreader.readtag
+local readbytes = streamreader.readbytes
local gsubhandlers = { }
local gposhandlers = { }
@@ -2191,7 +2192,7 @@ function readers.math(f,fontdata,specification)
setposition(f,tableoffset)
local version = readulong(f)
if version ~= 0x00010000 then
- report("table version %a of %a is not supported (yet), maybe font %s is bad",version,what,fontdata.filename)
+ report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"math",fontdata.filename)
return
end
local constants = readushort(f)
@@ -2211,3 +2212,144 @@ function readers.math(f,fontdata,specification)
end
end
end
+
+function readers.colr(f,fontdata,specification)
+ if specification.details then
+ local datatable = fontdata.tables.colr
+ if datatable then
+ local tableoffset = datatable.offset
+ setposition(f,tableoffset)
+ local version = readushort(f)
+ if version ~= 0 then
+ report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"colr",fontdata.filename)
+ return
+ end
+ if not fontdata.tables.cpal then
+ report("color table %a in font %a has no mandate %a table","colr",fontdata.filename,"cpal")
+ fontdata.colorpalettes = { }
+ end
+ local glyphs = fontdata.glyphs
+ local nofglyphs = readushort(f)
+ local baseoffset = readulong(f)
+ local layeroffset = readulong(f)
+ local noflayers = readushort(f)
+ local layerrecords = { }
+ local maxclass = 0
+ -- The special value 0xFFFF is foreground (but we index from 1). It
+ -- more looks like indices into a palette so 'class' is a better name
+ -- than 'palette'.
+ setposition(f,tableoffset + layeroffset)
+ for i=1,noflayers do
+ local slot = readushort(f)
+ local class = readushort(f)
+ if class < 0xFFFF then
+ class = class + 1
+ if class > maxclass then
+ maxclass = class
+ end
+ end
+ layerrecords[i] = {
+ slot = slot,
+ class = class,
+ }
+ end
+ fontdata.maxcolorclass = maxclass
+ setposition(f,tableoffset + baseoffset)
+ for i=0,nofglyphs-1 do
+ local glyphindex = readushort(f)
+ local firstlayer = readushort(f)
+ local noflayers = readushort(f)
+ local t = { }
+ for i=1,noflayers do
+ t[i] = layerrecords[firstlayer+i]
+ end
+ glyphs[glyphindex].colors = t
+ end
+ end
+ end
+end
+
+function readers.cpal(f,fontdata,specification)
+ if specification.details then
+ local datatable = fontdata.tables.cpal
+ if datatable then
+ local tableoffset = datatable.offset
+ setposition(f,tableoffset)
+ local version = readushort(f)
+ if version > 1 then
+ report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"cpal",fontdata.filename)
+ return
+ end
+ local nofpaletteentries = readushort(f)
+ local nofpalettes = readushort(f)
+ local nofcolorrecords = readushort(f)
+ local firstcoloroffset = readulong(f)
+ local colorrecords = { }
+ local palettes = { }
+ for i=1,nofpalettes do
+ palettes[i] = readushort(f)
+ end
+ if version == 1 then
+ -- used for guis
+ local palettettypesoffset = readulong(f)
+ local palettelabelsoffset = readulong(f)
+ local paletteentryoffset = readulong(f)
+ end
+ setposition(f,tableoffset+firstcoloroffset)
+ for i=1,nofcolorrecords do
+ local b, g, r, a = readbytes(f,4)
+ colorrecords[i] = {
+ r, g, b, a ~= 255 and a or nil,
+ }
+ end
+ for i=1,nofpalettes do
+ local p = { }
+ local o = palettes[i]
+ for j=1,nofpaletteentries do
+ p[j] = colorrecords[o+j]
+ end
+ palettes[i] = p
+ end
+ fontdata.colorpalettes = palettes
+ end
+ end
+end
+
+function readers.svg(f,fontdata,specification)
+ if specification.details then
+ local datatable = fontdata.tables.svg
+ if datatable then
+ local tableoffset = datatable.offset
+ setposition(f,tableoffset)
+ local version = readushort(f)
+ if version ~= 0 then
+ report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"svg",fontdata.filename)
+ return
+ end
+ local glyphs = fontdata.glyphs
+ local indexoffset = tableoffset + readulong(f)
+ local reserved = readulong(f)
+ setposition(f,indexoffset)
+ local nofentries = readushort(f)
+ local entries = { }
+ for i=1,nofentries do
+ entries[i] = {
+ first = readushort(f),
+ last = readushort(f),
+ offset = indexoffset + readulong(f),
+ length = readulong(f),
+ }
+ end
+ for i=1,nofentries do
+ local entry = entries[i]
+ setposition(f,entry.offset)
+ entries[i] = {
+ first = entry.first,
+ last = entry.last,
+ data = readstring(f,entry.length)
+ }
+ end
+ fontdata.svgshapes = entries
+ end
+ end
+end
diff --git a/src/fontloader/misc/fontloader-font-map.lua b/src/fontloader/misc/fontloader-font-map.lua
index db43495..6151b37 100644
--- a/src/fontloader/misc/fontloader-font-map.lua
+++ b/src/fontloader/misc/fontloader-font-map.lua
@@ -139,7 +139,7 @@ local f_double = formatters["%04X%04X"]
-- end
-- end
-local function tounicode16(unicode,name)
+local function tounicode16(unicode)
if unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then
return f_single(unicode)
else
@@ -148,7 +148,7 @@ local function tounicode16(unicode,name)
end
end
-local function tounicode16sequence(unicodes,name)
+local function tounicode16sequence(unicodes)
local t = { }
for l=1,#unicodes do
local u = unicodes[l]
diff --git a/src/fontloader/misc/fontloader-font-one.lua b/src/fontloader/misc/fontloader-font-one.lua
index a9f78f4..a6f47e8 100644
--- a/src/fontloader/misc/fontloader-font-one.lua
+++ b/src/fontloader/misc/fontloader-font-one.lua
@@ -45,14 +45,14 @@ local definers = fonts.definers
local readers = fonts.readers
local constructors = fonts.constructors
-local afm = constructors.newhandler("afm")
-local pfb = constructors.newhandler("pfb")
+local afm = constructors.handlers.afm
+local pfb = constructors.handlers.pfb
local otf = fonts.handlers.otf
local otfreaders = otf.readers
local otfenhancers = otf.enhancers
-local afmfeatures = constructors.newfeatures("afm")
+local afmfeatures = constructors.features.afm
local registerafmfeature = afmfeatures.register
afm.version = 1.512 -- incrementing this number one up will force a re-cache
diff --git a/src/fontloader/misc/fontloader-font-osd.lua b/src/fontloader/misc/fontloader-font-osd.lua
index d2bb210..a3dda67 100644
--- a/src/fontloader/misc/fontloader-font-osd.lua
+++ b/src/fontloader/misc/fontloader-font-osd.lua
@@ -82,7 +82,7 @@ local otf = fonts.handlers.otf
local handlers = otf.handlers
local methods = fonts.analyzers.methods
-local otffeatures = fonts.constructors.newfeatures("otf")
+local otffeatures = fonts.constructors.features.otf
local registerotffeature = otffeatures.register
local nuts = nodes.nuts
diff --git a/src/fontloader/misc/fontloader-font-ota.lua b/src/fontloader/misc/fontloader-font-ota.lua
index 42566eb..4ddb831 100644
--- a/src/fontloader/misc/fontloader-font-ota.lua
+++ b/src/fontloader/misc/fontloader-font-ota.lua
@@ -55,7 +55,7 @@ local fontdata = fonts.hashes.identifiers
local categories = characters and characters.categories or { } -- sorry, only in context
local chardata = characters and characters.data
-local otffeatures = fonts.constructors.newfeatures("otf")
+local otffeatures = fonts.constructors.features.otf
local registerotffeature = otffeatures.register
--[[ldx--
diff --git a/src/fontloader/misc/fontloader-font-otd.lua b/src/fontloader/misc/fontloader-font-otd.lua
index fc5ba64..64cb1bc 100644
--- a/src/fontloader/misc/fontloader-font-otd.lua
+++ b/src/fontloader/misc/fontloader-font-otd.lua
@@ -132,6 +132,10 @@ local wildcard = "*"
-- needs checking: some added features can pass twice
+local P, C, Cc, lpegmatch = lpeg.P, lpeg.C, lpeg.Cc, lpeg.match
+
+local pattern = P("always") * (P(-1) * Cc(true) + P(":") * C((1-P(-1))^1))
+
local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr,dynamic,ra,autoscript,autolanguage)
local features = sequence.features
if features then
@@ -148,21 +152,34 @@ local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr
e_e = s_enabled and s_enabled[kind] -- the value (font)
end
if e_e then
- local scripts = features[kind] --
- local languages = scripts[script] or scripts[wildcard]
- if not languages and autoscript then
- langages = defaultscript(featuretype,autoscript,scripts)
- end
- if languages then
- -- we need detailed control over default becase we want to trace
- -- only first attribute match check, so we assume simple fina's
- local valid = false
- if languages[language] then
- valid = e_e
- elseif languages[wildcard] then
- valid = e_e
- elseif autolanguage and defaultlanguage(featuretype,autolanguage,languages) then
- valid = e_e
+ local valid = type(e_e) == "string" and lpegmatch(pattern,e_e)
+ if valid then
+ -- we have hit always
+ local attribute = autofeatures[kind] or false
+ if trace_applied then
+ report_process(
+ "font %s, dynamic %a (%a), feature %a, script %a, language %a, lookup %a, value %a",
+ font,attr or 0,dynamic,kind,"*","*",sequence.name,valid)
+ end
+ ra[#ra+1] = { valid, attribute, sequence, kind }
+ else
+ -- we already checked for e_e
+ local scripts = features[kind] --
+ local languages = scripts[script] or scripts[wildcard]
+ if not languages and autoscript then
+ langages = defaultscript(featuretype,autoscript,scripts)
+ end
+ if languages then
+ -- we need detailed control over default becase we want to trace
+ -- only first attribute match check, so we assume simple fina's
+ -- local valid = false
+ if languages[language] then
+ valid = e_e
+ elseif languages[wildcard] then
+ valid = e_e
+ elseif autolanguage and defaultlanguage(featuretype,autolanguage,languages) then
+ valid = e_e
+ end
end
if valid then
local attribute = autofeatures[kind] or false
@@ -241,6 +258,7 @@ function otf.dataset(tfmdata,font,attr) -- attr only when explicit (as in specia
local autoscript = (s_enabled and s_enabled.autoscript ) or (a_enabled and a_enabled.autoscript )
local autolanguage = (s_enabled and s_enabled.autolanguage) or (a_enabled and a_enabled.autolanguage)
for s=1,#sequences do
+ -- just return nil or ra step
initialize(sequences[s],script,language,s_enabled,a_enabled,font,attr,dynamic,ra,autoscript,autolanguage)
end
end
diff --git a/src/fontloader/misc/fontloader-font-oti.lua b/src/fontloader/misc/fontloader-font-oti.lua
index bacd001..d74d2d5 100644
--- a/src/fontloader/misc/fontloader-font-oti.lua
+++ b/src/fontloader/misc/fontloader-font-oti.lua
@@ -11,8 +11,8 @@ local lower = string.lower
local fonts = fonts
local constructors = fonts.constructors
-local otf = constructors.newhandler("otf")
-local otffeatures = constructors.newfeatures("otf")
+local otf = constructors.handlers.otf
+local otffeatures = constructors.features.otf
local registerotffeature = otffeatures.register
local otftables = otf.tables or { }
diff --git a/src/fontloader/misc/fontloader-font-otj.lua b/src/fontloader/misc/fontloader-font-otj.lua
index 0db30c6..d1408fd 100644
--- a/src/fontloader/misc/fontloader-font-otj.lua
+++ b/src/fontloader/misc/fontloader-font-otj.lua
@@ -24,6 +24,8 @@ if not modules then modules = { } end modules ['font-otj'] = {
-- The use_advance code is just a test and is meant for testing and manuals. There is no
-- performance (or whatever) gain and using kerns is somewhat cleaner (at least for now).
+-- Maybe: subtype fontkern when pure kerns.
+
if not nodes.properties then return end
local next, rawget = next, rawget
diff --git a/src/fontloader/misc/fontloader-font-otl.lua b/src/fontloader/misc/fontloader-font-otl.lua
index 73e3df9..c7c278a 100644
--- a/src/fontloader/misc/fontloader-font-otl.lua
+++ b/src/fontloader/misc/fontloader-font-otl.lua
@@ -53,8 +53,12 @@ local report_otf = logs.reporter("fonts","otf loading")
local fonts = fonts
local otf = fonts.handlers.otf
-otf.version = 3.021 -- beware: also sync font-mis.lua and in mtx-fonts
+otf.version = 3.022 -- beware: also sync font-mis.lua and in mtx-fonts
otf.cache = containers.define("fonts", "otl", otf.version, true)
+otf.svgcache = containers.define("fonts", "svg", otf.version, true)
+otf.pdfcache = containers.define("fonts", "pdf", otf.version, true)
+
+otf.svgenabled = false
local otfreaders = otf.readers
@@ -63,7 +67,7 @@ local definers = fonts.definers
local readers = fonts.readers
local constructors = fonts.constructors
-local otffeatures = constructors.newfeatures("otf")
+local otffeatures = constructors.features.otf
local registerotffeature = otffeatures.register
local enhancers = allocate()
@@ -270,6 +274,25 @@ function otf.load(filename,sub,featurefile) -- second argument (format) is gone
--
--
if data then
+ --
+ local resources = data.resources
+ local svgshapes = resources.svgshapes
+ if svgshapes then
+ resources.svgshapes = nil
+ if otf.svgenabled then
+ local timestamp = os.date()
+ -- work in progress ... a bit boring to do
+ containers.write(otf.svgcache,hash, {
+ svgshapes = svgshapes,
+ timestamp = timestamp,
+ })
+ data.properties.svg = {
+ hash = hash,
+ timestamp = timestamp,
+ }
+ end
+ end
+ --
otfreaders.compact(data)
otfreaders.rehash(data,"unicodes")
otfreaders.addunicodetable(data)
@@ -346,7 +369,6 @@ end
local function copytotfm(data,cache_id)
if data then
local metadata = data.metadata
- local resources = data.resources
local properties = derivetable(data.properties)
local descriptions = derivetable(data.descriptions)
local goodies = derivetable(data.goodies)
diff --git a/src/fontloader/misc/fontloader-font-otr.lua b/src/fontloader/misc/fontloader-font-otr.lua
index 6595262..e09e87d 100644
--- a/src/fontloader/misc/fontloader-font-otr.lua
+++ b/src/fontloader/misc/fontloader-font-otr.lua
@@ -129,12 +129,11 @@ local function readlongdatetime(f)
return 0x100000000 * d + 0x1000000 * e + 0x10000 * f + 0x100 * g + h
end
-local tableversion = 0.004
-local privateoffset = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -- 0x10FFFF
+local tableversion = 0.004
+readers.tableversion = tableversion
+local privateoffset = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -- 0x10FFFF
+local reportedskipped = { }
-readers.tableversion = tableversion
-
-local reportedskipped = { }
local function reportskippedtable(tag)
if not reportedskipped[tag] then
@@ -1657,6 +1656,26 @@ function readers.glyf(f,fontdata,specification) -- part goes to cff module
end
end
+-- Experimental (we need fonts).
+
+function readers.colr(f,fontdata,specification)
+ if specification.details then
+ reportskippedtable("colr")
+ end
+end
+
+function readers.cpal(f,fontdata,specification)
+ if specification.details then
+ reportskippedtable("cpal")
+ end
+end
+
+function readers.svg(f,fontdata,specification)
+ if specification.details then
+ reportskippedtable("svg")
+ end
+end
+
-- Here we have a table that we really need for later processing although a more advanced gpos table
-- can also be available. Todo: we need a 'fake' lookup for this (analogue to ff).
@@ -1997,6 +2016,9 @@ local function readdata(f,offset,specification)
readers["cmap"](f,fontdata,specification)
readers["loca"](f,fontdata,specification)
readers["glyf"](f,fontdata,specification)
+ readers["colr"](f,fontdata,specification)
+ readers["cpal"](f,fontdata,specification)
+ readers["svg" ](f,fontdata,specification)
readers["kern"](f,fontdata,specification)
readers["gdef"](f,fontdata,specification)
readers["gsub"](f,fontdata,specification)
@@ -2165,7 +2187,8 @@ function readers.loadfont(filename,n)
goodies = { },
metadata = getinfo(fontdata,n), -- no platformnames here !
properties = {
- hasitalics = fontdata.hasitalics or false,
+ hasitalics = fontdata.hasitalics or false,
+ maxcolorclass = fontdata.maxcolorclass,
},
resources = {
-- filename = fontdata.filename,
@@ -2182,6 +2205,8 @@ function readers.loadfont(filename,n)
version = getname(fontdata,"version"),
cidinfo = fontdata.cidinfo,
mathconstants = fontdata.mathconstants,
+ colorpalettes = fontdata.colorpalettes,
+ svgshapes = fontdata.svgshapes,
},
}
end
diff --git a/src/fontloader/misc/fontloader-font-ots.lua b/src/fontloader/misc/fontloader-font-ots.lua
index 669668e..51704bf 100644
--- a/src/fontloader/misc/fontloader-font-ots.lua
+++ b/src/fontloader/misc/fontloader-font-ots.lua
@@ -124,7 +124,7 @@ local trace_cursive = false registertracker("otf.cursive", function(v
local trace_preparing = false registertracker("otf.preparing", function(v) trace_preparing = v end)
local trace_bugs = false registertracker("otf.bugs", function(v) trace_bugs = v end)
local trace_details = false registertracker("otf.details", function(v) trace_details = v end)
-local trace_applied = false registertracker("otf.applied", function(v) trace_applied = v end)
+----- trace_applied = false registertracker("otf.applied", function(v) trace_applied = v end)
local trace_steps = false registertracker("otf.steps", function(v) trace_steps = v end)
local trace_skips = false registertracker("otf.skips", function(v) trace_skips = v end)
local trace_directions = false registertracker("otf.directions", function(v) trace_directions = v end)
@@ -239,7 +239,7 @@ local cursonce = true
local fonthashes = fonts.hashes
local fontdata = fonthashes.identifiers
-local otffeatures = fonts.constructors.newfeatures("otf")
+local otffeatures = fonts.constructors.features.otf
local registerotffeature = otffeatures.register
local onetimemessage = fonts.loggers.onetimemessage or function() end
@@ -3389,9 +3389,13 @@ local function featuresprocessor(head,font,attr)
end
- if attr == 0 then
- attr = false -- some 10% faster when no dynamics but hardly measureable on real runs
- end
+ -- some 10% faster when no dynamics but hardly measureable on real runs .. but: it only
+ -- works when we have no other dynamics as otherwise the zero run will be applied to the
+ -- whole stream for which we then need to pass another variable which we won't
+
+ -- if attr == 0 then
+ -- attr = false
+ -- end
head = tonut(head)
@@ -3484,7 +3488,6 @@ local function featuresprocessor(head,font,attr)
local start = head -- local ?
rlmode = 0 -- to be checked ?
if nofsteps == 1 then -- happens often
-
local step = steps[1]
local lookupcache = step.coverage
if not lookupcache then
diff --git a/src/fontloader/misc/fontloader-font-oup.lua b/src/fontloader/misc/fontloader-font-oup.lua
index bd47e71..e2d209a 100644
--- a/src/fontloader/misc/fontloader-font-oup.lua
+++ b/src/fontloader/misc/fontloader-font-oup.lua
@@ -707,6 +707,19 @@ local function unifyglyphs(fontdata,usenames)
end
end
--
+ local colorpalettes = resources.colorpalettes
+ if colorpalettes then
+ for index=1,#glyphs do
+ local colors = glyphs[index].colors
+ if colors then
+ for i=1,#colors do
+ local c = colors[i]
+ c.slot = indices[c.slot]
+ end
+ end
+ end
+ end
+ --
fontdata.private = private
fontdata.glyphs = nil
fontdata.names = names
@@ -1159,6 +1172,7 @@ function readers.pack(data)
local sequences = resources.sequences
local sublookups = resources.sublookups
local features = resources.features
+ local palettes = resources.colorpalettes
local chardata = characters and characters.data
local descriptions = data.descriptions or data.glyphs
@@ -1191,6 +1205,14 @@ function readers.pack(data)
end
end
end
+ -- if palettes then
+ -- local color = description.color
+ -- if color then
+ -- for i=1,#color do
+ -- color[i] = pack_normal(color[i])
+ -- end
+ -- end
+ -- end
end
local function packthem(sequences)
@@ -1315,6 +1337,16 @@ function readers.pack(data)
end
end
+ if palettes then
+ for i=1,#palettes do
+ local p = palettes[i]
+ for j=1,#p do
+ p[j] = pack_indexed(p[j])
+ end
+ end
+
+ end
+
if not success(1,pass) then
return
end
@@ -1462,6 +1494,7 @@ function readers.unpack(data)
local sequences = resources.sequences
local sublookups = resources.sublookups
local features = resources.features
+ local palettes = resources.colorpalettes
local unpacked = { }
setmetatable(unpacked,unpacked_mt)
for unicode, description in next, descriptions do
@@ -1488,6 +1521,17 @@ function readers.unpack(data)
end
end
end
+ -- if palettes then
+ -- local color = description.color
+ -- if color then
+ -- for i=1,#color do
+ -- local tv = tables[color[i]]
+ -- if tv then
+ -- color[i] = tv
+ -- end
+ -- end
+ -- end
+ -- end
end
local function unpackthem(sequences)
@@ -1717,6 +1761,18 @@ function readers.unpack(data)
end
end
+ if palettes then
+ for i=1,#palettes do
+ local p = palettes[i]
+ for j=1,#p do
+ local tv = tables[p[j]]
+ if tv then
+ p[j] = tv
+ end
+ end
+ end
+ end
+
data.tables = nil
end
end
diff --git a/src/fontloader/misc/fontloader-font-tfm.lua b/src/fontloader/misc/fontloader-font-tfm.lua
index f790064..ab6d795 100644
--- a/src/fontloader/misc/fontloader-font-tfm.lua
+++ b/src/fontloader/misc/fontloader-font-tfm.lua
@@ -23,12 +23,12 @@ local readers = fonts.readers
local constructors = fonts.constructors
local encodings = fonts.encodings
-local tfm = constructors.newhandler("tfm")
+local tfm = constructors.handlers.tfm
tfm.version = 1.000
tfm.maxnestingdepth = 5
tfm.maxnestingsize = 65536*1024
-local tfmfeatures = constructors.newfeatures("tfm")
+local tfmfeatures = constructors.features.tfm
----- registertfmfeature = tfmfeatures.register
constructors.resolvevirtualtoo = false -- wil be set in font-ctx.lua
diff --git a/src/fontloader/misc/fontloader-fonts-ext.lua b/src/fontloader/misc/fontloader-fonts-ext.lua
index b60d045..9d8d307 100644
--- a/src/fontloader/misc/fontloader-fonts-ext.lua
+++ b/src/fontloader/misc/fontloader-fonts-ext.lua
@@ -12,7 +12,7 @@ if context then
end
local fonts = fonts
-local otffeatures = fonts.constructors.newfeatures("otf")
+local otffeatures = fonts.constructors.features.otf
-- A few generic extensions.
diff --git a/src/fontloader/misc/fontloader-fonts.lua b/src/fontloader/misc/fontloader-fonts.lua
index c493844..83d52d9 100644
--- a/src/fontloader/misc/fontloader-fonts.lua
+++ b/src/fontloader/misc/fontloader-fonts.lua
@@ -186,6 +186,7 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then
loadmodule("l-file.lua")
loadmodule("l-boolean.lua")
loadmodule("l-math.lua")
+ loadmodule("l-unicode.lua")
-- A few slightly higher level support modules:
@@ -257,6 +258,7 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then
loadmodule('font-ota.lua')
loadmodule('font-ots.lua')
loadmodule('font-osd.lua')
+ loadmodule('font-ocl.lua') -- svg needs 0.97 (for fix in memstreams)
-- type one code
diff --git a/src/fontloader/misc/fontloader-math.tex b/src/fontloader/misc/fontloader-math.tex
index 604b4a1..b249021 100644
--- a/src/fontloader/misc/fontloader-math.tex
+++ b/src/fontloader/misc/fontloader-math.tex
@@ -40,9 +40,9 @@
\font\tenbf = file:lmroman10-bold.otf:+liga;+kern;+tlig;+trep at 10pt
\font\tenbi = file:lmroman10-bolditalic.otf:+liga;+kern;+tlig;+trep at 10pt
%
- \font\mathfonttextupright = file:latinmodern-math.otf:ssty=0;fixmath=yes at 10pt
- \font\mathfontscriptupright = file:latinmodern-math.otf:ssty=1;fixmath=yes at 7pt
- \font\mathfontscriptscriptupright = file:latinmodern-math.otf:ssty=2;fixmath=yes at 5pt
+ \font\mathfonttextupright = file:latinmodern-math.otf:script=math;ssty=0;mathsize=yes at 10pt
+ \font\mathfontscriptupright = file:latinmodern-math.otf:script=math;ssty=1;mathsize=yes at 7pt
+ \font\mathfontscriptscriptupright = file:latinmodern-math.otf:script=math;ssty=2;mathsize=yes at 5pt
%
\textfont 0 = \mathfonttextupright
\scriptfont 0 = \mathfontscriptupright
@@ -61,9 +61,9 @@
\font\tenbf = file:lucidabrightot-demi.otf:+liga;+kern;+tlig;+trep at 10pt
\font\tenbi = file:lucidabrightot-demiitalic.otf:+liga;+kern;+tlig;+trep at 10pt
%
- \font\mathfonttextupright = file:lucidabrightmathot.otf:ssty=0;fixmath=yes at 10pt
- \font\mathfontscriptupright = file:lucidabrightmathot.otf:ssty=1;fixmath=yes at 7pt
- \font\mathfontscriptscriptupright = file:lucidabrightmathot.otf:ssty=2;fixmath=yes at 5pt
+ \font\mathfonttextupright = file:lucidabrightmathot.otf:script=math;ssty=0;mathsize=yes at 10pt
+ \font\mathfontscriptupright = file:lucidabrightmathot.otf:script=math;ssty=1;mathsize=yes at 7pt
+ \font\mathfontscriptscriptupright = file:lucidabrightmathot.otf:script=math;ssty=2;mathsize=yes at 5pt
%
\textfont 0 = \mathfonttextupright
\scriptfont 0 = \mathfontscriptupright
diff --git a/src/fontloader/runtime/fontloader-reference.lua b/src/fontloader/runtime/fontloader-reference.lua
index 4d1ef83..350d3cf 100644
--- a/src/fontloader/runtime/fontloader-reference.lua
+++ b/src/fontloader/runtime/fontloader-reference.lua
@@ -1,6 +1,6 @@
-- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua
-- parent file : c:/data/develop/context/sources/luatex-fonts.lua
--- merge date : 05/31/16 09:02:55
+-- merge date : 06/10/16 23:51:36
do -- begin closure to overcome local limits and interference
@@ -2785,6 +2785,620 @@ end -- closure
do -- begin closure to overcome local limits and interference
+if not modules then modules={} end modules ['l-unicode']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+utf=utf or (unicode and unicode.utf8) or {}
+utf.characters=utf.characters or string.utfcharacters
+utf.values=utf.values or string.utfvalues
+local type=type
+local char,byte,format,sub,gmatch=string.char,string.byte,string.format,string.sub,string.gmatch
+local concat=table.concat
+local P,C,R,Cs,Ct,Cmt,Cc,Carg,Cp=lpeg.P,lpeg.C,lpeg.R,lpeg.Cs,lpeg.Ct,lpeg.Cmt,lpeg.Cc,lpeg.Carg,lpeg.Cp
+local lpegmatch=lpeg.match
+local patterns=lpeg.patterns
+local tabletopattern=lpeg.utfchartabletopattern
+local bytepairs=string.bytepairs
+local finder=lpeg.finder
+local replacer=lpeg.replacer
+local utfvalues=utf.values
+local utfgmatch=utf.gmatch
+local p_utftype=patterns.utftype
+local p_utfstricttype=patterns.utfstricttype
+local p_utfoffset=patterns.utfoffset
+local p_utf8char=patterns.utf8character
+local p_utf8byte=patterns.utf8byte
+local p_utfbom=patterns.utfbom
+local p_newline=patterns.newline
+local p_whitespace=patterns.whitespace
+if not unicode then
+ unicode={ utf=utf }
+end
+if not utf.char then
+ local floor,char=math.floor,string.char
+ function utf.char(n)
+ if n<0x80 then
+ return char(n)
+ elseif n<0x800 then
+ return char(
+ 0xC0+floor(n/0x40),
+ 0x80+(n%0x40)
+ )
+ elseif n<0x10000 then
+ return char(
+ 0xE0+floor(n/0x1000),
+ 0x80+(floor(n/0x40)%0x40),
+ 0x80+(n%0x40)
+ )
+ elseif n<0x200000 then
+ return char(
+ 0xF0+floor(n/0x40000),
+ 0x80+(floor(n/0x1000)%0x40),
+ 0x80+(floor(n/0x40)%0x40),
+ 0x80+(n%0x40)
+ )
+ else
+ return ""
+ end
+ end
+end
+if not utf.byte then
+ local utf8byte=patterns.utf8byte
+ function utf.byte(c)
+ return lpegmatch(utf8byte,c)
+ end
+end
+local utfchar,utfbyte=utf.char,utf.byte
+function utf.filetype(data)
+ return data and lpegmatch(p_utftype,data) or "unknown"
+end
+local toentities=Cs (
+ (
+ patterns.utf8one+(
+ patterns.utf8two+patterns.utf8three+patterns.utf8four
+ )/function(s) local b=utfbyte(s) if b<127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+patterns.toentities=toentities
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+local one=P(1)
+local two=C(1)*C(1)
+local four=C(R(utfchar(0xD8),utfchar(0xFF)))*C(1)*C(1)*C(1)
+local pattern=P("\254\255")*Cs((
+ four/function(a,b,c,d)
+ local ab=0xFF*byte(a)+byte(b)
+ local cd=0xFF*byte(c)+byte(d)
+ return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000)
+ end+two/function(a,b)
+ return utfchar(byte(a)*256+byte(b))
+ end+one
+ )^1 )+P("\255\254")*Cs((
+ four/function(b,a,d,c)
+ local ab=0xFF*byte(a)+byte(b)
+ local cd=0xFF*byte(c)+byte(d)
+ return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000)
+ end+two/function(b,a)
+ return utfchar(byte(a)*256+byte(b))
+ end+one
+ )^1 )
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s
+end
+local validatedutf=Cs (
+ (
+ patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four+P(1)/"�"
+ )^0
+)
+patterns.validatedutf=validatedutf
+function utf.is_valid(str)
+ return type(str)=="string" and lpegmatch(validatedutf,str) or false
+end
+if not utf.len then
+ local n,f=0,1
+ local utfcharcounter=patterns.utfbom^-1*Cmt (
+ Cc(1)*patterns.utf8one^1+Cc(2)*patterns.utf8two^1+Cc(3)*patterns.utf8three^1+Cc(4)*patterns.utf8four^1,
+ function(_,t,d)
+ n=n+(t-f)/d
+ f=t
+ return true
+ end
+ )^0
+ function utf.len(str)
+ n,f=0,1
+ lpegmatch(utfcharcounter,str or "")
+ return n
+ end
+end
+utf.length=utf.len
+if not utf.sub then
+ local utflength=utf.length
+ local b,e,n,first,last=0,0,0,0,0
+ local function slide_zero(s,p)
+ n=n+1
+ if n>=last then
+ e=p-1
+ else
+ return p
+ end
+ end
+ local function slide_one(s,p)
+ n=n+1
+ if n==first then
+ b=p
+ end
+ if n>=last then
+ e=p-1
+ else
+ return p
+ end
+ end
+ local function slide_two(s,p)
+ n=n+1
+ if n==first then
+ b=p
+ else
+ return true
+ end
+ end
+ local pattern_zero=Cmt(p_utf8char,slide_zero)^0
+ local pattern_one=Cmt(p_utf8char,slide_one )^0
+ local pattern_two=Cmt(p_utf8char,slide_two )^0
+ local pattern_first=C(patterns.utf8character)
+ function utf.sub(str,start,stop)
+ if not start then
+ return str
+ end
+ if start==0 then
+ start=1
+ end
+ if not stop then
+ if start<0 then
+ local l=utflength(str)
+ start=l+start
+ else
+ start=start-1
+ end
+ b,n,first=0,0,start
+ lpegmatch(pattern_two,str)
+ if n>=first then
+ return sub(str,b)
+ else
+ return ""
+ end
+ end
+ if start<0 or stop<0 then
+ local l=utf.length(str)
+ if start<0 then
+ start=l+start
+ if start<=0 then
+ start=1
+ else
+ start=start+1
+ end
+ end
+ if stop<0 then
+ stop=l+stop
+ if stop==0 then
+ stop=1
+ else
+ stop=stop+1
+ end
+ end
+ end
+ if start==1 and stop==1 then
+ return lpegmatch(pattern_first,str) or ""
+ elseif start>stop then
+ return ""
+ elseif start>1 then
+ b,e,n,first,last=0,0,0,start-1,stop
+ lpegmatch(pattern_one,str)
+ if n>=first and e==0 then
+ e=#str
+ end
+ return sub(str,b,e)
+ else
+ b,e,n,last=1,0,0,stop
+ lpegmatch(pattern_zero,str)
+ if e==0 then
+ e=#str
+ end
+ return sub(str,b,e)
+ end
+ end
+end
+function utf.remapper(mapping,option,action)
+ local variant=type(mapping)
+ if variant=="table" then
+ action=action or mapping
+ if option=="dynamic" then
+ local pattern=false
+ table.setmetatablenewindex(mapping,function(t,k,v) rawset(t,k,v) pattern=false end)
+ return function(str)
+ if not str or str=="" then
+ return ""
+ else
+ if not pattern then
+ pattern=Cs((tabletopattern(mapping)/action+p_utf8char)^0)
+ end
+ return lpegmatch(pattern,str)
+ end
+ end
+ elseif option=="pattern" then
+ return Cs((tabletopattern(mapping)/action+p_utf8char)^0)
+ else
+ local pattern=Cs((tabletopattern(mapping)/action+p_utf8char)^0)
+ return function(str)
+ if not str or str=="" then
+ return ""
+ else
+ return lpegmatch(pattern,str)
+ end
+ end,pattern
+ end
+ elseif variant=="function" then
+ if option=="pattern" then
+ return Cs((p_utf8char/mapping+p_utf8char)^0)
+ else
+ local pattern=Cs((p_utf8char/mapping+p_utf8char)^0)
+ return function(str)
+ if not str or str=="" then
+ return ""
+ else
+ return lpegmatch(pattern,str)
+ end
+ end,pattern
+ end
+ else
+ return function(str)
+ return str or ""
+ end
+ end
+end
+function utf.replacer(t)
+ local r=replacer(t,false,false,true)
+ return function(str)
+ return lpegmatch(r,str)
+ end
+end
+function utf.subtituter(t)
+ local f=finder (t)
+ local r=replacer(t,false,false,true)
+ return function(str)
+ local i=lpegmatch(f,str)
+ if not i then
+ return str
+ elseif i>#str then
+ return str
+ else
+ return lpegmatch(r,str)
+ end
+ end
+end
+local utflinesplitter=p_utfbom^-1*lpeg.tsplitat(p_newline)
+local utfcharsplitter_ows=p_utfbom^-1*Ct(C(p_utf8char)^0)
+local utfcharsplitter_iws=p_utfbom^-1*Ct((p_whitespace^1+C(p_utf8char))^0)
+local utfcharsplitter_raw=Ct(C(p_utf8char)^0)
+patterns.utflinesplitter=utflinesplitter
+function utf.splitlines(str)
+ return lpegmatch(utflinesplitter,str or "")
+end
+function utf.split(str,ignorewhitespace)
+ if ignorewhitespace then
+ return lpegmatch(utfcharsplitter_iws,str or "")
+ else
+ return lpegmatch(utfcharsplitter_ows,str or "")
+ end
+end
+function utf.totable(str)
+ return lpegmatch(utfcharsplitter_raw,str)
+end
+function utf.magic(f)
+ local str=f:read(4) or ""
+ local off=lpegmatch(p_utfoffset,str)
+ if off<4 then
+ f:seek('set',off)
+ end
+ return lpegmatch(p_utftype,str)
+end
+local utf16_to_utf8_be,utf16_to_utf8_le
+local utf32_to_utf8_be,utf32_to_utf8_le
+local utf_16_be_getbom=patterns.utfbom_16_be^-1
+local utf_16_le_getbom=patterns.utfbom_16_le^-1
+local utf_32_be_getbom=patterns.utfbom_32_be^-1
+local utf_32_le_getbom=patterns.utfbom_32_le^-1
+local utf_16_be_linesplitter=utf_16_be_getbom*lpeg.tsplitat(patterns.utf_16_be_nl)
+local utf_16_le_linesplitter=utf_16_le_getbom*lpeg.tsplitat(patterns.utf_16_le_nl)
+local utf_32_be_linesplitter=utf_32_be_getbom*lpeg.tsplitat(patterns.utf_32_be_nl)
+local utf_32_le_linesplitter=utf_32_le_getbom*lpeg.tsplitat(patterns.utf_32_le_nl)
+local more=0
+local p_utf16_to_utf8_be=C(1)*C(1)/function(left,right)
+ local now=256*byte(left)+byte(right)
+ if more>0 then
+ now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
+ more=0
+ return utfchar(now)
+ elseif now>=0xD800 and now<=0xDBFF then
+ more=now
+ return ""
+ else
+ return utfchar(now)
+ end
+end
+local p_utf16_to_utf8_le=C(1)*C(1)/function(right,left)
+ local now=256*byte(left)+byte(right)
+ if more>0 then
+ now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
+ more=0
+ return utfchar(now)
+ elseif now>=0xD800 and now<=0xDBFF then
+ more=now
+ return ""
+ else
+ return utfchar(now)
+ end
+end
+local p_utf32_to_utf8_be=C(1)*C(1)*C(1)*C(1)/function(a,b,c,d)
+ return utfchar(256*256*256*byte(a)+256*256*byte(b)+256*byte(c)+byte(d))
+end
+local p_utf32_to_utf8_le=C(1)*C(1)*C(1)*C(1)/function(a,b,c,d)
+ return utfchar(256*256*256*byte(d)+256*256*byte(c)+256*byte(b)+byte(a))
+end
+p_utf16_to_utf8_be=P(true)/function() more=0 end*utf_16_be_getbom*Cs(p_utf16_to_utf8_be^0)
+p_utf16_to_utf8_le=P(true)/function() more=0 end*utf_16_le_getbom*Cs(p_utf16_to_utf8_le^0)
+p_utf32_to_utf8_be=P(true)/function() more=0 end*utf_32_be_getbom*Cs(p_utf32_to_utf8_be^0)
+p_utf32_to_utf8_le=P(true)/function() more=0 end*utf_32_le_getbom*Cs(p_utf32_to_utf8_le^0)
+patterns.utf16_to_utf8_be=p_utf16_to_utf8_be
+patterns.utf16_to_utf8_le=p_utf16_to_utf8_le
+patterns.utf32_to_utf8_be=p_utf32_to_utf8_be
+patterns.utf32_to_utf8_le=p_utf32_to_utf8_le
+utf16_to_utf8_be=function(s)
+ if s and s~="" then
+ return lpegmatch(p_utf16_to_utf8_be,s)
+ else
+ return s
+ end
+end
+local utf16_to_utf8_be_t=function(t)
+ if not t then
+ return nil
+ elseif type(t)=="string" then
+ t=lpegmatch(utf_16_be_linesplitter,t)
+ end
+ for i=1,#t do
+ local s=t[i]
+ if s~="" then
+ t[i]=lpegmatch(p_utf16_to_utf8_be,s)
+ end
+ end
+ return t
+end
+utf16_to_utf8_le=function(s)
+ if s and s~="" then
+ return lpegmatch(p_utf16_to_utf8_le,s)
+ else
+ return s
+ end
+end
+local utf16_to_utf8_le_t=function(t)
+ if not t then
+ return nil
+ elseif type(t)=="string" then
+ t=lpegmatch(utf_16_le_linesplitter,t)
+ end
+ for i=1,#t do
+ local s=t[i]
+ if s~="" then
+ t[i]=lpegmatch(p_utf16_to_utf8_le,s)
+ end
+ end
+ return t
+end
+utf32_to_utf8_be=function(s)
+ if s and s~="" then
+ return lpegmatch(p_utf32_to_utf8_be,s)
+ else
+ return s
+ end
+end
+local utf32_to_utf8_be_t=function(t)
+ if not t then
+ return nil
+ elseif type(t)=="string" then
+ t=lpegmatch(utf_32_be_linesplitter,t)
+ end
+ for i=1,#t do
+ local s=t[i]
+ if s~="" then
+ t[i]=lpegmatch(p_utf32_to_utf8_be,s)
+ end
+ end
+ return t
+end
+utf32_to_utf8_le=function(s)
+ if s and s~="" then
+ return lpegmatch(p_utf32_to_utf8_le,s)
+ else
+ return s
+ end
+end
+local utf32_to_utf8_le_t=function(t)
+ if not t then
+ return nil
+ elseif type(t)=="string" then
+ t=lpegmatch(utf_32_le_linesplitter,t)
+ end
+ for i=1,#t do
+ local s=t[i]
+ if s~="" then
+ t[i]=lpegmatch(p_utf32_to_utf8_le,s)
+ end
+ end
+ return t
+end
+utf.utf16_to_utf8_le_t=utf16_to_utf8_le_t
+utf.utf16_to_utf8_be_t=utf16_to_utf8_be_t
+utf.utf32_to_utf8_le_t=utf32_to_utf8_le_t
+utf.utf32_to_utf8_be_t=utf32_to_utf8_be_t
+utf.utf16_to_utf8_le=utf16_to_utf8_le
+utf.utf16_to_utf8_be=utf16_to_utf8_be
+utf.utf32_to_utf8_le=utf32_to_utf8_le
+utf.utf32_to_utf8_be=utf32_to_utf8_be
+function utf.utf8_to_utf8_t(t)
+ return type(t)=="string" and lpegmatch(utflinesplitter,t) or t
+end
+function utf.utf16_to_utf8_t(t,endian)
+ return endian and utf16_to_utf8_be_t(t) or utf16_to_utf8_le_t(t) or t
+end
+function utf.utf32_to_utf8_t(t,endian)
+ return endian and utf32_to_utf8_be_t(t) or utf32_to_utf8_le_t(t) or t
+end
+local function little(b)
+ if b<0x10000 then
+ return char(b%256,b/256)
+ else
+ b=b-0x10000
+ local b1,b2=b/1024+0xD800,b%1024+0xDC00
+ return char(b1%256,b1/256,b2%256,b2/256)
+ end
+end
+local function big(b)
+ if b<0x10000 then
+ return char(b/256,b%256)
+ else
+ b=b-0x10000
+ local b1,b2=b/1024+0xD800,b%1024+0xDC00
+ return char(b1/256,b1%256,b2/256,b2%256)
+ end
+end
+local l_remap=Cs((p_utf8byte/little+P(1)/"")^0)
+local b_remap=Cs((p_utf8byte/big+P(1)/"")^0)
+local function utf8_to_utf16_be(str,nobom)
+ if nobom then
+ return lpegmatch(b_remap,str)
+ else
+ return char(254,255)..lpegmatch(b_remap,str)
+ end
+end
+local function utf8_to_utf16_le(str,nobom)
+ if nobom then
+ return lpegmatch(l_remap,str)
+ else
+ return char(255,254)..lpegmatch(l_remap,str)
+ end
+end
+utf.utf8_to_utf16_be=utf8_to_utf16_be
+utf.utf8_to_utf16_le=utf8_to_utf16_le
+function utf.utf8_to_utf16(str,littleendian,nobom)
+ if littleendian then
+ return utf8_to_utf16_le(str,nobom)
+ else
+ return utf8_to_utf16_be(str,nobom)
+ end
+end
+local pattern=Cs (
+ (p_utf8byte/function(unicode ) return format("0x%04X",unicode) end)*(p_utf8byte*Carg(1)/function(unicode,separator) return format("%s0x%04X",separator,unicode) end)^0
+)
+function utf.tocodes(str,separator)
+ return lpegmatch(pattern,str,1,separator or " ")
+end
+function utf.ustring(s)
+ return format("U+%05X",type(s)=="number" and s or utfbyte(s))
+end
+function utf.xstring(s)
+ return format("0x%05X",type(s)=="number" and s or utfbyte(s))
+end
+function utf.toeight(str)
+ if not str or str=="" then
+ return nil
+ end
+ local utftype=lpegmatch(p_utfstricttype,str)
+ if utftype=="utf-8" then
+ return sub(str,4)
+ elseif utftype=="utf-16-be" then
+ return utf16_to_utf8_be(str)
+ elseif utftype=="utf-16-le" then
+ return utf16_to_utf8_le(str)
+ else
+ return str
+ end
+end
+local p_nany=p_utf8char/""
+if utfgmatch then
+ function utf.count(str,what)
+ if type(what)=="string" then
+ local n=0
+ for _ in utfgmatch(str,what) do
+ n=n+1
+ end
+ return n
+ else
+ return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str)
+ end
+ end
+else
+ local cache={}
+ function utf.count(str,what)
+ if type(what)=="string" then
+ local p=cache[what]
+ if not p then
+ p=Cs((P(what)/" "+p_nany)^0)
+ cache[p]=p
+ end
+ return #lpegmatch(p,str)
+ else
+ return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str)
+ end
+ end
+end
+if not utf.characters then
+ function utf.characters(str)
+ return gmatch(str,".[\128-\191]*")
+ end
+ string.utfcharacters=utf.characters
+end
+if not utf.values then
+ local find=string.find
+ local dummy=function()
+ end
+ function utf.values(str)
+ local n=#str
+ if n==0 then
+ return dummy
+ elseif n==1 then
+ return function() return utfbyte(str) end
+ else
+ local p=1
+ return function()
+ local b,e=find(str,".[\128-\191]*",p)
+ if b then
+ p=e+1
+ return utfbyte(sub(str,b,e))
+ end
+ end
+ end
+ end
+ string.utfvalues=utf.values
+end
+function utf.chrlen(u)
+ return
+ (u<0x80 and 1) or
+ (u<0xE0 and 2) or
+ (u<0xF0 and 3) or
+ (u<0xF8 and 4) or
+ (u<0xFC and 5) or
+ (u<0xFE and 6) or 0
+end
+
+end -- closure
+
+do -- begin closure to overcome local limits and interference
+
if not modules then modules={} end modules ['util-str']={
version=1.001,
comment="companion to luat-lib.mkiv",
@@ -5890,15 +6504,11 @@ hashmethods.normal=function(list)
elseif k=="number" or k=="features" then
else
n=n+1
- s[n]=k
+ s[n]=k..'='..tostring(v)
end
end
if n>0 then
sort(s)
- for i=1,n do
- local k=s[i]
- s[i]=k..'='..tostring(list[k])
- end
return concat(s,"+")
end
end
@@ -6045,7 +6655,10 @@ function constructors.getfeatureaction(what,where,mode,name)
end
end
end
-function constructors.newhandler(what)
+local newhandler={}
+constructors.handlers=newhandler
+constructors.newhandler=newhandler
+local function setnewhandler(what)
local handler=handlers[what]
if not handler then
handler={}
@@ -6053,7 +6666,14 @@ function constructors.newhandler(what)
end
return handler
end
-function constructors.newfeatures(what)
+setmetatable(newhandler,{
+ __call=function(t,k) local v=t[k] return v end,
+ __index=function(t,k) local v=setnewhandler(k) t[k]=v return v end,
+})
+local newfeatures={}
+constructors.newfeatures=newfeatures
+constructors.features=newfeatures
+local function setnewfeatures(what)
local handler=handlers[what]
local features=handler.features
if not features then
@@ -6072,6 +6692,10 @@ function constructors.newfeatures(what)
end
return features
end
+setmetatable(newfeatures,{
+ __call=function(t,k) local v=t[k] return v end,
+ __index=function(t,k) local v=setnewfeatures(k) t[k]=v return v end,
+})
function constructors.checkedfeatures(what,features)
local defaults=handlers[what].features.defaults
if features and next(features) then
@@ -6440,7 +7064,7 @@ local function makenameparser(str)
end
local f_single=formatters["%04X"]
local f_double=formatters["%04X%04X"]
-local function tounicode16(unicode,name)
+local function tounicode16(unicode)
if unicode<0xD7FF or (unicode>0xDFFF and unicode<=0xFFFF) then
return f_single(unicode)
else
@@ -6448,7 +7072,7 @@ local function tounicode16(unicode,name)
return f_double(floor(unicode/1024)+0xD800,unicode%1024+0xDC00)
end
end
-local function tounicode16sequence(unicodes,name)
+local function tounicode16sequence(unicodes)
local t={}
for l=1,#unicodes do
local u=unicodes[l]
@@ -6836,11 +7460,11 @@ local handlers=fonts.handlers
local readers=fonts.readers
local constructors=fonts.constructors
local encodings=fonts.encodings
-local tfm=constructors.newhandler("tfm")
+local tfm=constructors.handlers.tfm
tfm.version=1.000
tfm.maxnestingdepth=5
tfm.maxnestingsize=65536*1024
-local tfmfeatures=constructors.newfeatures("tfm")
+local tfmfeatures=constructors.features.tfm
constructors.resolvevirtualtoo=false
fonts.formats.tfm="type1"
fonts.formats.ofm="type1"
@@ -6985,8 +7609,8 @@ if not modules then modules={} end modules ['font-oti']={
local lower=string.lower
local fonts=fonts
local constructors=fonts.constructors
-local otf=constructors.newhandler("otf")
-local otffeatures=constructors.newfeatures("otf")
+local otf=constructors.handlers.otf
+local otffeatures=constructors.features.otf
local registerotffeature=otffeatures.register
local otftables=otf.tables or {}
otf.tables=otftables
@@ -7172,8 +7796,8 @@ local function readlongdatetime(f)
return 0x100000000*d+0x1000000*e+0x10000*f+0x100*g+h
end
local tableversion=0.004
-local privateoffset=fonts.constructors and fonts.constructors.privateoffset or 0xF0000
readers.tableversion=tableversion
+local privateoffset=fonts.constructors and fonts.constructors.privateoffset or 0xF0000
local reportedskipped={}
local function reportskippedtable(tag)
if not reportedskipped[tag] then
@@ -8177,6 +8801,21 @@ function readers.glyf(f,fontdata,specification)
reportskippedtable("glyf")
end
end
+function readers.colr(f,fontdata,specification)
+ if specification.details then
+ reportskippedtable("colr")
+ end
+end
+function readers.cpal(f,fontdata,specification)
+ if specification.details then
+ reportskippedtable("cpal")
+ end
+end
+function readers.svg(f,fontdata,specification)
+ if specification.details then
+ reportskippedtable("svg")
+ end
+end
function readers.kern(f,fontdata,specification)
if specification.kerns then
local datatable=fontdata.tables.kern
@@ -8485,6 +9124,9 @@ local function readdata(f,offset,specification)
readers["cmap"](f,fontdata,specification)
readers["loca"](f,fontdata,specification)
readers["glyf"](f,fontdata,specification)
+ readers["colr"](f,fontdata,specification)
+ readers["cpal"](f,fontdata,specification)
+ readers["svg" ](f,fontdata,specification)
readers["kern"](f,fontdata,specification)
readers["gdef"](f,fontdata,specification)
readers["gsub"](f,fontdata,specification)
@@ -8640,6 +9282,7 @@ function readers.loadfont(filename,n)
metadata=getinfo(fontdata,n),
properties={
hasitalics=fontdata.hasitalics or false,
+ maxcolorclass=fontdata.maxcolorclass,
},
resources={
filename=filename,
@@ -8655,6 +9298,8 @@ function readers.loadfont(filename,n)
version=getname(fontdata,"version"),
cidinfo=fontdata.cidinfo,
mathconstants=fontdata.mathconstants,
+ colorpalettes=fontdata.colorpalettes,
+ svgshapes=fontdata.svgshapes,
},
}
end
@@ -10603,6 +11248,7 @@ local readshort=streamreader.readinteger2
local readfword=readshort
local readstring=streamreader.readstring
local readtag=streamreader.readtag
+local readbytes=streamreader.readbytes
local gsubhandlers={}
local gposhandlers={}
local lookupidoffset=-1
@@ -12502,7 +13148,7 @@ function readers.math(f,fontdata,specification)
setposition(f,tableoffset)
local version=readulong(f)
if version~=0x00010000 then
- report("table version %a of %a is not supported (yet), maybe font %s is bad",version,what,fontdata.filename)
+ report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"math",fontdata.filename)
return
end
local constants=readushort(f)
@@ -12522,6 +13168,140 @@ function readers.math(f,fontdata,specification)
end
end
end
+function readers.colr(f,fontdata,specification)
+ if specification.details then
+ local datatable=fontdata.tables.colr
+ if datatable then
+ local tableoffset=datatable.offset
+ setposition(f,tableoffset)
+ local version=readushort(f)
+ if version~=0 then
+ report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"colr",fontdata.filename)
+ return
+ end
+ if not fontdata.tables.cpal then
+ report("color table %a in font %a has no mandate %a table","colr",fontdata.filename,"cpal")
+ fontdata.colorpalettes={}
+ end
+ local glyphs=fontdata.glyphs
+ local nofglyphs=readushort(f)
+ local baseoffset=readulong(f)
+ local layeroffset=readulong(f)
+ local noflayers=readushort(f)
+ local layerrecords={}
+ local maxclass=0
+ setposition(f,tableoffset+layeroffset)
+ for i=1,noflayers do
+ local slot=readushort(f)
+ local class=readushort(f)
+ if class<0xFFFF then
+ class=class+1
+ if class>maxclass then
+ maxclass=class
+ end
+ end
+ layerrecords[i]={
+ slot=slot,
+ class=class,
+ }
+ end
+ fontdata.maxcolorclass=maxclass
+ setposition(f,tableoffset+baseoffset)
+ for i=0,nofglyphs-1 do
+ local glyphindex=readushort(f)
+ local firstlayer=readushort(f)
+ local noflayers=readushort(f)
+ local t={}
+ for i=1,noflayers do
+ t[i]=layerrecords[firstlayer+i]
+ end
+ glyphs[glyphindex].colors=t
+ end
+ end
+ end
+end
+function readers.cpal(f,fontdata,specification)
+ if specification.details then
+ local datatable=fontdata.tables.cpal
+ if datatable then
+ local tableoffset=datatable.offset
+ setposition(f,tableoffset)
+ local version=readushort(f)
+ if version>1 then
+ report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"cpal",fontdata.filename)
+ return
+ end
+ local nofpaletteentries=readushort(f)
+ local nofpalettes=readushort(f)
+ local nofcolorrecords=readushort(f)
+ local firstcoloroffset=readulong(f)
+ local colorrecords={}
+ local palettes={}
+ for i=1,nofpalettes do
+ palettes[i]=readushort(f)
+ end
+ if version==1 then
+ local palettettypesoffset=readulong(f)
+ local palettelabelsoffset=readulong(f)
+ local paletteentryoffset=readulong(f)
+ end
+ setposition(f,tableoffset+firstcoloroffset)
+ for i=1,nofcolorrecords do
+ local b,g,r,a=readbytes(f,4)
+ colorrecords[i]={
+ r,g,b,a~=255 and a or nil,
+ }
+ end
+ for i=1,nofpalettes do
+ local p={}
+ local o=palettes[i]
+ for j=1,nofpaletteentries do
+ p[j]=colorrecords[o+j]
+ end
+ palettes[i]=p
+ end
+ fontdata.colorpalettes=palettes
+ end
+ end
+end
+function readers.svg(f,fontdata,specification)
+ if specification.details then
+ local datatable=fontdata.tables.svg
+ if datatable then
+ local tableoffset=datatable.offset
+ setposition(f,tableoffset)
+ local version=readushort(f)
+ if version~=0 then
+ report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"svg",fontdata.filename)
+ return
+ end
+ local glyphs=fontdata.glyphs
+ local indexoffset=tableoffset+readulong(f)
+ local reserved=readulong(f)
+ setposition(f,indexoffset)
+ local nofentries=readushort(f)
+ local entries={}
+ for i=1,nofentries do
+ entries[i]={
+ first=readushort(f),
+ last=readushort(f),
+ offset=indexoffset+readulong(f),
+ length=readulong(f),
+ }
+ end
+ for i=1,nofentries do
+ local entry=entries[i]
+ setposition(f,entry.offset)
+ entries[i]={
+ first=entry.first,
+ last=entry.last,
+ data=readstring(f,entry.length)
+ }
+ end
+ fontdata.svgshapes=entries
+ end
+ end
+end
end -- closure
@@ -13179,6 +13959,18 @@ local function unifyglyphs(fontdata,usenames)
end
end
end
+ local colorpalettes=resources.colorpalettes
+ if colorpalettes then
+ for index=1,#glyphs do
+ local colors=glyphs[index].colors
+ if colors then
+ for i=1,#colors do
+ local c=colors[i]
+ c.slot=indices[c.slot]
+ end
+ end
+ end
+ end
fontdata.private=private
fontdata.glyphs=nil
fontdata.names=names
@@ -13579,6 +14371,7 @@ function readers.pack(data)
local sequences=resources.sequences
local sublookups=resources.sublookups
local features=resources.features
+ local palettes=resources.colorpalettes
local chardata=characters and characters.data
local descriptions=data.descriptions or data.glyphs
if not descriptions then
@@ -13721,6 +14514,14 @@ function readers.pack(data)
end
end
end
+ if palettes then
+ for i=1,#palettes do
+ local p=palettes[i]
+ for j=1,#p do
+ p[j]=pack_indexed(p[j])
+ end
+ end
+ end
if not success(1,pass) then
return
end
@@ -13841,6 +14642,7 @@ function readers.unpack(data)
local sequences=resources.sequences
local sublookups=resources.sublookups
local features=resources.features
+ local palettes=resources.colorpalettes
local unpacked={}
setmetatable(unpacked,unpacked_mt)
for unicode,description in next,descriptions do
@@ -14079,6 +14881,17 @@ function readers.unpack(data)
end
end
end
+ if palettes then
+ for i=1,#palettes do
+ local p=palettes[i]
+ for j=1,#p do
+ local tv=tables[p[j]]
+ if tv then
+ p[j]=tv
+ end
+ end
+ end
+ end
data.tables=nil
end
end
@@ -14532,14 +15345,17 @@ local trace_defining=false registertracker("fonts.defining",function(v) trace_de
local report_otf=logs.reporter("fonts","otf loading")
local fonts=fonts
local otf=fonts.handlers.otf
-otf.version=3.021
+otf.version=3.022
otf.cache=containers.define("fonts","otl",otf.version,true)
+otf.svgcache=containers.define("fonts","svg",otf.version,true)
+otf.pdfcache=containers.define("fonts","pdf",otf.version,true)
+otf.svgenabled=false
local otfreaders=otf.readers
local hashes=fonts.hashes
local definers=fonts.definers
local readers=fonts.readers
local constructors=fonts.constructors
-local otffeatures=constructors.newfeatures("otf")
+local otffeatures=constructors.features.otf
local registerotffeature=otffeatures.register
local enhancers=allocate()
otf.enhancers=enhancers
@@ -14679,6 +15495,22 @@ function otf.load(filename,sub,featurefile)
starttiming(otfreaders)
data=otfreaders.loadfont(filename,sub or 1)
if data then
+ local resources=data.resources
+ local svgshapes=resources.svgshapes
+ if svgshapes then
+ resources.svgshapes=nil
+ if otf.svgenabled then
+ local timestamp=os.date()
+ containers.write(otf.svgcache,hash,{
+ svgshapes=svgshapes,
+ timestamp=timestamp,
+ })
+ data.properties.svg={
+ hash=hash,
+ timestamp=timestamp,
+ }
+ end
+ end
otfreaders.compact(data)
otfreaders.rehash(data,"unicodes")
otfreaders.addunicodetable(data)
@@ -14732,7 +15564,6 @@ end
local function copytotfm(data,cache_id)
if data then
local metadata=data.metadata
- local resources=data.resources
local properties=derivetable(data.properties)
local descriptions=derivetable(data.descriptions)
local goodies=derivetable(data.goodies)
@@ -16893,7 +17724,7 @@ local math_code=nodecodes.math
local fontdata=fonts.hashes.identifiers
local categories=characters and characters.categories or {}
local chardata=characters and characters.data
-local otffeatures=fonts.constructors.newfeatures("otf")
+local otffeatures=fonts.constructors.features.otf
local registerotffeature=otffeatures.register
local s_init=1 local s_rphf=7
local s_medi=2 local s_half=8
@@ -17258,7 +18089,6 @@ local trace_cursive=false registertracker("otf.cursive",function(v) trace_cursiv
local trace_preparing=false registertracker("otf.preparing",function(v) trace_preparing=v end)
local trace_bugs=false registertracker("otf.bugs",function(v) trace_bugs=v end)
local trace_details=false registertracker("otf.details",function(v) trace_details=v end)
-local trace_applied=false registertracker("otf.applied",function(v) trace_applied=v end)
local trace_steps=false registertracker("otf.steps",function(v) trace_steps=v end)
local trace_skips=false registertracker("otf.skips",function(v) trace_skips=v end)
local trace_directions=false registertracker("otf.directions",function(v) trace_directions=v end)
@@ -17346,7 +18176,7 @@ local getligaindex=injections.getligaindex
local cursonce=true
local fonthashes=fonts.hashes
local fontdata=fonthashes.identifiers
-local otffeatures=fonts.constructors.newfeatures("otf")
+local otffeatures=fonts.constructors.features.otf
local registerotffeature=otffeatures.register
local onetimemessage=fonts.loggers.onetimemessage or function() end
otf.defaultnodealternate="none"
@@ -19960,9 +20790,6 @@ local function featuresprocessor(head,font,attr)
nesting=nesting-1
return head,false
end
- if attr==0 then
- attr=false
- end
head=tonut(head)
if trace_steps then
checkstep(head)
@@ -20318,7 +21145,7 @@ fonts.analyzers.methods=fonts.analyzers.methods or { node={ otf={} } }
local otf=fonts.handlers.otf
local handlers=otf.handlers
local methods=fonts.analyzers.methods
-local otffeatures=fonts.constructors.newfeatures("otf")
+local otffeatures=fonts.constructors.features.otf
local registerotffeature=otffeatures.register
local nuts=nodes.nuts
local tonode=nuts.tonode
@@ -22271,6 +23098,250 @@ end -- closure
do -- begin closure to overcome local limits and interference
+if not modules then modules={} end modules ['font-ocl']={
+ version=1.001,
+ comment="companion to font-otf.lua (context)",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local formatters=string.formatters
+local otf=fonts.handlers.otf
+local f_color_start=formatters["pdf:direct: %f %f %f rg"]
+local s_color_stop="pdf:direct:"
+if context then
+ local startactualtext=nil
+ local stopactualtext=nil
+ function otf.getactualtext(n)
+ if not startactualtext then
+ startactualtext=backends.codeinjections.startunicodetoactualtext
+ stopactualtext=backends.codeinjections.stopunicodetoactualtext
+ end
+ return startactualtext(n),stopactualtext()
+ end
+else
+ local tounicode=fonts.mappings.tounicode16
+ function otf.getactualtext(n)
+ return "/Span << /ActualText <feff"..tounicode(n).."> >> BDC","EMC"
+ end
+end
+local function initializecolr(tfmdata,kind,value)
+ if value then
+ local palettes=tfmdata.resources.colorpalettes
+ if palettes then
+ local palette=palettes[tonumber(value) or 1] or palettes[1] or {}
+ local classes=#palette
+ if classes==0 then
+ return
+ end
+ local characters=tfmdata.characters
+ local descriptions=tfmdata.descriptions
+ local properties=tfmdata.properties
+ local colorvalues={}
+ properties.virtualized=true
+ tfmdata.fonts={
+ { id=0 }
+ }
+ for i=1,classes do
+ local p=palette[i]
+ colorvalues[i]={ "special",f_color_start(p[1]/255,p[2]/255,p[3]/255) }
+ end
+ local getactualtext=otf.getactualtext
+ for unicode,character in next,characters do
+ local description=descriptions[unicode]
+ if description then
+ local colorlist=description.colors
+ if colorlist then
+ local b,e=getactualtext(unicode)
+ local w=character.width or 0
+ local s=#colorlist
+ local n=1
+ local t={
+ { "special","pdf:direct: q "..b }
+ }
+ for i=1,s do
+ local entry=colorlist[i]
+ n=n+1 t[n]=colorvalues[entry.class]
+ n=n+1 t[n]={ "char",entry.slot }
+ if s>1 and i<s and w~=0 then
+ n=n+1 t[n]={ "right",-w }
+ end
+ end
+ n=n+1 t[n]={ "special","pdf:direct:"..e.." Q" }
+ character.commands=t
+ end
+ end
+ end
+ end
+ end
+end
+fonts.handlers.otf.features.register {
+ name="colr",
+ description="color glyphs",
+ manipulators={
+ base=initializecolr,
+ node=initializecolr,
+ }
+}
+local otfsvg=otf.svg or {}
+otf.svg=otfsvg
+otf.svgenabled=true
+do
+ local nofstreams=0
+ local f_name=formatters[ [[svg-glyph-%05i]] ]
+ local f_used=context and formatters[ [[original:///%s]] ] or formatters[ [[%s]] ]
+ local cache={}
+ function otfsvg.storepdfdata(pdf)
+ nofstreams=nofstreams+1
+ local o,n=epdf.openMemStream(pdf,#pdf,f_name(nofstreams))
+ cache[n]=o
+ return nil,f_used(n),nil
+ end
+ if context then
+ local storepdfdata=otfsvg.storepdfdata
+ local initialized=false
+ function otfsvg.storepdfdata(pdf)
+ if not initialized then
+ if resolvers.setmemstream then
+ local f_setstream=formatters[ [[resolvers.setmemstream("svg-glyph-%05i",%q,true)]] ]
+ local f_getstream=formatters[ [[memstream:///svg-glyph-%05i]] ]
+ local f_nilstream=formatters[ [[resolvers.resetmemstream("svg-glyph-%05i",true)]] ]
+ storepdfdata=function(pdf)
+ nofstreams=nofstreams+1
+ return
+ f_setstream(nofstreams,pdf),
+ f_getstream(nofstreams),
+ f_nilstream(nofstreams)
+ end
+ otfsvg.storepdfdata=storepdfdata
+ end
+ initialized=true
+ end
+ return storepdfdata(pdf)
+ end
+ end
+end
+if context and xml.convert then
+ local report_svg=logs.reporter("fonts","svg conversion")
+ function otfsvg.topdf(svgshapes)
+ local svgfile="temp-otf-svg-shape.svg"
+ local pdffile="temp-otf-svg-shape.pdf"
+ local command="inkscape "..svgfile.." --export-pdf="..pdffile
+ local testrun=false
+ local pdfshapes={}
+ local nofshapes=#svgshapes
+ report_svg("processing %i svg containers",nofshapes)
+ for i=1,nofshapes do
+ local entry=svgshapes[i]
+ for j=entry.first,entry.last do
+ local svg=xml.convert(entry.data)
+ local data=xml.first(svg,"/svg[@id='glyph"..j.."']")
+ io.savedata(svgfile,tostring(data))
+ report_svg("processing svg shape of glyph %i in container %i",j,i)
+ os.execute(command)
+ pdfshapes[j]=io.loaddata(pdffile)
+ end
+ if testrun and i>testrun then
+ report_svg("quiting test run")
+ break
+ end
+ end
+ os.remove(svgfile)
+ return pdfshapes
+ end
+else
+ function otfsvg.topdf(svgshapes)
+ local svgfile="temp-otf-svg-shape.svg"
+ local pdffile="temp-otf-svg-shape.pdf"
+ local command="inkscape "..svgfile.." --export-pdf="..pdffile
+ local pdfshapes={}
+ local nofshapes=#svgshapes
+ texio.write(formatters["[converting %i svg glyphs to pdf using command %q : "](nofshapes,command))
+ for i=1,nofshapes do
+ local entry=svgshapes[i]
+ for j=entry.first,entry.last do
+ texio.write(formatters["%i "](j))
+ io.savedata(svgfile,tostring(entry.data))
+ os.execute(command)
+ pdfshapes[j]=io.loaddata(pdffile)
+ end
+ end
+ os.remove(svgfile)
+ texio.write("done]")
+ return pdfshapes
+ end
+end
+local function initializesvg(tfmdata,kind,value)
+ if value and otf.svgenabled then
+ local characters=tfmdata.characters
+ local descriptions=tfmdata.descriptions
+ local properties=tfmdata.properties
+ local svg=properties.svg
+ local hash=svg and svg.hash
+ local timestamp=svg and svg.timestamp
+ if not hash then
+ return
+ end
+ local pdffile=containers.read(otf.pdfcache,hash)
+ local pdfshapes=pdffile and pdffile.pdfshapes
+ if not pdfshapes or pdffile.timestamp~=timestamp then
+ local svgfile=containers.read(otf.svgcache,hash)
+ local svgshapes=svgfile and svgfile.svgshapes
+ pdfshapes=svgshapes and otfsvg.topdf(svgshapes) or {}
+ containers.write(otf.pdfcache,hash,{
+ pdfshapes=pdfshapes,
+ timestamp=timestamp,
+ })
+ end
+ if not pdfshapes or not next(pdfshapes) then
+ return
+ end
+ properties.virtualized=true
+ tfmdata.fonts={
+ { id=0 }
+ }
+ local getactualtext=otf.getactualtext
+ local storepdfdata=otfsvg.storepdfdata
+ local nop={ "nop" }
+ for unicode,character in next,characters do
+ local index=character.index
+ if index then
+ local pdf=pdfshapes[index]
+ if pdf then
+ local setcode,name,nilcode=storepdfdata(pdf)
+ if name then
+ local bt,et=getactualtext(unicode)
+ local wd=character.width or 0
+ local ht=character.height or 0
+ local dp=character.depth or 0
+ character.commands={
+ { "special","pdf:direct:"..bt },
+ { "down",dp },
+ setcode and { "lua",setcode } or nop,
+ { "image",{ filename=name,width=wd,height=ht,depth=dp } },
+ nilcode and { "lua",nilcode } or nop,
+ { "special","pdf:direct:"..et },
+ }
+ character.svg=true
+ end
+ end
+ end
+ end
+ end
+end
+fonts.handlers.otf.features.register {
+ name="svg",
+ description="svg glyphs",
+ manipulators={
+ base=initializesvg,
+ node=initializesvg,
+ }
+}
+
+end -- closure
+
+do -- begin closure to overcome local limits and interference
+
if not modules then modules={} end modules ['font-onr']={
version=1.001,
comment="companion to font-ini.mkiv",
@@ -22569,12 +23640,12 @@ local findbinfile=resolvers.findbinfile
local definers=fonts.definers
local readers=fonts.readers
local constructors=fonts.constructors
-local afm=constructors.newhandler("afm")
-local pfb=constructors.newhandler("pfb")
+local afm=constructors.handlers.afm
+local pfb=constructors.handlers.pfb
local otf=fonts.handlers.otf
local otfreaders=otf.readers
local otfenhancers=otf.enhancers
-local afmfeatures=constructors.newfeatures("afm")
+local afmfeatures=constructors.features.afm
local registerafmfeature=afmfeatures.register
afm.version=1.512
afm.cache=containers.define("fonts","afm",afm.version,true)
@@ -23901,7 +24972,7 @@ if context then
os.exit()
end
local fonts=fonts
-local otffeatures=fonts.constructors.newfeatures("otf")
+local otffeatures=fonts.constructors.features.otf
local function initializeitlc(tfmdata,value)
if value then
local parameters=tfmdata.parameters