ทำให้คัดลอกและวางข้อความ CJK และอาหรับจาก PDF ได้ถูกต้อง
ภาพรวมโดยย่อ
หัวข้อที่มีชื่อว่า “ภาพรวมโดยย่อ”สร้างไฟล์ Portable Document Format (PDF) ที่มีข้อความภาษาจีน ญี่ปุ่น เกาหลี (CJK) และอาหรับซึ่งคัดลอกและวางออกมาเป็นอักขระเชิงตรรกะดั้งเดิมได้ เอนจินแมปกลิฟทุกตัวไปยัง Unicode ผ่าน /ToUnicode CMap ทำให้ผลลัพธ์อยู่ในรูปแบบบัญญัติด้วย Normalization Form Compatibility Composition (NFKC) และห่อรันที่ถูกจัดรูปหรือมีระยะห่างตัวอักษรไว้ใน /Span ที่มี /ActualText เมื่อลงทะเบียนฟอนต์แล้วเขียนเนื้อหา การแยกดึงจะยังคงถูกต้อง ตรวจสอบยืนยันการแยกดึงด้วย pdftotext/Poppler ไม่ใช่ PyMuPDF ส่วน veraPDF ใช้ตรวจสอบยืนยัน PDF/Universal Accessibility 2 (PDF/UA-2) ไม่ใช่ตรวจสอบการแยกดึง
การติดตั้ง
หัวข้อที่มีชื่อว่า “การติดตั้ง”composer require nextpdf/coreลงทะเบียนฟอนต์ CJK เช่น Noto Sans CJK และฟอนต์ที่รองรับอาหรับซึ่งมีตารางอักขระครอบคลุมบล็อก Arabic Presentation Forms-B เช่น Noto Naskh Arabic ฝังเฉพาะฟอนต์ที่คุณมีสิทธิ์ฝังเท่านั้น
ภาพรวมเชิงแนวคิด
หัวข้อที่มีชื่อว่า “ภาพรวมเชิงแนวคิด”รหัสกลิฟในสตรีมเนื้อหาไม่ใช่ Unicode โดยตรง /ToUnicode CMap จะแมปแต่ละรหัสกลับเป็น Unicode เพื่อให้ตัวอ่านแยกดึงข้อความได้ (ISO 32000-2 §9.10) เอนจินทำให้ค่าเหล่านั้นอยู่ในรูปแบบบัญญัติด้วย Normalization Form Compatibility Composition (NFKC) ตามนิยามใน Unicode UAX #15 อักษรภาพเพื่อความเข้ากันได้ของ CJK และรูปแบบการแสดงผลของอาหรับจะแมปกลับไปยังอักขระฐานของตน ดังนั้นการค้นหาและการคัดลอกจึงคืนค่าข้อความบัญญัติแทน code point เพื่อความเข้ากันได้
มีสองกรณีที่ต้องใช้มากกว่า /ToUnicode ได้แก่ ภาษาละตินที่มีระยะห่างตัวอักษรและภาษาอาหรับแบบขวาไปซ้ายที่ถูกจัดรูป เอนจินวาดข้อความเหล่านี้เป็นกลิฟที่มีระยะห่างหรือถูกเรียงลำดับใหม่ ลำดับกลิฟเพียงอย่างเดียวจึงไม่สามารถกู้คืนสตริงเชิงตรรกะได้ เอนจินจึงห่อแต่ละรันไว้ในลำดับเนื้อหาที่มาร์กเป็น /Span และมี /ActualText ซึ่งเป็นการแทนที่เนื้อหาที่ห่อไว้อย่างตรงกันทุกประการ (ISO 32000-2 §14.9) เครื่องมือแยกดึงที่เคารพ /ActualText จะคืนค่าสตริงเชิงตรรกะ
ส่วนติดต่อ API
หัวข้อที่มีชื่อว่า “ส่วนติดต่อ API”| สัญลักษณ์ | ตำแหน่ง | บทบาท |
|---|---|---|
FontRegistry::register(string $fontFile, string $alias = ''): FontInfo | NextPDF\Typography\FontRegistry | ลงทะเบียนฟอนต์ CJK และอาหรับ |
DocumentFactory::create(): Document | NextPDF\Core\DocumentFactory | สร้างเอกสารโดยใช้รีจิสทรีที่กำหนด |
Document::writeHtml(string $html): static | NextPDF\Core\Concerns\HasTextOutput | เรนเดอร์เนื้อหาหลายภาษา |
ตัวอย่างโค้ด — เริ่มต้นอย่างรวดเร็ว
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — เริ่มต้นอย่างรวดเร็ว”<?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');pdftotext multilingual.pdf - | head# Extracts the logical text: "PDF 2.0 引擎 — 量子" and the logical Arabic "فاتورة",# not compatibility code points or reversed presentation forms.ตัวอย่างโค้ด — สำหรับการใช้งานจริง
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — สำหรับการใช้งานจริง”ตัวอย่างแบบครบในตัวนี้จะแท็กเอกสาร เพิ่มส่วนหัวที่มีระยะห่างตัวอักษร และเขียนไฟล์ไปยังพาธของฮาร์เนส
<?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";เรียกใช้ pdftotext กับผลลัพธ์ ส่วนหัวที่มีระยะห่างตัวอักษรจะแยกดึงออกมาเป็น CODE WORD โดยไม่มีช่องว่างแทรก บรรทัด CJK จะแยกดึงออกมาเป็นอักขระฐานของตน และบรรทัดอาหรับจะแยกดึงออกมาเป็นสตริงเชิงตรรกะ
กรณีขอบและข้อควรระวัง
หัวข้อที่มีชื่อว่า “กรณีขอบและข้อควรระวัง”- ตรวจสอบยืนยันการแยกดึงด้วย pdftotext ไม่ใช่ PyMuPDF โหมดข้อความดิบของ PyMuPDF จะเพิกเฉยต่อ
/ActualTextแบบ inline และคืนค่ากลิฟเชิงภาพ จึงอาจรายงานความถูกต้องต่ำกว่าความเป็นจริง Poppler (pdftotext) เคารพ/ActualTextส่วน veraPDF ใช้ตรวจสอบยืนยัน PDF/UA-2 ไม่ใช่ตรวจสอบการแยกดึง - การแยกดึงต้องอาศัย
/ToUnicodeลงทะเบียนและฝังฟอนต์เพื่อให้ตัวเขียนสร้าง/ToUnicodeCMap ฟอนต์ที่ไม่ได้ฝังและไม่เป็นมาตรฐานไม่สามารถรับประกันการแมป Unicode ได้ /ActualTextครอบคลุมรันที่ถูกจัดรูปและมีระยะห่างตัวอักษร สำหรับข้อความธรรมดาที่ไม่ถูกจัดรูปและไม่มีระยะห่าง/ToUnicodeเพียงอย่างเดียวก็แยกดึงได้ถูกต้อง ส่วนการห่อด้วย/Spanจะรักษารันที่มีระยะห่างหรือถูกเรียงลำดับใหม่ไว้- ตาราง HTML ที่แท็กไว้ผ่านการตรวจสอบ PDF/UA-2 การแยกดึงถูกต้อง และ
<table>HTML ที่แท็กไว้ผ่านveraPDF --flavour ua2โดยมีความล้มเหลวเป็นศูนย์แล้วในขณะนี้ — ดู การเข้าถึง
ประสิทธิภาพ
หัวข้อที่มีชื่อว่า “ประสิทธิภาพ”การสร้าง /ToUnicode CMap และการห่อด้วย /Span ใช้ทรัพยากรเพิ่มขึ้นเชิงเส้นตามจำนวนกลิฟ สูตรนี้กำหนดงบประมาณไว้ที่ wall_ms: 1500, peak_mb: 96
หมายเหตุด้านความปลอดภัย
หัวข้อที่มีชื่อว่า “หมายเหตุด้านความปลอดภัย”ตรวจสอบความถูกต้องของความยาวสตริงหลายภาษาที่ผู้ใช้ป้อนเพื่อให้ขนาดผลลัพธ์อยู่ในขอบเขตที่จำกัด ตัวสร้าง /ToUnicode ปฏิเสธ surrogate ครึ่งเดียวและรหัสที่อยู่นอก codespace ดังนั้นการแมปที่มีรูปแบบผิดจึงไม่สามารถสร้างทรัพยากรการแยกดึงที่เสียหายได้ เอนจินไม่รันสคริปต์ใดและไม่ดึงทรัพยากรระยะไกลสำหรับฟอนต์ในเครื่อง
ความสอดคล้อง
หัวข้อที่มีชื่อว่า “ความสอดคล้อง”| ข้อความระบุ | ข้อกำหนด | ข้อ |
|---|---|---|
/ToUnicode CMap แมปรหัสอักขระไปยัง Unicode สำหรับการแยกดึง | ISO 32000-2 | §9.10 |
/ActualText เป็นการแทนที่เนื้อหาที่ห่อไว้อย่างตรงกันทุกประการ | ISO 32000-2 | §14.9 |
| NFKC คือการแยกองค์ประกอบเพื่อความเข้ากันได้แล้วประกอบกลับแบบบัญญัติ | Unicode UAX #15 | §1.2 |
บริบทเชิงพาณิชย์
หัวข้อที่มีชื่อว่า “บริบทเชิงพาณิชย์”ไม่มี
ดูเพิ่มเติม
หัวข้อที่มีชื่อว่า “ดูเพิ่มเติม”- แยกดึงเนื้อหาข้อความ — รากฐานสำหรับการแยกดึงแบบแท็ก
- เรนเดอร์ HTML อาหรับจากขวาไปซ้าย — การจัดรูปข้อความอาหรับและข้อความจากขวาไปซ้าย
- ตัวพิมพ์ —
/ToUnicodeและการทำให้เป็นรูปแบบบัญญัติด้วย NFKC - การเข้าถึง —
/ActualTextและการรองรับตารางที่แท็กไว้