Przejdź do głównej zawartości

Czcionki niestandardowe: kontrakt rozszerzenia FontRegistry

FontRegistryInterface definiuje kontrakt obowiązujący przez czas życia procesu, służący do rejestrowania i wyszukiwania czcionek. Rejestruj czcionki ze ścieżki do pliku, z katalogu albo z surowych danych binarnych, a następnie zablokuj rejestr, aby procesy robocze w środowisku produkcyjnym nie mogły go modyfikować.

Okno terminala
composer require nextpdf/core:^3

Rejestr czcionek to singleton istniejący dłużej niż każda instancja Document. Przechowuje wyłącznie czyste dane PHP, bez uchwytów do zasobów ani obiektów rozszerzeń, dzięki czemu można go współdzielić między żądaniami w długo działającym procesie roboczym.

Skorzystaj z jednej z trzech ścieżek rejestracji:

  • Z pliku. register() analizuje plik .ttf, .otf, .ttc lub .pfb i zwraca metadane. Dla kolekcji TrueType Collection przekaż indeks podczcionki.
  • Z katalogu. addFontDirectory() dodaje ścieżkę wyszukiwania; silnik przeszukuje ją podczas rozpoznawania rodziny czcionek po nazwie.
  • Z danych binarnych. registerFromBinary() analizuje surowe bajty TrueType lub OpenType. Użyj tej ścieżki w przypadku mostka @font-face, gdy czcionki pochodzą z identyfikatora Uniform Resource Identifier (URI) data: albo ze źródła zdalnego.

Aby zmniejszyć opóźnienie przy pierwszym żądaniu, wywołaj warmup() podczas uruchamiania procesu roboczego i wstępnie przeanalizuj partię czcionek. Następnie wywołaj lock(). Po wywołaniu lock() każda metoda modyfikująca zgłasza LogicException: register(), addFontDirectory(), warmup(), registerBase14() oraz registerFromBinary(). Metody wyszukiwania pozostają dostępne: get(), has(), all() oraz getSearchDirectories(). Ta blokada chroni procesy robocze w środowisku produkcyjnym, gwarantując, że żadne żądanie nie może zmienić współdzielonego zestawu czcionek.

Zazwyczaj nie trzeba implementować FontRegistryInterface. Silnik dostarcza implementację, z której korzysta kod rozszerzenia. Implementuj interfejs tylko wtedy, gdy potrzebna jest niestandardowa strategia rozpoznawania czcionek, na przykład oparta na magazynie adresowanym treścią. W obu przypadkach granicą pozostaje kontrakt.

NextPDF\Contracts\FontRegistryInterface (stabilny, od wersji 1.7.0):

MetodaZwracaPrzeznaczenie
register(string $fontFile, string $alias, int $fontIndex)FontInfoAnalizuje i rejestruje plik czcionki. Zgłasza wyjątek, gdy rejestr jest zablokowany albo pliku nie można przeanalizować.
registerFromBinary(string $fontData, string $alias)FontInfoRejestruje czcionkę z surowych bajtów TrueType lub OpenType.
registerBase14(string $key, FontInfo $font)voidRejestruje gotową czcionkę standardową Base 14.
addFontDirectory(string $directory)voidDodaje katalog wyszukiwania czcionek.
warmup(array $fontFiles)voidWstępnie analizuje partię czcionek podczas uruchamiania procesu roboczego.
lock()voidZamraża rejestr, aby zapobiec dalszym modyfikacjom.
isLocked()boolInformuje, czy rejestr jest zablokowany.
get(string $family, string $style)FontInfo | nullWyszukuje czcionkę według rodziny i stylu.
has(string $key)boolSprawdza, czy klucz rejestracji istnieje.
all()array<string, FontInfo>Zwraca wszystkie zarejestrowane czcionki.
getSearchDirectories()list<string>Zwraca katalogi wyszukiwania w kolejności.
memoryUsage()MemoryReportRaportuje bieżące zużycie pamięci przez rejestr.
<?php
declare(strict_types=1);
use NextPDF\Contracts\FontRegistryInterface;
/** @var FontRegistryInterface $fonts */
$info = $fonts->register('/srv/fonts/Inter-Regular.ttf', 'Inter');
if (!$fonts->has('inter')) {
throw new RuntimeException('Inter failed to register');
}

Podczas uruchamiania procesu roboczego wstępnie przygotuj zestaw czcionek, zablokuj rejestr i monitoruj każde ładowanie na potrzeby śledzenia licencji. Ten przykład korzysta wyłącznie z typów publicznych.

<?php
declare(strict_types=1);
use NextPDF\Contracts\FontRegistryInterface;
use NextPDF\Event\Content\FontLoadedEvent;
use NextPDF\Event\EventDispatcher;
use NextPDF\Event\ListenerProvider;
use Psr\Log\LoggerInterface;
final class FontWarmup
{
/** @param list<string> $fontFiles */
public function __construct(
private readonly FontRegistryInterface $fonts,
private readonly LoggerInterface $logger,
private readonly array $fontFiles,
) {}
public function boot(): EventDispatcher
{
$listeners = new ListenerProvider();
$listeners->addListener(
FontLoadedEvent::class,
function (FontLoadedEvent $event): void {
$this->logger->info('font.loaded', [
'family' => $event->family,
'style' => $event->style,
'type' => $event->fontType->name,
]);
},
);
if (!$this->fonts->isLocked()) {
$this->fonts->warmup($this->fontFiles);
$this->fonts->lock();
}
return new EventDispatcher($listeners);
}
}
  • Zablokowany rejestr. Po wywołaniu lock() każda modyfikacja zgłasza LogicException. Sprawdź isLocked() przed warunkowym rozgrzaniem w ponownie używanym procesie roboczym.
  • Rejestracja binarna nie jest buforowana według klucza. registerFromBinary() zapisuje dane do pliku tymczasowego i analizuje go. Użyj zwróconego obiektu FontInfo jako uchwytu.
  • Indeks kolekcji TrueType Collection (TTC). W przypadku kolekcji TrueType Collection trzeci argument metody register() wybiera podczcionkę. Wartość domyślna 0 wybiera pierwszy krój.
  • Rozpoznawanie rodziny czcionek. get() zwraca null dla nieznanej pary rodziny i stylu. Nigdy nie zakładaj, że wynik będzie różny od null.

warmup() przenosi koszt analizy z pierwszego żądania na etap uruchamiania procesu roboczego. Metody rejestru korzystają z czystych danych PHP, a wyszukiwania są odczytami z mapy w stałym czasie. Wywołaj memoryUsage(), aby dopasować rezydentny zestaw czcionek procesu roboczego do budżetu pamięci.

Zarejestrowaną czcionkę można osadzić w treści dokumentu Portable Document Format (PDF). Przed rejestracją sprawdź pochodzenie czcionki. Nie rejestruj danych binarnych kontrolowanych przez atakującego bez sprawdzenia rozmiaru i formatu. Użyj punktu zaczepienia FontLoadedEvent, aby wymuszać zgodność z licencjami czcionek i rejestrować, które kroje osadza dokument.

Nie mają zastosowania żadne deklaracje normatywne dotyczące podpisywania ani archiwizacji. Osadzanie czcionek i tworzenie podzbiorów są zgodne z modelem czcionek PDF 2.0. Za tę zgodność odpowiada wewnętrzny mechanizm tworzenia podzbiorów, a nie ten kontrakt.

NextPDF Enterprise dodaje atestację licencji czcionek oraz audytowaną politykę tworzenia podzbiorów na podstawie tego samego FontRegistryInterface. Kod rejestracji działa tak samo we wszystkich edycjach, ponieważ granicą jest kontrakt.

Słownik definiuje pojęcia rejestr czcionek, rejestr obrazów oraz nasłuchiwacz zdarzeń; kanoniczne definicje znajdują się w opublikowanym słowniku.