ข้ามไปยังเนื้อหา
getnextpdf.com

ความเสถียร: ทดลอง

การรองรับการ 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)

Terminal window
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 ในแนวตั้ง จากบนลงล่าง

ตัว 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 นี้หรือใน เอกสารเหล่านี้ ความเท่าเทียมเชิงวัตถุวิสัยได้รับการยืนยัน; คุณภาพด้านสุนทรียะไม่ได้ ยืนยัน

สัญลักษณ์ตำแหน่งบทบาท
CssFeatureFlags::$complexTextShapingsrc/Html/CssFeatureFlags.phpแฟล็ก opt-in สำหรับตัว shaper ทิเบต/มองโกเลีย (ค่าเริ่มต้น false)
Config::withCssFeatureFlags(CssFeatureFlags $flags): selfsrc/Core/Config.phpแนบชุดแฟล็กเข้ากับการกำหนดค่าเอกสาร
ComplexScriptShapingExceptionsrc/Font/Shaper/ComplexScriptShapingException.phpถูกโยนเมื่อ run ที่อยู่ในขอบเขตไม่สามารถ shape ได้อย่างซื่อตรง
HarfBuzzUnavailableExceptionsrc/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 0ISO 32000-2§9.7.4
ตัว shaper ใช้ glyph substitution และ positioning ของ OpenType ของฟอนต์OpenType SpecificationGSUB / GPOS
การก่อตัวของ cluster เป็นไปตามพร็อพเพอร์ตีสคริปต์สำหรับทิเบตและมองโกเลียUnicode Standard AnnexTibetan and Mongolian

นี่คือการนำมาใช้แบบ preview ที่กำหนดขอบเขตไว้ที่ทิเบตและมองโกเลีย ตรวจสอบความ เท่าเทียมเชิงวัตถุวิสัยกับ HarfBuzz แล้ว มันไม่อ้างคุณภาพด้านภาษาและไม่ยืนยันความ สอดคล้องแบบ end-to-end สำหรับไฟล์ที่ผลิตออกมา ไม่มีการคัดลอกข้อความมาตรฐานซ้ำ