콘텐츠로 이동

사용자 지정 글꼴: FontRegistry 확장 계약

FontRegistryInterface는 글꼴 등록과 조회를 위한, 프로세스 수명 동안 유지되는 계약입니다. 파일 경로, 디렉터리 또는 원시 바이너리 데이터에서 글꼴을 등록한 다음, 레지스트리를 잠가 프로덕션 워커가 이를 변경할 수 없도록 합니다.

Terminal window
composer require nextpdf/core:^3

글꼴 레지스트리는 개별 Document 인스턴스보다 생명 주기가 긴 싱글턴입니다. 리소스 핸들이나 확장 객체는 보유하지 않고 순수한 PHP 데이터만 보유합니다. 따라서 장기 실행 워커에서 여러 요청에 걸쳐 안전하게 공유할 수 있습니다.

이 계약은 세 가지 등록 경로를 지원합니다.

  • 파일에서. register().ttf, .otf, .ttc 또는 .pfb 파일을 구문 분석하고 분석된 메타데이터를 반환합니다. TrueType Collection의 경우 하위 글꼴 인덱스를 전달합니다.
  • 디렉터리에서. addFontDirectory()는 엔진이 이름으로 패밀리를 확인할 때 스캔할 검색 경로를 추가합니다.
  • 바이너리 데이터에서. registerFromBinary()는 원시 TrueType 또는 OpenType 바이트를 구문 분석합니다. 이 경로는 @font-face 브리지가 data: URI 또는 원격 소스에서 가져온 글꼴에 사용합니다.

첫 요청에 몰리는 지연 시간을 줄이려면 워커 부팅 시 warmup()을 호출하여 글꼴 배치를 미리 구문 분석합니다. 그런 다음 lock()을 호출합니다. lock() 이후에는 모든 변경 메서드가 LogicException을 발생시킵니다. 여기에는 register(), addFontDirectory(), warmup(), registerBase14()registerFromBinary()가 포함됩니다. 조회 메서드인 get(), has(), all()getSearchDirectories()는 계속 사용할 수 있습니다. 이 잠금은 프로덕션 안전 메커니즘이며, 어떤 요청도 공유 글꼴 집합을 변경할 수 없도록 보장합니다.

대부분의 경우 FontRegistryInterface를 직접 구현하지 않습니다. 엔진이 구현을 제공하므로 그 구현을 호출하면 됩니다. 예를 들어 콘텐츠 주소 지정 저장소를 기반으로 하는 사용자 지정 글꼴 해석 전략이 필요한 경우에는 직접 구현합니다. 어느 경우든 이 계약이 경계를 정의합니다.

NextPDF\Contracts\FontRegistryInterface (stable, 1.7.0 이후):

메서드반환값용도
register(string $fontFile, string $alias, int $fontIndex)FontInfo글꼴 파일을 구문 분석해 등록합니다. 레지스트리가 잠겨 있거나 파일을 구문 분석할 수 없는 경우 예외를 발생시킵니다.
registerFromBinary(string $fontData, string $alias)FontInfo원시 TrueType 또는 OpenType 바이트에서 글꼴을 등록합니다.
registerBase14(string $key, FontInfo $font)void미리 빌드된 Base 14 표준 글꼴을 등록합니다.
addFontDirectory(string $directory)void글꼴 검색 디렉터리를 추가합니다.
warmup(array $fontFiles)void워커 부팅 시 글꼴 배치를 미리 구문 분석합니다.
lock()void추가 변경을 막기 위해 레지스트리를 동결합니다.
isLocked()bool레지스트리가 잠겨 있는지 여부를 보고합니다.
get(string $family, string $style)FontInfo | null패밀리와 스타일로 글꼴을 조회합니다.
has(string $key)bool등록 키가 존재하는지 확인합니다.
all()array<string, FontInfo>등록된 모든 글꼴을 반환합니다.
getSearchDirectories()list<string>검색 디렉터리를 순서대로 반환합니다.
memoryUsage()MemoryReport현재 레지스트리 메모리 사용량을 보고합니다.
<?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');
}

이 워커 부팅 루틴은 글꼴 집합을 미리 준비하고, 레지스트리를 잠그며, 라이선스 추적을 위해 각 로드를 관찰합니다. 여기서 사용하는 모든 타입은 공개 API입니다.

<?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);
}
}
  • 잠긴 레지스트리. lock() 이후의 모든 변경은 LogicException을 발생시킵니다. 재사용되는 워커에서 조건부 워밍을 수행하기 전에 항상 isLocked()를 확인합니다.
  • 바이너리 등록은 키로 캐시되지 않습니다. registerFromBinary()는 임시 파일에 기록한 다음 이를 구문 분석합니다. 반환된 FontInfo를 핸들로 취급합니다.
  • TTC 인덱스. TrueType Collection의 경우, register()의 세 번째 인수가 하위 글꼴을 선택합니다. 기본값 0은 첫 번째 페이스를 선택합니다.
  • 패밀리 해석. get()은 알 수 없는 패밀리-스타일 쌍에 대해 null을 반환합니다. 결과가 non-null이라고 절대 가정하지 마십시오.

warmup()은 구문 분석 비용을 첫 요청에서 부팅 시점으로 이동시킵니다. 레지스트리 메서드는 순수 PHP 데이터에 대해 작동합니다. 조회는 상수 시간의 맵 읽기입니다. 메모리 예산에 맞춰 워커의 상주 글꼴 집합 크기를 산정하려면 memoryUsage()를 호출합니다.

등록된 글꼴은 PDF에 임베드할 수 있는 콘텐츠가 됩니다. 등록하기 전에 글꼴의 출처를 검증합니다. 크기 및 형식 검사 없이 공격자가 제어하는 바이너리 데이터를 등록하지 마십시오. FontLoadedEvent 후크는 글꼴 라이선스 준수를 강제하고 문서가 임베드하는 페이스를 기록하기 위해 제공되는 지점입니다.

서명 또는 아카이브 관련 규범적 주장은 적용되지 않습니다. 글꼴 임베딩 및 서브셋 처리는 PDF 2.0 글꼴 모델을 준수합니다. 해당 적합성은 이 계약이 아니라 내부 서브셋터가 담당합니다.

NextPDF Enterprise는 동일한 FontRegistryInterface 위에 글꼴 라이선스 증명과 감사된 서브셋 정책을 계층화합니다. 계약이 경계를 정의하므로 등록 코드는 에디션 전반에 걸쳐 변경되지 않습니다.

용어집은 font registry, image registryevent listener를 정의합니다. 각 표준화된 정의는 게시된 용어집을 참조하십시오.