
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 xelatex
ergibt:
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 lualatex
für die obige Datei:
(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 xetex
statt 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}
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üchernfontspec
und dokumentiertpolyglossia
. 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
R
mü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-view
das mit einer Schriftart und einer Textzeichenfolge aufgerufen werden kann. Damit erhalte ich die folgende Ausgabe:
hb-view NotoSansKannada-Regular.ttf "ಶ್ರೀ"
und mit--script=knda
:hb-view NotoSansKannada-Regular.ttf " ಶ್ರೀ"
und mit--script=knda
:hb-view NotoSansKannada-Regular.ttf "Rಶ್ರೀ"
und mit--script=knda
hb-view NotoSansKannada-Regular.ttf "R ಶ್ರೀ"
und mit--script=knda
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 demucharclasses
Paket.
Ich konnte es aus irgendeinem Grund nicht zum Laufen bringen, also habe ich es einfach manuell gemacht (unter Bezugnahme aufdas Beispiel intexdoc xetex
und 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}
R
Dadurch 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