Dokumentation

Schriften

Ohne jede Einrichtung haben Sie die 14 Standard-PDF-Schriften. Bringen Sie eine eigene TrueType-Schrift mit, wenn Sie Ihre Markenschrift oder Zeichen jenseits des lateinischen Alphabets brauchen, und jasy bettet sie ein, macht ein Subset aus den verwendeten Zeichen und komprimiert sie für Sie.

Die Standardschriften

Drei Familien bringt jeder PDF-Reader mit, jasy bettet für sie also nichts ein. Wählen Sie eine mit font; der Standard ist Helvetica. bold und italic wählen die passende fette oder kursive Variante.

Text("Helvetica is the default");
Text("A serif heading", { font: "Times-Roman", bold: true });
Text("Monospaced code", { font: "Courier" });

Die Familien heißen Helvetica, Times-Roman und Courier. Sie decken lateinischen Text ab (Windows-1252), einschließlich Euro-Zeichen und Buchstaben mit Akzenten.

Eine eigene Schrift einbetten

Registrieren Sie eine Schrift mit addFont(name, source) am Dokument und verwenden Sie den Namen dann als font an jedem Text. Die Quelle ist ein Pfad (jasy liest ihn in Node), die rohen Bytes oder eine Familie mit einem Eintrag pro Variante - und das Dateiformat spielt keine Rolle: .ttf, .woff und .woff2 sind beim Aufruf dasselbe.

import { writeFileSync } from "node:fs";
import { Document, Page, Column, Text, renderToBytes } from "@jasy/pdf";

async function build() {
  const doc = Document([
    Page({ size: "A4", margin: 56 }, [
      Column({ gap: 10 }, [
        Text("Set in Inter", { font: "Inter", size: 22 }),
        Text("Full Unicode too: Привет, Γειά, čeština", { font: "Inter" }),
      ]),
    ]),
  ]);

  doc.addFont("Inter", "Inter-Regular.ttf"); // a path - jasy reads it

  writeFileSync("typed.pdf", await renderToBytes(doc));
}

build();

Der Name ist das, was Sie an Text({ font }) übergeben. Eine eigene Schrift schaltet auch volles Unicode frei (Kyrillisch, Griechisch, erweitertes Latein), das die Standardschriften nicht darstellen können - und weil sie ihre eigenen OpenType-Tabellen mitbringt, bringt sie auch Kerning und lateinische Ligaturen mit (beides standardmäßig an) und macht arabisches Shaping und Unterstreichungen mit skipInk möglich. Siehe Text.

Sie haben die Bytes schon (etwa aus einem Upload im Browser)? Übergeben Sie sie statt eines Pfads:

import { readFileSync } from "node:fs";
doc.addFont("Inter", readFileSync("Inter-Regular.ttf"));

Von einer URL

addFontFromUrl lädt die Schrift für Sie - die eine Form, die auch im Browser funktioniert, wo es kein Dateisystem gibt, auf das man zeigen könnte. Sie wird bei der Registrierung aufgelöst, genau wie addFont einen Pfad sofort liest, ein toter Link scheitert also in der Zeile, die die Schrift angefordert hat, und nicht erst in einem späteren Rendervorgang.

await doc.addFontFromUrl("Inter", "https://example.com/Inter-Regular.woff2");

// a whole family in one call - the files are fetched in parallel
await doc.addFontFromUrl("Inter", {
  normal: "https://example.com/Inter-Regular.woff2",
  bold: "https://example.com/Inter-Bold.woff2",
});

Abgesichert ist das wie jeder andere Netzwerkzugriff: 15 Sekunden Timeout, eine Obergrenze von 32 MB, geprüft, während die Daten ankommen, und jeder Fehler als FontUrlError, der sagt, was die Datei wirklich war - eine HTML-Seite mit 404 wird als solche gemeldet, nicht als kaputte Schrifttabelle.

In einem Bundler liefert import url from "./Inter.woff2?url" genau die URL, die hier gebraucht wird. Das ist alles, was es im Browser braucht: ein Import und eine Zeile.

Die Registrierung verwalten

Das Dokument besitzt seine Schriften, Sie können es also fragen, was registriert ist - und abmelden müssen Sie nie:

doc.getFonts(); // ["Inter"]  - the registered names
doc.hasFont("Inter"); // true
doc.addFont("Inter", "..."); // re-adding a name overwrites it

Eine Schrift, die Sie registrieren, aber an keinem Text verwenden, fällt beim Rendern weg und kostet nichts. Registrieren Sie großzügig; eingebettet werden nur die Varianten, die Sie tatsächlich verwenden.

Fett, kursiv und eine ganze Familie

Registrieren Sie die Varianten einer Familie unter einem Namen, und jasy wählt für bold / italic die richtige. Ein angeforderter Stil, den Sie nicht registriert haben, fällt sauber auf die normale Variante der Familie zurück.

doc.addFont("Inter", {
  normal: "Inter-Regular.ttf",
  bold: "Inter-Bold.ttf",
  italic: "Inter-Italic.ttf",
  boldItalic: "Inter-BoldItalic.ttf",
});
Text("Bold Inter", { font: "Inter", bold: true });
Text("Italic Inter", { font: "Inter", italic: true });

Nur normal ist Pflicht; ergänzen Sie bold / italic / boldItalic, soweit Sie sie haben, jeweils als Pfad oder Bytes.

Was jasy für Sie erledigt

  • Subsetting - eingebettet werden nur die Glyphs, die Sie verwenden (eine Schrift mit 740 KB schrumpft auf einige zehn KB).
  • Kompression - das eingebettete Programm wird mit FlateDecode komprimiert.
  • Kopieren und Suchen - mit der Schrift kommt eine ToUnicode-Tabelle, der Text bleibt im Reader also markierbar und durchsuchbar.

Welche Dateien jasy liest

FormatUnterstützt
.ttf (TrueType, und OpenType mit TrueType-Umrissen)ja
.woffja - wird für Sie entpackt
.woff2ja - wird für Sie entpackt
.otf mit CFF-Umrissennoch nicht, und das wird ausdrücklich gemeldet

Ein WOFF ist dieselbe Schrift hinter einem kleinen Wrapper; ein WOFF2 ist mehr als das - es komprimiert die glyf-Tabelle nicht nur, es schreibt sie um und verteilt die Punkte auf fünf getrennte Streams. jasy entpackt beides selbst. Die einzige Abhängigkeit auf diesem Weg ist ein Brotli-Decoder, und der wird nur geladen, wenn tatsächlich ein WOFF2 auftaucht, ein Dokument ohne eines zahlt also nie dafür.

Die Rekonstruktion ist gegen die Quelle geprüft, nicht angenommen: Alle 6.253 Glyph-Outlines einer echten Schrift kommen identisch zurück, und die gerenderte Seite ist Pixel für Pixel dieselbe wie die aus ihrer .ttf.