I am trying to use an existing glyph from an OpenType font to fill an empty slot in the same font using LuaLaTeX. fontspec.pdf (v2.6g, part VI) shows a hack that can substitute already existing glyphs using fonts.handlers.otf.addfeature, but not empty slots, presumably because their name does not exist.
The font in question is the proprietary Garamond Premier Pro, but the same issue is found with EB Garamond, available in outdated upstream form in TeXLive as ebgaramond or newer as a Google Fonts fork from their repo. So while the immediate solution is to contribute to EB Garamond, the real world problem is with a font that can not be modified.
U+03F5 (ϵ) (c-shaped) is normally the glyph named epsilon1, which is the slot I want to fill with the similar enough (in Noto Sans they are linked directly) ukrainian ie U+0454 (є) which is cryptically named afii10101 (not even opentype.js.org gets it right, uni0454 will not show up in the MWE).
For text, we can use newunicodechar and it is working nicely, except the minor issue that copy-paste gives an ukrainian letter.
For math, neither 0x03F5, "uni03F5" or "epsilon1" has any effect in the Lua code. We can replace the U+03B5 if we like, but we don't. luaotfload.pdf (v2.8, chapter 5) has some info on how to combine separate fonts, but not how to (re)map glyphs from scratch within a single font.
Do we need to create a “ghost” glyph entry before we can remap it? Can we create it from scratch (and reference the outline, to get proper copy-paste)? Is there some documentation I am missing?
\documentclass{article}
\usepackage{fontspec}
\usepackage[math-style=ISO]{unicode-math}
\usepackage{newunicodechar}
\directlua{
fonts.handlers.otf.addfeature {
name = "cstm",
type = "substitution",
data = {
[0x261E] = "afii10101",% pointing finger for example
%[0x261E] = "uni0454",% has NO effect
["uni03F5"] = "afii10101",% c-shape, has NO effect
[0x03F5] = "afii10101",% c-shape, has NO effect
["epsilon1"] = "afii10101",% c-shape, has NO effect
%["uni03B5"] = "afii10101",% 3-shape, has NO effect
%[0x03B5] = "afii10101",% 3-shape, DOES HAVE effect
%["epsilon"] = "afii10101",% 3-shape, DOES HAVE effect
} } }
\setmainfont{EB Garamond}[RawFeature=+cstm]
\setmathfont{Latin Modern Math}
\setmathfont{EB Garamond Italic}[range=it,RawFeature=+cstm]
\newunicodechar{ϵ}{\char"0454}
\begin{document}
{\addfontfeature{RawFeature=-cstm}\itshape ☞} ← normal\par
{\addfontfeature{RawFeature=+cstm}\itshape ☞} ← substitution in action\par
\begin{tabular}{cccc}
& 03B5 & 03F5 & 0454 \\
text & ({\itshape ε}) & ({\itshape ϵ}) & ({\itshape є}) \\
math & ($\symit{ε}$) & ($\symit{ϵ}$) & {\scshape n/a} \\
\end{tabular}
\end{document}

