Kuonen.PDFTools Prüfstand 1.1436.0 · M1436
↓ Download
↓ Notes (PDF)
↓ Roadmap (PDF)
♫ Noten-Editor

Mathematischer Formelsatz

Formel eintippen, PDF sofort sehen. Die Eingabe ist eine benannte LaTeX-Teilmenge — was nicht dazugehört, steht im Bericht darunter und wird übersprungen; der Rest der Formel wird trotzdem gesetzt.
Formel
Unterstützt: Gruppen, ^/_, \frac, \sqrt (auch mit Wurzelexponent), \left\right, \sum/\prod/\int, Akzente (\hat, \vec, \widehat …), \overline/\underline, die Matrix-Umgebungen, griechische Buchstaben und rund 90 benannte Zeichen.
Zum Ausprobieren
  • Die Formel traegt ihre LaTeX-Quelle als /ActualText — sie ist kein Text, ihre Glyphen sind teilweise Bauteile ohne Codepunkt.
  • Mathe-Schrift: TeX Gyre Termes Math (GUST Font License). Die Bibliothek liefert keine Schrift mit; der Aufrufer stellt sie bereit.
Berichte zu diesem Lauf
Formel — nicht gesetzte Eingabe Kuonen.PDFTools.Formula.FormulaReport ohne Befund

Die unterstuetzte LaTeX-Teilmenge ist eng und benannt. Was nicht dazugehoert, wird uebersprungen und hier gemeldet — die uebrige Formel wird trotzdem gesetzt, statt die ganze Eingabe abzulehnen.

Bericht leer — die Eingabe wurde vollstaendig verstanden.

Quelltext — ausgeschnitten aus der eingebetteten Beispieldatei, nicht abgetippt
using Kuonen.PDFTools.Authoring;
using Kuonen.PDFTools.Formula;
using Kuonen.PDFTools.Pages;

// Eine Schrift MIT MATH-Tabelle ist Voraussetzung. Die Bibliothek liefert
// keine mit (lizenziert) — hier etwa TeX Gyre Termes Math.
byte[] mathFont = File.ReadAllBytes("texgyretermes-math.otf");

var options = new FormulaOptions(
    mathFont,
    SizePt: 22,
    Display: true);

MathFormula formel = MathFormula.Compose(
    "\\sum_{i=1}^{n} \\left( \\frac{x_i - \\bar{x}}{\\sigma} \\right)^2 \\leq \\sqrt[3]{\\alpha}", options);

var builder = new PdfDocumentBuilder { Title = "Formelsatz" };
PageCanvas page = builder.AddPage(PageSize.A4);

// (x, y) ist die GRUNDLINIE, nicht die Unterkante — ein Bruch ragt darunter.
page.DrawFormula(formel, 56, 640);

// Hoehe und Tiefe stehen VOR dem Zeichnen bereit — daraus baut man den Kasten.
FormulaMetrics m = formel.Metrics;   // Width / Height / Depth / TotalHeight

byte[] pdf = builder.Build();
FormulaReport report = formel.Report;   // unbekannte Befehle stehen hier
Gebaut und verifiziert

Stufe 1 — die OpenType-MATH-Tabelle lesen (Protokoll 92, öffentlich in Kuonen.PDFTools.Fonts). Aus einer Mathe-Schrift werden die rund fünfzig Konstanten, die Kursivkorrektur, die Größenvarianten und das Glyph-Assembly gelesen — byte-genau gegen fontTools geprüft.

Stufe 2 — das Satzmodell (Protokoll 128): Box-Modell mit Höhe und Tiefe, Atomtypen und Abstandsmatrix, Indizes/Exponenten und Brüche — jede Position aus den MATH-Konstanten, Stelle für Stelle von Hand gegen fontTools gerechnet (etwa : der Exponent sitzt exakt auf SuperscriptShiftUp, verschoben um die Kursivkorrektur). Das ist heute intern (Namensraum Formula) — nach dem Vorbild des CSS-Bausteins wird es öffentlich, wenn ein Konsument es braucht.

Stufe 3 — Wurzeln, mitwachsende Klammern, große Operatoren (Protokoll 162). Eine Klammer wächst auf ihren Inhalt: erst über die fertigen Größenvarianten der Schrift, und reicht keine, aus Bauteilen (Fuß, Mittelstück, Kopf) mit der vorgeschriebenen Überlappung. Der Wurzelhaken hängt an seiner Oberkante am Überstrich, Klammern sitzen auf der Achse statt auf der Grundlinie, und das Summenzeichen wächst im Display-Stil auf DisplayOperatorMinHeight und trägt seine Grenzen darüber und darunter. Neun Prüfungen, jede von Hand aus den fontTools-Werten gerechnet; das gerenderte PDF von pypdfium2 bestätigt.

Stufe 4 — Akzente, Ueber-/Unterstriche und Matrizen (Protokoll 163). Ein Akzent richtet sich nach dem TopAccentAttachment-Punkt, den die Schrift für Grundzeichen und Akzent angibt — wer statt dessen mittig zentriert, setzt das Dach über einem geneigten f sichtbar zu weit links; über einem hohen Grundzeichen fährt er mit, gedeckelt auf AccentBaseHeight, und auf Wunsch wächst er in der Breite mit. Matrizen sind das einzige, wofür zwei Maße nicht aus der Schrift stammen können: die MATH-Tabelle sagt zu ihnen nichts, Spalten- und Zeilenabstand sind deshalb benannte TeX-Konventionen im Geviert.

Stufe 5 — LaTeX als Eingabe (Protokoll 164). Eine benannte Teilmenge: Gruppen, ^/_, \frac, \sqrt (auch mit Wurzelexponent), \left…\right, die großen Operatoren, Akzente, \overline/\underline, die Matrix-Umgebungen, die griechischen Buchstaben und rund 90 benannte Zeichen. Was nicht dazugehört, wird gemeldet — nie still verschluckt, und der Rest der Formel wird trotzdem gesetzt. Kein Makro-System, keine Textbefehle, keine Ausrichtungsumgebungen.

Stufe 6 — die öffentliche Fassade

(Protokoll 165.) MathFormula.Compose liest und setzt, PageCanvas.DrawFormula zeichnet, FormulaFrame und FlowDocument.Formula setzen sie in den Fließtext. Die Maße (Metrics) stehen vor dem Zeichnen bereit — Höhe und Tiefe getrennt, denn ein Bruch ragt unter die Grundlinie.

Der Knackpunkt war das Zeichnen selbst. Der Setzer liefert rohe Glyph-IDs — die gedehnten Klammern und ihre Bauteile stammen aus MathVariants und haben gar keinen Codepunkt, während der Zeichenweg Glyphen sonst über Text auflöst. Gelöst über ein Segment für rohe IDs samt der Abbildung Original→Subset, die im selben Durchlauf entsteht wie die eingebettete Schrift: getrennt gerechnet könnte sie »umnummeriert« sagen, während die Bytes das Original sind — und dann stünden lautlos die falschen Zeichen auf dem Blatt.

Eine Formel ist kein Text. Deshalb trägt sie ihre LaTeX-Quelle als /ActualText und wird als /Formula ausgezeichnet — sonst wäre sie beim Kopieren und für Screenreader stumm.

Die Mathe-Schrift

Voraussetzung bleibt eine Schrift mit MATH-Tabelle. Die Bibliothek liefert keine mit (Zero-NuGet, lizenziert); die stellt der Aufrufer bereit. Diese Seite benutzt TeX Gyre Termes Math aus dem Werkzeugprojekt (GUST Font License = LPPL 1.3c). Ebenfalls frei lizenziert und geeignet: Latin Modern Math (GUST) oder STIX Two Math (SIL OFL).