> Attached is an improved version. As usual: right after sending an improved version I find a problem :-)
The old version only checked the first lookup of a 'mark' feature; this is now fixed. Werner
% version 2025-Sep-16 \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 local have_mark_feature = false local base_glyph_in_coverage = false local mark_glyph_in_coverage = false for _, sequence in ipairs(fontdata.resources.sequences) do if (sequence.type == "gpos_mark2base" and sequence.features["mark"]) then have_mark_feature = true for _, step in ipairs(sequence.steps) do local coverage = step.coverage if coverage then local coverage_mark = coverage[uni_mark] if coverage_mark then mark_glyph_in_coverage = true local coverage_base = coverage_mark[1][uni_base] if coverage_base then base_glyph_in_coverage = true 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 end end end end end end if not have_mark_feature then report("log", 0, "add_to_mark", "no 'mark' feature in font '%s'", filename) else if not base_glyph_in_coverage then missing_base_glyph(base, filename) end if not mark_glyph_in_coverage then missing_mark_glyph(mark, filename) end end 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 _, patch_function in pairs(patch_functions) do patch_function(fontdata) end end, "patch-fonts" ) end \end{luacode*} \begin{luacode*} add_to_mark_feature("EBGaramond-Regular.otf", "uni0364", "e", "gravecomb", 115, 440) add_to_mark_feature("EBGaramond-Italic.otf", "uni0364", "e", "gravecomb", 115, 440) \end{luacode*} \setmainfont{EB Garamond} \begin{document} schoͤn \emph{schoͤn} \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: