TrueType 글꼴 임베딩 및 서브셋 생성
한눈에 보기
섹션 제목: “한눈에 보기”TrueType 글꼴을 등록한 뒤 이를 사용해 텍스트를 렌더링하면 작성기가 해당 페이스의 서브셋을 임베딩합니다. 이 레시피는 examples/04-text-and-fonts.php와 동일한 콘텐츠 경로를 따르며, 등록된 TrueType(.ttf) 글꼴이 추가되어 있습니다.
composer require nextpdf/core:^3이 버전 제약은 nextpdf/core 패키지와 일치하며, 이 예제는 PHP 8.4에서 실행됩니다. 번들로 제공되는 LiberationSans-Regular.ttf 테스트 픽스처를 사용하므로 이 레시피는 자체 완결적입니다.
개념 개요
섹션 제목: “개념 개요”페이스는 FontRegistry::register($path, $alias)로 등록합니다. 레지스트리는 파일을 파싱해 FontInfo를 반환하며, .ttf 및 .otf 파일에는 TrueTypeParser를 사용합니다. 해당 페이스를 사용하려면 setFont($alias, ...)로 그 별칭을 선택합니다. 이 호출은 사용된 코드포인트도 기록합니다.
서브셋은 save() 시점에 자동으로 실행됩니다. PDF 글꼴 작성기는 사용된 코드포인트를 수집해 FontSubsetter::subset()를 호출하며, Compact Font Format(CFF) 또는 OpenType 페이스에는 CffSubsetter를 호출합니다. 서브셋이 전체 프로그램보다 작은 경우, 작성기는 서브셋을 임베딩하고 BaseFont와 FontName을 여섯 개의 대문자 뒤에 플러스 기호를 붙인 서브셋 태그 형식으로 다시 씁니다. 이것이 ISO 32000-2가 글꼴 서브셋에 대해 요구하는 ABCDEF+FontName 형식입니다. 작성기는 임베딩된 TrueType 프로그램을 글꼴 디스크립터의 FontFile2로 저장합니다(ISO 32000-2).
서브셋 접두사는 PostScript 이름에서 결정론적으로 생성되므로, 결정론적 빌드에서는 안정적인 태그가 생성됩니다. 그렇기 때문에 이 레시피의 재현성 프로필은 structural입니다. structural 프로필은 서브셋 접두사와 트레일러 /ID의 바이트 단위 일치를 단언하는 대신 정규화해 제외합니다.
API 표면
섹션 제목: “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. 등록된 별칭을$family로 전달합니다.- 서브셋은 작성기 내부에서 처리됩니다(
NextPDF\Writer\PdfFontWriter->NextPDF\Typography\FontSubsetter). 공개된 켜기/끄기 스위치는 없습니다. 작성기는 코드포인트가 알려져 있고 서브셋이 더 작은 경우 항상 서브셋을 만듭니다.
전체 PHPDoc 표는 소스에서 생성됩니다.
코드 샘플 — 빠른 시작
섹션 제목: “코드 샘플 — 빠른 시작”<?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()은 자체 레지스트리를 구성합니다. 직접 채운 레지스트리를 사용하려면, 프로덕션 샘플에서 보여주듯이 DocumentFactory를 통해 문서를 빌드합니다. 팩토리는 등록된 페이스를 작성기가 읽는 페이스로 전달합니다.
코드 샘플 — 프로덕션
섹션 제목: “코드 샘플 — 프로덕션”이 샘플은 자체 완결적이며 하니스에서 실행할 수 있습니다. 번들로 제공되는 LiberationSans-Regular.ttf를 등록하고 DocumentFactory를 통해 렌더링하므로, 채워 둔 레지스트리가 실제 사용되는 레지스트리가 되며, 저장 시점에 수행되는 자동 서브셋에 의존합니다.
<?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";예상 STDOUT:
Wrote embed-and-subset-fonts.pdf서브셋을 확인하려면 출력 파일을 열고 글꼴 딕셔너리를 살펴봅니다. BaseFont는 <TAG>+LiberationSans로 표시되며, 디스크립터에는 FontFile2가 포함됩니다. qpdf --check를 실행하면 구조적 오류가 보고되지 않습니다.
엣지 케이스 및 주의사항
섹션 제목: “엣지 케이스 및 주의사항”- 레지스트리 소유권.
Document::createStandalone()은 자체 레지스트리를 빌드합니다. 별도의FontRegistry에 등록한 글꼴은 이 문서에서는 보이지 않습니다. 프로덕션 샘플처럼DocumentFactory를 사용하여 레지스트리를 전달합니다. - 임베딩 권리. 서브셋을 만들어도 라이선스는 변경되지 않습니다. 임베딩 라이선스를 보유한 글꼴만 임베딩하십시오. 일부 글꼴은 임베딩 제한 비트를 설정합니다. 파서는 해당 비트를 읽지만, 규정 준수 책임은 여전히 사용자에게 있습니다.
- CFF/OpenType 경로.
.otf및 CFF 페이스는CffSubsetter가 서브셋을 수행하며,FontSubsetter는 사용하지 않습니다. 동작과 서브셋 태그 재작성은 동일하며, 코드 경로만 다릅니다. - 크기 이점 없음. 서브셋이 원본보다 작지 않을 때가 있으며, 이는 매우 작은 글꼴이거나 모든 글리프가 사용될 때 발생합니다. 이 경우 작성기는 서브셋 태그 없이 원본 프로그램을 임베딩합니다. 이는 실패가 아니라 올바른 동작입니다.
- CJK 글꼴. 대용량 중국어, 일본어, 한국어(CJK) 페이스는 ADR-008에 따라 격리된 하위 프로세스와 PHP 네이티브 폴백을 사용하는 계층형 서브셋 전략을 사용합니다. CJK 세부 사항과 현재 파이프라인 상태는 cmap 인식 인코딩으로 CJK 텍스트 설정을 참조하십시오.
파싱은 글꼴 테이블을 한 번 순회하며, 서브셋 비용은 글리프 수에 따라 증가합니다. 비 CJK 라틴 페이스는 wall_ms: 1500, peak_mb: 96 예산 내에서 프로세스 내에서 서브셋됩니다. 대용량 CJK 페이스는 2초 월클럭 시간 제한과 PHP 네이티브 폴백을 갖춘 격리된 하위 프로세스로 라우팅됩니다(ADR-008). 이러한 라우팅은 느리거나 크래시가 발생하는 서브셋 작업이 호출자를 차단할 수 없음을 의미합니다.
보안 참고사항
섹션 제목: “보안 참고사항”글꼴 파일은 신뢰할 수 없는 바이너리 입력입니다. 파서는 스트림 래퍼 경로와 널 바이트를 거부합니다. CJK 서브셋 하위 프로세스는 상속된 데이터베이스 연결, 파일 핸들 또는 프레임워크 상태 없이 실행되며, 크래시나 시간 초과가 발생하면 안전하게 폴백합니다(ADR-008). 최종 사용자로부터 받은 글꼴의 출처를 검증하십시오.
적합성
섹션 제목: “적합성”| 진술 | 사양 | 조항 | reference_id (참조 ID) |
|---|---|---|---|
| 글꼴 서브셋의 BaseFont/FontName은 여섯 개의 대문자 뒤에 플러스 기호가 붙은 서브셋 접두사를 가집니다. | ISO 32000-2 | iso32000_2_sec9#x1.x66.p2 조항 | |
| 임베딩된 TrueType 글꼴 프로그램은 글꼴 디스크립터에 FontFile2로 저장됩니다. | ISO 32000-2 | iso32000_2_sec9#x1.x65.p15 조항 |
이 레시피는 NextPDF가 TrueType 페이스를 임베딩하고 서브셋하여 규격에 맞는 서브셋 접두사를 생성하는 방법을 보여줍니다. 이 레시피는 글꼴 라이선스 준수를 보장하지 않으며, 임베딩 권리는 통합 담당자에게 있습니다.
상업적 맥락
섹션 제목: “상업적 맥락”해당 없음.