콘텐츠로 이동

글꼴: 값 타입, 임베딩, 대체

NextPDF에서 글꼴은 불변 FontInfo 값 객체와 엔진이 이를 임베딩하는 방식을 결정하는 기술 타입으로 구성됩니다. 엔진이 사용하는 모든 글꼴은 임베딩됩니다. 레거시 Base 14 참조는 번들로 제공되는 메트릭 호환 대체 글꼴로 폴백 처리됩니다.

Terminal window
composer require nextpdf/core:^3

FontInfo는 엔진이 글꼴을 임베딩하는 데 필요한 모든 정보를 담는 단일 불변 값 객체입니다. 여기에는 패밀리와 스타일, PostScript 이름, 디스크립터 플래그, 1000 단위 em으로 스케일된 메트릭, 문자 너비, 글리프-유니코드 맵, 정방향 cmap(유니코드에서 글리프 식별자로), 원시 글꼴 바이트가 포함되며, 있는 경우 베리에이션 축, 명명된 인스턴스, 베리에이션 셀렉터, 커닝 쌍, 세로 메트릭도 함께 담습니다. 이 객체는 final readonly입니다. 생성자 시그니처와 public 속성은 고정되어 있으므로, 파싱된 글꼴 정보는 안정적으로 공유할 수 있는 사실 값입니다. 실제 작업을 수행하는 유일한 메서드는 FontInfo::encodeText()입니다. 이 메서드는 인코딩 리졸버를 거쳐 EncodedGlyphRun을 반환합니다.

FontType은 엔진이 임베딩에 사용할 기술을 열거합니다. 값은 TrueType(단일 바이트 인코딩), TrueTypeUnicode(유니코드 범위가 넓은 스크립트를 위한 다중 바이트 CID 인코딩), OpenType(Compact Font Format 아웃라인), Type1(PostScript Type 1, PFB와 AFM 쌍에서 등록됨), CidFont0(PostScript 기반 CID 글꼴)입니다. 파서가 할당한 타입에 따라 라이터가 출력하는 글꼴 딕셔너리의 형태가 결정됩니다.

엔진은 글꼴 프로그램을 임베딩하므로 설치된 시스템 글꼴과 관계없이 어떤 뷰어에서도 문서가 동일하게 렌더링됩니다 — ISO 32000-2 §9. TrueType 프로그램은 FontFile2 글꼴 디스크립터 항목을 통해 임베딩되며, glyf, head, hhea, hmtx, loca, maxp 테이블을 포함해야 합니다 — ISO 32000-2 §9.6.5(RAG 다이제스트는 라이선스 상한 때문에 잘렸으며 _downgraded-claims-o3.md에 기록되어 있습니다). Compact Font Format 아웃라인 테이블을 가진 OpenType 프로그램은 FontFile3을 통해 임베딩됩니다 — ISO 32000-2 §9.6.5(RAG 다이제스트가 잘렸습니다. 동일한 로그를 참조하십시오). 서브셋터는 이 필수 테이블 집합을 정확히 재구성하므로 임베딩된 서브셋은 적합한 프로그램으로 유지됩니다.

폴백은 레거시 Base 14 사례를 처리합니다. Base14SubstituteFonts는 정규화된 Base 14 키(helvetica, helveticab, times, courier 등)를 번들로 제공되는 Liberation Fonts 파일에 매핑합니다. Liberation Sans, Serif, Mono는 각각 Helvetica 또는 Arial, Times Roman, Courier와 메트릭 호환됩니다. 각각은 임베딩된 TrueType 페이스이므로, standard-14 참조가 요구하는 전체 WinAnsiEncoding(Windows-1252) 라틴 레퍼토리, 즉 악센트가 있는 라틴 문자, 유로 기호, 일반적인 조판 문장 부호를 렌더링합니다(ISO 32000-2 Annex D.2). SymbolZapfDingbats에는 허용 라이선스의 메트릭 호환 대체 글꼴이 없으므로 의도적으로 대체되지 않습니다. 이를 필요로 하는 문서는 임베딩 가능한 글꼴을 등록해야 합니다. 리졸버는 부작용이 없습니다 — 키가 어떤 파일에 매핑되는지만 알려 주며, 다른 작업은 수행하지 않습니다. 레지스트리 등록은 계속 호출자의 책임이므로 잠금 시맨틱과 워밍업 파이프라인이 보존됩니다.

타입종류주요 멤버안정성도입 버전
FontInfofinal readonly 클래스$family, $style, $type, $unitsPerEm, $widths, $unicodeMap, $cmapForward, $fileData, $variationAxes, $kernPairs, getKey(), encodeText()stable (안정)1.0.0
FontTypeenum (string)TrueType, TrueTypeUnicode, OpenType, Type1, CidFont0stable (안정)1.0.0
Base14SubstituteFontsfinal 클래스 (내부)정규화된 Base 14 키에서 번들 Liberation 파일 경로로 매핑stable (안정)2.7.0
ShaperFactoryfinal 클래스default(), create(), wouldUseRealShaper()stable (안정)3.2.0
ShapingResultfinal readonly 클래스$glyphRuns, $originalText, $script, $direction, $shaperImplstable (안정)3.2.0

Base14SubstituteFonts@internal입니다 — 프레임워크 내부 전용이며, 이 API 표면에 대한 하위 호환성은 보장되지 않습니다.

examples/35-cjk-cmap-demo.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Typography\FontRegistry;
use NextPDF\Typography\FontType;
$registry = new FontRegistry();
$font = $registry->register('/path/to/NotoSansTC-Regular.ttf', alias: 'NotoSansTC');
// FontInfo is the immutable parsed fact about the face.
echo $font->family, ' / ', $font->type->value, "\n"; // e.g. "Noto Sans TC / TrueTypeUnicode"
assert($font->type === FontType::TrueTypeUnicode);

파서는 FontInfo를 채우고 FontType을 할당합니다. 유니코드 cmap을 가진 TrueType 페이스는 TrueTypeUnicode가 되며, 라이터는 이를 Type 0 합성 글꼴로 출력합니다.

examples/font/base14-fallback.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Typography\Base14SubstituteFonts;
use NextPDF\Typography\FontRegistry;
final readonly class Base14EmbeddingResolver
{
public function __construct(private FontRegistry $registry) {}
/**
* Register an embeddable substitute for a legacy Base 14 key so the
* output document embeds every font (PDF/A-4 and PDF/UA-2 require it).
*/
public function ensureEmbeddable(string $base14Key): void
{
$path = Base14SubstituteFonts::resolve($base14Key);
if ($path === null) {
// Symbol / ZapfDingbats have no permissive substitute — the
// caller must supply its own embeddable font.
throw new \RuntimeException("No bundled substitute for {$base14Key}");
}
if (!$this->registry->has($base14Key)) {
$this->registry->register($path, alias: $base14Key);
}
}
}

리졸버에는 부작용이 없습니다. 등록은 명시적으로 수행되므로 레지스트리의 잠금 및 워밍업 계약이 지켜집니다. SymbolZapfDingbats는 의도적으로 경로를 반환하지 않습니다.

  • SymbolZapfDingbats는 의도적으로 대체되지 않습니다. 해당 키에 대한 null 결과는 누락된 글꼴 버그가 아니라 문서화된 동작입니다.
  • FontInfofinal readonly입니다. 파싱된 글꼴은 값으로 취급하십시오. 너비나 메트릭을 그 자리에서 변경할 수 있다고 기대하지 마십시오. 소스가 변경되면 다시 등록하십시오.
  • Type 1 글꼴에는 PFB 아웃라인과 AFM 메트릭이 모두 필요합니다. FontRegistry::registerType1()은 이 쌍을 받습니다. 자동 검색은 PFB 경로의 확장자를 바탕으로 AFM 경로를 도출합니다.
  • FontType::TrueTypeFontType::TrueTypeUnicode의 차이는 단일 바이트와 다중 바이트 구분입니다. 인코딩 리졸버는 패밀리 이름이 아니라 채워진 정방향 cmap을 기준으로 동작하므로, 유니코드 TrueType 페이스는 자동으로 Identity-H 경로로 라우팅됩니다.
  • 베리에이션 글꼴 축과 명명된 인스턴스는 있으면 FontInfo로 파싱되지만, 작성된 CJK 예제는 파싱된 FontInfo를 결정론적으로 유지하기 위해 의도적으로 정적 페이스를 사용합니다.

FontInfo는 레지스트리에 의해 프로세스당 글꼴별로 한 번 할당되며, 이후에는 참조로 공유됩니다. 이 객체는 원시 글꼴 바이트를 담고 있고, 이것이 메모리 비용의 대부분을 차지합니다. 워커는 필요한 글꼴만 워밍업하고 memoryUsage()를 추적해야 합니다. Base 14 대체 리졸버는 상수 시간 맵 조회이며, 호출자가 결정된 파일을 등록하기 전까지는 I/O가 없습니다. 벽시계 시간 1500 ms와 피크 64 MB의 performance_budget은 일반적인 글꼴 세트 워밍업과 렌더링을 포함합니다. 글꼴별 메모리 사용량은 서브셋터가 실행되기 전까지 글리프 수가 아니라 글꼴 파일 크기에 비례합니다.

FontInfo 자체는 비활성입니다 — 순수한 encodeText() 변환을 제외하면 어떤 동작도 없는 파싱된 데이터입니다. 공격 표면은 상류, 즉 파싱 시점에 있습니다. 임의의 글꼴 바이트가 TrueType 또는 Type 1 파서에 도달하는 지점입니다. 파서는 모든 바이너리 오프셋을 경계 검사하고, 경로 안의 스트림 래퍼와 null 바이트를 거부합니다. 신뢰할 수 없는 글꼴 입력은 등록 전에 크기와 글리프 수를 제한하는 외부 리소스 정책을 통과해야 합니다. 번들로 제공되는 Liberation 대체 글꼴은 패키지와 함께 배포되는 신뢰할 수 있는 자산이므로, 폴백 경로는 신뢰할 수 없는 새로운 입력을 도입하지 않습니다.

주장표준조항근거
문서가 사용하는 모든 글꼴이 임베딩되므로 문서는 시스템 글꼴에 의존하지 않고 렌더링됩니다.ISO 32000-2§9
TrueType 프로그램은 FontFile2를 통해 glyf, head, hhea, hmtx, loca, maxp 테이블과 함께 임베딩됩니다.ISO 32000-2§9.6.5RAG 다이제스트가 라이선스 상한으로 잘림. 접두사 7b26f37996239b2a, 참조: _downgraded-claims-o3.md
OpenType(CFF) 프로그램은 FontFile3을 통해 임베딩됩니다.ISO 32000-2§9.6.5RAG 다이제스트가 라이선스 상한으로 잘림. 접두사 801549ee00623baf, 참조: _downgraded-claims-o3.md

첫 번째 조항은 다이제스트로 고정되어 있으며 B1로 입증됩니다. FontFile2 및 FontFile3 조항은 의역되었습니다. 전체 RAG 다이제스트는 반환되지 않았으며(라이선스 상한 때문에 잘림), FontSubsetter(glyf/head/hhea/hmtx/loca/maxp 집합을 정확히 재구성함)와 FontType enum으로 입증됩니다. NextPDF는 규범 텍스트를 재현하지 않습니다. Base14SubstituteFonts는 소스에서 ISO 32000-2 §9.6.2.2(표준 Type 1 글꼴 처리), ISO 14289-2:2024 §8.4.5.5.1(PDF/UA-2 글꼴 임베딩), ISO 19005-4:2020 §6.3.5(PDF/A-4 글꼴 임베딩)을 인용합니다. 접근성 및 적합성 페이지에 전체 프로필 적합성이 수록되어 있습니다.

상업용 글꼴 라이선싱 팩과 동적 서브셋 서비스는 Core FontInfo와 레지스트리 위에 구축됩니다. Core 글꼴 모듈은 라이선스 없이 임베딩, 서브셋, 폴백을 수행합니다. 전환 링크를 생략한 것은 의도적입니다.