Bỏ qua để đến nội dung
getnextpdf.com

Tạo PDF CJK và tiếng Ả Rập có thể sao chép và dán chính xác

Tạo một tệp Portable Document Format (PDF) chứa văn bản tiếng Trung, tiếng Nhật, tiếng Hàn (CJK) và tiếng Ả Rập sao cho thao tác sao chép và dán trả về đúng các ký tự hợp lý ban đầu. Engine ánh xạ mỗi glyph sang Unicode thông qua một CMap /ToUnicode, chuẩn hóa kết quả bằng Normalization Form Compatibility Composition (NFKC), và bọc các đoạn được tạo hình hoặc giãn cách chữ cái trong một /Span mang theo /ActualText. Hãy đăng ký các phông chữ rồi ghi nội dung; việc trích xuất vẫn chính xác. Hãy xác minh việc trích xuất bằng pdftotext/Poppler, không phải PyMuPDF; veraPDF xác thực PDF/Universal Accessibility 2 (PDF/UA-2), chứ không xác minh việc trích xuất.

Terminal window
composer require nextpdf/core

Đăng ký một phông chữ CJK, chẳng hạn như Noto Sans CJK, và một phông chữ hỗ trợ tiếng Ả Rập có bản đồ ký tự bao phủ khối Arabic Presentation Forms-B, chẳng hạn như Noto Naskh Arabic. Chỉ nhúng những phông chữ bạn được cấp phép nhúng.

Mã glyph trong một luồng nội dung không phải là Unicode. Một CMap /ToUnicode ánh xạ từng mã trở lại Unicode để trình đọc có thể trích xuất văn bản (ISO 32000-2 §9.10). Engine chuẩn hóa các giá trị đó bằng Normalization Form Compatibility Composition (NFKC), theo định nghĩa trong Unicode UAX #15. Một CJK Compatibility Ideograph và một dạng trình bày tiếng Ả Rập được ánh xạ về ký tự cơ sở tương ứng, nên thao tác tìm kiếm và sao chép trả về văn bản chuẩn tắc thay vì điểm mã tương thích.

Hai trường hợp cần nhiều hơn /ToUnicode: chữ Latinh giãn cách chữ cái và tiếng Ả Rập phải-sang-trái được tạo hình. Engine vẽ chúng dưới dạng các glyph bị giãn cách hoặc được sắp xếp lại, nên chỉ dựa vào thứ tự glyph thì không thể khôi phục chuỗi hợp lý. Engine bọc mỗi đoạn trong một chuỗi nội dung được đánh dấu /Span mang theo /ActualText, một bản thay thế chính xác cho nội dung được bao bọc (ISO 32000-2 §14.9). Các trình trích xuất tôn trọng /ActualText sẽ trả về chuỗi hợp lý.

Ký hiệuVị tríVai trò
FontRegistry::register(string $fontFile, string $alias = ''): FontInfoNextPDF\Typography\FontRegistryĐăng ký các phông chữ CJK và tiếng Ả Rập.
DocumentFactory::create(): DocumentNextPDF\Core\DocumentFactoryTạo tài liệu dùng registry của bạn.
Document::writeHtml(string $html): staticNextPDF\Core\Concerns\HasTextOutputKết xuất nội dung đa ngôn ngữ.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\DocumentFactory;
use NextPDF\Graphics\ImageRegistry;
use NextPDF\Typography\FontRegistry;
$fonts = new FontRegistry();
$fonts->register(__DIR__ . '/NotoSansCJK-Regular.ttf', alias: 'CJK');
$fonts->register(__DIR__ . '/NotoNaskhArabic-Regular.ttf', alias: 'Arabic');
$doc = (new DocumentFactory($fonts, new ImageRegistry(maxCacheBytes: 0)))->create();
$doc->addPage();
$doc->writeHtml(
'<p style="font-family: \'CJK\';">PDF 2.0 引擎 — 量子</p>'
. '<p style="direction: rtl; font-family: \'Arabic\';">فاتورة</p>'
);
$doc->save(__DIR__ . '/multilingual.pdf');
Terminal window
pdftotext multilingual.pdf - | head
# Extracts the logical text: "PDF 2.0 引擎 — 量子" and the logical Arabic "فاتورة",
# not compatibility code points or reversed presentation forms.

Ví dụ khép kín này gắn thẻ tài liệu, thêm tiêu đề có giãn cách chữ cái, rồi ghi vào đường dẫn do harness cung cấp.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\DocumentFactory;
use NextPDF\Graphics\ImageRegistry;
use NextPDF\Typography\FontRegistry;
$fonts = new FontRegistry();
$fonts->register(__DIR__ . '/NotoSansCJK-Regular.ttf', alias: 'CJK');
$fonts->register(__DIR__ . '/NotoNaskhArabic-Regular.ttf', alias: 'Arabic');
$doc = (new DocumentFactory($fonts, new ImageRegistry(maxCacheBytes: 0)))->create();
$doc->setTitle('Multilingual extraction');
$doc->enableTaggedPdf('en');
$doc->addPage();
$html = <<<'HTML'
<h1 style="font-family: 'CJK'; letter-spacing: 3px;">CODE WORD</h1>
<p style="font-family: 'CJK';">中文 · 日本語 · 한국어 · 量子 (compatibility ideograph)</p>
<p style="direction: rtl; font-family: 'Arabic';">المبلغ الإجمالي 380.00</p>
HTML;
$doc->writeHtml($html);
$out = getenv('NEXTPDF_OUT');
$doc->save($out !== false ? $out : __DIR__ . '/multilingual-copy-paste-extraction.pdf');
echo "Wrote the multilingual PDF\n";

Chạy pdftotext trên đầu ra. Tiêu đề có giãn cách chữ cái được trích xuất thành CODE WORD mà không chèn thêm khoảng trắng, dòng CJK được trích xuất thành các ký tự cơ sở, và dòng tiếng Ả Rập được trích xuất thành chuỗi hợp lý.

Trường hợp đặc biệt & điểm cần lưu ý

Phần tiêu đề “Trường hợp đặc biệt & điểm cần lưu ý”
  • Xác minh việc trích xuất bằng pdftotext, không phải PyMuPDF. Chế độ văn bản thô của PyMuPDF bỏ qua /ActualText nội tuyến và trả về các glyph trực quan, nên có thể báo sai rằng kết quả không đúng. Poppler (pdftotext) tôn trọng /ActualText; veraPDF xác thực PDF/UA-2, không xác minh việc trích xuất.
  • Việc trích xuất cần /ToUnicode. Hãy đăng ký và nhúng phông chữ để bộ ghi phát ra CMap /ToUnicode. Một phông chữ không nhúng, phi tiêu chuẩn không thể bảo đảm ánh xạ Unicode.
  • /ActualText bao phủ các đoạn được tạo hình và giãn cách chữ cái. Với văn bản thuần, không tạo hình, không giãn cách, chỉ riêng /ToUnicode đã cho kết quả trích xuất chính xác; lớp bọc /Span bảo toàn các đoạn bị giãn cách hoặc bị sắp xếp lại.
  • Bảng HTML được gắn thẻ vượt qua các bước kiểm tra PDF/UA-2. Việc trích xuất vẫn chính xác, và một <table> HTML được gắn thẻ nay vượt qua veraPDF --flavour ua2 với không có lỗi nào — xem Khả năng tiếp cận.

Chi phí dựng CMap /ToUnicode và các lớp bọc /Span tăng tuyến tính theo số lượng glyph. Công thức này có ngân sách wall_ms: 1500, peak_mb: 96.

Hãy xác thực độ dài của các chuỗi đa ngôn ngữ do người dùng cung cấp để kích thước đầu ra nằm trong giới hạn. Bộ dựng /ToUnicode từ chối các nửa surrogate và các mã nằm ngoài không gian mã, nên một ánh xạ sai định dạng không thể tạo ra tài nguyên trích xuất bị hỏng. Engine không chạy script nào và không nạp bất kỳ tài nguyên từ xa nào cho các phông chữ cục bộ.

Phát biểuĐặc tảĐiều khoản
Một CMap /ToUnicode ánh xạ mã ký tự sang Unicode để trích xuất.ISO 32000-2§9.10
/ActualText là một bản thay thế chính xác cho nội dung được bao bọc.ISO 32000-2§14.9
NFKC là phân rã tương thích, sau đó là kết hợp chuẩn tắc.Unicode UAX #15§1.2

Không áp dụng.