Bỏ qua để đến nội dung

Phông chữ: kiểu giá trị, nhúng và dự phòng

Trong NextPDF, một phông chữ là đối tượng giá trị bất biến FontInfo cùng với kiểu công nghệ cho engine biết cách nhúng phông chữ đó. Engine nhúng mọi phông chữ mà nó sử dụng. Một tham chiếu Base 14 cũ sẽ được dự phòng bằng phông chữ thay thế đi kèm, tương thích về số đo.

Terminal window
composer require nextpdf/core:^3

FontInfo là đối tượng giá trị bất biến cung cấp cho engine mọi thứ cần thiết để nhúng một phông chữ: họ và kiểu chữ, tên PostScript, các cờ descriptor, số đo được chia tỷ lệ theo em 1.000 đơn vị, chiều rộng ký tự, bản đồ glyph-sang-Unicode, bản đồ ký tự xuôi (cmap, Unicode sang định danh glyph), byte phông chữ thô và, khi có, các trục biến thể, thực thể có tên, bộ chọn biến thể, cặp kern cùng số đo dọc. Nó là final readonly. Chữ ký constructor và các thuộc tính public của nó được cố định, nên một phông chữ đã phân tích cú pháp là một thực thể ổn định, có thể chia sẻ. FontInfo::encodeText() là phương thức duy nhất có hành vi. Nó định tuyến qua bộ phân giải mã hóa và trả về một EncodedGlyphRun.

FontType liệt kê các công nghệ mà engine nhúng: TrueType (mã hóa đơn byte), TrueTypeUnicode (mã hóa định danh ký tự (CID) đa byte cho các hệ chữ viết giàu Unicode), OpenType (đường viền Compact Font Format), Type1 (PostScript Type 1, được đăng ký từ cặp Printer Font Binary (PFB) và Adobe Font Metrics (AFM)) và CidFont0 (một phông chữ CID dựa trên PostScript). Kiểu do bộ phân tích cú pháp gán sẽ quyết định hình dạng của từ điển phông chữ mà bộ ghi phát ra.

Để việc kết xuất không phụ thuộc vào các phông chữ hệ thống đã cài đặt, engine nhúng chương trình phông chữ — ISO 32000-2 §9. Một chương trình TrueType được nhúng thông qua mục font-descriptor FontFile2 và phải bao gồm các bảng glyf, head, hhea, hmtx, locamaxp — ISO 32000-2 §9.6.5 (bản tóm tắt RAG bị cắt do giới hạn giấy phép; ghi lại trong _downgraded-claims-o3.md). Một chương trình OpenType với bảng đường viền Compact Font Format được nhúng thông qua FontFile3 — ISO 32000-2 §9.6.5 (bản tóm tắt RAG bị cắt; xem cùng nhật ký đó). Bộ tạo tập con xây dựng lại đúng tập bảng bắt buộc này, nên tập con được nhúng vẫn là một chương trình tuân thủ.

Phương án dự phòng bao quát trường hợp Base 14 cũ. Base14SubstituteFonts ánh xạ một khóa Base 14 đã chuẩn hóa — helvetica, helveticab, times, courier và phần còn lại — tới một tệp Liberation Fonts đi kèm. Liberation Sans, Serif và Mono tương thích về số đo với Helvetica hoặc Arial, Times Roman và Courier. Mỗi phông chữ là một face TrueType được nhúng, nên nó kết xuất toàn bộ kho ký tự Latinh của WinAnsiEncoding (Windows-1252) mà một tham chiếu standard-14 yêu cầu — Latinh có dấu, ký hiệu Euro và các dấu chấm câu kiểu chữ thông dụng (ISO 32000-2 Annex D.2). SymbolZapfDingbats không có bản thay thế tương thích về số đo với giấy phép thông thoáng, nên NextPDF cố ý không thay thế chúng; tài liệu nào cần một trong hai phông chữ này phải đăng ký một phông chữ có thể nhúng. Bộ phân giải không có tác dụng phụ: nó chỉ cho biết một khóa ánh xạ tới tệp nào. Bên gọi vẫn chịu trách nhiệm đăng ký với registry, giữ nguyên ngữ nghĩa khóa và pipeline khởi động.

KiểuLoạiThành viên chínhĐộ ổn địnhTừ phiên bản
FontInfofinal readonly class$family, $style, $type, $unitsPerEm, $widths, $unicodeMap, $cmapForward, $fileData, $variationAxes, $kernPairs, getKey(), encodeText()ổn định1.0.0
FontTypeenum (string)TrueType, TrueTypeUnicode, OpenType, Type1, CidFont0ổn định1.0.0
Base14SubstituteFontsfinal class (nội bộ)khóa Base 14 đã chuẩn hóa sang đường dẫn tệp Liberation đi kèmổn định2.7.0
ShaperFactoryfinal classdefault(), create(), wouldUseRealShaper()ổn định3.2.0
ShapingResultfinal readonly class$glyphRuns, $originalText, $script, $direction, $shaperImplổn định3.2.0

Base14SubstituteFonts@internal: chỉ dùng trong framework, không bảo đảm tương thích ngược (xem ma trận tương thích) cho bề mặt của nó.

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);

Bộ phân tích cú pháp điền FontInfo và gán FontType. Một face TrueType có bản đồ ký tự Unicode sẽ trở thành TrueTypeUnicode, và bộ ghi phát ra nó dưới dạng một phông chữ ghép 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);
}
}
}

Bộ phân giải không có tác dụng phụ. Việc đăng ký vẫn diễn ra tường minh, nên các hợp đồng khóa và khởi động của registry được giữ vững. Theo thiết kế, SymbolZapfDingbats không trả về đường dẫn nào.

  • SymbolZapfDingbats được cố ý không thay thế. Kết quả null cho những khóa đó là hành vi đã được tài liệu hóa, không phải lỗi thiếu phông chữ.
  • FontInfofinal readonly. Hãy xem một phông chữ đã phân tích cú pháp như một giá trị: đừng bao giờ kỳ vọng có thể thay đổi chiều rộng hay số đo tại chỗ; hãy đăng ký lại nếu nguồn thay đổi.
  • Một phông chữ Type 1 cần cả đường viền PFB lẫn số đo AFM. FontRegistry::registerType1() nhận cặp này; tự động khám phá suy ra đường dẫn AFM từ đường dẫn PFB theo phần mở rộng.
  • FontType::TrueTypeFontType::TrueTypeUnicode đánh dấu khác biệt giữa đơn byte và đa byte. Bộ phân giải mã hóa dùng bản đồ ký tự xuôi đã được điền, không dùng tên họ, nên một face TrueType Unicode tự động định tuyến tới đường Identity-H.
  • Các trục phông chữ biến thể và thực thể có tên được phân tích cú pháp vào FontInfo khi có, nhưng ví dụ tiếng Trung, tiếng Nhật và tiếng Hàn (CJK) được chủ ý viết bằng face tĩnh để giữ cho FontInfo đã phân tích cú pháp có tính tất định.

Registry cấp phát FontInfo một lần cho mỗi phông chữ trong mỗi tiến trình, rồi chia sẻ nó theo tham chiếu. Byte phông chữ thô chiếm phần lớn chi phí bộ nhớ. Chỉ khởi động sẵn những phông chữ mà một worker cần và theo dõi memoryUsage(). Bộ phân giải thay thế Base 14 thực hiện tra cứu bản đồ với thời gian hằng số mà không có input/output (I/O) cho đến khi bên gọi đăng ký tệp đã được phân giải. performance_budget 1500 ms thời gian thực và đỉnh 64 MB bao quát việc khởi động một bộ phông chữ thông thường cộng với kết xuất. Cho đến khi bộ tạo tập con chạy, dấu chân bộ nhớ của mỗi phông chữ tỷ lệ với kích thước tệp phông chữ, chứ không phải số lượng glyph.

FontInfo tự nó là trơ: dữ liệu đã phân tích cú pháp không có hành vi nào ngoài phép biến đổi thuần túy encodeText(). Bề mặt tấn công nằm ở thượng nguồn, tại thời điểm phân tích cú pháp, khi byte phông chữ tùy ý đến được bộ phân tích cú pháp TrueType hoặc Type 1. Các bộ phân tích cú pháp kiểm tra giới hạn mọi offset nhị phân và từ chối các stream wrapper cùng byte null trong đường dẫn. Trước khi đăng ký, đầu vào phông chữ không tin cậy phải vượt qua một chính sách tài nguyên bên ngoài, giới hạn kích thước và số lượng glyph. Các bản thay thế Liberation đi kèm là tài sản tin cậy được phân phối cùng gói, nên đường dẫn dự phòng không đưa thêm đầu vào không tin cậy nào vào hệ thống.

Tuyên bốTiêu chuẩnĐiều khoảnBằng chứng
Mọi phông chữ mà tài liệu sử dụng đều được nhúng để tài liệu kết xuất mà không dựa vào phông chữ hệ thống.ISO 32000-2§9
Một chương trình TrueType được nhúng thông qua FontFile2 với các bảng glyf, head, hhea, hmtx, loca, maxp.ISO 32000-2§9.6.5Bản tóm tắt RAG bị cắt do giới hạn giấy phép; tiền tố 7b26f37996239b2a, xem _downgraded-claims-o3.md
Một chương trình OpenType (CFF) được nhúng thông qua FontFile3.ISO 32000-2§9.6.5Bản tóm tắt RAG bị cắt do giới hạn giấy phép; tiền tố 801549ee00623baf, xem _downgraded-claims-o3.md

Điều khoản đầu tiên được ghim theo bản tóm tắt và được B1 xác nhận. Các điều khoản FontFile2 và FontFile3 là diễn giải. Bản tóm tắt RAG đầy đủ cho những điều khoản đó không được trả về (bị cắt do giới hạn giấy phép), nên bằng chứng cũng được xác nhận bởi FontSubsetter (vốn xây dựng lại đúng tập glyf/head/hhea/hmtx/loca/maxp) và enum FontType. NextPDF không tái tạo văn bản quy phạm. Trong mã nguồn, Base14SubstituteFonts trích dẫn ISO 32000-2 §9.6.2.2 (xử lý phông chữ Type 1 chuẩn), ISO 14289-2:2024 §8.4.5.5.1 (nhúng phông chữ PDF/UA-2), và ISO 19005-4:2020 §6.3.5 (nhúng phông chữ PDF/A-4). Các trang về khả năng tiếp cận và tuân thủ chứa đầy đủ thông tin tuân thủ hồ sơ.

Một gói cấp phép phông chữ thương mại và một dịch vụ tạo tập con động được xây dựng trên Core FontInfo và registry. Mô-đun phông chữ Core nhúng, tạo tập con và dự phòng mà không yêu cầu giấy phép. Việc bỏ qua liên kết chuyển đổi là có chủ ý.