Anzeigen von Text mit Uniscribe

Ihre Anwendungen können Uniscribe-API-Funktionen verwenden, um Typografie sowie die Anzeige und Bearbeitung von internationalem Text zu unterstützen. Uniscribe verwendet den Absatz als Einheit für die Textanzeige, und die Uniscribe-Funktionalität muss für den gesamten Absatz verwendet werden.

Wenn Sie Uniscribe zur Anzeige von Text verwenden, muss eine Anwendung einen Formatierungsprozess („Layoutprozess“) durchlaufen, für den in der Regel Uniscribe verwendet wird. Die Anwendung teilt einen Textabsatz in Zeichenfolgen mit derselben Formatierung auf. Diese werden als „Runs“ bezeichnet. Das Format wird durch die jeweilige Implementierung bestimmt, enthält aber in der Regel Attribute wie Schriftart, Schriftgrad und Farbe. Beim Definieren von Runs kann die Anwendung auch andere Informationen anwenden, z. B. Sprach- und Gebietsschemadaten zur Verwendung mit lexikalischen Tools. Eine Anwendung kann beispielsweise einen Abschnitt in einem in erster Linie englischen Text, der in französischer Sprache gerendert wird, als separaten Run behandeln.

Nachdem sie die Runs für alle Absätze bestimmt hat, teilt die Anwendung jeden Absatz in Zeichenfolgen mit demselben Skript und derselben Richtung („Elemente“) auf. Die Anwendung wendet die Elementinformationen an, um Runs zu erzeugen, die in Skript und Richtung eindeutig sind und vollständig in ein einzelnes Element fallen („Bereiche“).

Die Aufschlüsselung eines Elements in Bereiche ist etwas willkürlich, obwohl ein Bereich aus einer oder mehreren aufeinanderfolgenden skriptdefinierten, unteilbaren Zeichengruppierungen bestehen sollte, die als „Cluster“ bezeichnet werden. Bei europäischen Sprachen entspricht ein Cluster in der Regel einem einzelnen Codepagezeichen oder Unicode-Codepunkt und besteht aus einer einzelnen Glyphe. In Sprachen wie Thai ist ein Cluster dagegen eine Gruppierung von Glyphen und entspricht mehreren aufeinanderfolgenden Zeichen oder Codepunkten. Ein thailändischer Cluster kann beispielsweise einen Konsonanten, einen Vokal und ein Tonzeichen enthalten. Damit Cluster nicht aufgeteilt werden, sollte die Anwendung in der Regel entweder die längsten Bereiche verwenden, die sie nutzen kann, oder eigene lexikalischen Informationen verwenden, um zwischen Bereichen an Stellen zu unterteilen, die sich nicht in der Mitte eines Clusters befinden.

Wenn sie die Cluster in jedem Bereich identifiziert hat, muss die Anwendung die Größe jedes Clusters bestimmen. Sie verwendet Uniscribe, um die Cluster zu addieren und so die Größe jedes Bereichs zu bestimmen. Anschließend summiert die Anwendung die Größen der Bereiche, bis es in einer Zeile zu einem Überlauf kommt, d. h. der Rand erreicht wird. Der Bereich, der in der Zeile zum Überlauf führt, wird zwischen der aktuellen und der nächsten Zeile aufgeteilt. Die Anwendung erstellt für jede Zeile eine Zuordnung zwischen visueller und logischer Position für jeden Bereich. Anschließend gestaltet die Anwendung die Codepunkte für jeden Bereich in Glyphen um, die anschließend positioniert und gerendert werden können.

Eine Anwendung führt den Layoutprozess für den Texts nur einmal aus. Anschließend speichert sie entweder die Glyphen und Positionen zu Anzeigezwecken oder generiert sie jedes Mal neu, wenn sie den Text anzeigt, was entweder auf Kosten der Geschwindigkeit oder des Speichers geht. Eine typische Anwendung implementiert den Layoutprozess einmal und generiert dann bei jeder Anzeige des Texts die Glyphen und Positionen.

Eine Anwendung, die komplexe Skripts verwendet, steht bei einem einfachen Ansatz zum Layout und Anzeigen vor folgenden Problemen.

  • Die Breite eines komplexen Skriptzeichens hängt vom Kontext ab. Es ist nicht möglich, die Breite in einfachen Tabellen zu speichern.
  • Das Umbrechen zwischen Wörtern in Skripts wie Thai erfordert eine Wörterbuchunterstützung. So wird beispielsweise zwischen thailändischen Wörtern kein Trennzeichen verwendet.
  • Arabisch, Hebräisch, Persisch, Urdu und andere bidirektionale Textsprachen erfordern vor der Anzeige eine Neuanordnung.
  • Für die einfachere Verwendung komplexer Skripts ist häufig eine Form der Schriftartzuordnung erforderlich.

Die Tatsache, dass Uniscribe den Absatz als Anzeigeeinheit verwendet, hilft der Anwendung, mit diesen komplexen Skriptproblemen angemessen umzugehen.

Hinweis

Uniscribe muss für einen ganzen Absatz verwendet werden, auch wenn Abschnitte des Absatzes keine komplexen Skripts sind.

 

Wie in der folgenden Tabelle dargestellt, unterstützt Uniscribe in der Version 1.6 oder höher mehrere Funktionen, die OpenType-Tags nutzen. Sie können durch die entsprechenden regulären Uniscribe-Funktionen ersetzt werden. Im Allgemeinen sollten Ihre Anwendungen vollständig mit Funktionen aus dem einen oder anderen Satz arbeiten und nicht versuchen, Funktionen zu „kombinieren“.

Reguläre Uniscribe-Funktion Entsprechende OpenType-Funktion
ScriptItemize ScriptItemizeOpenType
ScriptShape ScriptShapeOpenType
ScriptPlace ScriptPlaceOpenType

 

Text mit Uniscribe anordnen

Ihre Anwendung kann die folgenden Schritte verwenden, um einen Textabsatz mit Uniscribe anzuordnen. Bei diesem Vorgehen wird davon ausgegangen, dass die Anwendung den Absatz bereits in Runs unterteilt hat.

  1. Rufen Sie ScriptRecordDigitSubstitution nur beim Starten oder Empfangen einer WM_SETTINGCHANGE-Nachricht auf.

  2. (Optional) Rufen Sie ScriptIsComplex auf, um festzustellen, ob der Absatz eine komplexe Verarbeitung erfordert.

  3. (Optional) Wenn Sie Uniscribe zum Behandeln bidirektionaler Text- und/oder Ziffernersetzung verwenden, rufen Sie ScriptApplyDigitSubstitution auf, um die SCRIPT_CONTROL- und SCRIPT_STATE-Strukturen als Eingaben für ScriptItemize vorzubereiten. Wenn Sie diesen Schritt überspringen, aber dennoch eine Ziffernersetzung erfordern, ersetzen Sie nationale Ziffern für Unicode U+0030 bis U+0039 (europäische Ziffern). Informationen zur Ziffernersetzung finden Sie unter Digit Shapes.

  4. Rufen Sie ScriptItemize auf, um den Absatz in Elemente aufzuteilen. Wenn Sie Uniscribe für die Ziffernersetzung nicht verwenden und Ihnen die bidirektionale Reihenfolge bekannt ist, z. B. aufgrund des Tastaturlayouts, das zum Eingeben des Zeichens verwendet wird, rufen Sie ScriptItemize auf. Geben Sie im Aufruf Nullzeiger für die SCRIPT_CONTROL- und die SCRIPT_STATE-Struktur an. Diese Technik generiert Elemente nur mithilfe des Shaping-Moduls, und die Elemente können mithilfe der Modulinformationen neu angeordnet werden.

    Hinweis

    In der Regel sollten Anwendungen, die nur mit Links-nach-rechts-Skripts und ohne Ziffernersetzung arbeiten, für die SCRIPT_CONTROL- und die SCRIPT_STATE-Struktur Nullzeiger übergeben.

     

  5. Führen Sie die Elementinformationen mit den Run-Informationen zusammen, um Bereiche zu erzeugen.

  6. Rufen Sie ScriptShape auf, um Cluster zu identifizieren und Glyphen zu generieren.

  7. Wenn ScriptShape den Code „USP_E_SCRIPT_NOT_IN_FONT“ oder „S_OK“ mit einer Ausgabe zurückgibt, die fehlende Glyphen enthält, wählen Sie Zeichen aus einer anderen Schriftart aus. Ersetzen Sie entweder eine andere Schriftart, oder deaktivieren Sie das Shaping, indem Sie das eScript-Member der SCRIPT_ANALYSIS-Struktur, das an ScriptShape übergeben wird, auf „SCRIPT_UNDEFINED“ festlegen. Weitere Informationen finden Sie unter Verwenden des Schriftarten-Fallbacks.

  8. Rufen Sie ScriptPlace auf, um erweiterte Breiten und X- und Y-Positionen für die Glyphen in jedem nachfolgenden Bereich zu generieren. Dies ist der erste Schritt, in dem die Textgröße Berücksichtigung findet.

  9. Summieren Sie die Bereichsgrößen, bis die Zeile überläuft.

  10. Brechen Sie den Bereich an einer Wortgrenze um, indem Sie die Member fSoftBreak und fWhiteSpace in den logischen Attributen verwenden. Um einen einzelnen Zeichencluster aus dem Run umzubrechen, verwenden Sie die Informationen, die durch Aufrufen von ScriptBreak zurückgegeben werden.

    Hinweis

    Entscheiden Sie, ob der erste Codepunkt eines Bereichs ein Wortumbruchspunkt sein soll, da er für das letzte Zeichen des vorherigen Bereichs erforderlich ist. Wenn beispielsweise ein Bereich mit einem Komma endet, sollten Sie das erste Zeichen des nächsten Bereichs als Wortumbruchspunkt betrachten.

     

  11. Wiederholen Sie die Schritte 6 bis 10 für jede Zeile im Absatz. Wenn der letzte Run jedoch in der Zeile umgebrochen wird, rufen Sie ScriptShape auf, um den verbleibenden Teil des Runs als ersten Run der nächsten Zeile neu zu gestalten.

Anzeigen von Text mit Uniscribe

Ihre Anwendung kann die folgenden Schritte verwenden, um einen Textabsatz anzuzeigen. Bei diesem Verfahren wird davon ausgegangen, dass die Anwendung den Text bereits angeordnet und die Glyphen und Positionen nicht aus dem Layoutprozess gespeichert hat. Wenn Geschwindigkeit Priorität hat, kann die Anwendung die Glyphen und Positionen aus dem Layoutverfahren speichern und mit Schritt 2 im Anzeigeverfahren beginnen.

Hinweis

Die Anwendung kann Schritt 2 überspringen, wenn der Text keine Zeichen aus Rechts-nach-links-Skripts und keine bidirektionalen Steuerzeichen enthält und eine Links-nach-rechts-Basiseinbettungsebene verwendet.

 

  1. Gehen Sie für jeden Run folgendermaßen vor:

    1. Wenn sich das Format seit dem letzten Run geändert hat, aktualisieren Sie das Handle auf den Gerätekontext, indem Sie es freigeben und erneut abrufen.
    2. Rufen Sie ScriptShape auf, um Glyphen für den Run zu generieren.
    3. Rufen Sie ScriptPlace auf, um eine erweiterte Breite und einen X,Y-Offset für jede Glyphe zu generieren.
  2. Führen Sie die folgenden Schritte aus, um die richtige visuelle Reihenfolge für die Runs in der Zeile festzulegen:

    1. Extrahieren Sie ein Array bidirektionaler Einbettungsebenen pro Bereich. Die Einbettungsebene wird durch (SCRIPT_ITEM) si.(SCRIPT_ANALYSIS) a. (SCRIPT_STATE) s.uBidiLevel angegeben.
    2. Übergeben Sie dieses Array an ScriptLayout, um eine Zuordnung visueller Positionen zu logischen Positionen zu generieren.
  3. (Optional) Um den Text im Blocksatz auszurichten, rufen Sie entweder ScriptJustify auf, oder verwenden Sie spezielle Kenntnisse des Texts.

  4. Verwenden Sie die „visuelle zu logische“ Zuordnung, um die Runs in der sichtbaren Reihenfolge anzuzeigen. Rufen Sie beginnend am linken Ende der Zeile scriptTextOut auf, um den Run anzuzeigen, der durch den ersten Eintrag in der Zuordnung angegeben wird. Rufen Sie für jeden nachfolgenden Eintrag in der Zuordnung ScriptTextOut auf, um den angegebenen Run rechts neben dem zuvor angezeigten anzuzeigen.

    Wenn Sie Schritt 2 überspringen, beginnen Sie am linken Ende der Zeile und rufen ScriptTextOut auf, um die erste logische Ausführung und dann jede logische Ausführung rechts neben der vorherigen Ausführung anzuzeigen.

  5. Wiederholen Sie die obigen Schritte für alle Zeilen im Absatz.

Verwenden von Uniscribe