Fuentes personalizadas: el contrato de extensión FontRegistry
De un vistazo
Sección titulada «De un vistazo»FontRegistryInterface es un contrato vigente durante todo el ciclo de vida del proceso para registrar y buscar fuentes. Permite registrar fuentes desde una ruta de archivo, un directorio o datos binarios sin procesar y, a continuación, bloquear el registro para que los workers de producción no puedan mutarlo.
Instalación
Sección titulada «Instalación»composer require nextpdf/core:^3Visión conceptual
Sección titulada «Visión conceptual»El registro de fuentes es un singleton que persiste más allá de las instancias individuales de Document. Solo contiene datos PHP puros, sin manejadores de recursos ni objetos de extensión. Eso permite compartirlo con seguridad entre solicitudes en un worker de larga duración.
El contrato admite tres vías de registro:
- Desde un archivo.
register()analiza un archivo.ttf,.otf,.ttco.pfby devuelve los metadatos analizados. En una colección TrueType, se pasa el índice de la subfuente. - Desde un directorio.
addFontDirectory()añade una ruta de búsqueda que el motor explora al resolver una familia por su nombre. - Desde datos binarios.
registerFromBinary()analiza bytes TrueType u OpenType sin procesar. Esta es la vía que utiliza el puente@font-facepara las fuentes obtenidas desde URIdata:o fuentes remotas.
Para repartir la latencia de la primera solicitud, llamar a warmup() durante el arranque del worker permite preanalizar un lote de fuentes. Después, llamar a lock(). Tras lock(), cada método de mutación lanza LogicException. Esos métodos son register(), addFontDirectory(), warmup(), registerBase14() y registerFromBinary(). Los métodos de búsqueda siguen disponibles: get(), has(), all() y getSearchDirectories(). Este bloqueo es el mecanismo de seguridad de producción. Garantiza que ninguna solicitud pueda alterar el conjunto de fuentes compartido.
En la mayoría de los casos no se implementa FontRegistryInterface. El motor proporciona la implementación y el código de extensión la invoca. Sí se implementa cuando se necesita una estrategia de resolución de fuentes personalizada, por ejemplo, una respaldada por un almacén direccionado por contenido. En ambos casos, el contrato es la frontera.
Superficie de la API
Sección titulada «Superficie de la API»NextPDF\Contracts\FontRegistryInterface (estable, desde 1.7.0):
| Método | Devuelve | Propósito |
|---|---|---|
register(string $fontFile, string $alias, int $fontIndex) | FontInfo | Analiza y registra un archivo de fuente. Lanza una excepción si el registro está bloqueado o el archivo no se puede analizar. |
registerFromBinary(string $fontData, string $alias) | FontInfo | Registra una fuente a partir de bytes TrueType u OpenType sin procesar. |
registerBase14(string $key, FontInfo $font) | void | Registra una fuente estándar Base 14 predefinida. |
addFontDirectory(string $directory) | void | Añade un directorio de búsqueda de fuentes. |
warmup(array $fontFiles) | void | Analiza por adelantado un lote de fuentes en el arranque del worker. |
lock() | void | Congela el registro frente a cualquier mutación posterior. |
isLocked() | bool | Indica si el registro está bloqueado. |
get(string $family, string $style) | FontInfo | null | Busca una fuente por familia y estilo. |
has(string $key) | bool | Comprueba si existe una clave de registro. |
all() | array<string, FontInfo> | Devuelve todas las fuentes registradas. |
getSearchDirectories() | list<string> | Devuelve los directorios de búsqueda en orden. |
memoryUsage() | MemoryReport | Informa sobre el uso de memoria actual del registro. |
Ejemplo de código — Inicio rápido
Sección titulada «Ejemplo de código — Inicio rápido»<?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');}Ejemplo de código — Producción
Sección titulada «Ejemplo de código — Producción»Esta rutina de arranque del worker precalienta un conjunto de fuentes, bloquea el registro y observa cada carga para el seguimiento de licencias. Cada tipo que utiliza es público.
<?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); }}Casos límite y trampas
Sección titulada «Casos límite y trampas»- Registro bloqueado. Cualquier mutación posterior a
lock()lanzaLogicException. Comprobar siempreisLocked()antes de un precalentamiento condicional en un worker reciclado. - El registro binario no se almacena en caché por clave.
registerFromBinary()escribe en un archivo temporal y lo analiza. Tratar elFontInfodevuelto como el manejador. - Índice de TTC. Para una colección TrueType, el tercer argumento de
register()selecciona la subfuente. El valor predeterminado0selecciona la primera cara. - Resolución de familia.
get()devuelvenullpara un par de familia y estilo desconocido. No asumir nunca un resultado no nulo.
Rendimiento
Sección titulada «Rendimiento»warmup() traslada el costo del análisis de la primera solicitud al arranque. Los métodos del registro trabajan sobre datos PHP puros. Las búsquedas son lecturas de un mapa en tiempo constante. Llamar a memoryUsage() permite dimensionar el conjunto de fuentes residente de un worker respecto del presupuesto de memoria.
Notas de seguridad
Sección titulada «Notas de seguridad»Una fuente registrada se convierte en contenido PDF incrustable. Validar la procedencia de la fuente antes del registro. No registrar datos binarios controlados por un atacante sin comprobaciones de tamaño y formato. El hook FontLoadedEvent es el punto admitido para hacer cumplir las licencias de fuentes y registrar qué caras incrusta un documento.
Conformidad
Sección titulada «Conformidad»No se aplican afirmaciones normativas de firma ni de archivado. La incrustación y el subconjunto de fuentes se ajustan al modelo de fuentes de PDF 2.0; esa conformidad corresponde al subconjuntador interno, no a este contrato.
Contexto comercial
Sección titulada «Contexto comercial»NextPDF Enterprise añade la atestación de licencias de fuentes y una política de subconjunto auditada sobre la misma FontRegistryInterface. El código de registro no cambia entre ediciones porque el contrato es la frontera.
Consulta también
Sección titulada «Consulta también»- Visión general de la creación de extensiones
- Desencadenadores de acciones y escuchas de eventos
- Diseño personalizado e interceptación de texto
- Reglas de estabilidad de la SPI
Contratos y módulos relacionados
Sección titulada «Contratos y módulos relacionados»- Referencia del módulo de fuentes — la implementación del registro, el análisis y los detalles internos del subconjunto.
- Referencia de los contratos de tipografía — donde se documenta
FontRegistryInterface. - Desencadenadores de acciones y escuchas de eventos —
FontLoadedEventy el despachador. - Diseño personalizado e interceptación de texto — el contrato hermano para estrategias en tiempo de renderizado.
- Reglas de estabilidad de la SPI — la promesa de interfaz que respalda
FontRegistryInterface.
El glosario define registro de fuentes, registro de imágenes y escucha de eventos; consultar el glosario publicado para cada definición canónica.