Hinweis
Zum Ende, um den vollständigen Beispielcode herunterzuladen.
Schriften in Matplotlib#
Matplotlib benötigt Schriften für seine Text-Engine, von denen einige mit der Installation mitgeliefert werden. Die Standardschrift ist DejaVu Sans, die die meisten europäischen Schriftsysteme abdeckt. Benutzer können jedoch die Standardschriften konfigurieren und eigene benutzerdefinierte Schriften bereitstellen. Weitere Details finden Sie unter Anpassen von Texteigenschaften und insbesondere unter Text mit Nicht-Lateinischen Glyphen für Glyphen, die von DejaVu Sans nicht unterstützt werden.
Matplotlib bietet auch die Option, die Textdarstellung an eine TeX-Engine auszulagern (usetex=True). Siehe Textdarstellung mit LaTeX.
Schriften in PDF und PostScript#
Schriften haben eine lange (und manchmal inkompatible) Geschichte in der Informatik, was dazu führt, dass verschiedene Plattformen unterschiedliche Schrifttypen unterstützen. In der Praxis unterstützt Matplotlib drei Schrifttypen (zusätzlich zu den PDF-"Core Fonts", die später im Handbuch erläutert werden).
Typ 1 (PDF) |
Typ 3 (PDF/PS) |
TrueType (PDF) |
|---|---|---|
Einer der ältesten Typen, eingeführt von Adobe |
Ähnlich wie Typ 1 in Bezug auf die Einführung |
Neuer als die vorherigen Typen, heute gebräuchlich, eingeführt von Apple |
Eingeschränkter Teilmengen von PostScript, Zeichenkodierungen sind im Bytecode |
Vollständige PostScript-Sprache, erlaubt das Einbetten von beliebigem Code (theoretisch sogar das Rendern von Fraktalen beim Rasterisieren!) |
Enthalten eine virtuelle Maschine, die Code ausführen kann! |
Diese Schriften unterstützen Schrifthinweise (Font Hinting) |
Unterstützen keine Schrifthinweise |
Hinweise unterstützt (virtuelle Maschine verarbeitet die "Hinweise") |
Nicht teilsubsettisiert über Matplotlib |
Teilsubsettisiert über das externe Modul ttconv |
Teilsubsettisiert über das externe Modul fontTools |
Hinweis
Adobe hat die Unterstützung für die Erstellung mit Type 1-Schriften im Januar 2023 eingestellt.
Weitere Schrifttypen, die Matplotlib unterstützt
Typ 42-Schriften (PS)
PostScript-Wrapper um TrueType-Schriften
42 ist die Antwort auf das Leben, das Universum und alles!
Matplotlib verwendet die externe Bibliothek fontTools, um diese Schrifttypen teilsubsettisiert zu verwenden.
OpenType-Schriften
OpenType ist ein neuer Standard für digitale Schriftarten, der gemeinsam von Adobe und Microsoft entwickelt wurde
Enthalten im Allgemeinen einen viel größeren Zeichensatz!
Begrenzte Unterstützung in Matplotlib
Schriften-Subsetting#
Die Formate PDF und PostScript unterstützen das Einbetten von Schriften in Dateien, wodurch das Anzeigeprogramm den Text korrekt rendern kann, unabhängig davon, welche Schriften auf dem Computer des Betrachters installiert sind, und ohne dass der Text vorab gerastert werden muss. Dies stellt sicher, dass der Text beim Zoomen oder Ändern der Größe der Ausgabe nicht pixelig wird. Das Einbetten vollständiger Schriften kann jedoch zu großen Ausgabedateien führen, insbesondere bei Schriften mit vielen Glyphen, wie z. B. solchen, die CJK (Chinesisch/Japanisch/Koreanisch) unterstützen.
Die Lösung für dieses Problem ist das Subsetting der im Dokument verwendeten Schriften und das Einbetten nur der tatsächlich verwendeten Glyphen. Dies ermöglicht sowohl Vektortext als auch kleine Dateigrößen. Die Berechnung des benötigten Unterteils der Schriftart und das Schreiben der neuen (reduzierten) Schriftart sind beides komplexe Probleme, und daher stützt sich Matplotlib auf fontTools und einen mitgelieferten Fork von ttconv.
Derzeit werden Typ 3-, Typ 42- und TrueType-Schriften teilsubsettisiert. Type 1-Schriften werden nicht teilsubsettisiert.
Kernschriften#
Zusätzlich zur Möglichkeit, Schriften einzubetten, gibt es im Rahmen der PostScript- und PDF-Spezifikation 14 Kernschriften, die konforme Betrachter verfügbar haben müssen. Wenn Sie Ihr Dokument auf nur diese Schriften beschränken, müssen Sie keine Schriftinformationen in das Dokument einbetten, erhalten aber dennoch Vektortext.
Dies ist besonders hilfreich, um *wirklich leichte* Dokumente zu erstellen.
# trigger core fonts for PDF backend
plt.rcParams["pdf.use14corefonts"] = True
# trigger core fonts for PS backend
plt.rcParams["ps.useafm"] = True
chars = "AFM ftw!"
fig, ax = plt.subplots()
ax.text(0.5, 0.5, chars)
fig.savefig("AFM_PDF.pdf", format="pdf")
fig.savefig("AFM_PS.ps", format="ps")
Schriften in SVG#
Text kann auf zwei Arten in SVG ausgegeben werden, gesteuert durch rcParams["svg.fonttype"] (Standard: 'path')
als Pfad (
'path') in der SVGals Zeichenkette in der SVG mit Schriftstilen auf dem Element (
'none')
Beim Speichern über 'path' berechnet Matplotlib den Pfad der verwendeten Glyphen als Vektorpfade und schreibt diese in die Ausgabe. Der Vorteil dabei ist, dass die SVG auf allen Computern gleich aussieht, unabhängig von den installierten Schriften. Der Text ist jedoch nachträglich nicht mehr bearbeitbar. Im Gegensatz dazu führt das Speichern mit 'none' zu kleineren Dateien und der Text erscheint direkt im Markup. Das Erscheinungsbild kann jedoch je nach SVG-Betrachter und verfügbaren Schriften variieren.
Schriften in Agg#
Um Text über Agg in Rasterformate auszugeben, stützt sich Matplotlib auf FreeType. Da die genaue Darstellung der Glyphen zwischen den FreeType-Versionen variiert, fixieren wir eine bestimmte Version für unsere Bildvergleichstests.
Wie Matplotlib Schriften auswählt#
Intern ist die Verwendung einer Schrift in Matplotlib ein dreistufiger Prozess:
ein
FontProperties-Objekt wird erstellt (explizit oder implizit)basierend auf dem
FontProperties-Objekt werden die Methoden aufFontManagerverwendet, um die nächstgelegene "beste" Schrift auszuwählen, die Matplotlib bekannt ist (außer im Modus'none'für SVG).der Python-Proxy für das Schriftobjekt wird vom Backend-Code zur Darstellung des Textes verwendet – die genauen Details hängen vom Backend über
font_manager.get_fontab.
Der Algorithmus zur Auswahl der "besten" Schrift ist eine modifizierte Version des Algorithmus, der in den CSS1-Spezifikationen definiert ist und von Webbrowsern verwendet wird. Dieser Algorithmus berücksichtigt den Schriftfamiliennamen (z. B. "Arial", "Noto Sans CJK", "Hack", ...), die Größe, den Stil und die Stärke. Zusätzlich zu den Schriftfamiliennamen, die direkt auf Schriften abgebildet werden, gibt es fünf "generische Schriftfamiliennamen" (serif, monospace, fantasy, cursive und sans-serif), die intern auf eine beliebige Schrift aus einer Gruppe von Schriften abgebildet werden.
Derzeit ist die öffentliche API für Schritt 2 FontManager.findfont (und diese Methode auf der globalen FontManager-Instanz ist auf Modulebene als font_manager.findfont aliased), die nur eine einzelne Schrift findet und den absoluten Pfad zur Schrift auf dem Dateisystem zurückgibt.
Schrift-Fallback#
Es gibt keine Schrift, die den gesamten Unicode-Bereich abdeckt, daher ist es möglich, dass Benutzer eine Mischung von Glyphen benötigen, die nicht von einer einzigen Schriftart erfüllt werden können. Obwohl es möglich war, mehrere Schriftarten innerhalb einer Figur auf separaten Text-Instanzen zu verwenden, war es bisher nicht möglich, mehrere Schriftarten in derselben Text-Instanz zu verwenden (wie es ein Webbrowser tut). Ab Matplotlib 3.6 "fallbacken" die Backends Agg, SVG, PDF und PS über mehrere Schriftarten in einer einzigen Text-Instanz.
fig, ax = plt.subplots()
ax.text(
.5, .5, "There are 几个汉字 in between!",
family=['DejaVu Sans', 'Noto Sans CJK JP', 'Noto Sans TC'],
ha='center'
)
Die Zeichenkette "There are 几个汉字 in between!" gerendert mit 2 Schriftarten.
Intern wird dies implementiert, indem die "Schriftfamilie" auf FontProperties-Objekten auf eine Liste von Schriftfamilien gesetzt wird. Eine (derzeit) private API extrahiert eine Liste von Pfaden zu allen gefundenen Schriften und erstellt dann ein einzelnes ft2font.FT2Font-Objekt, das über alle Schriften informiert ist. Jede Glyphe der Zeichenkette wird mit der ersten Schrift in der Liste gerendert, die diese Glyphe enthält.
Ein Großteil dieser Arbeit wurde von Aitik Gupta im Rahmen des Google Summer of Code 2021 geleistet.