Nhúng và rút gọn (subset) phông chữ TrueType
Tổng quan nhanh
Phần tiêu đề “Tổng quan nhanh”Đăng ký một phông chữ TrueType, kết xuất văn bản bằng phông chữ đó, rồi để writer chỉ nhúng đúng subset cần thiết. Công thức này dùng cùng content path với examples/04-text-and-fonts.php, cùng với một phông chữ TrueType (.ttf) đã đăng ký.
Cài đặt
Phần tiêu đề “Cài đặt”composer require nextpdf/core:^3Ràng buộc này cài đặt gói nextpdf/core. Ví dụ này chạy trên PHP 8.4 và đi kèm test fixture LiberationSans-Regular.ttf, giúp công thức tự khép kín.
Tổng quan về khái niệm
Phần tiêu đề “Tổng quan về khái niệm”Đăng ký một phông chữ bằng FontRegistry::register($path, $alias). Registry phân tích tệp, trả về một FontInfo và dùng TrueTypeParser cho các tệp .ttf và .otf. Để dùng phông chữ, hãy chọn alias của nó bằng setFont($alias, ...). Lệnh gọi này cũng ghi lại các codepoint được sử dụng.
Việc rút gọn (subset) chạy tự động khi gọi save(). PDF font writer thu thập các codepoint được dùng và gọi FontSubsetter::subset(), hoặc CffSubsetter cho các phông chữ Compact Font Format (CFF) hoặc OpenType. Khi subset nhỏ hơn chương trình phông chữ đầy đủ, writer nhúng subset đó. Nó cũng ghi lại BaseFont và FontName bằng một thẻ subset gồm sáu chữ cái viết hoa được nối bằng dấu cộng. Đây là dạng ABCDEF+FontName mà ISO 32000-2 yêu cầu đối với một subset phông chữ. Writer lưu chương trình TrueType được nhúng dưới dạng FontFile2 trong font descriptor (ISO 32000-2).
Tiền tố subset được tạo tất định từ tên PostScript, vì vậy một bản build tất định sẽ tạo ra một thẻ ổn định. Đó là lý do reproducibility profile của công thức này là structural. Profile structural chuẩn hóa tiền tố subset và /ID trong trailer thay vì kiểm tra chúng theo từng byte.
Bề mặt API
Phần tiêu đề “Bề mặt 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; truyền alias đã đăng ký làm$family.- Việc rút gọn (subset) là nội bộ của writer (
NextPDF\Writer\PdfFontWriter->NextPDF\Typography\FontSubsetter). Không có công tắc công khai để bật hay tắt: writer luôn rút gọn (subset) khi đã biết các codepoint và subset nhỏ hơn bản đầy đủ.
Bảng PHPDoc đầy đủ được tạo từ mã nguồn.
Mã mẫu — bắt đầu nhanh
Phần tiêu đề “Mã mẫu — bắt đầu nhanh”<?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() tự tạo registry riêng. Để dùng một registry do bạn tự điền, hãy dựng tài liệu thông qua DocumentFactory, như được minh họa trong mã mẫu cho production. Factory giúp writer đọc các phông chữ bạn đã đăng ký.
Mã mẫu — Production
Phần tiêu đề “Mã mẫu — Production”Mã mẫu này tự khép kín và chạy được trong harness. Nó đăng ký LiberationSans-Regular.ttf đi kèm và kết xuất thông qua DocumentFactory, nên registry đã được điền cũng chính là registry đang dùng. Nó dựa vào việc rút gọn (subset) tự động khi lưu.
<?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 dự kiến:
Wrote embed-and-subset-fonts.pdfĐể xác nhận subset, hãy mở tệp đầu ra và kiểm tra font dictionary. Phần BaseFont hiển thị <TAG>+LiberationSans, và descriptor chứa một FontFile2. Chạy qpdf --check sẽ không báo lỗi cấu trúc nào.
Trường hợp biên & điều cần lưu ý
Phần tiêu đề “Trường hợp biên & điều cần lưu ý”- Quyền sở hữu registry.
Document::createStandalone()tự tạo registry riêng. Một phông chữ bạn đăng ký trên mộtFontRegistryriêng sẽ không được tài liệu đó nhìn thấy. Hãy dùngDocumentFactoryđể truyền registry của bạn, như trong mã mẫu cho production. - Quyền nhúng. Việc rút gọn (subset) không làm thay đổi giấy phép. Chỉ nhúng các phông chữ mà bạn có quyền nhúng. Một số phông chữ thiết lập các bit hạn chế nhúng; parser đọc các bit đó, nhưng bạn vẫn chịu trách nhiệm tuân thủ.
- Đường dẫn CFF/OpenType. Các phông chữ
.otfvà CFF được rút gọn (subset) bởiCffSubsetter, chứ không phảiFontSubsetter. Hành vi và việc ghi lại thẻ subset là tương đương nhau. Chỉ code path là khác. - Không giảm được kích thước. Đôi khi subset không nhỏ hơn bản gốc. Điều này có thể xảy ra với các phông chữ rất nhỏ hoặc khi mọi glyph đều được sử dụng. Trong trường hợp đó, writer nhúng chương trình phông chữ gốc mà không có thẻ subset. Đây là hành vi đúng, không phải lỗi.
- Phông chữ CJK. Các phông chữ lớn cho tiếng Trung, tiếng Nhật và tiếng Hàn (CJK) dùng một chiến lược rút gọn (subset) phân tầng theo ADR-008, với một subprocess được cô lập và một phương án dự phòng PHP-native. Xem Đặt văn bản CJK với mã hóa nhận biết cmap để biết chi tiết về CJK và trạng thái pipeline hiện tại.
Hiệu năng
Phần tiêu đề “Hiệu năng”Bước phân tích chỉ duyệt một lượt qua các bảng phông chữ, và chi phí rút gọn (subset) tăng theo số lượng glyph. Các phông chữ Latin không thuộc CJK được rút gọn (subset) ngay trong tiến trình, trong giới hạn wall_ms: 1500, peak_mb: 96. Các phông chữ CJK lớn được định tuyến tới một subprocess được cô lập với thời gian chờ thực tế là hai giây và một phương án dự phòng PHP-native (ADR-008). Nhờ cách định tuyến này, một quá trình subset chậm hoặc bị sập không thể chặn bên gọi.
Ghi chú về bảo mật
Phần tiêu đề “Ghi chú về bảo mật”Một tệp phông chữ là dữ liệu đầu vào nhị phân không đáng tin. Parser từ chối đường dẫn stream-wrapper và byte null. Subprocess rút gọn (subset) CJK chạy mà không kế thừa kết nối cơ sở dữ liệu, file handle hay trạng thái framework nào. Nó chuyển sang phương án dự phòng an toàn khi bị sập hoặc hết thời gian chờ (ADR-008). Hãy kiểm tra nguồn gốc của các phông chữ nhận từ người dùng cuối.
Mức độ tuân thủ
Phần tiêu đề “Mức độ tuân thủ”| Phát biểu | Đặc tả | Điều khoản | reference_id |
|---|---|---|---|
| BaseFont/FontName của một subset phông chữ mang một tiền tố subset gồm sáu chữ cái viết hoa, nối với nhau bằng dấu cộng. | ISO 32000-2 | iso32000_2_sec9#x1.x66.p2 | |
| Một chương trình phông chữ TrueType được nhúng sẽ được lưu dưới dạng FontFile2 trong font descriptor. | ISO 32000-2 | iso32000_2_sec9#x1.x65.p15 |
Công thức này cho thấy cách NextPDF nhúng và rút gọn (subset) một phông chữ TrueType, rồi phát ra một tiền tố subset đúng chuẩn. Nó không khẳng định việc tuân thủ giấy phép phông chữ. Quyền nhúng là trách nhiệm của bên tích hợp.
Bối cảnh thương mại
Phần tiêu đề “Bối cảnh thương mại”Không áp dụng.