XeTeX-Textlayout reagiert seltsam empfindlich auf Leerzeichen

XeTeX-Textlayout reagiert seltsam empfindlich auf Leerzeichen

Ich habe ein Dokument in einem Skript, das erfordertkomplexes Textlayoutwas, wie ich glaube, in XeTeX funktionieren sollte. Aber ich bekomme überraschende Ergebnisse:

\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}

Die Kompilierung xelatexergibt:

Ausgabe

Für diejenigen, die das Skript nicht lesen können: Das, was links steht (wenn die Eingabe R ಶ್ರೀವತ್ಸein Leerzeichen nach dem „R“ enthält), ist korrekt, während das, was rechts steht (die Eingabe enthält den gleichen Text, aber ohne das Leerzeichen nach dem „R“), nicht korrekt ist.

Ich verstehe die „Kästchen“ in der Ausgabe: Sie sind darauf zurückzuführen, dass die ausgewählten Kannada-Schriftarten das Zeichen R nicht enthalten. (Dank wird im Terminal eine entsprechende Meldung ausgegeben \tracinglostchars=2.)

Frage: Warum ist die Ausgabe falsch, wenn das Leerzeichen weggelassen wird? Und wie kann ich dafür sorgen, dass es auch ohne das Leerzeichen richtig funktioniert?

So wie ich es verstehe, wird in XeTeX das Textlayout (auch Textdarstellung oder Textgestaltung genannt) von der Bibliothek HarfBuzz bereitgestellt, die von vielen anderen Anwendungen verwendet wird und mit diesem Text gut umgehen können sollte. In LuaTeX versucht man, Systemabhängigkeiten zu vermeiden und hofft, alles selbst (in Lua-Code) zu implementieren, was die Komplexität des Textlayouts wahrscheinlich unterschätzt, und in jedem Fall bietet LuaTeX derzeit absolut keine Unterstützung für indische Schriften außer Devanagari und Malayalam. Das ergibt also lualatexfür die obige Datei:

Abonnieren

(Zumindest ist es durchweg falsch, was ich verstehe!)


Bearbeiten: Dank der Antwort von @cfr unten weiß ich, was ich tun sollte, um das eigentliche Problem zu lösen: das Skript beim Laden der Schriftart angeben (z. B. \fontspec{Noto Sans Kannada}[Script=Kannada]oder die bessere Methode in ihrer Antwort). Es ist also möglich, das Problem zu lösen. Die einzige verbleibende Frage ist:Was ist los?

Und hier ist eine minimale Plain-XeTeX-Datei, die das Problem reproduziert (kompilieren Sie mit xetexstatt 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

Antwort1

Ich habe weder die erste noch die letzte Schriftart. Polyglossia funktioniert bei mir jedoch einwandfrei. (Ich gehe davon aus, dass es wahrscheinlich auch mit der richtigen Schriftartkonfiguration funktionieren würde, aber ich habe es so gemacht, weil das vermutlich das ist, was Sie letztendlich wollen.)

\documentclass{article}
\usepackage{polyglossia}
\setmainlanguage{kannada}
\setotherlanguage[variant=british]{english}
\newfontfamily\kannadafont{Noto Serif Kannada}[Script=Kannada]
\newfontfamily\kannadafontsf{Noto Sans Kannada}[Script=Kannada]
\tracinglostchars=2 % https://tex.stackexchange.com/a/41235/48
\def\testtext{R ಶ್ರೀವತ್ಸ \quad Rಶ್ರೀವತ್ಸ}

\begin{document}

% \fontspec{Arial Unicode MS} \testtext

\testtext

\sffamily \testtext

% \fontspec{Kedage} \testtext

\end{document}

Schriftartkonfiguration

Antwort2

(Ich teile mit, was ich als Ergebnis all dessen verstanden habe.)

Lösungen

Zunächst die Lösungen des Problems:

  • Als@cfrs Antwort[Script=Kannada]darauf hingewiesen, dass ich diese Schriftart verwenden sollte , wie in den Handbüchern fontspecund dokumentiert polyglossia. Und wenn ich sie verwende, funktioniert alles wie erwartet: mit oder ohne Leerzeichen wird der gesamte Text so wiedergegeben, wie es für die Kannada-Schrift angemessen ist.
  • Darüber hinaus möchten wir eigentlich nicht, dass Nicht-Kannada-Zeichen, wie etwa das R, in der Kannada-Schrift wiedergegeben werden: Die Zeichen einer anderen Schrift Rmüssen als zu einer anderen Sprache gehörend oder zumindest in einer anderen Schriftart dargestellt werden (siehe unten, wie das geht).

Handelt es sich hier also um einen Fehler, entweder in XeTeX oder in einer von ihm verwendeten Bibliothek? Nein, ich würde sagen, es handelt sich um einen Benutzerfehler. Dennoch macht die Tatsache, dass alles einwandfrei funktioniert, wenn Leerzeichen zwischen Wörtern stehen (ohne dass das Skript angegeben werden muss), diesen Benutzerfehler möglicherweise wahrscheinlicher.

Erläuterung

Was erklärt diese Diskrepanz im Verhalten je nach Speicherplatz (was genau passiert hier)? Und kann dieses Verhalten in XeTeX geändert werden? Ich habe Folgendes herausgefunden.

Die von XeTeX für das Textlayout verwendete Bibliothek, nämlichAbonnieren(wird in Firefox, Chrome, LibreOffice usw. verwendet, sieheWas ist Harfbuzz?), verfügt über ein Kommandozeilenprogramm namens , hb-viewdas mit einer Schriftart und einer Textzeichenfolge aufgerufen werden kann. Damit erhalte ich die folgende Ausgabe:

  • hb-view NotoSansKannada-Regular.ttf "ಶ್ರೀ"und mit --script=knda:

    ohne Skript, kein Platz mit Schrift, Leerzeichen

  • hb-view NotoSansKannada-Regular.ttf " ಶ್ರೀ"und mit --script=knda:

    ohne Skript, beginnt mit Leerzeichen mit Skript, beginnt mit Leerzeichen

  • hb-view NotoSansKannada-Regular.ttf "Rಶ್ರೀ"und mit--script=knda

    ohne Skript, beginnt mit R, kein Leerzeichen mit Skript, beginnt mit R, kein Leerzeichen

  • hb-view NotoSansKannada-Regular.ttf "R ಶ್ರೀ"und mit--script=knda

    ohne Skript, beginnt mit R und Leerzeichen mit Skript, beginnt mit R und Leerzeichen

Dies zeigt, dass die Ausgabe korrekt ist, wennentwederDas erste Zeichen, das kein Leerzeichen ist, stammt aus der richtigen Schrift.oderdas Skript wird explizit angegeben.

Das in XeTeX beobachtete Verhalten (der Unterschied zwischen "Rಶ್ರೀ" und "R ಶ್ರೀ") wird also dadurch erklärt, was@Ulrike Fischerwies darauf hin inDer XeTeX-Begleiter:

Der Ansatz von XeTeX ist der folgende:

  • der Satzprozess sammelt Buchstabenfolgen (Wörter), deren Breiten über die API zu den Systembibliotheken abgerufen werden […], um die Breiten zu bestimmen,

  • Ein XeTeX-Absatz ist eine Folge vonWortKnoten getrennt durchKleber.

Daher platziert die Satz-Engine von XeTeX Wörter statt Glyphen, wobei letztere von der Schriftart-Rendering-Engine gezeichnet werden.

(Die oben genannten „Systembibliotheken“ und „Font-Rendering-Engine“ sind jetzt HarfBuzz (danke anKhaled Hosny); früher waren sie auf der Intensivstation.) Also

  • mit „Rಶ್ರೀವತ್ಸ“ fordert XeTeX HarfBuzz auf, den gesamten String als eine Einheit darzustellen, was fehlschlägt (wie in den obigen hb-view-Experimenten zu sehen), da er weder mit einem Zeichen aus der gewünschten Schrift beginnt, noch wir die Schrift richtig angegeben haben, während

  • mit „R ಶ್ರೀವತ್ಸ“ fragt XeTeX HarfBuzz separat für jedes der beiden Wörter ab, und in diesem Fall wird das zweite Wort korrekt wiedergegeben (auch wenn wir die Schrift nicht angegeben haben), weil es mit einem Zeichen aus der richtigen Schrift beginnt.

Dennoch scheint es am besten, sich nicht auf solche Vermutungen zu verlassen und das Skript explizit anzugeben.

Arbeiten mit beiden Skripten

Damit beide Skripte reibungslos funktionieren, sollten wir angeben, dass die Zeichen wie R in einer anderen Sprache sind. Wir könnten dies tun, indem wir \textenglish{R}ಶ್ರೀವತ್ಸanstelle von schreiben Rಶ್ರೀವತ್ಸ. Wenn wir die Eingabe jedoch nicht ändern möchten, gibt es eine Möglichkeit, dies mit demucharclassesPaket.

Ich konnte es aus irgendeinem Grund nicht zum Laufen bringen, also habe ich es einfach manuell gemacht (unter Bezugnahme aufdas Beispiel intexdoc xetexund einPostvom Autor von ucharclasses, und mit 255 geändert in 4095, wie erwähnt in zum Beispieldiese Antwort):

\documentclass{article}
\usepackage{fontspec}
\usepackage{polyglossia}

\newfontfamily\kannadafont{Noto Serif Kannada}[Script=Kannada]
\newfontfamily\englishfont{Georgia}
\setdefaultlanguage{kannada}
\setotherlanguage{english}

\XeTeXinterchartokenstate = 1   % Enable the character classes functionality

\newXeTeXintercharclass \CharEnglish
\XeTeXcharclass `R = \CharEnglish

\XeTeXinterchartoks 0 \CharEnglish = {\selectlanguage{english}}
\XeTeXinterchartoks 4095 \CharEnglish = {\selectlanguage{english}}
\XeTeXinterchartoks \CharEnglish 0 = {\selectlanguage{kannada}}
\XeTeXinterchartoks \CharEnglish 4095 = {\selectlanguage{kannada}}

\begin{document}

R ಶ್ರೀವತ್ಸ \quad Rಶ್ರೀವತ್ಸ

\end{document}

RDadurch wird die Sprache jedes Mal geändert, wenn wir zwischen einem englischen Zeichen (nur oben) und entweder einer Wortgrenze (4095) oder einem regulären (nicht als englisches Zeichen angegeben) Zeichen (0) wechseln .

Um in meinem Originaldokument alle englischen Zeichen verarbeiten zu können, habe ich eine Schleife geschrieben, die das Äquivalent von

\XeTeXcharclass `R = \CharEnglish

für jeden Groß- und Kleinbuchstaben des Alphabets:

\newcount\tmpchar
\tmpchar = `A
\loop
  \ifnum \tmpchar < `[          % [ comes just after Z
    \XeTeXcharclass \tmpchar = \CharEnglish
    \XeTeXcharclass \lccode \tmpchar = \CharEnglish
    \advance \tmpchar by 1
\repeat

verwandte Informationen