diff options
author | Philipp Gesang <phg@phi-gamma.net> | 2016-07-28 00:06:07 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-07-28 00:06:07 +0200 |
commit | 2fcdccf7edfa1cfb0f03fe8f2163c7c5d8281984 (patch) | |
tree | fcb876f65c47989ecdf254c5ea9d54caa3be10ae /src | |
parent | deef74c357ff2f88d53bc6a745b36b6a75717d2d (diff) | |
parent | d37cfaf8b6bd3e82c8220d385e5da53793f332e1 (diff) | |
download | luaotfload-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.lua | 10 | ||||
-rw-r--r-- | src/fontloader/misc/fontloader-font-gbn.lua | 4 | ||||
-rw-r--r-- | src/fontloader/misc/fontloader-font-osd.lua | 12 | ||||
-rw-r--r-- | src/fontloader/misc/fontloader-font-otd.lua | 268 | ||||
-rw-r--r-- | src/fontloader/misc/fontloader-font-otl.lua | 49 | ||||
-rw-r--r-- | src/fontloader/misc/fontloader-font-otr.lua | 2 | ||||
-rw-r--r-- | src/fontloader/misc/fontloader-font-ots.lua | 6 | ||||
-rw-r--r-- | src/fontloader/misc/fontloader-font-tfm.lua | 6 | ||||
-rw-r--r-- | src/fontloader/misc/fontloader-plain-tfm.lua | 120 | ||||
-rw-r--r-- | src/fontloader/misc/fontloader-util-fil.lua | 35 | ||||
-rw-r--r-- | src/fontloader/runtime/fontloader-reference.lua | 97 | ||||
-rw-r--r-- | src/luaotfload-auxiliary.lua | 12 | ||||
-rw-r--r-- | src/luaotfload-features.lua | 66 | ||||
-rw-r--r-- | src/luaotfload-loaders.lua | 5 | ||||
-rw-r--r-- | src/luaotfload-resolvers.lua | 1 |
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 |