ความเสถียร: ทดลอง
การรองรับการ shaping สคริปต์ซับซ้อน
ภาพรวมโดยย่อ
หัวข้อที่มีชื่อว่า “ภาพรวมโดยย่อ”Preview แบบ opt-in การ shaping สคริปต์ซับซ้อนเปิดเป็นค่าเริ่มต้นปิด เมื่อมัน ปิด เอนจินจะเรนเดอร์ผ่านเส้นทาง codepoint-to-cmap ที่มีอยู่ — เหมือนกันทุกไบต์ กับบิลด์ที่ไม่มีคุณสมบัตินี้ เปิดมันเฉพาะเมื่อคุณมี libharfbuzz และฟอนต์ที่ shape ได้ และตรวจสอบผลลัพธ์
ตัวเรนเดอร์ HTML เพิ่มตัว shaper สคริปต์ซับซ้อนแบบ opt-in สำหรับทิเบตและมองโกเลีย เมื่อตัว shaper เปิด run ทิเบตหรือมองโกเลียที่อยู่ในขอบเขตและถูกตรวจพบจะถูก shape ผ่าน libharfbuzz และส่งออกเป็นรหัสกลีฟแบบ Identity-H ตัว shaper ครอบคลุมทิเบต แนวนอนในฟอนต์ TrueType และ CFF/OTTO รวมถึงการ wrap และมองโกเลียแนวตั้งที่ตั้ง จากบนลงล่าง (TTB)
การติดตั้ง
หัวข้อที่มีชื่อว่า “การติดตั้ง”composer require nextpdf/core:^3ตัว shaper มาในแพ็กเกจ core opt-in CssFeatureFlags::$complexTextShaping เป็น
@since 6.1.0 libharfbuzz เป็นข้อกำหนดในขณะรันเมื่อแฟล็กเปิด — ตัว shaper
เรียกเข้าสู่ libharfbuzz ผ่านส่วนขยาย FFI ของ PHP เมื่อแฟล็กปิด ไลบรารีไม่มีการ
พึ่งพา libharfbuzz
ภาพรวมเชิงแนวคิด
หัวข้อที่มีชื่อว่า “ภาพรวมเชิงแนวคิด”สคริปต์ซับซ้อนจัดเรียงใหม่ แทนที่ และจัดตำแหน่งกลีฟใหม่ตามบริบท การแมป codepoint-to-glyph แบบไร้เดียงสาจะเรนเดอร์มันผิดอย่างเห็นได้ชัด ตัว shaper ส่ง run ที่อยู่ในขอบเขตให้ libharfbuzz ซึ่งใช้ตาราง OpenType shaping ของฟอนต์ และเอนจิน ส่งลำดับกลีฟที่ได้ออกมาเป็น composite Type 0 font ที่มีการเข้ารหัส Identity-H (ISO 32000-2 §9.7.4 — สตริงที่แสดงเป็น CID สองไบต์)
ขอบเขตถูกกำหนดอย่างจงใจ ตัว shaper รู้จัก run ทิเบตและมองโกเลียและ shape มัน; มันไม่อ้างการครอบคลุมสคริปต์ซับซ้อนทั่วไป ทิเบตแนวนอนถูก shape ในฟอนต์ TrueType และ CFF/OTTO พร้อมการ wrap บรรทัด มองโกเลียถูก shape ในแนวตั้ง จากบนลงล่าง
ขอบเขต fail-closed — เข้มงวดและมีชนิด
หัวข้อที่มีชื่อว่า “ขอบเขต fail-closed — เข้มงวดและมีชนิด”ตัว shaper ไม่เคยส่งกลีฟที่ไม่ได้ shape ซึ่งเสียหายในเชิงสายตาเป็น fallback run ที่ ไม่สามารถ shape ได้อย่างซื่อตรงจะยกข้อยกเว้นแบบมีชนิดแทน:
ComplexScriptShapingException— run ไม่สามารถ shape ได้อย่างซื่อตรง: ฟอนต์ ขาดกลีฟที่ต้องการ (จะได้.notdef), ฟอนต์ CFF ถูกขอให้ shape ในเส้นทางแนวตั้ง, run มีลิงก์ หรือคอลัมน์มองโกเลียต้องการการ wrap (กรณีนอกขอบเขต)HarfBuzzUnavailableException— แฟล็กเปิดแต่ libharfbuzz เข้าถึงไม่ได้ผ่าน FFI ในขณะรัน
เมื่อแฟล็ก ปิด run ที่อยู่ในขอบเขตจะเรนเดอร์ผ่านเส้นทาง codepoint-to-cmap ที่มี อยู่ นั่นเป็นข้อจำกัดที่บันทึกไว้ ไม่ใช่การอ้าง shaping: เส้นทางปิดไม่ใช้ OpenType shaping ดังนั้นรูปแบบตามบริบทจึงไม่รับประกัน อย่าอธิบายเอาต์พุตของเส้นทางปิดว่า “shape แล้ว”
ขอบเขตด้านความซื่อตรง — ความเท่าเทียมเชิงวัตถุวิสัย ไม่ใช่การอนุมัติด้านสุนทรียะ
หัวข้อที่มีชื่อว่า “ขอบเขตด้านความซื่อตรง — ความเท่าเทียมเชิงวัตถุวิสัย ไม่ใช่การอนุมัติด้านสุนทรียะ”ความซื่อตรงของการ shaping ถูกตรวจสอบเชิงวัตถุวิสัยเทียบกับ HarfBuzz: ตัวระบุกลีฟ ที่ส่งออก การแมป cluster และตำแหน่งกลีฟตรงกับเอาต์พุตอ้างอิงของ HarfBuzz (ความ เท่าเทียมของกลีฟ cluster และตำแหน่ง) การทบทวนด้าน สุนทรียะ โดยเจ้าของภาษา — การตัดสินว่าผลลัพธ์อ่านเป็นธรรมชาติสำหรับผู้อ่านที่คล่องหรือไม่ — เป็นงานติดตามผล หลังการ ship ที่ถูกติดตามไว้ NextPDF ไม่ได้อ้างคุณภาพด้านภาษา ใน API นี้หรือใน เอกสารเหล่านี้ ความเท่าเทียมเชิงวัตถุวิสัยได้รับการยืนยัน; คุณภาพด้านสุนทรียะไม่ได้ ยืนยัน
พื้นผิวของ API
หัวข้อที่มีชื่อว่า “พื้นผิวของ API”| สัญลักษณ์ | ตำแหน่ง | บทบาท |
|---|---|---|
CssFeatureFlags::$complexTextShaping | src/Html/CssFeatureFlags.php | แฟล็ก opt-in สำหรับตัว shaper ทิเบต/มองโกเลีย (ค่าเริ่มต้น false) |
Config::withCssFeatureFlags(CssFeatureFlags $flags): self | src/Core/Config.php | แนบชุดแฟล็กเข้ากับการกำหนดค่าเอกสาร |
ComplexScriptShapingException | src/Font/Shaper/ComplexScriptShapingException.php | ถูกโยนเมื่อ run ที่อยู่ในขอบเขตไม่สามารถ shape ได้อย่างซื่อตรง |
HarfBuzzUnavailableException | src/Font/Shaper/HarfBuzzUnavailableException.php | ถูกโยนเมื่อแฟล็กเปิดแต่ libharfbuzz ไม่พร้อมใช้งาน |
ตัวอย่างโค้ด — เริ่มต้นอย่างรวดเร็ว
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — เริ่มต้นอย่างรวดเร็ว”<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Config;use NextPDF\Core\Document;use NextPDF\Html\Css\CssFeatureFlags;
$config = (new Config())->withCssFeatureFlags( new CssFeatureFlags(complexTextShaping: true),);
$doc = Document::createStandalone($config);$doc->addPage();$doc->writeHtml( '<div style="font-family: NotoSerifTibetan;">བོད་སྐད་</div>',);$doc->save(__DIR__ . '/tibetan.pdf');ตัวอย่างโค้ด — สำหรับใช้งานจริง
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — สำหรับใช้งานจริง”ลงทะเบียนฟอนต์ที่ shape ได้ เลือกใช้ตัว shaper และจัดการโหมดความล้มเหลวแบบมีชนิด สองแบบอย่างชัดเจน การเรนเดอร์ที่ซื่อตรงหรือข้อยกเว้นที่ชัดเจน — ไม่ใช่ run กลีฟที่ เสียหายอย่างเงียบ ๆ
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Config;use NextPDF\Core\DocumentFactory;use NextPDF\Exception\ComplexScriptShapingException;use NextPDF\Exception\HarfBuzzUnavailableException;use NextPDF\Graphics\ImageRegistry;use NextPDF\Html\Css\CssFeatureFlags;use NextPDF\Typography\FontRegistry;
$fontRegistry = new FontRegistry();$fontRegistry->register('/path/to/NotoSerifTibetan-Regular.ttf', alias: 'NotoSerifTibetan');
$config = (new Config())->withCssFeatureFlags( new CssFeatureFlags(complexTextShaping: true),);
$factory = new DocumentFactory($fontRegistry, new ImageRegistry(maxCacheBytes: 0));$doc = $factory->create($config);$doc->setLanguage('bo');$doc->addPage();
try { $doc->writeHtml('<div style="font-family: NotoSerifTibetan;">བོད་སྐད་</div>');} catch (HarfBuzzUnavailableException $e) { // The flag is on but libharfbuzz is not reachable. Install it, or turn the // flag off to fall back to the unshaped cmap path. throw $e;} catch (ComplexScriptShapingException $e) { // The run cannot be shaped faithfully (missing glyphs, link in run, // out-of-scope case). Fix the font or the content; do not ship broken glyphs. throw $e;}
$doc->save($out);กรณีขอบและข้อควรระวัง
หัวข้อที่มีชื่อว่า “กรณีขอบและข้อควรระวัง”- ต้องมี libharfbuzz เมื่อเปิด เมื่อแฟล็กเปิดและไม่มี libharfbuzz เอนจินจะโยน
HarfBuzzUnavailableExceptionมันไม่ลดทอนอย่างเงียบ ๆ - ปิดไม่ใช่ “shape แล้ว” เมื่อแฟล็กปิด run ที่อยู่ในขอบเขตจะเรนเดอร์ผ่านเส้นทาง cmap โดยไม่มี OpenType shaping นี่เป็นข้อจำกัดที่บันทึกไว้; อย่าเรียกมันว่าเอาต์พุต ที่ shape แล้ว
- ขอบเขตคือทิเบตและมองโกเลีย สคริปต์ซับซ้อนอื่นอยู่นอกขอบเขตสำหรับสไลซ์นี้
- ลิงก์ใน run จะ fail closed run ที่มี link annotation จะยก
ComplexScriptShapingExceptionเพราะสี่เหลี่ยมลิงก์ไม่สามารถตามการจัดเรียง ใหม่ที่ shape แล้วได้ - ไม่มีการอ้างคุณภาพด้านภาษา ความเท่าเทียมกับ HarfBuzz ได้รับการยืนยัน; คุณภาพด้านสุนทรียะโดยเจ้าของภาษาเป็นงานติดตามผลที่ถูกติดตามไว้และไม่ได้อ้าง
ประสิทธิภาพ
หัวข้อที่มีชื่อว่า “ประสิทธิภาพ”การ shaping เพิ่มการเรียก libharfbuzz หนึ่งครั้งต่อ run ที่อยู่ในขอบเขต บวกกับการ
ผ่านการส่งกลีฟ ซึ่งเป็นเชิงเส้นตามจำนวนกลีฟ งบประมาณ (wall_ms: 2000,
peak_mb: 128) เป็นไปตามโปรไฟล์ CJK/สคริปต์ซับซ้อน เพราะฟอนต์ที่ shape มีขนาด
ใหญ่และการจัดการฟอนต์ครอบงำต้นทุน
หมายเหตุด้านความปลอดภัย
หัวข้อที่มีชื่อว่า “หมายเหตุด้านความปลอดภัย”การเปิดใช้ตัว shaper นำเข้าการเรียก FFI ไปยัง libharfbuzz ซึ่งเป็นไลบรารีเนทีฟ ไฟล์ ฟอนต์ยังคงเป็นอินพุตไบนารีที่ไม่น่าเชื่อถือซึ่งจัดการโดยการตรวจสอบความถูกต้องที่มีอยู่ ของชั้น typography ก่อนที่จะถึงตัว shaper ตัว shaper บริโภคฟอนต์ที่ลงทะเบียนแล้วและ ตรวจสอบความถูกต้องแล้ว ถือว่าที่มาของฟอนต์ที่ผู้ใช้ปลายทางจัดหามาให้เป็นสิ่งที่ไม่น่า เชื่อถือ และจัดหา libharfbuzz จากแหล่งที่น่าเชื่อถือ
ความสอดคล้อง
หัวข้อที่มีชื่อว่า “ความสอดคล้อง”| ข้อความ | มาตรฐาน | ข้อ |
|---|---|---|
| run ที่ shape แล้วถูกส่งออกเป็น Identity-H CID สองไบต์ในฟอนต์ composite Type 0 | ISO 32000-2 | §9.7.4 |
| ตัว shaper ใช้ glyph substitution และ positioning ของ OpenType ของฟอนต์ | OpenType Specification | GSUB / GPOS |
| การก่อตัวของ cluster เป็นไปตามพร็อพเพอร์ตีสคริปต์สำหรับทิเบตและมองโกเลีย | Unicode Standard Annex | Tibetan and Mongolian |
นี่คือการนำมาใช้แบบ preview ที่กำหนดขอบเขตไว้ที่ทิเบตและมองโกเลีย ตรวจสอบความ เท่าเทียมเชิงวัตถุวิสัยกับ HarfBuzz แล้ว มันไม่อ้างคุณภาพด้านภาษาและไม่ยืนยันความ สอดคล้องแบบ end-to-end สำหรับไฟล์ที่ผลิตออกมา ไม่มีการคัดลอกข้อความมาตรฐานซ้ำ