>> I've come up with the attached solution, which works fine for the
>> small example. Not sure whether this is the correct way, though.
>
> A couple small comments: [...]
>
> Otherwise, it looks good to me.
Thanks a lot for the review! Attached is an improved version.
Werner
\documentclass{article}
\usepackage{luacode}
\usepackage{fontspec}
\begin{luacode*}
local report = luaotfload.log.report
local function glyph_to_unicode(glyph, unicodes, fontname)
local unicode = unicodes[glyph]
if not unicode then
report("both", 0, "add_to_mark",
"error: there is no glyph '%s' in font '%s'",
glyph, fontname)
end
return unicode
end
local function missing_base_glyph(base_glyph, fontname)
report("both", 0, "add_to_mark",
"error: base glyph '%s' not in 'mark' feature of font '%s'",
base_glyph, fontname)
end
local function missing_mark_glyph(mark_glyph, fontname)
report("both", 0, "add_to_mark",
"error: mark glyph '%s' not in 'mark' feature of font '%s'",
mark_glyph, fontname)
end
local patch_functions = {}
-- Add glyph with name ACC as a diacritic to an existing 'mark'
-- feature of font file FONT. The arguments BASE and MARK specify
-- names of glyphs that represent the desired anchor class that
-- connects base and mark glyphs, respectively, to which ACC should
-- be added. The coordinates X and Y give the position of the
-- anchor for ACC.
--
-- FONT should be the base name of an OpenType font, i.e., a file
-- name without a path (example: `foo.otf`).
--
-- BASE and MARK must exist in FONT, and there must be an entry in
-- the 'mark' feature that pairs them. ACC must exist in FONT, too.
--
-- This function can be used repeatedly. Note, however, that a mark
-- glyph can only be part of a single anchor class. As a
-- consequence, a second call to this function with the same
-- argument ACC (for a particular font) that results in a different
-- anchor class overrides the result of the first call.
function add_to_mark_feature(font, acc, base, mark, x, y)
if not patch_functions[font] then
patch_functions[font] = {}
end
local function patch_function(fontdata)
local path = fontdata.specification.filename
local filename = file.basename(path)
local unicodes = fontdata.resources.unicodes
if not unicodes then
report("both", 0, "add_to_mark",
"error: 'unicodes' subtable missing;"
.. " cannot map glyph names to Unicode")
return
end
local uni_acc = glyph_to_unicode(acc, unicodes, filename)
local uni_base = glyph_to_unicode(base, unicodes, filename)
local uni_mark = glyph_to_unicode(mark, unicodes, filename)
if not (uni_acc and uni_base and uni_mark) then
return
end
for _, sequence in ipairs(fontdata.resources.sequences) do
if (sequence.type == "gpos_mark2base"
and sequence.features["mark"]) then
for _, step in ipairs(sequence.steps) do
local coverage = step.coverage
if coverage then
local coverage_mark = coverage[uni_mark]
if coverage_mark then
local coverage_base = coverage_mark[1][uni_base]
if coverage_base then
for i, baseclass in ipairs(step.baseclasses) do
if baseclass[uni_base] then
report("log", 0, "add_to_mark",
"found base-mark glyph combination '%s+%s'"
.. " in 'mark' feature of font '%s'",
base, mark, filename)
-- Report OpenType value for anchor class, not
-- the one used in luatex.
report("log", 0, "add_to_mark",
"adding glyph '%s' to anchor class %d",
acc, i - 1)
coverage[uni_acc] = {baseclass, {x, y}}
return
end
end
else
missing_base_glyph(base, filename)
return
end
else
missing_mark_glyph(mark, filename)
return
end
end
end
end
end
report("log", 0, "add_to_mark",
"no 'mark' feature in font '%s'",
filename)
return
end
table.insert(patch_functions[font], patch_function)
luatexbase.add_to_callback(
"luaotfload.patch_font",
function(fontdata)
local path = fontdata.specification.filename
local filename = file.basename(path)
local patch_functions = patch_functions[filename]
if not patch_functions then
return
end
for _, v in pairs(patch_functions) do
v(fontdata)
end
end,
"patch-fonts"
)
end
\end{luacode*}
\begin{luacode*}
add_to_mark_feature("EBGaramond-Regular.otf",
"uni0364", "e", "gravecomb", 115, 440)
\end{luacode*}
\setmainfont{EB Garamond}
\begin{document}
schoͤn
\end{document}
%%% Local Variables:
%%% mode: latex
%%% TeX-master: t
%%% End: