summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPhilipp Gesang <phg@phi-gamma.net>2016-07-28 00:06:07 +0200
committerGitHub <noreply@github.com>2016-07-28 00:06:07 +0200
commit2fcdccf7edfa1cfb0f03fe8f2163c7c5d8281984 (patch)
treefcb876f65c47989ecdf254c5ea9d54caa3be10ae /src
parentdeef74c357ff2f88d53bc6a745b36b6a75717d2d (diff)
parentd37cfaf8b6bd3e82c8220d385e5da53793f332e1 (diff)
downloadluaotfload-2fcdccf7edfa1cfb0f03fe8f2163c7c5d8281984.tar.gz
Merge pull request #373 from phi-gamma/master
fix adding of custom features
Diffstat (limited to 'src')
-rw-r--r--src/fontloader/misc/fontloader-basics-nod.lua10
-rw-r--r--src/fontloader/misc/fontloader-font-gbn.lua4
-rw-r--r--src/fontloader/misc/fontloader-font-osd.lua12
-rw-r--r--src/fontloader/misc/fontloader-font-otd.lua268
-rw-r--r--src/fontloader/misc/fontloader-font-otl.lua49
-rw-r--r--src/fontloader/misc/fontloader-font-otr.lua2
-rw-r--r--src/fontloader/misc/fontloader-font-ots.lua6
-rw-r--r--src/fontloader/misc/fontloader-font-tfm.lua6
-rw-r--r--src/fontloader/misc/fontloader-plain-tfm.lua120
-rw-r--r--src/fontloader/misc/fontloader-util-fil.lua35
-rw-r--r--src/fontloader/runtime/fontloader-reference.lua97
-rw-r--r--src/luaotfload-auxiliary.lua12
-rw-r--r--src/luaotfload-features.lua66
-rw-r--r--src/luaotfload-loaders.lua5
-rw-r--r--src/luaotfload-resolvers.lua1
15 files changed, 248 insertions, 445 deletions
diff --git a/src/fontloader/misc/fontloader-basics-nod.lua b/src/fontloader/misc/fontloader-basics-nod.lua
index e7b5ab2..42a7a2e 100644
--- a/src/fontloader/misc/fontloader-basics-nod.lua
+++ b/src/fontloader/misc/fontloader-basics-nod.lua
@@ -71,7 +71,7 @@ nodes.nodecodes = nodecodes
nodes.glyphcodes = glyphcodes
nodes.disccodes = disccodes
-local free_node = node.free
+local flush_node = node.flush_node
local remove_node = node.remove
local new_node = node.new
local traverse_id = node.traverse_id
@@ -95,7 +95,7 @@ function nodes.remove(head, current, free_too)
head, current = remove_node(head,current)
if t then
if free_too then
- free_node(t)
+ flush_node(t)
t = nil
else
t.next, t.prev = nil, nil
@@ -128,12 +128,14 @@ nodes.setattr = setfield
nodes.tostring = node.tostring or tostring
nodes.copy = node.copy
+nodes.copy_node = node.copy
nodes.copy_list = node.copy_list
nodes.delete = node.delete
nodes.dimensions = node.dimensions
nodes.end_of_math = node.end_of_math
nodes.flush_list = node.flush_list
nodes.flush_node = node.flush_node
+nodes.flush = node.flush_node
nodes.free = node.free
nodes.insert_after = node.insert_after
nodes.insert_before = node.insert_before
@@ -149,7 +151,6 @@ nodes.first_glyph = node.first_glyph
nodes.has_glyph = node.has_glyph or node.first_glyph
nodes.current_attr = node.current_attr
-nodes.do_ligature_n = node.do_ligature_n
nodes.has_field = node.has_field
nodes.last_node = node.last_node
nodes.usedlist = node.usedlist
@@ -253,9 +254,12 @@ nuts.insert_before = direct.insert_before
nuts.insert_after = direct.insert_after
nuts.delete = direct.delete
nuts.copy = direct.copy
+nuts.copy_node = direct.copy
nuts.copy_list = direct.copy_list
nuts.tail = direct.tail
nuts.flush_list = direct.flush_list
+nuts.flush_node = direct.flush_node
+nuts.flush = direct.flush
nuts.free = direct.free
nuts.remove = direct.remove
nuts.is_node = direct.is_node
diff --git a/src/fontloader/misc/fontloader-font-gbn.lua b/src/fontloader/misc/fontloader-font-gbn.lua
index 1ae817d..1f8df64 100644
--- a/src/fontloader/misc/fontloader-font-gbn.lua
+++ b/src/fontloader/misc/fontloader-font-gbn.lua
@@ -19,7 +19,7 @@ local nodes = nodes
local nuts = nodes.nuts -- context abstraction of direct nodes
local traverse_id = nuts.traverse_id
-local free_node = nuts.free
+local flush_node = nuts.flush_node
local glyph_code = nodes.nodecodes.glyph
local disc_code = nodes.nodecodes.disc
@@ -159,7 +159,7 @@ function nodes.handlers.nodepass(head)
end
end
end
- free_node(r)
+ flush_node(r)
end
end
for d in traverse_id(disc_code,nuthead) do
diff --git a/src/fontloader/misc/fontloader-font-osd.lua b/src/fontloader/misc/fontloader-font-osd.lua
index a3dda67..26af691 100644
--- a/src/fontloader/misc/fontloader-font-osd.lua
+++ b/src/fontloader/misc/fontloader-font-osd.lua
@@ -107,9 +107,9 @@ local ischar = nuts.is_char
local insert_node_after = nuts.insert_after
local copy_node = nuts.copy
-local free_node = nuts.free
local remove_node = nuts.remove
local flush_list = nuts.flush_list
+local flush_node = nuts.flush_node
local copyinjection = nodes.injections.copy -- KE: is this necessary? HH: probably not as positioning comes later and we rawget/set
@@ -792,7 +792,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
if current == stop then
stop = getprev(stop)
head = remove_node(head,current)
- free_node(current)
+ flush_node(current)
return head, stop, nbspaces
else
nbspaces = nbspaces + 1
@@ -830,7 +830,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
setchar(current,getchar(tempcurrent)) -- we assumes that the result of blwf consists of one node
local freenode = getnext(current)
setlink(current,tmp)
- free_node(freenode)
+ flush_node(freenode)
flush_list(tempcurrent)
if changestop then
stop = current
@@ -1093,7 +1093,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
if getchar(base) == c_nbsp then
nbspaces = nbspaces - 1
head = remove_node(head,base)
- free_node(base)
+ flush_node(base)
end
return head, stop, nbspaces
@@ -1571,7 +1571,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pa
if current == stop then
stop = getprev(stop)
head = remove_node(head,current)
- free_node(current)
+ flush_node(current)
return head, stop, nbspaces
else
nbspaces = nbspaces + 1
@@ -1768,7 +1768,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pa
if getchar(base) == c_nbsp then
nbspaces = nbspaces - 1
head = remove_node(head, base)
- free_node(base)
+ flush_node(base)
end
return head, stop, nbspaces
diff --git a/src/fontloader/misc/fontloader-font-otd.lua b/src/fontloader/misc/fontloader-font-otd.lua
deleted file mode 100644
index 64cb1bc..0000000
--- a/src/fontloader/misc/fontloader-font-otd.lua
+++ /dev/null
@@ -1,268 +0,0 @@
-if not modules then modules = { } end modules ['font-otd'] = {
- version = 1.001,
- comment = "companion to font-ini.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local type = type
-local match = string.match
-local sequenced = table.sequenced
-
-local trace_dynamics = false trackers.register("otf.dynamics", function(v) trace_dynamics = v end)
-local trace_applied = false trackers.register("otf.applied", function(v) trace_applied = v end)
-
-local report_otf = logs.reporter("fonts","otf loading")
-local report_process = logs.reporter("fonts","otf process")
-
-local allocate = utilities.storage.allocate
-
-local fonts = fonts
-local otf = fonts.handlers.otf
-local hashes = fonts.hashes
-local definers = fonts.definers
-local constructors = fonts.constructors
-local specifiers = fonts.specifiers
-
-local fontidentifiers = hashes.identifiers
-local fontresources = hashes.resources
-local fontproperties = hashes.properties
-local fontdynamics = hashes.dynamics
-
-local contextsetups = specifiers.contextsetups
-local contextnumbers = specifiers.contextnumbers
-local contextmerged = specifiers.contextmerged
-
-local setmetatableindex = table.setmetatableindex
-
-local a_to_script = { }
-local a_to_language = { }
-
--- we can have a scripts hash in fonts.hashes
-
-function otf.setdynamics(font,attribute)
- -- local features = contextsetups[contextnumbers[attribute]] -- can be moved to caller
- local features = contextsetups[attribute]
- if features then
- local dynamics = fontdynamics[font]
- dynamic = contextmerged[attribute] or 0
- local script, language
- if dynamic == 2 then -- merge
- language = features.language or fontproperties[font].language or "dflt"
- script = features.script or fontproperties[font].script or "dflt"
- else -- if dynamic == 1 then -- replace
- language = features.language or "dflt"
- script = features.script or "dflt"
- end
- if script == "auto" then
- -- checkedscript and resources are defined later so we cannot shortcut them -- todo: make installer
- script = definers.checkedscript(fontidentifiers[font],fontresources[font],features)
- end
- local ds = dynamics[script] -- can be metatable magic (less testing)
--- or dynamics.dflt
- if not ds then
- ds = { }
- dynamics[script] = ds
- end
- local dsl = ds[language]
--- or ds.dflt
- if not dsl then
- dsl = { }
- ds[language] = dsl
- end
- local dsla = dsl[attribute]
- if not dsla then
- local tfmdata = fontidentifiers[font]
- a_to_script [attribute] = script
- a_to_language[attribute] = language
- -- we need to save some values .. quite messy
- local properties = tfmdata.properties
- local shared = tfmdata.shared
- local s_script = properties.script
- local s_language = properties.language
- local s_mode = properties.mode
- local s_features = shared.features
- properties.mode = "node"
- properties.language = language
- properties.script = script
- properties.dynamics = true -- handy for tracing
- shared.features = { }
- -- end of save
- local set = constructors.checkedfeatures("otf",features)
- set.mode = "node" -- really needed
- dsla = otf.setfeatures(tfmdata,set)
- if trace_dynamics then
- report_otf("setting dynamics %s: attribute %a, script %a, language %a, set %a",contextnumbers[attribute],attribute,script,language,set)
- end
- -- we need to restore some values
- properties.script = s_script
- properties.language = s_language
- properties.mode = s_mode
- shared.features = s_features
- -- end of restore
- dynamics[script][language][attribute] = dsla -- cache
- elseif trace_dynamics then
- -- report_otf("using dynamics %s: attribute %a, script %a, language %a",contextnumbers[attribute],attribute,script,language)
- end
- return dsla
- end
-end
-
-function otf.scriptandlanguage(tfmdata,attr)
- local properties = tfmdata.properties
- if attr and attr > 0 then
- return a_to_script[attr] or properties.script or "dflt", a_to_language[attr] or properties.language or "dflt"
- else
- return properties.script or "dflt", properties.language or "dflt"
- end
-end
-
--- we reimplement the dataset resolver
-
-local autofeatures = fonts.analyzers.features
-local featuretypes = otf.tables.featuretypes
-local defaultscript = otf.features.checkeddefaultscript
-local defaultlanguage = otf.features.checkeddefaultlanguage
-
-local resolved = { } -- we only resolve a font,script,language,attribute pair once
-local wildcard = "*"
-
--- what about analyze in local and not in font
-
--- needs checking: some added features can pass twice
-
-local P, C, Cc, lpegmatch = lpeg.P, lpeg.C, lpeg.Cc, lpeg.match
-
-local pattern = P("always") * (P(-1) * Cc(true) + P(":") * C((1-P(-1))^1))
-
-local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr,dynamic,ra,autoscript,autolanguage)
- local features = sequence.features
- if features then
- local order = sequence.order
- if order then
- local featuretype = featuretypes[sequence.type or "unknown"]
- for i=1,#order do --
- local kind = order[i] --
- local e_e
- local a_e = a_enabled and a_enabled[kind] -- the value (location)
- if a_e ~= nil then
- e_e = a_e
- else
- e_e = s_enabled and s_enabled[kind] -- the value (font)
- end
- if e_e then
- local valid = type(e_e) == "string" and lpegmatch(pattern,e_e)
- if valid then
- -- we have hit always
- local attribute = autofeatures[kind] or false
- if trace_applied then
- report_process(
- "font %s, dynamic %a (%a), feature %a, script %a, language %a, lookup %a, value %a",
- font,attr or 0,dynamic,kind,"*","*",sequence.name,valid)
- end
- ra[#ra+1] = { valid, attribute, sequence, kind }
- else
- -- we already checked for e_e
- local scripts = features[kind] --
- local languages = scripts[script] or scripts[wildcard]
- if not languages and autoscript then
- langages = defaultscript(featuretype,autoscript,scripts)
- end
- if languages then
- -- we need detailed control over default becase we want to trace
- -- only first attribute match check, so we assume simple fina's
- -- local valid = false
- if languages[language] then
- valid = e_e
- elseif languages[wildcard] then
- valid = e_e
- elseif autolanguage and defaultlanguage(featuretype,autolanguage,languages) then
- valid = e_e
- end
- end
- if valid then
- local attribute = autofeatures[kind] or false
- if trace_applied then
- report_process(
- "font %s, dynamic %a (%a), feature %a, script %a, language %a, lookup %a, value %a",
- font,attr or 0,dynamic,kind,script,language,sequence.name,valid)
- end
- ra[#ra+1] = { valid, attribute, sequence, kind }
- end
- end
- end
- end
- end
- end
-end
-
--- there is some fuzzy language/script state stuff in properties (temporary)
-
-function otf.dataset(tfmdata,font,attr) -- attr only when explicit (as in special parbuilder)
-
- local script, language, s_enabled, a_enabled, dynamic
-
- if attr and attr ~= 0 then
- dynamic = contextmerged[attr] or 0
- -- local features = contextsetups[contextnumbers[attr]] -- could be a direct list
- local features = contextsetups[attr]
- a_enabled = features -- location based
- if dynamic == 1 then -- or dynamic == -1 then
- -- replace
- language = features.language or "dflt"
- script = features.script or "dflt"
- elseif dynamic == 2 then -- or dynamic == -2 then
- -- merge
- local properties = tfmdata.properties
- s_enabled = tfmdata.shared.features -- font based
- language = features.language or properties.language or "dflt"
- script = features.script or properties.script or "dflt"
- else
- -- error
- local properties = tfmdata.properties
- language = properties.language or "dflt"
- script = properties.script or "dflt"
- end
- else
- local properties = tfmdata.properties
- language = properties.language or "dflt"
- script = properties.script or "dflt"
- s_enabled = tfmdata.shared.features -- can be made local to the resolver
- dynamic = 0
- end
-
- local res = resolved[font]
- if not res then
- res = { }
- resolved[font] = res
- end
- local rs = res[script]
- if not rs then
- rs = { }
- res[script] = rs
- end
- local rl = rs[language]
- if not rl then
- rl = { }
- rs[language] = rl
- end
- local ra = rl[attr]
- if ra == nil then -- attr can be false
- ra = {
- -- indexed but we can also add specific data by key in:
- }
- rl[attr] = ra
- local sequences = tfmdata.resources.sequences
- if sequences then
- local autoscript = (s_enabled and s_enabled.autoscript ) or (a_enabled and a_enabled.autoscript )
- local autolanguage = (s_enabled and s_enabled.autolanguage) or (a_enabled and a_enabled.autolanguage)
- for s=1,#sequences do
- -- just return nil or ra step
- initialize(sequences[s],script,language,s_enabled,a_enabled,font,attr,dynamic,ra,autoscript,autolanguage)
- end
- end
- end
- return ra
-
-end
diff --git a/src/fontloader/misc/fontloader-font-otl.lua b/src/fontloader/misc/fontloader-font-otl.lua
index a35db5b..bdce80d 100644
--- a/src/fontloader/misc/fontloader-font-otl.lua
+++ b/src/fontloader/misc/fontloader-font-otl.lua
@@ -574,10 +574,48 @@ local function copytotfm(data,cache_id)
end
end
+-- These woff files are a kind of joke in a tex environment because one can simply convert
+-- them to ttf/otf and use them as such (after all, we cache them too). The successor format
+-- woff2 is more complex so there we can as well call an external converter which in the end
+-- makes this code kind of obsolete before it's even used. Although ... it might become a
+-- more general conversion plug in.
+
+local converters = {
+ woff = {
+ cachename = "webfonts",
+ action = otf.readers.woff2otf,
+ }
+}
+
+local function checkconversion(specification)
+ local filename = specification.filename
+ local converter = converters[lower(file.suffix(filename))]
+ if converter then
+ local base = file.basename(filename)
+ local name = file.removesuffix(base)
+ local attr = lfs.attributes(filename)
+ local size = attr and attr.size or 0
+ local time = attr and attr.modification or 0
+ if size > 0 then
+ local cleanname = containers.cleanname(name)
+ local cachename = caches.setfirstwritablefile(cleanname,converter.cachename)
+ if not io.exists(cachename) or (time ~= lfs.attributes(cachename).modification) then
+ report_otf("caching font %a in %a",filename,cachename)
+ converter.action(filename,cachename) -- todo infoonly
+ lfs.touch(cachename,time,time)
+ end
+ specification.filename = cachename
+ end
+ end
+end
+
local function otftotfm(specification)
local cache_id = specification.hash
local tfmdata = containers.read(constructors.cache,cache_id)
if not tfmdata then
+
+ checkconversion(specification) -- for the moment here
+
local name = specification.name
local sub = specification.sub
local subindex = specification.subindex
@@ -811,9 +849,14 @@ end
readers.opentype = opentypereader -- kind of useless and obsolete
-function readers.otf (specification) return opentypereader(specification,"otf") end
-function readers.ttf (specification) return opentypereader(specification,"ttf") end
-function readers.ttc (specification) return opentypereader(specification,"ttf") end
+function readers.otf(specification) return opentypereader(specification,"otf") end
+function readers.ttf(specification) return opentypereader(specification,"ttf") end
+function readers.ttc(specification) return opentypereader(specification,"ttf") end
+
+function readers.woff(specification)
+ checkconversion(specification)
+ opentypereader(specification,"")
+end
-- this will be overloaded
diff --git a/src/fontloader/misc/fontloader-font-otr.lua b/src/fontloader/misc/fontloader-font-otr.lua
index 7d0bf04..7c81285 100644
--- a/src/fontloader/misc/fontloader-font-otr.lua
+++ b/src/fontloader/misc/fontloader-font-otr.lua
@@ -94,8 +94,10 @@ otf.readers = readers
----- streamreader = utilities.streams -- faster on big files
local streamreader = utilities.files -- faster on identify
+local streamwriter = utilities.files
readers.streamreader = streamreader
+readers.streamwriter = streamwriter
local openfile = streamreader.open
local closefile = streamreader.close
diff --git a/src/fontloader/misc/fontloader-font-ots.lua b/src/fontloader/misc/fontloader-font-ots.lua
index 0f38508..10f0518 100644
--- a/src/fontloader/misc/fontloader-font-ots.lua
+++ b/src/fontloader/misc/fontloader-font-ots.lua
@@ -184,7 +184,7 @@ local copy_node = nuts.copy
local copy_node_list = nuts.copy_list
local find_node_tail = nuts.tail
local flush_node_list = nuts.flush_list
-local free_node = nuts.free
+local flush_node = nuts.flush_node
local end_of_math = nuts.end_of_math
local traverse_nodes = nuts.traverse
local traverse_id = nuts.traverse_id
@@ -366,7 +366,7 @@ end
local function flattendisk(head,disc)
local _, _, replace, _, _, replacetail = getdisc(disc,true)
setfield(disc,"replace",nil)
- free_node(disc)
+ flush_node(disc)
if head == disc then
local next = getnext(disc)
if replace then
@@ -2744,6 +2744,7 @@ local function kernrun(disc,k_run,font,attr,...)
done = true
end
setprev(pre,nest)
+-- setprev(pre,nil)
setnext(prev,disc)
end
end
@@ -2773,6 +2774,7 @@ local function kernrun(disc,k_run,font,attr,...)
done = true
end
setprev(replace,nest)
+-- setprev(replace,nil)
setnext(prev,disc)
end
if next then
diff --git a/src/fontloader/misc/fontloader-font-tfm.lua b/src/fontloader/misc/fontloader-font-tfm.lua
index d9b0523..6565a0e 100644
--- a/src/fontloader/misc/fontloader-font-tfm.lua
+++ b/src/fontloader/misc/fontloader-font-tfm.lua
@@ -85,6 +85,12 @@ local steps = {
enhancers["check extra features"] = otf.enhancers.enhance
+--[[ PHG: begin hack for Luaotfload ]]--
+luaotfload_tfm_enhancers_reregister = function ()
+ enhancers["check extra features"]=otf.enhancers.enhance
+end
+--[[ PHG: end hack for Luaotfload ]]--
+
local function applyenhancers(data,filename)
for i=1,#steps do
local step = steps[i]
diff --git a/src/fontloader/misc/fontloader-plain-tfm.lua b/src/fontloader/misc/fontloader-plain-tfm.lua
deleted file mode 100644
index 4a08fb4..0000000
--- a/src/fontloader/misc/fontloader-plain-tfm.lua
+++ /dev/null
@@ -1,120 +0,0 @@
-if not modules then modules = { } end modules ['luatex-plain-tfm'] = {
- version = 1.001,
- comment = "companion to luatex-*.tex",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- \font\foo=file:luatex-plain-tfm.lua:tfm=csr10;enc=csr;pfb=csr10 at 12pt
--- \font\bar=file:luatex-plain-tfm.lua:tfm=csr10;enc=csr at 12pt
---
--- \foo áäčďěíĺľňóôŕřšťúýž ff ffi \input tufte\par
--- \bar áäčďěíĺľňóôŕřšťúýž ff ffi \input tufte\par
-
-local outfiles = { }
-
-return function(specification)
-
- local size = specification.size
- local name = specification.name
- local feat = specification.features and specification.features.normal
-
- if not feat then
- return
- end
-
- local tfm = feat.tfm
- local enc = feat.enc or tfm
- local pfb = feat.pfb
-
- if not tfm then
- return
- end
-
- local tfmfile = tfm .. ".tfm"
- local encfile = enc .. ".enc"
-
- local tfmdata, id = fonts.constructors.readanddefine("file:"..tfmfile,size)
-
- local encoding = fonts.encodings.load(encfile)
- if encoding then
- encoding = encoding.hash
- else
- encoding = false
- end
-
- local unicoding = fonts.encodings.agl and fonts.encodings.agl.unicodes
-
- if tfmdata and encoding and unicoding then
-
- tfmdata = table.copy(tfmdata) -- good enough for small fonts
-
- local characters = { }
- local originals = tfmdata.characters
- local indices = { }
- local parentfont = { "font", 1 }
- local private = fonts.constructors.privateoffset
-
- -- create characters table
-
- for name, index in table.sortedhash(encoding) do -- predictable order
- local unicode = unicoding[name]
- local original = originals[index]
- if not unicode then
- unicode = private
- private = private + 1
- report_tfm("glyph %a in font %a gets private unicode %U",name,tfmfile,private)
- end
- characters[unicode] = original
- indices[index] = unicode
- original.name = name -- so one can lookup weird names
- original.commands = { parentfont, { "char", index } }
- end
-
- -- redo kerns and ligatures
-
- for k, v in next, characters do
- local kerns = v.kerns
- if kerns then
- local t = { }
- for k, v in next, kerns do
- local i = indices[k]
- t[i] = v
- end
- v.kerns = t
- end
- local ligatures = v.ligatures
- if ligatures then
- local t = { }
- for k, v in next, ligatures do
- t[indices[k]] = v
- v.char = indices[v.char]
- end
- v.ligatures = t
- end
- end
-
- -- wrap up
-
- tfmdata.fonts = { { id = id } }
- tfmdata.characters = characters
-
- -- resources
-
- local outfile = outfiles[tfmfile]
-
- if outfile == nil then
- if pfb then
- outfile = pfb .. ".pfb"
- pdf.mapline(tfm .. "<" .. outfile)
- else
- outfile = false
- end
- outfiles[tfmfile] = outfile
- end
-
- end
-
- return tfmdata
-end
diff --git a/src/fontloader/misc/fontloader-util-fil.lua b/src/fontloader/misc/fontloader-util-fil.lua
index 47d9d03..eeb6856 100644
--- a/src/fontloader/misc/fontloader-util-fil.lua
+++ b/src/fontloader/misc/fontloader-util-fil.lua
@@ -6,8 +6,10 @@ if not modules then modules = { } end modules ['util-fil'] = {
license = "see context related readme files"
}
-local byte = string.byte
+local byte = string.byte
+local char = string.char
local extract = bit32.extract
+local floor = math.floor
-- Here are a few helpers (the starting point were old ones I used for parsing
-- flac files). In Lua 5.3 we can probably do this better. Some code will move
@@ -36,6 +38,8 @@ function files.size(f)
return f:seek("end")
end
+files.getsize = files.size
+
function files.setposition(f,n)
if zerobased[f] then
f:seek("set",n)
@@ -180,3 +184,32 @@ end
function files.skiplong(f,n)
f:read(4*(n or 1))
end
+
+-- writers (kind of slow)
+
+function files.writecardinal2(f,n)
+ local a = char(n % 256)
+ n = floor(n/256)
+ local b = char(n % 256)
+ f:write(b,a)
+end
+
+function files.writecardinal4(f,n)
+ local a = char(n % 256)
+ n = floor(n/256)
+ local b = char(n % 256)
+ n = floor(n/256)
+ local c = char(n % 256)
+ n = floor(n/256)
+ local d = char(n % 256)
+ f:write(d,c,b,a)
+end
+
+function files.writestring(f,s)
+ f:write(char(byte(s,1,#s)))
+end
+
+function files.writebyte(f,b)
+ f:write(char(b))
+end
+
diff --git a/src/fontloader/runtime/fontloader-reference.lua b/src/fontloader/runtime/fontloader-reference.lua
index e6738ea..13c45aa 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 : 07/13/16 15:09:54
+-- merge date : 07/25/16 21:49:08
do -- begin closure to overcome local limits and interference
@@ -4103,7 +4103,9 @@ if not modules then modules={} end modules ['util-fil']={
license="see context related readme files"
}
local byte=string.byte
+local char=string.char
local extract=bit32.extract
+local floor=math.floor
utilities=utilities or {}
local files={}
utilities.files=files
@@ -4122,6 +4124,7 @@ end
function files.size(f)
return f:seek("end")
end
+files.getsize=files.size
function files.setposition(f,n)
if zerobased[f] then
f:seek("set",n)
@@ -4242,6 +4245,28 @@ end
function files.skiplong(f,n)
f:read(4*(n or 1))
end
+function files.writecardinal2(f,n)
+ local a=char(n%256)
+ n=floor(n/256)
+ local b=char(n%256)
+ f:write(b,a)
+end
+function files.writecardinal4(f,n)
+ local a=char(n%256)
+ n=floor(n/256)
+ local b=char(n%256)
+ n=floor(n/256)
+ local c=char(n%256)
+ n=floor(n/256)
+ local d=char(n%256)
+ f:write(d,c,b,a)
+end
+function files.writestring(f,s)
+ f:write(char(byte(s,1,#s)))
+end
+function files.writebyte(f,b)
+ f:write(char(b))
+end
end -- closure
@@ -4704,7 +4729,7 @@ end
nodes.nodecodes=nodecodes
nodes.glyphcodes=glyphcodes
nodes.disccodes=disccodes
-local free_node=node.free
+local flush_node=node.flush_node
local remove_node=node.remove
local new_node=node.new
local traverse_id=node.traverse_id
@@ -4724,7 +4749,7 @@ function nodes.remove(head,current,free_too)
head,current=remove_node(head,current)
if t then
if free_too then
- free_node(t)
+ flush_node(t)
t=nil
else
t.next,t.prev=nil,nil
@@ -4748,12 +4773,14 @@ nodes.getattr=getfield
nodes.setattr=setfield
nodes.tostring=node.tostring or tostring
nodes.copy=node.copy
+nodes.copy_node=node.copy
nodes.copy_list=node.copy_list
nodes.delete=node.delete
nodes.dimensions=node.dimensions
nodes.end_of_math=node.end_of_math
nodes.flush_list=node.flush_list
nodes.flush_node=node.flush_node
+nodes.flush=node.flush_node
nodes.free=node.free
nodes.insert_after=node.insert_after
nodes.insert_before=node.insert_before
@@ -4767,7 +4794,6 @@ nodes.vpack=node.vpack
nodes.first_glyph=node.first_glyph
nodes.has_glyph=node.has_glyph or node.first_glyph
nodes.current_attr=node.current_attr
-nodes.do_ligature_n=node.do_ligature_n
nodes.has_field=node.has_field
nodes.last_node=node.last_node
nodes.usedlist=node.usedlist
@@ -4854,9 +4880,12 @@ nuts.insert_before=direct.insert_before
nuts.insert_after=direct.insert_after
nuts.delete=direct.delete
nuts.copy=direct.copy
+nuts.copy_node=direct.copy
nuts.copy_list=direct.copy_list
nuts.tail=direct.tail
nuts.flush_list=direct.flush_list
+nuts.flush_node=direct.flush_node
+nuts.flush=direct.flush
nuts.free=direct.free
nuts.remove=direct.remove
nuts.is_node=direct.is_node
@@ -7608,7 +7637,9 @@ handlers.otf=otf
local readers=otf.readers or {}
otf.readers=readers
local streamreader=utilities.files
+local streamwriter=utilities.files
readers.streamreader=streamreader
+readers.streamwriter=streamwriter
local openfile=streamreader.open
local closefile=streamreader.close
local setposition=streamreader.setposition
@@ -15613,10 +15644,38 @@ local function copytotfm(data,cache_id)
}
end
end
+local converters={
+ woff={
+ cachename="webfonts",
+ action=otf.readers.woff2otf,
+ }
+}
+local function checkconversion(specification)
+ local filename=specification.filename
+ local converter=converters[lower(file.suffix(filename))]
+ if converter then
+ local base=file.basename(filename)
+ local name=file.removesuffix(base)
+ local attr=lfs.attributes(filename)
+ local size=attr and attr.size or 0
+ local time=attr and attr.modification or 0
+ if size>0 then
+ local cleanname=containers.cleanname(name)
+ local cachename=caches.setfirstwritablefile(cleanname,converter.cachename)
+ if not io.exists(cachename) or (time~=lfs.attributes(cachename).modification) then
+ report_otf("caching font %a in %a",filename,cachename)
+ converter.action(filename,cachename)
+ lfs.touch(cachename,time,time)
+ end
+ specification.filename=cachename
+ end
+ end
+end
local function otftotfm(specification)
local cache_id=specification.hash
local tfmdata=containers.read(constructors.cache,cache_id)
if not tfmdata then
+ checkconversion(specification)
local name=specification.name
local sub=specification.sub
local subindex=specification.subindex
@@ -15824,9 +15883,13 @@ local function opentypereader(specification,suffix)
end
end
readers.opentype=opentypereader
-function readers.otf (specification) return opentypereader(specification,"otf") end
-function readers.ttf (specification) return opentypereader(specification,"ttf") end
-function readers.ttc (specification) return opentypereader(specification,"ttf") end
+function readers.otf(specification) return opentypereader(specification,"otf") end
+function readers.ttf(specification) return opentypereader(specification,"ttf") end
+function readers.ttc(specification) return opentypereader(specification,"ttf") end
+function readers.woff(specification)
+ checkconversion(specification)
+ opentypereader(specification,"")
+end
function otf.scriptandlanguage(tfmdata,attr)
local properties=tfmdata.properties
return properties.script or "dflt",properties.language or "dflt"
@@ -18042,7 +18105,7 @@ local copy_node=nuts.copy
local copy_node_list=nuts.copy_list
local find_node_tail=nuts.tail
local flush_node_list=nuts.flush_list
-local free_node=nuts.free
+local flush_node=nuts.flush_node
local end_of_math=nuts.end_of_math
local traverse_nodes=nuts.traverse
local traverse_id=nuts.traverse_id
@@ -18176,7 +18239,7 @@ end
local function flattendisk(head,disc)
local _,_,replace,_,_,replacetail=getdisc(disc,true)
setfield(disc,"replace",nil)
- free_node(disc)
+ flush_node(disc)
if head==disc then
local next=getnext(disc)
if replace then
@@ -21087,9 +21150,9 @@ local setprop=nuts.setprop
local ischar=nuts.is_char
local insert_node_after=nuts.insert_after
local copy_node=nuts.copy
-local free_node=nuts.free
local remove_node=nuts.remove
local flush_list=nuts.flush_list
+local flush_node=nuts.flush_node
local copyinjection=nodes.injections.copy
local unsetvalue=attributes.unsetvalue
local fontdata=fonts.hashes.identifiers
@@ -21599,7 +21662,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
if current==stop then
stop=getprev(stop)
head=remove_node(head,current)
- free_node(current)
+ flush_node(current)
return head,stop,nbspaces
else
nbspaces=nbspaces+1
@@ -21637,7 +21700,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
setchar(current,getchar(tempcurrent))
local freenode=getnext(current)
setlink(current,tmp)
- free_node(freenode)
+ flush_node(freenode)
flush_list(tempcurrent)
if changestop then
stop=current
@@ -21874,7 +21937,7 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces)
if getchar(base)==c_nbsp then
nbspaces=nbspaces-1
head=remove_node(head,base)
- free_node(base)
+ flush_node(base)
end
return head,stop,nbspaces
end
@@ -22242,7 +22305,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces)
if current==stop then
stop=getprev(stop)
head=remove_node(head,current)
- free_node(current)
+ flush_node(current)
return head,stop,nbspaces
else
nbspaces=nbspaces+1
@@ -22427,7 +22490,7 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces)
if getchar(base)==c_nbsp then
nbspaces=nbspaces-1
head=remove_node(head,base)
- free_node(base)
+ flush_node(base)
end
return head,stop,nbspaces
end
@@ -25658,7 +25721,7 @@ local fonts=fonts
local nodes=nodes
local nuts=nodes.nuts
local traverse_id=nuts.traverse_id
-local free_node=nuts.free
+local flush_node=nuts.flush_node
local glyph_code=nodes.nodecodes.glyph
local disc_code=nodes.nodecodes.disc
local tonode=nuts.tonode
@@ -25782,7 +25845,7 @@ function nodes.handlers.nodepass(head)
end
end
end
- free_node(r)
+ flush_node(r)
end
end
for d in traverse_id(disc_code,nuthead) do
diff --git a/src/luaotfload-auxiliary.lua b/src/luaotfload-auxiliary.lua
index 3c43eb9..1a21405 100644
--- a/src/luaotfload-auxiliary.lua
+++ b/src/luaotfload-auxiliary.lua
@@ -43,13 +43,11 @@ local luaotfload_callbacks = { }
local rewrite_fontname = function (tfmdata, specification)
local format = tfmdata.format or tfmdata.properties.format
- if format ~= "type1" then
- if stringfind (specification, " ") then
- tfmdata.name = stringformat ("%q", specification)
- else
- --- other specs should parse just fine
- tfmdata.name = specification
- end
+ if stringfind (specification, " ") then
+ tfmdata.name = stringformat ("%q", specification)
+ else
+ --- other specs should parse just fine
+ tfmdata.name = specification
end
end
diff --git a/src/luaotfload-features.lua b/src/luaotfload-features.lua
index b432022..5905c19 100644
--- a/src/luaotfload-features.lua
+++ b/src/luaotfload-features.lua
@@ -2035,29 +2035,61 @@ local rot13_specification = {
prepend = true,
}
-local extrafeatures = {
- tlig = { tlig_specification, "tex ligatures and substitutions" },
- anum = { anum_specification, "arabic numerals" },
- rot13 = { rot13_specification, "rot13" },
-}
+
+local extrafeatures = { }
+local knownfeatures = { }
function add_otf_feature (name, specification)
if type (name) == "table" then
specification = name
- name = specification.name
end
+ specification, name = validspecification (specification, name)
if type (specification) ~= "table" then
logreport ("both", 0, "features",
"invalid feature specification “%s”", tostring (name))
return
end
+ specification.name = name
if name and specification then
- extrafeatures[name] = specification
+ if knownfeatures [name] then
+ logreport ("both", 0, "features",
+ "prevent redefinition of extra feature “%s”", name)
+ else
+ extrafeatures [#extrafeatures + 1] = specification
+ knownfeatures [name] = true
+ end
end
end
otf.addfeature = add_otf_feature
+local autofeatures = {
+ --- always present with Luaotfload
+ { "tlig" , tlig_specification , "tex ligatures and substitutions" },
+ { "anum" , anum_specification , "arabic numerals" },
+ { "rot13", rot13_specification, "rot13" },
+}
+
+local add_auto_features = function ()
+ local nfeats = #autofeatures
+ logreport ("both", 5, "features",
+ "auto-installing %d feature definitions", nfeats)
+ for i = 1, nfeats do
+ local name, spec, desc = unpack (autofeatures [i])
+ spec.description = desc
+ add_otf_feature (name, spec)
+ end
+end
+
+local function enhance(data,filename,raw)
+ for slot=1,#extrafeatures do
+ local specification = extrafeatures[slot]
+ addfeature(data,specification.name,specification)
+ end
+end
+
+otf.enhancers.enhance = enhance
+
local install_extra_features = function (data, filename, raw)
local metadata = data and data.metadata
if not metadata then
@@ -2068,20 +2100,23 @@ local install_extra_features = function (data, filename, raw)
end
local format = data.format
if not format then
+ --- font not fully loaded, happens with TFM/PFB
logreport ("both", 4, "features",
- "no format info for font “%s”/“%s”; not \z
+ "no format info for font “%s”; not \z
installing extra features.",
- fontname, filename)
- return
+ filename)
+ --return
end
- for feature, specification in next, extrafeatures do
- if not fontname then fontname = "<unknown>" end
- if not subfont then subfont = -1 end
+ for i = 1, #extrafeatures do
+ local specification = extrafeatures [i]
+ local feature = specification.name
local fontname = tostring (data.metadata.fontname) or "<unknown>"
local subfont = tonumber (metadata.subfontindex) or -1
+ if not fontname then fontname = filename end
+ if not subfont then subfont = -1 end
logreport ("both", 3, "features",
"register synthetic feature “%s” for %s font “%s”(%d)",
- feature, format, fontname, subfont)
+ feature, format or "tfm", filename, subfont)
otf.features.register { name = feature, description = specification[2] }
otf.enhancers.addfeature (data, feature, specification[1])
end
@@ -2099,8 +2134,11 @@ return {
return false
end
+ add_auto_features ()
+
otf = fonts.handlers.otf
otf.enhancers.addfeature = addfeature
+ luaotfload_tfm_enhancers_reregister ()
otf.enhancers.register ("check extra features",
install_extra_features)
diff --git a/src/luaotfload-loaders.lua b/src/luaotfload-loaders.lua
index d7be31e..87275ef 100644
--- a/src/luaotfload-loaders.lua
+++ b/src/luaotfload-loaders.lua
@@ -50,6 +50,7 @@ local unsupported_reader = function (format)
end
local type1_reader = fonts.readers.afm
+local tfm_reader = fonts.readers.tfm
local install_formats = function ()
local fonts = fonts
@@ -82,9 +83,9 @@ local install_formats = function ()
and aux ("lua", lua_reader)
and aux ("pfa", unsupported_reader "pfa")
and aux ("afm", type1_reader)
- and aux ("tfm", type1_reader)
and aux ("pfb", type1_reader)
- and aux ("ofm", readers.tfm)
+ and aux ("tfm", tfm_reader)
+ and aux ("ofm", tfm_reader)
and aux ("dfont", unsupported_reader "dfont")
end
diff --git a/src/luaotfload-resolvers.lua b/src/luaotfload-resolvers.lua
index a1e702b..983d3fc 100644
--- a/src/luaotfload-resolvers.lua
+++ b/src/luaotfload-resolvers.lua
@@ -173,6 +173,7 @@ local resolve_tex_format = function (specification)
local usename = suffix == format and fileremovesuffix (name) or name
specification.forcedname = file.addsuffix (usename, format)
specification.forced = format
+---- specification.resolved = name
return true
end
end