I have a document in a script that requires complex text layout which I believe is supposed to work in XeTeX. But I get surprising results:
\documentclass{article}
\usepackage{fontspec}
\tracinglostchars=2 % https://tex.stackexchange.com/a/41235/48
\def\testtext{R ಶ್ರೀವತ್ಸ \quad Rಶ್ರೀವತ್ಸ}
\begin{document}
\fontspec{Arial Unicode MS} \testtext
\fontspec{Noto Sans Kannada} \testtext
\fontspec{Noto Serif Kannada} \testtext
\fontspec{Kedage} \testtext
\end{document}
When compiled with xelatex
this gives:
For those who cannot read the script, the thing on the left (when the input has R ಶ್ರೀವತ್ಸ
with a space after the R) is correct, while the thing on the right (the input has the same text but without the space after the R) is not.
I understand the “boxes” in the output: they are because the Kannada fonts selected don't have the R character in them. (A message to this effect is printed in the terminal thanks to \tracinglostchars=2
.)
Question: Why is the output wrong when the space is omitted? And how can I make things work properly even without the space?
As I understand it, in XeTeX the text layout (aka text rendering, aka text shaping) is provided by the library HarfBuzz, which is used by a lot of other applications and should be able to handle this text fine. In LuaTeX they try to avoid system dependencies and hope to implement everything themselves (in Lua code), which probably underestimates the complexity of text layout and in any case LuaTeX currently has absolutely no support for any Indic scripts other than Devanagari and Malayalam. So this is what lualatex
produces for the above file:
(At least it's consistently wrong which I understand!)
Edit: Thanks to @cfr's answer below, I know what I should do to resolve the actual problem: specify the script when loading the font (e.g. \fontspec{Noto Sans Kannada}[Script=Kannada]
or the better way in her answer). So it's possible to resolve the issue; the only remaining question is: What's going on?
And for what it's worth, here's a minimal plain-XeTeX file that reproduces the issue (compile with xetex
rather than xelatex
):
\font\notosansnone="Noto Sans Kannada"
% \font\notosanskndt="Noto Sans Kannada:script=knd2"
\font\notosansknda="Noto Sans Kannada:script=knda"
\def\testtext{R ಶ್ರೀ Rಶ್ರೀ}
{\notosansnone \testtext} (No script)
% {\notosanskndt \testtext} (knd2)
{\notosansknda \testtext} (knda)
\bye
\/
or\hspace{0pt}
between the two part.Rಶ್ರೀವತ್ಸ
and have it work. I think it should be possible. (Some context: the input file is exported from .odt (that my mother typed in) using writer2latex, and she's going to continue to edit it, and I'd rather not have to preprocess the input file each time.) and (2) I want to understand why this is happening here.