-
-
Save hmenke/6e8ff7c90a5e5df3c4895f60059a2ef7 to your computer and use it in GitHub Desktop.
\ifdefined\directlua | |
\input XeTeXemulate.sty | |
\input luaotfload.sty | |
\XeTeXemulate | |
\fi | |
\font\1="[lmroman10-italic.otf]" at 10pt\1 | |
\font\2=cmr10 at 10pt | |
\edef\x{\the\XeTeXfonttype\1}“\x” | |
\edef\x{\the\XeTeXfonttype\2}“\x” | |
\edef\x{\the\XeTeXversion}“\x” | |
\edef\x{\XeTeXrevision}“\x” | |
\edef\x{\char\XeTeXfirstfontchar\1}“\x” | |
\edef\x{\char\XeTeXfirstfontchar\2}“\x” | |
\edef\x{\char\XeTeXlastfontchar\1}“\x” | |
\edef\x{\char\XeTeXlastfontchar\2}“\x” | |
\edef\x{\XeTeXglyph150}“\x” | |
\edef\x{\the\XeTeXcountglyphs\1}“\x” | |
\edef\x{\the\XeTeXcountglyphs\2}“\x” | |
\edef\x{\XeTeXglyphname\1 150}“\x” | |
\edef\x{\the\XeTeXglyphindex"acircumflexgrave"\relax}“\x” | |
\edef\x{\the\XeTeXglyphindex"acircumflexgrave" }“\x” | |
\edef\x{\the\XeTeXcharglyph"00A5}“\x” | |
\edef\x{\the\XeTeXglyphbounds 1 \XeTeXcharglyph`f}“\x” | |
\edef\x{\the\XeTeXglyphbounds 2 \XeTeXcharglyph`f}“\x” | |
\edef\x{\the\XeTeXglyphbounds 3 \XeTeXcharglyph`f}“\x” | |
\edef\x{\the\XeTeXglyphbounds 4 \XeTeXcharglyph`f}“\x” | |
\edef\x{[\the\XeTeXglyphindex yen ] x}“\x” | |
\edef\x{[\the\XeTeXglyphindex "yen" ] x}“\x” | |
\edef\x{[\the\XeTeXglyphindex"yen"\relax] x }“\x” | |
\edef\x{[\the\XeTeXglyphindex"yen"] x }“\x” | |
\edef\x{[\the\XeTeXglyphindex "yen" *2]}“\x” | |
\edef\x{[\the\XeTeXglyphindex "yen"\relax*2]}“\x” | |
\edef\x{[\XeTeXglyphindex"yen"] }“\meaning\x” | |
\edef\x{[\XeTeXglyphindex] }“\meaning\x” | |
\bye |
\ifcsname ProvidesPackage\endcsname | |
\NeedsTeXFormat{LaTeX2e} | |
\ProvidesPackage{XeTeXemulate}[2018/09/03 v0.0 Emulate the XeTeX font primitives in LuaTeX] | |
\fi | |
\def\XeTeXemulate{% | |
\chardef\XeTeXversion=0 | |
\def\XeTeXrevision{.99999}% | |
% Circumvent \outer error | |
\csname newcount\endcsname\XeTeXtracingfonts \XeTeXtracingfonts=0 | |
\csname newcount\endcsname\XeTeXuseglyphmetrics \XeTeXuseglyphmetrics=1 | |
% | |
\let\XeTeXmathcode\Umathcode | |
% | |
\protected\def\XeTeXfonttype{% | |
\directlua{ | |
local fid = token.scan_int() | |
local tfmdata = font.getfont(fid) | |
local fonttype = tfmdata.format == "opentype" and 2 or 0 | |
tex.print([[\numexpr]] .. fonttype .. [[\relax]]) | |
}\fontid | |
}% | |
% | |
\protected\def\XeTeXfirstfontchar{% | |
\directlua{ | |
local fid = token.scan_int() | |
local tfmdata = font.getfont(fid) | |
local min | |
for slot in pairs(tfmdata.characters) do | |
min = min and (slot < min and slot or min) or slot | |
end | |
tex.print([[\numexpr]] .. min .. [[\relax]]) | |
}\fontid | |
}% | |
% | |
\protected\def\XeTeXlastfontchar{% | |
\directlua{ | |
local fid = token.scan_int() | |
local tfmdata = font.getfont(fid) | |
local max | |
for slot in pairs(tfmdata.characters) do | |
max = max and (slot > max and slot < 2^16 and slot or max) or slot | |
end | |
tex.print([[\numexpr]] .. max .. [[\relax]]) | |
}\fontid | |
}% | |
% | |
\def\XeTeXglyph{% | |
\directlua{ | |
local index = token.scan_int() | |
local tfmdata = font.getfont(font.current()) | |
if tfmdata.format \string~= "opentype" then | |
tex.error([[Cannot use \string\XeTeXglyph]] .. [[ with ]] .. | |
tfmdata.name .. [[; not a native platform font]]) | |
end | |
for slot, char in pairs(tfmdata.characters) do | |
if char.index == index then | |
tex.print(utf.char(char.unicode)) | |
return | |
end | |
end | |
}}% | |
% | |
\protected\def\XeTeXcountglyphs{% | |
\directlua{ | |
local fid = token.scan_int() | |
local tfmdata = font.getfont(fid) | |
local count = 0 | |
if tfmdata.format == "opentype" then | |
for _ in pairs(tfmdata.characters) do | |
count = count + 1 | |
end | |
end | |
tex.print([[\numexpr]] .. count .. [[\relax]]) | |
}\fontid | |
}% | |
% | |
\def\XeTeXglyphname{% | |
\directlua{ | |
local fid = token.scan_int() | |
local index = token.scan_int() | |
local tfmdata = font.getfont(fid) | |
if tfmdata.format \string~= "opentype" then | |
tex.error([[Cannot use \string\XeTeXglyphname]] .. [[ with ]] .. | |
tfmdata.name .. [[; not a native platform font]]) | |
end | |
local count = 0 | |
for slot, char in pairs(tfmdata.shared.rawdata.descriptions) do | |
if char.index == index then | |
tex.print(char.name) | |
return | |
end | |
end | |
}\fontid | |
}% | |
% | |
\protected\def\XeTeXglyphindex{% | |
\directlua{ | |
local k = string.gsub(token.scan_string(),'"','') | |
token.scan_keyword(' ') % remove optional space | |
local tfmdata = font.getfont(font.current()) | |
if tfmdata.format \string~= "opentype" then | |
tex.error([[Cannot use \string\XeTeXglyphindex]] .. [[ with ]] .. | |
tfmdata.name .. [[; not a native platform font]]) | |
end | |
local index = 0 | |
for slot, char in pairs(tfmdata.shared.rawdata.descriptions) do | |
if char.name == k then | |
index = char.index | |
break | |
end | |
end | |
tex.print([[\numexpr]] .. index .. [[\relax]]) | |
}}% | |
% | |
\protected\def\XeTeXcharglyph{% | |
\directlua{ | |
local id = token.scan_int() | |
local tfmdata = font.getfont(font.current()) | |
if tfmdata.format \string~= "opentype" then | |
tex.error([[Cannot use \string\XeTeXcharglyph]] .. [[ with ]] .. | |
tfmdata.name .. [[; not a native platform font]]) | |
end | |
local index = tfmdata.characters[id].index | |
tex.print([[\numexpr]] .. index .. [[\relax]]) | |
}}% | |
% | |
\protected\def\XeTeXglyphbounds{% | |
\directlua{ | |
local edge = token.scan_int() | |
local slot = token.scan_int() | |
local tfmdata = font.getfont(font.current()) | |
if tfmdata.format \string~= "opentype" then | |
tex.error([[Cannot use \string\XeTeXglyphname]] .. [[ with ]] .. | |
tfmdata.name .. [[; not a native platform font]]) | |
end | |
for _,char in pairs(tfmdata.shared.rawdata.descriptions) do | |
if char and char.index == slot then | |
local bbox = char.boundingbox | |
local dimen = 0 | |
if edge == 1 then | |
dimen = bbox and bbox[1] / 100 * 2^16 or 0 | |
elseif edge == 2 then | |
dimen = tfmdata.characters[char.unicode].height | |
elseif edge == 3 then | |
dimen = bbox and (char.width - bbox[3]) / 100 * 2^16 or 0 | |
elseif edge == 4 then | |
dimen = tfmdata.characters[char.unicode].depth | |
end | |
tex.print([[\dimexpr]] .. tex.round(dimen) .. [[sp\relax]]) | |
break | |
end | |
end | |
}}% | |
} | |
\endinput |
It may be better to add the \relax
in the tex.print to prevent following tokens being takes as the numexpr, I added (..)
but that would still gobble *2
etc. Also the "
in xetex are actually optional, this works
\typeout{YEN 1b: [\the\XeTeXglyphindex yen ] x}
better emulation using token scanner
\documentclass{article}
\makeatletter
\ifx\directlua\@undefined\else
\protected\def\XeTeXglyphindex"#1"{%
\directlua{
local tfmdata = font.getfont(font.current())
if tfmdata.format \string~= "opentype" then
tex.error([[Cannot use \string\XeTeXglyphindex]] .. [[ with ]] ..
tfmdata.name .. [[; not a native platform font]])
end
local index = 0
for slot, char in pairs(tfmdata.shared.rawdata.descriptions) do
if char.name == "\luaescapestring{#1}" then
index = char.index
break
end
end
tex.print([[\numexpr(]] .. index .. ')')
}}%
%
\protected\def\XeTeXglyphindex{%
\directlua{
local k = string.gsub(token.scan_string(),'"','')
local sp = token.scan_keyword(' ')
local tfmdata = font.getfont(font.current())
if tfmdata.format \string~= "opentype" then
tex.error([[Cannot use \string\XeTeXglyphindex]] .. [[ with ]] ..
tfmdata.name .. [[; not a native platform font]])
end
local index = 0
for slot, char in pairs(tfmdata.shared.rawdata.descriptions) do
if char.name == k then
index = char.index
break
end
end
tex.print([[\numexpr]] .. index .. [[\relax]])
}}%
%
\fi
\begin{document}
\typeout{YEN 0: [\the\XeTeXglyphindex yen ] x}
\typeout{YEN 1: [\the\XeTeXglyphindex "yen" ] x}
\typeout{YEN 2: [\the\XeTeXglyphindex"yen"\relax] x }
\typeout{YEN 3: [\the\XeTeXglyphindex"yen"] x }
\typeout{YEN 4: [\XeTeXglyphindex"yen"] }
\typeout{YEN 5: [\XeTeXglyphindex] }
\typeout{YEN 6: [\the\XeTeXglyphindex "yen" *2]}
\typeout{YEN 7: [\the\XeTeXglyphindex "yen"\relax*2]}
\end{document}
with xelatex
YEN 0: [638] x
YEN 1: [638] x
YEN 2: [638\relax ] x
YEN 3: [0x
YEN 4: [\XeTeXglyphindex "yen"]
YEN 5: [\XeTeXglyphindex ]
YEN 6: [638*2]
YEN 7: [638\relax *2]
with lualatex
YEN 0: [638] x
YEN 1: [638] x
YEN 2: [638\relax ] x
YEN 3: [0x
YEN 4: [\XeTeXglyphindex "yen"]
YEN 5: [\XeTeXglyphindex ]
YEN 6: [638*2]
YEN 7: [638\relax *2]
IMHO, it would be great to have this released ...
- it seems it would be good to check for truetype as well as opentype in the tfmdata.format \string. at least, once I made that change, it all worked for me with a ttf.
- it is possible to use ttf/otf which are not platform fonts, so the error message is misleading. also, it's helpful to show the actual string being tested.
I ended up with thefor \XeTeXglyph, used to typeset the visible glyph (a la Unicode font charts) for U+FE00 (variation selector-1). Using Base rendering mode was also necessary to stop the normal Unicode interpretation. I'll append my whole test document for the heck of it, but the relevant thing for your code is just the tweaks to the Lua condition and error string.
\documentclass{article}
\pagestyle{empty}
\usepackage{fontspec}
\ifx\undefined\XeTeXglyph
\def\XeTeXglyph{%
\directlua{
local index = token.scan_int()
local tfmdata = font.getfont(font.current())
if tfmdata.format \string ~= "opentype"
and tfmdata.format \string ~= "truetype" then
tex.error([[Cannot use \string\XeTeXglyph]] .. [[ with ]] ..
tfmdata.name .. tfmdata.format \string ..
[[; not opentype or truetype]])
end
for slot, char in pairs(tfmdata.characters) do
if char.index == index then
tex.print(utf.char(char.unicode))
return
end
end
}}%
%
\newfontfamily{\NSM}[Renderer=Base]{NotoSansManichaean-Regular.ttf}
\newcommand{\VSone}{{\NSM\XeTeXglyph58}} % FE00
\else
\newcommand{\VSone}{{\fontspec{NotoSansManichaean-Regular.ttf}\XeTeXglyph58}}
\fi
\begin{document}
\VSone
\end{document}
I'd actually rather reimplement the entire thing in pure Lua and expose the commands via token.set_lua
. That makes them feel a lot more like actual primitives since they expand in a single step. That will need some expandafter magic for \fontid
, but other than that should be straight-forward.
@kberry https://github.com/latex3/xxetex is in the works
currently
\typeout{YEN: \the\XeTeXglyphindex"yen" }
produces
YEN: 638\ignorespaces
in luatex as
\ignorespaces
isn't expandable, also it modifies the value of\count@
which may cause some surprises.May I suggest