Osadzanie czcionki TrueType i tworzenie jej podzbioru
W skrócie
Dział zatytułowany „W skrócie”Zarejestruj czcionkę TrueType, renderuj nią tekst i pozwól zapisującemu osadzić tylko potrzebny podzbiór. Ten przepis korzysta z tego samego przepływu tworzenia treści co examples/04-text-and-fonts.php, uzupełnionego o zarejestrowaną czcionkę TrueType (.ttf).
Instalacja
Dział zatytułowany „Instalacja”composer require nextpdf/core:^3Ta deklaracja zależności instaluje pakiet nextpdf/core. Przykład działa na PHP 8.4, a dołączony testowy plik LiberationSans-Regular.ttf sprawia, że przepis jest samowystarczalny.
Przegląd koncepcyjny
Dział zatytułowany „Przegląd koncepcyjny”Zarejestruj krój za pomocą FontRegistry::register($path, $alias). Rejestr analizuje plik i zwraca FontInfo, używając TrueTypeParser dla plików .ttf i .otf. Aby aktywować krój, wybierz jego alias za pomocą setFont($alias, ...). To wywołanie rejestruje także użyte punkty kodowe.
Tworzenie podzbioru jest uruchamiane automatycznie podczas save(). Zapisujący czcionki w PDF zbiera użyte punkty kodowe i wywołuje FontSubsetter::subset() albo CffSubsetter w przypadku krojów Compact Font Format (CFF) lub OpenType. Gdy podzbiór jest mniejszy niż pełny program, zapisujący osadza podzbiór. Przepisuje także BaseFont i FontName, dodając sześcioliterowy znacznik podzbioru zapisany wielkimi literami i połączony znakiem plus. Powstaje forma ABCDEF+FontName, której ISO 32000-2 wymaga dla podzbioru czcionki. Zapisujący przechowuje osadzony program TrueType jako FontFile2 w deskryptorze czcionki (ISO 32000-2).
Prefiks podzbioru jest generowany deterministycznie na podstawie nazwy PostScript, więc deterministyczna kompilacja tworzy stabilny znacznik. Dlatego profil odtwarzalności tego przepisu to structural. Profil structural normalizuje prefiks podzbioru oraz /ID ze zwiastuna, zamiast weryfikować je bajt po bajcie.
Powierzchnia API
Dział zatytułowany „Powierzchnia API”FontRegistry::register(string $fontFile, string $alias = '', int $fontIndex = 0): FontInfo—NextPDF\Typography\FontRegistry.setFont(string $family, string $style = '', float $size = 12.0): static—NextPDF\Core\Concerns\HasTypography; przekaż zarejestrowany alias jako$family.- Tworzenie podzbioru odbywa się wewnątrz zapisującego (
NextPDF\Writer\PdfFontWriter->NextPDF\Typography\FontSubsetter). Nie ma publicznego przełącznika do jego włączania ani wyłączania: zapisujący zawsze tworzy podzbiór, gdy punkty kodowe są znane, a podzbiór jest mniejszy.
Pełna tabela PHPDoc jest generowana ze źródła.
Przykład kodu — szybki start
Dział zatytułowany „Przykład kodu — szybki start”<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;use NextPDF\Typography\FontRegistry;
$registry = new FontRegistry();$registry->register(__DIR__ . '/MyFont-Regular.ttf', alias: 'MyFont');
$doc = Document::createStandalone();$doc->addPage();$doc->setFont('MyFont', '', 14);$doc->cell(0, 10, 'Rendered with an embedded, subset TrueType face.', newLine: true);
$doc->save(__DIR__ . '/out.pdf');Document::createStandalone() tworzy własny rejestr. Aby użyć samodzielnie wypełnionego rejestru, zbuduj dokument za pomocą DocumentFactory, jak pokazano w przykładzie produkcyjnym. Dzięki fabryce zapisujący odczytuje wcześniej zarejestrowany krój.
Przykład kodu — produkcja
Dział zatytułowany „Przykład kodu — produkcja”Ten przykład jest samowystarczalny i nadaje się do uruchomienia w środowisku testowym. Rejestruje dołączoną LiberationSans-Regular.ttf i renderuje dokument przez DocumentFactory, dzięki czemu używany jest wypełniony rejestr. Opiera się na automatycznym tworzeniu podzbioru przy zapisie.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\DocumentFactory;use NextPDF\Graphics\ImageRegistry;use NextPDF\Typography\FontRegistry;
// A bundled TrueType test fixture keeps this recipe self-contained.// Replace with a font you have the right to embed.$fontPath = __DIR__ . '/../../fonts/test-fixtures/LiberationSans/LiberationSans-Regular.ttf';if (!is_file($fontPath)) { // Fall back to the repository-relative fixture location. $fontPath = dirname(__DIR__, 2) . '/fonts/test-fixtures/LiberationSans/LiberationSans-Regular.ttf';}
$fontRegistry = new FontRegistry();$fontRegistry->register($fontPath, alias: 'LiberationSans');
$imageRegistry = new ImageRegistry(maxCacheBytes: 0);$documentFactory = new DocumentFactory($fontRegistry, $imageRegistry);
$doc = $documentFactory->create();$doc->setTitle('Embedded Subset Font');$doc->addPage();
$doc->setFont('LiberationSans', '', 20);$doc->cell(0, 14, 'Embedded TrueType face', newLine: true);
$doc->setFont('LiberationSans', '', 12);$doc->multiCell(0, 7, 'Only the glyphs used by this document are embedded. ' . 'The writer subsets the font program and rewrites the BaseFont with a ' . 'deterministic six-letter subset prefix, for example ABCDEF+LiberationSans.');
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');$doc->save($out !== false ? $out : __DIR__ . '/embed-and-subset-fonts.pdf');
echo "Wrote embed-and-subset-fonts.pdf\n";Oczekiwane STDOUT:
Wrote embed-and-subset-fonts.pdfAby potwierdzić podzbiór, otwórz wynik i sprawdź słownik czcionki. Wpis BaseFont ma wartość <TAG>+LiberationSans, a deskryptor zawiera FontFile2. Polecenie qpdf --check nie zgłasza błędów strukturalnych.
Przypadki brzegowe i pułapki
Dział zatytułowany „Przypadki brzegowe i pułapki”- Własność rejestru.
Document::createStandalone()tworzy własny rejestr. Czcionka zarejestrowana w osobnymFontRegistrynie będzie w nim widoczna. UżyjDocumentFactory, aby przekazać swój rejestr, jak w przykładzie produkcyjnym. - Prawa do osadzania. Tworzenie podzbioru nie zmienia licencjonowania. Osadzaj tylko czcionki, do których osadzania masz licencję. Niektóre czcionki ustawiają bity ograniczeń osadzania; analizator odczytuje te bity, ale odpowiedzialność za zgodność pozostaje po stronie integratora.
- Ścieżka CFF/OpenType. Dla krojów
.otfi CFF podzbiór tworzyCffSubsetter, a nieFontSubsetter. Zachowanie oraz przepisanie znacznika podzbioru są równoważne. Różni się tylko ścieżka kodu. - Brak zysku na rozmiarze. Czasami podzbiór nie jest mniejszy niż oryginał. Może się to zdarzyć w przypadku bardzo małych czcionek lub gdy użyto wszystkich glifów. W takim przypadku zapisujący osadza oryginalny program bez znacznika podzbioru. Jest to poprawne, a nie błąd.
- Czcionki CJK. Duże kroje chińskie, japońskie i koreańskie (CJK) korzystają z warstwowej strategii tworzenia podzbioru zgodnie z ADR-008, z izolowanym podprocesem i natywnym dla PHP rozwiązaniem awaryjnym. Zobacz Składanie tekstu CJK z kodowaniem uwzględniającym cmap, aby poznać szczegóły dotyczące CJK i bieżący stan potoku.
Wydajność
Dział zatytułowany „Wydajność”Analiza wymaga jednego przejścia przez tabele czcionki, a koszt tworzenia podzbioru rośnie wraz z liczbą glifów. Dla łacińskich krojów spoza CJK podzbiór powstaje w bieżącym procesie w ramach budżetu wall_ms: 1500, peak_mb: 96. Duże kroje CJK są kierowane do izolowanego podprocesu z dwusekundowym limitem czasu rzeczywistego i natywnym dla PHP rozwiązaniem awaryjnym (ADR-008). Dzięki temu powolne lub kończące się awarią tworzenie podzbioru nie może zablokować wywołującego.
Uwagi dotyczące bezpieczeństwa
Dział zatytułowany „Uwagi dotyczące bezpieczeństwa”Plik czcionki to niezaufane dane binarne. Analizator odrzuca ścieżki ze stream wrapperami oraz bajty zerowe. Podproces tworzenia podzbioru CJK działa bez odziedziczonych połączeń z bazą danych, uchwytów plików ani stanu frameworka. W razie awarii lub przekroczenia limitu czasu mechanizm bezpiecznie przełącza się na rozwiązanie awaryjne (ADR-008). Weryfikuj pochodzenie czcionek przyjmowanych od użytkowników końcowych.
Zgodność
Dział zatytułowany „Zgodność”| Stwierdzenie | Specyfikacja | Klauzula | reference_id |
|---|---|---|---|
| BaseFont/FontName podzbioru czcionki zawiera sześcioliterowy prefiks podzbioru zapisany wielkimi literami i połączony znakiem plus. | ISO 32000-2 | iso32000_2_sec9#x1.x66.p2 | |
| Osadzony program czcionki TrueType jest przechowywany jako FontFile2 w deskryptorze czcionki. | ISO 32000-2 | iso32000_2_sec9#x1.x65.p15 |
Ten przepis pokazuje, jak NextPDF osadza krój TrueType, tworzy jego podzbiór i emituje zgodny prefiks podzbioru. Nie potwierdza zgodności z licencją czcionki. Za prawa do osadzania odpowiada integrator.
Kontekst komercyjny
Dział zatytułowany „Kontekst komercyjny”Nie dotyczy.