Skip to content

Commit

Permalink
Fix some bugs and initial multiscript/fallback support
Browse files Browse the repository at this point in the history
  • Loading branch information
zauguin committed Dec 21, 2019
1 parent d188899 commit b8f3d92
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 47 deletions.
20 changes: 3 additions & 17 deletions src/luaotfload-fallback.lua
Expand Up @@ -41,22 +41,7 @@ local fallback_table = setmetatable({}, {
__index = function(tt, size)
local lookup = {}
for i=#names,1,-1 do
local f = define_font(names[i], size)
local fid
if type(f) == 'table' then
fid = font.define(f)
definers.register(f, fid)
elseif f then
fid = f
f = font.getfont(fid)
end
for uni, _ in next, f.characters do
rawset(lookup, uni, fid)
end
end
local lookup = {}
for i=#names,1,-1 do
local f = define_font(names[i], size)
local f = define_font(names[i] .. ';-fallback', size)
local fid
if type(f) == 'table' then
fid = font.define(f)
Expand All @@ -65,6 +50,7 @@ local fallback_table = setmetatable({}, {
fid = f
f = font.getfont(fid)
end
lookup[-i] = f -- Needed for multiscript interactions
for uni, _ in next, f.characters do
rawset(lookup, uni, fid)
end
Expand Down Expand Up @@ -123,7 +109,7 @@ end
function luaotfload.add_fallback(name, fonts)
if fonts == nil then
fonts = name
name = #additional_scripts_fonts + 1
name = #fallback_table_fontnames + 1
end
fallback_table_fontnames[name] = fonts
fallback_table[name] = nil
Expand Down
2 changes: 1 addition & 1 deletion src/luaotfload-main.lua
Expand Up @@ -326,8 +326,8 @@ luaotfload.main = function ()
loadmodule "harf-plug"
end
initialize "auxiliary" --- additional high-level functionality
loadmodule "multiscript" --- ...
loadmodule "fallback" --- ...
loadmodule "multiscript" --- ...
loadmodule "tounicode"
luaotfload.aux.start_rewrite_fontname () --- to be migrated to fontspec
Expand Down
99 changes: 70 additions & 29 deletions src/luaotfload-multiscript.lua
Expand Up @@ -146,7 +146,7 @@ local function collect_scripts(tfmdata)
if hbdata then
local face = hbdata.shared.face
for _, tag in next, { GSUBtag, GPOStag } do
local script_tags = face:ot_layout_get_script_tags(tag)
local script_tags = face:ot_layout_get_script_tags(tag) or {}
for i = 1, #script_tags do
script_dict[tostring(script_tags[i]):gsub(" +$", "")] = true
end
Expand Down Expand Up @@ -200,34 +200,75 @@ local function makecombifont(tfmdata, _, additional_scripts)
additional_scripts = {}
end
if has_auto then
local spec = tfmdata.specification
local collected = collect_scripts(tfmdata)
for script in next, collected do
local iso_script = script_to_iso(script)
if is_dominant_script(collected, script, script_to_ot(iso_script)) then
additional_scripts[iso_script] = spec.specification .. ';-multiscript;script=' .. script
---- FIXME: IMHO the following which just modiefies the spec
-- would be nicer, but it breaks font patching callbacks
-- (except if we ignore them, but that would be inconsistant to
-- other fonts)
-- local new_raw_features = {}
-- local new_features = { raw = new_raw_features, normal = new_raw_features }
-- for f, v in next, spec.features.raw do
-- new_raw_features[f] = v
-- end
-- new_raw_features.multiscript = false
-- new_raw_features.script = script
-- local new_normal_features = luaotfload.apply_default_features(new_raw_features)
-- new_normal_features.sub = nil
-- new_normal_features.lookup = nil
-- new_features.normal = normalize(new_normal_features)
-- local new_spec = {}
-- for k, v in next, spec do
-- new_spec[k] = v
-- end
-- new_spec.hash = nil
-- new_spec.features = new_features
-- additional_scripts[script] = new_spec
local fallback = tfmdata.fallback_lookup
if fallback then -- FIXME: here be dragons
local fallbacks = {}
local current = tfmdata
local i = 0
while current do
local collected = collect_scripts(current)
for script in next, collected do
local scr_fb = fallbacks[script]
if not scr_fb then
scr_fb = {}
fallbacks[script] = scr_fb
end
scr_fb[#scr_fb + 1] = current.specification.specification
end
i = i - 1
current = fallback[i]
end
current = tfmdata
i = 0
while current do
local collected = collect_scripts(current)
for script, scr_fb in next, fallbacks do
if not collected[script] then
scr_fb[#scr_fb + 1] = current.specification.specification
end
end
i = i - 1
current = fallback[i]
end
for script, scr_fb in next, fallbacks do
local iso_script = script_to_iso(script)
if is_dominant_script(scr_fb, script, script_to_ot(iso_script)) then
local main = scr_fb[1]
table.remove(scr_fb, 1)
local fbid = luaotfload.add_fallback(scr_fb)
additional_scripts[iso_script] = main .. ';-multiscript;script=' .. script .. ';fallback=' .. fbid
end
end
else
local spec = tfmdata.specification
local collected = collect_scripts(tfmdata)
for script in next, collected do
local iso_script = script_to_iso(script)
if is_dominant_script(collected, script, script_to_ot(iso_script)) then
additional_scripts[iso_script] = spec.specification .. ';-multiscript;script=' .. script
---- FIXME: IMHO the following which just modiefies the spec
-- would be nicer, but it breaks font patching callbacks
-- (except if we ignore them, but that would be inconsistant to
-- other fonts)
-- local new_raw_features = {}
-- local new_features = { raw = new_raw_features, normal = new_raw_features }
-- for f, v in next, spec.features.raw do
-- new_raw_features[f] = v
-- end
-- new_raw_features.multiscript = false
-- new_raw_features.script = script
-- local new_normal_features = luaotfload.apply_default_features(new_raw_features)
-- new_normal_features.sub = nil
-- new_normal_features.lookup = nil
-- new_features.normal = normalize(new_normal_features)
-- local new_spec = {}
-- for k, v in next, spec do
-- new_spec[k] = v
-- end
-- new_spec.hash = nil
-- new_spec.features = new_features
-- additional_scripts[script] = new_spec
end
end
end
end
Expand Down

3 comments on commit b8f3d92

@u-fischer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very nice. Small remark: I declared a fallback "myfallbackA" (with an uppercase letter) and tried to use with fallback=myfallbackA but this errors:

Unknown fallback table myfallbacka

@zauguin
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@u-fischer That's because all features are lowercased during normalization. That has been introduced in 631c921, I don't know why. We could either disable it or accept that names have to be lowercase, probably adding some checks.

Probably it would be best to start with identifying where lowercasing even has an effect, most features I can currently think of only accept booleans and numbers anyway.

@u-fischer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zauguin yes I guess that. Wouldn't make it sense then to normalize/lowercase the name in luaotfload.add_fallback("myfallback" too?

Please sign in to comment.