From 0a1b9b746b5ce4cd740af8948f083685879c4eb9 Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Mon, 15 Feb 2016 08:26:54 +0100 Subject: [parsers,features] parse combo requests Highly experimental at this point. The font request parser has been extended to handle combinations of already defined fonts. Nothing else has been implemented yet, so the request handler will simply error out with a message. --- src/luaotfload-features.lua | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src/luaotfload-features.lua') diff --git a/src/luaotfload-features.lua b/src/luaotfload-features.lua index fd43e58..6df04b2 100644 --- a/src/luaotfload-features.lua +++ b/src/luaotfload-features.lua @@ -993,7 +993,10 @@ local import_values = { { "mode", true }, } -local lookup_types = { "anon", "file", "kpse", "my", "name", "path" } +local lookup_types = { "anon" , "file", "kpse" + , "my" , "name", "path" + , "combo" + } local select_lookup = function (request) for i=1, #lookup_types do @@ -1049,6 +1052,7 @@ end local handle_request = function (specification) local request = lpegmatch(luaotfload.parsers.font_request, specification.specification) +----inspect(request) if not request then --- happens when called with an absolute path --- in an anonymous lookup; @@ -1077,7 +1081,13 @@ local handle_request = function (specification) specification.lookup = "path" return specification end + local lookup, name = select_lookup(request) + if lookup == "combo" then + report ("both", 0, "load", + "‘combo’ lookup not implemented at this stage.") + os.exit(-42) + end request.features = apply_default_features(request.features) if name then @@ -1749,4 +1759,4 @@ return { end } --- vim:tw=71:sw=4:ts=4:expandtab +-- vim:tw=79:sw=4:ts=4:expandtab -- cgit v1.2.3 From de3abd3209745257c1fbb7bf08be6b189d5e3cdd Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Tue, 16 Feb 2016 08:23:41 +0100 Subject: [features] handle combination definitions --- src/luaotfload-features.lua | 113 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 106 insertions(+), 7 deletions(-) (limited to 'src/luaotfload-features.lua') diff --git a/src/luaotfload-features.lua b/src/luaotfload-features.lua index 6df04b2..723fd54 100644 --- a/src/luaotfload-features.lua +++ b/src/luaotfload-features.lua @@ -19,6 +19,7 @@ local C = lpeg.C local table = table local tabletohash = table.tohash +local tablesort = table.sort local setmetatableindex = table.setmetatableindex local insert = table.insert @@ -28,6 +29,7 @@ local insert = table.insert local fonts = fonts local definers = fonts.definers local handlers = fonts.handlers +local fontidentifiers = fonts.hashes and fonts.hashes.identifiers local as_script, normalize @@ -65,6 +67,104 @@ local stringformat = string.format local stringis_empty = string.is_empty local mathceil = math.ceil +local cmp_by_idx = function (a, b) return a.idx < b.idx end + +local handle_combination = function (combo, spec) + if not combo [1] then + report ("both", 0, "load", "Empty font combination requested.") + return false + end + inspect(combo) + + if not fontidentifiers then + fontidentifiers = fonts.hashes and fonts.hashes.identifiers + end + + local chain = { } + local fontids = { } + local n = #combo + + tablesort (combo, cmp_by_idx) + + --- pass 1: skim combo and resolve fonts + report ("both", 0, "load", "Combining %d fonts.", n) + for i = 1, n do + local cur = combo [i] + local id = cur.id + local idx = cur.idx + local fnt = fontidentifiers [id] + if fnt then + local chars = cur.chars + report ("both", 0, "load", + " *> %.2d: include font %d at rank %d (%d items).", + i, id, idx, (chars and #chars or 0)) + chain [#chain + 1] = { fnt, chars, idx = idx } + fontids [#fontids + 1] = id + else + report ("both", 0, "load", + " *> %.2d: font %d at rank %d unknown, skipping.", + n, id, idx) + --- TODO might instead attempt to define the font at this point + --- but that’d require some modifications to the syntax + end + end + + local nc = #chain + if nc == 0 then + report ("both", 0, "load", + " *> no valid font (of %d) in combination.", n) + return false + end + + local basefnt = chain [1] [1] + if nc == 1 then + report ("both", 0, "load", + " *> combination boils down to a single font (%s) \z + of %d initially specified; not pursuing this any \z + further.", basefnt.fullname, n) + return basefnt + end + + local basechar = basefnt.characters + local baseprop = basefnt.properties + baseprop.name = spec.name + baseprop.virtualized = true + baseprop.fonts = fontids + + for i = 2, nc do + local cur = chain [i] + local fnt = cur [1] + local def = cur [2] + local src = fnt.characters + local cnt = 0 + + local pickchr = function (uc) + local chr = src [uc] + if chr then + chr.commands = { "slot", i, uc } + basechar [uc] = chr + cnt = cnt + 1 + end + end + + for j = 1, #def do + local this = def [j] + if type (this) == "number" then + pickchr (this) + elseif type (this) == "table" then + for uc = this [1], this [2] do pickchr (uc) end + else + report ("both", 0, "load", + " *> item no. %d of combination definition \z + %d not processable.", j, i) + end + end + report ("both", 0, "load", + " *> font %d / %d: imported %d glyphs into combo.", + i, nc, cnt) + end + return basefnt +end ---[[ begin excerpt from font-ott.lua ]] @@ -1082,13 +1182,12 @@ local handle_request = function (specification) return specification end - local lookup, name = select_lookup(request) + local lookup, name = select_lookup (request) if lookup == "combo" then - report ("both", 0, "load", - "‘combo’ lookup not implemented at this stage.") - os.exit(-42) + return handle_combination (request.combo, specification) end - request.features = apply_default_features(request.features) + + request.features = apply_default_features(request.features) if name then specification.name = name @@ -1126,8 +1225,8 @@ if as_script == true then --- skip the remainder of the file return else local registersplit = definers.registersplit - registersplit (":", handle_request, "cryptic") - registersplit ("", handle_request, "more cryptic") -- catches \font\text=[names] + registersplit (":", handle_request, "common") + registersplit ("", handle_request, "xetex path style") -- catches \font\text=[names] end ---[[ end included font-ltx.lua ]] -- cgit v1.2.3 From 1a6a253e85e609d37113585081b6cf9711757208 Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Thu, 18 Feb 2016 08:35:22 +0100 Subject: [features,loaders] allow for direct injection of tfmdata when defining fonts --- src/luaotfload-features.lua | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'src/luaotfload-features.lua') diff --git a/src/luaotfload-features.lua b/src/luaotfload-features.lua index 723fd54..0ca58c1 100644 --- a/src/luaotfload-features.lua +++ b/src/luaotfload-features.lua @@ -74,7 +74,6 @@ local handle_combination = function (combo, spec) report ("both", 0, "load", "Empty font combination requested.") return false end - inspect(combo) if not fontidentifiers then fontidentifiers = fonts.hashes and fonts.hashes.identifiers @@ -150,9 +149,16 @@ local handle_combination = function (combo, spec) for j = 1, #def do local this = def [j] if type (this) == "number" then + report ("both", 0, "load", + " *> [%d][%d]: import codepoint U+%.4X", + i, j, this) pickchr (this) elseif type (this) == "table" then - for uc = this [1], this [2] do pickchr (uc) end + local lo, hi = unpack (this) + report ("both", 0, "load", + " *> [%d][%d]: import codepoint range U+%.4X--U+%.4X", + i, j, lo, hi) + for uc = lo, hi do pickchr (uc) end else report ("both", 0, "load", " *> item no. %d of combination definition \z @@ -163,7 +169,12 @@ local handle_combination = function (combo, spec) " *> font %d / %d: imported %d glyphs into combo.", i, nc, cnt) end - return basefnt + spec.lookup = nil + spec.method = nil + spec.name = spec.specification + spec.forced = nil + spec.data = function () return basefnt end + return spec end ---[[ begin excerpt from font-ott.lua ]] -- cgit v1.2.3 From 128b29a4260f0454996f5663a02c0f7c575b2d6b Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Fri, 19 Feb 2016 00:51:24 +0100 Subject: =?UTF-8?q?[features,loaders]=20fix=20lookup=20conflicts=20via=20i?= =?UTF-8?q?ntroduction=20of=20=E2=80=9Cevl=E2=80=9D=20lookup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This introduces a forced lookup type “evl” that bypasses the other methods. The specification is extended with the correct values including a more meaningful hash string. As a result, the loader no longer attempts to interpret the specification as a “file:” request but the backend can still resolve the necessary files. --- src/luaotfload-features.lua | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'src/luaotfload-features.lua') diff --git a/src/luaotfload-features.lua b/src/luaotfload-features.lua index 0ca58c1..aeeaea3 100644 --- a/src/luaotfload-features.lua +++ b/src/luaotfload-features.lua @@ -69,9 +69,14 @@ local mathceil = math.ceil local cmp_by_idx = function (a, b) return a.idx < b.idx end +local defined_combos = 0 + local handle_combination = function (combo, spec) + defined_combos = defined_combos + 1 if not combo [1] then - report ("both", 0, "load", "Empty font combination requested.") + report ("both", 0, "load", + "combo %d: Empty font combination requested.", + defined_combos) return false end @@ -86,7 +91,8 @@ local handle_combination = function (combo, spec) tablesort (combo, cmp_by_idx) --- pass 1: skim combo and resolve fonts - report ("both", 0, "load", "Combining %d fonts.", n) + report ("both", 0, "load", "combo %d: combining %d fonts.", + defined_combos, n) for i = 1, n do local cur = combo [i] local id = cur.id @@ -98,7 +104,7 @@ local handle_combination = function (combo, spec) " *> %.2d: include font %d at rank %d (%d items).", i, id, idx, (chars and #chars or 0)) chain [#chain + 1] = { fnt, chars, idx = idx } - fontids [#fontids + 1] = id + fontids [#fontids + 1] = { id = id } else report ("both", 0, "load", " *> %.2d: font %d at rank %d unknown, skipping.", @@ -128,7 +134,7 @@ local handle_combination = function (combo, spec) local baseprop = basefnt.properties baseprop.name = spec.name baseprop.virtualized = true - baseprop.fonts = fontids + basefnt.fonts = fontids for i = 2, nc do local cur = chain [i] @@ -140,7 +146,7 @@ local handle_combination = function (combo, spec) local pickchr = function (uc) local chr = src [uc] if chr then - chr.commands = { "slot", i, uc } + chr.commands = { { "slot", i, uc } } basechar [uc] = chr cnt = cnt + 1 end @@ -169,11 +175,11 @@ local handle_combination = function (combo, spec) " *> font %d / %d: imported %d glyphs into combo.", i, nc, cnt) end - spec.lookup = nil - spec.method = nil - spec.name = spec.specification - spec.forced = nil - spec.data = function () return basefnt end + spec.file = basefnt.filename + spec.name = stringformat ("luaotfload<%d>", defined_combos) + spec.features = { normal = { spec.specification } } + spec.forced = "evl" + spec.eval = function () return basefnt end return spec end -- cgit v1.2.3 From 3447815896954281938500d49bedef715078a140 Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Fri, 19 Feb 2016 22:41:23 +0100 Subject: [features,parsers] implement font fallbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Building on the combination mechanism, this allows defining fallback fonts of which all glyphs are pulled that aren’t currently part of the base font. Example: \input luaotfload.sty \font \lm = file:lmroman10-regular.otf:mode=base \font \cmu = file:cmunrm.otf:mode=base \font \lmu = "combo: 1->\fontid\lm; 2->\fontid\cmu,fallback" \lmu Eh bien, mon prince. Gênes et Lueques ne sont plus que des apanages, des поместья, de la famille Buonaparte. \bye This allows setting Latin Modern text that contains Cyrillic letters. Note that -- as with the other combinations -- only glyphs are considered, no other properties of the fallback font. So besides the occasional letter in a different script this functionality is probably useless. --- src/luaotfload-features.lua | 56 ++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 21 deletions(-) (limited to 'src/luaotfload-features.lua') diff --git a/src/luaotfload-features.lua b/src/luaotfload-features.lua index aeeaea3..4bcfbc3 100644 --- a/src/luaotfload-features.lua +++ b/src/luaotfload-features.lua @@ -100,9 +100,15 @@ local handle_combination = function (combo, spec) local fnt = fontidentifiers [id] if fnt then local chars = cur.chars - report ("both", 0, "load", - " *> %.2d: include font %d at rank %d (%d items).", - i, id, idx, (chars and #chars or 0)) + if chars == true then + report ("both", 0, "load", + " *> %.2d: fallback font %d at rank %d.", + i, id, idx) + else + report ("both", 0, "load", + " *> %.2d: include font %d at rank %d (%d items).", + i, id, idx, (chars and #chars or 0)) + end chain [#chain + 1] = { fnt, chars, idx = idx } fontids [#fontids + 1] = { id = id } else @@ -143,8 +149,12 @@ local handle_combination = function (combo, spec) local src = fnt.characters local cnt = 0 - local pickchr = function (uc) + local pickchr = function (uc, unavailable) local chr = src [uc] + if unavailable == true and basechar [uc] then + --- fallback mode: already known + return + end if chr then chr.commands = { { "slot", i, uc } } basechar [uc] = chr @@ -152,23 +162,27 @@ local handle_combination = function (combo, spec) end end - for j = 1, #def do - local this = def [j] - if type (this) == "number" then - report ("both", 0, "load", - " *> [%d][%d]: import codepoint U+%.4X", - i, j, this) - pickchr (this) - elseif type (this) == "table" then - local lo, hi = unpack (this) - report ("both", 0, "load", - " *> [%d][%d]: import codepoint range U+%.4X--U+%.4X", - i, j, lo, hi) - for uc = lo, hi do pickchr (uc) end - else - report ("both", 0, "load", - " *> item no. %d of combination definition \z - %d not processable.", j, i) + if def == true then --> fallback; grab all currently unavailable + for uc, _chr in next, src do pickchr (uc, true) end + else --> grab only defined range + for j = 1, #def do + local this = def [j] + if type (this) == "number" then + report ("both", 0, "load", + " *> [%d][%d]: import codepoint U+%.4X", + i, j, this) + pickchr (this) + elseif type (this) == "table" then + local lo, hi = unpack (this) + report ("both", 0, "load", + " *> [%d][%d]: import codepoint range U+%.4X--U+%.4X", + i, j, lo, hi) + for uc = lo, hi do pickchr (uc) end + else + report ("both", 0, "load", + " *> item no. %d of combination definition \z + %d not processable.", j, i) + end end end report ("both", 0, "load", -- cgit v1.2.3