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

Dàn văn bản CJK bằng mã hóa nhận biết cmap

Công thức này đăng ký một bộ phông chữ TrueType cho tiếng Trung, tiếng Nhật và tiếng Hàn (CJK), sau đó mã hóa văn bản tiếng Trung phồn thể qua facade FontInfo::encodeText() nhận biết cmap. Facade trả về luồng byte CID Identity-H gồm các CID hai byte. Công thức này bám sát examples/35-cjk-cmap-demo.php. Hãy đọc ghi chú về phạm vi trước khi dựa vào nó.

Kiến trúc mã hóa văn bản nhận biết cmap được phát hành theo từng giai đoạn (ADR-013). Giai đoạn 1 đã hoàn tất: facade FontInfo::encodeText() và chiến lược mã hóa nhận biết cmap đã được kết nối và có thể truy cập từ mã người dùng. Giai đoạn 2 đang được tiến hành: giai đoạn này định tuyến bộ kết xuất và bộ ghi qua facade. Giai đoạn 3 và 4 đang chờ xử lý: việc phát ra /ToUnicode, /CIDSystemInfo, /Encoding/CIDToGIDMap theo từng phông chữ, cùng bộ phân giải phông chữ thay thế, vẫn chưa được kết nối vào bộ ghi.

Hãy tính đến các hệ quả sau:

  • Công thức này minh họa facade mã hóa, không phải một chế độ viết theo chiều dọc hoàn chỉnh. Bề mặt tài liệu hiện tại không có API chế độ viết công khai, nên không có lệnh gọi setWritingMode và không có setter vertical-rl.
  • Theo phần đầu của chính ví dụ nền, ví dụ này là một bài kiểm thử khói tích hợp, không phải một fixture tuân thủ. Quá trình kiểm định PDF/UA-2 và PDF/A-4 sẽ fail-closed đối với đầu ra tạo theo cách này cho đến khi Giai đoạn 3 và 4 hoàn tất. Đừng tuyên bố rằng đầu ra từ đường dẫn này là tuân thủ. Trình kiểm tra mới là nơi quyết định sự tuân thủ, và hiện nó chưa cho đầu ra này đạt.
  • Hạ tầng số liệu viết theo chiều dọc đã tồn tại nhưng vẫn là nội bộ. Nó bao gồm value object CjkVerticalMetrics cùng các bộ phát /W2/DW2. NextPDF không công khai nó thành một lệnh gọi “viết theo chiều dọc” cho người dùng, và bộ ghi vẫn chưa phát ra các từ điển tương ứng.
Terminal window
composer require nextpdf/core:^3

Ràng buộc này khớp với gói nextpdf/core. Ví dụ này chạy trên PHP 8.4. Fixture kiểm thử Noto Sans TC đi kèm giúp công thức này tự chứa đầy đủ.

ISO 32000-2 mô hình hóa việc phát ra văn bản qua ba lớp: điểm mã Unicode, mã ký tự và ID glyph. Đối với một bộ phông chữ TrueType CJK, công cụ dùng một phông chữ Type 0 phức hợp với mã hóa Identity-H. Với mã hóa này, chuỗi được hiển thị dùng các cặp byte để lập chỉ mục cho CIDFont (ISO 32000-2).

FontRegistry::register() phân tích cú pháp bộ phông chữ. FontInfo::encodeText($unicodeText) sau đó phân giải một chiến lược mã hóa qua FontEncodingStrategyResolver. Đối với một bộ phông chữ TrueType CJK đã đăng ký, nó điều phối đến TrueTypeCmapStrategy. EncodedGlyphRun trả về mang theo luồng byte Identity-H, toán hạng chuỗi PDF, các chiều rộng tiến theo từng glyph, các điểm mã đã dùng và bản đồ GID→Unicode. Quá trình tạo tập con CJK dùng các điểm mã theo ADR-008. Một luồng /ToUnicode trong tương lai sẽ dùng bản đồ GID→Unicode. Chế độ được chọn là EncodingMode::TwoByteCid.

Hai cấu trúc CIDFont định nghĩa việc viết theo chiều dọc trong PDF. Cấu trúc thứ nhất là mảng số liệu chiều dọc theo từng glyph /W2 (ISO 32000-2). Cấu trúc thứ hai là số liệu chiều dọc mặc định /DW2 (ISO 32000-2). NextPDF cung cấp value object và các bộ phát cho cả hai qua CjkVerticalMetrics::toW2Array(), toW2RangeArray()toDw2Array(). Chúng là thành phần nội bộ, và bộ ghi vẫn chưa phát ra chúng. Xem ghi chú về phạm vi.

  • FontRegistry::register(string $fontFile, string $alias = '', int $fontIndex = 0): FontInfoNextPDF\Typography\FontRegistry.
  • FontInfo::encodeText(string $unicodeText): EncodedGlyphRunNextPDF\Typography\FontInfo. Facade của Giai đoạn 1.
  • EncodedGlyphRunNextPDF\Typography\Encoding\EncodedGlyphRun (byteStream, pdfStringOperand, mode, advanceWidths, toUnicodeMap, usedCodepoints, glyphCount()).
  • EncodingModeNextPDF\Typography\Encoding\EncodingMode (SingleByte, TwoByteCid).
  • CjkVerticalMetricsNextPDF\Typography\CjkVerticalMetrics. Value object số liệu chiều dọc nội bộ. Nó được ghi tài liệu để minh bạch, không phải là một đường dẫn viết dành cho người dùng.

Bảng PHPDoc đầy đủ được tạo ra từ mã nguồn.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Typography\Encoding\EncodingMode;
use NextPDF\Typography\FontRegistry;
$registry = new FontRegistry();
$font = $registry->register('/path/to/NotoSansTC-Regular.ttf', alias: 'NotoSansTC');
$encoded = $font->encodeText('PDF 2.0 引擎');
assert($encoded->mode === EncodingMode::TwoByteCid); // cmap-aware branch fired
echo $encoded->glyphCount() . " glyph run entries\n";

Mẫu này tự chứa đầy đủ và có thể chạy bằng harness. Nó bám sát examples/35-cjk-cmap-demo.php. Trước tiên, hãy đăng ký fixture Noto Sans TC đi kèm. Tiếp theo, hãy xác nhận facade nhận biết cmap có thể truy cập được. Sau đó, hãy kết xuất qua DocumentFactory để tài liệu dùng registry mà bạn đã nạp.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\DocumentFactory;
use NextPDF\Graphics\ImageRegistry;
use NextPDF\Typography\Encoding\EncodingMode;
use NextPDF\Typography\FontRegistry;
$cjkFontPath = dirname(__DIR__, 2)
. '/fonts/test-fixtures/Noto Sans TC/NotoSansTC-Regular.ttf';
if (!is_file($cjkFontPath)) {
fwrite(STDERR, "Missing CJK font fixture: {$cjkFontPath}\n");
exit(1);
}
$fontRegistry = new FontRegistry();
$cjkFont = $fontRegistry->register($cjkFontPath, alias: 'NotoSansTC');
// Phase 1 facade: prove the cmap-aware path is reachable from userland.
$cjkSample = 'PDF 2.0 引擎 — 使用 CMap 編碼';
$encoded = $cjkFont->encodeText($cjkSample);
if ($encoded->mode !== EncodingMode::TwoByteCid) {
fwrite(STDERR, "Expected TwoByteCid (TrueTypeCmapStrategy branch)\n");
exit(2);
}
$imageRegistry = new ImageRegistry(maxCacheBytes: 0);
$documentFactory = new DocumentFactory($fontRegistry, $imageRegistry);
$doc = $documentFactory->create();
$doc->setTitle('NextPDF CJK CMap-Aware Encoding Demo');
$doc->setLanguage('zh-Hant');
$doc->addPage();
$doc->setFont('helvetica', 'B', 16);
$doc->cell(0, 12, 'CJK cmap-aware encoding (Phase 1 facade)', newLine: true);
$doc->setFont('helvetica', '', 10);
$doc->cell(0, 6, 'Mode: ' . $encoded->mode->name . ' (Identity-H, 2-byte CIDs)', newLine: true);
$doc->cell(0, 6, 'Glyphs: ' . $encoded->glyphCount() . ' run entries', newLine: true);
$doc->cell(0, 6, 'Bytes: ' . strlen($encoded->byteStream) . ' encoded bytes', newLine: true);
$doc->ln(4);
$doc->setFont('NotoSansTC', '', 18);
$doc->cell(0, 12, $cjkSample, newLine: true);
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');
$doc->save($out !== false ? $out : __DIR__ . '/cjk-vertical-writing.pdf');
echo "Wrote cjk-vertical-writing.pdf (Phase 1+2 dry-run; not a conformance fixture)\n";

STDOUT dự kiến:

Wrote cjk-vertical-writing.pdf (Phase 1+2 dry-run; not a conformance fixture)
  • Không phải một fixture tuân thủ. Theo phần đầu của chính ví dụ nền, đầu ra này là một bài kiểm thử khói tích hợp. Các phép kiểm tra PDF/UA-2 và PDF/A-4 sẽ fail-closed đối với nó cho đến khi Giai đoạn 3 và 4 hoàn tất. Đừng đăng ký nó làm golden tuân thủ.
  • Không có API chế độ viết. Không có lệnh gọi công khai nào chuyển sang viết theo chiều dọc, vốn sẽ bao gồm vertical-rlvertical-lr. Các bộ phát /W2/DW2 tồn tại trong nội bộ. Chúng không được công khai và vẫn chưa được ghi vào từ điển phông chữ.
  • Quyền sở hữu registry. Document::createStandalone() tự dựng registry riêng. Hãy dùng DocumentFactory để tài liệu đọc registry mà bạn đã nạp bộ phông chữ CJK.
  • Đường dẫn luồng byte cuối cùng. Cho đến khi Giai đoạn 2 khép lại, luồng nội dung hiển thị vẫn đi qua đường dẫn văn bản kế thừa. Phần đã được chứng minh và có thể truy cập hiện tại là bước mã hóa ở thượng nguồn: phép tra cứu xuôi của cmap kèm luồng byte Identity-H.
  • Chi phí tạo tập con CJK. Các bộ phông chữ CJK lớn được tạo tập con qua một tiến trình con biệt lập. Tiến trình con đó có một phương án dự phòng thuần PHP và thời gian chờ hai giây (ADR-008).

encodeText() thực hiện một lượt tra cứu xuôi cmap duy nhất cho đầu vào. Nó tuyến tính theo số lượng điểm mã, O(n). Ngân sách là wall_ms: 2000, peak_mb: 128. Ngân sách này là mức cao nhất trong nhóm này vì các bộ phông chữ CJK rất lớn, và việc tạo tập con là phần chi phí chủ đạo. ADR-008 cô lập công việc đó để nó không thể chặn bên gọi.

Một tệp phông chữ CJK là đầu vào nhị phân không đáng tin cậy. Bộ phân tích cú pháp từ chối các đường dẫn stream-wrapper và byte null. Việc tạo tập con CJK chạy trong một tiến trình con biệt lập không kế thừa trạng thái (ADR-008). Hãy xác minh nguồn gốc của các bộ phông chữ do người dùng cuối cung cấp. Nội dung văn bản CJK được kết xuất, không được diễn giải.

Tuyên bốĐặc tảĐiều khoảnreference_id
Đối với một phông chữ Type 0 Identity-H/Identity-V, chuỗi được hiển thị là các cặp byte dùng để lập chỉ mục cho CIDFont.ISO 32000-2iso32000_2_sec9#x1.x49.p90
Mảng W2 cung cấp số liệu viết theo chiều dọc theo từng glyph và chỉ áp dụng cho các CIDFont dùng để viết theo chiều dọc.ISO 32000-2iso32000_2_sec9#x1.x44.p23
Mảng DW2 cung cấp số liệu viết theo chiều dọc mặc định cho CIDFont.ISO 32000-2iso32000_2_sec9#x1.x44.p22

Công thức này cho thấy facade mã hóa CJK nhận biết cmap có thể truy cập từ mã người dùng (Giai đoạn 1). Nó không tuyên bố đầu ra viết theo chiều dọc hay sự tuân thủ PDF/UA-2 / PDF/A-4 cho tệp được tạo ra. Việc bộ ghi phát ra /ToUnicode và số liệu chiều dọc (Giai đoạn 3 và 4) đang chờ xử lý, và một trình kiểm tra sẽ chưa cho đầu ra này đạt hôm nay.

Không áp dụng.