Contracts / งานตัวอักษร
ภาพรวมโดยสังเขป
หัวข้อที่มีชื่อว่า “ภาพรวมโดยสังเขป”โดเมนงานตัวอักษรกำหนดสัญญาของรีจิสทรีฟอนต์และการประมวลผลข้อความเบื้องต้น ได้แก่ FontRegistryInterface TextPreprocessorInterface และอ็อบเจกต์ค่าที่เปลี่ยนแปลงไม่ได้อย่าง TextPreprocessResult และ TextSegment ทั้งหมดอยู่ในสถานะ stable
การติดตั้ง
หัวข้อที่มีชื่อว่า “การติดตั้ง”composer require nextpdf/core:^3ภาพรวมเชิงแนวคิด
หัวข้อที่มีชื่อว่า “ภาพรวมเชิงแนวคิด”FontRegistryInterface คือที่จัดเก็บฟอนต์ซึ่งมีอายุการใช้งานครอบคลุมทั้งโพรเซส รีจิสทรีลงทะเบียนฟอนต์ชนิด TrueType OpenType TrueType Collection (TTC) หรือ Printer Font Binary (PFB) และคืนค่าเมตาดาตา FontInfo ที่ผ่านการวิเคราะห์แล้ว เนื่องจากรีจิสทรีมีอายุการใช้งานยาวกว่าเอกสารแต่ละฉบับ เวิร์กเกอร์จึงวิเคราะห์ฟอนต์แต่ละตัวเพียงครั้งเดียว คุณสามารถวอร์มอัปฟอนต์เป็นชุดระหว่างบูตได้ จากนั้นล็อกรีจิสทรีเพื่อป้องกันไม่ให้ทราฟฟิกโปรดักชันเปลี่ยนแปลงรีจิสทรี รีจิสทรีที่ถูกล็อกจะโยน LogicException เมื่อเรียก register() addFontDirectory() หรือ warmup() แต่การค้นหายังคงใช้งานได้ รีจิสทรียังรับไบต์ฟอนต์ดิบผ่าน registerFromBinary() ได้ด้วย บริดจ์ @font-face ใช้เมท็อดนี้เพื่อลงทะเบียนฟอนต์ที่ดึงมาจากแหล่งภายนอกหรือจาก data URI (uniform resource identifier) รีจิสทรีจัดเก็บเฉพาะข้อมูล PHP ล้วน ไม่มี resource handle จึงแชร์ข้ามพูลเวิร์กเกอร์ได้
เอนจินจะฝังและทำซับเซ็ตฟอนต์ทุกตัวที่ใช้งาน โปรแกรมฟอนต์ที่ฝังไว้จะติดไปกับไฟล์ Portable Document Format (PDF) เอกสารจึงเรนเดอร์เหมือนกันในโปรแกรมแสดงผลทุกตัว โดยไม่ขึ้นอยู่กับฟอนต์ระบบที่ติดตั้งไว้ — ISO 32000-2 §9 ซับเซ็ตของฟอนต์บรรจุเฉพาะกลิฟที่เอกสารอ้างอิงใช้งานจริงเท่านั้น เรื่องนี้สำคัญเป็นพิเศษสำหรับเนื้อหาภาษาจีน ญี่ปุ่น และเกาหลี (CJK) หรือเนื้อหาอื่นที่มี Unicode จำนวนมาก — ISO 32000-2 §9 สัญญาของรีจิสทรีเปิดเผยเมตาดาตาที่ผ่านการวิเคราะห์แล้ว ซึ่งขั้นตอนการทำซับเซ็ตและการฝังนำไปใช้
TextPreprocessorInterface ดักจับข้อความก่อนที่ข้อความจะเข้าสู่การจัดวางกลิฟ การทำซับเซ็ตฟอนต์ ToUnicode character map (CMap) และต้นไม้โครงสร้าง ตำแหน่งนี้เป็นคุณสมบัติด้านความปลอดภัย กล่าวคือพรีโพรเซสเซอร์ที่ปกปิดเนื้อหาจะลบเนื้อหานั้นออกก่อนที่เนื้อหาจะไปถึง content stream ซับเซ็ตของฟอนต์ หรือเมตาดาตา สัญญานี้มีอินแวเรียนต์สองข้อ พรีโพรเซสเซอร์ต้องไม่เพิ่มอักขระที่ส่งผลต่อเค้าโครง และต้องรักษาลำดับการอ่านเชิงตรรกะไว้ ความรับผิดชอบของพรีโพรเซสเซอร์คือการแทนที่เนื้อหา ไม่ใช่การจัดเค้าโครง ผลลัพธ์คือ TextPreprocessResult ที่เปลี่ยนแปลงไม่ได้ ซึ่งมีรายการค่า TextSegment ที่เรียงลำดับไว้ เซกเมนต์เป็นได้ทั้งแบบส่งผ่าน (pass-through) หรือแบบถูกปกปิด สำหรับเซกเมนต์ที่ถูกปกปิด ข้อความที่แสดงจะขึ้นอยู่กับโหมดการมาสก์ ได้แก่ ค่าว่างสำหรับสี่เหลี่ยมทึบสีดำ เครื่องหมายดอกจันตามความยาวของข้อความต้นฉบับ หรือป้ายกำกับแบบคงที่ originalCharCount บนเซกเมนต์เป็นคำใบ้ด้านการวัดที่ย้อนกลับไม่ได้ ใช้เพียงเพื่อกำหนดขนาดของสี่เหลี่ยมการปกปิดเท่านั้น ต้องไม่นำคำใบ้นี้ไปใช้สร้างเนื้อหาต้นฉบับขึ้นใหม่โดยเด็ดขาด
พื้นผิว API
หัวข้อที่มีชื่อว่า “พื้นผิว API”| ชนิด | ประเภท | สมาชิกหลัก | ความเสถียร | ตั้งแต่ |
|---|---|---|---|---|
FontRegistryInterface | interface | register(), get(), has(), all(), addFontDirectory(), warmup(), lock(), isLocked(), registerBase14(), registerFromBinary(), memoryUsage() | stable | 1.7.0 |
TextPreprocessorInterface | interface | process(string): TextPreprocessResult | stable | 1.9.0 |
TextPreprocessResult | final readonly class | $segments, hasRedactions(), getDisplayText() | stable | 1.9.0 |
TextSegment | final readonly class | $displayText, $isRedacted, $originalCharCount, $fillColor | stable | 1.9.0 |
TextPreprocessResult และ TextSegment ตรึงลายเซ็นของคอนสตรักเตอร์และพรอเพอร์ตีสาธารณะไว้แล้ว สามารถเพิ่มเมท็อดใหม่ได้ แต่พรอเพอร์ตีจะเปลี่ยนแปลงไม่ได้
ตัวอย่างโค้ด — เริ่มต้นใช้งานอย่างรวดเร็ว
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — เริ่มต้นใช้งานอย่างรวดเร็ว”<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->addPage();$doc->setFont('helvetica', 'B', 18);$doc->cell(0, 12, 'Bold heading', newLine: true);$doc->setFont('helvetica', '', 11);$doc->multiCell(0, 7, 'Body text rendered with a registered font.');$doc->save(__DIR__ . '/output/04-text-and-fonts.pdf');setFont() แปลงชื่อตระกูลฟอนต์ผ่าน FontRegistryInterface เอกสารแบบสแตนด์อโลนใช้รีจิสทรีส่วนตัว สำหรับเวิร์กเกอร์ ให้แชร์รีจิสทรีเดียวกัน ดูรายละเอียดได้ที่หน้า document
ตัวอย่างโค้ด — โปรดักชัน
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — โปรดักชัน”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\FontRegistryInterface;use NextPDF\Contracts\TextPreprocessorInterface;use NextPDF\Exception\NextPdfException;use Psr\Log\LoggerInterface;
final readonly class FontWarmupService{ public function __construct( private FontRegistryInterface $fonts, private TextPreprocessorInterface $preprocessor, private LoggerInterface $logger, ) {}
/** * Warm a font set at boot, then lock the registry. * * @param list<string> $fontFiles Absolute paths to font files. */ public function boot(array $fontFiles): void { try { $this->fonts->warmup($fontFiles); $this->fonts->lock(); } catch (NextPdfException $e) { $this->logger->error('Font warmup failed', ['error' => $e->getMessage()]);
throw $e; } }
public function redact(string $text): string { $result = $this->preprocessor->process($text);
return $result->hasRedactions() ? $result->getDisplayText() : $text; }}warmup() ตามด้วย lock() คือลำดับการบูตของเวิร์กเกอร์ หลังจาก lock() แล้ว การเปลี่ยนแปลงจะโยนข้อยกเว้น ส่วนการค้นหายังคงให้บริการทราฟฟิกต่อไป
กรณีขอบและข้อควรระวัง
หัวข้อที่มีชื่อว่า “กรณีขอบและข้อควรระวัง”- รีจิสทรีที่ถูกล็อกจะปฏิเสธเมท็อดที่เปลี่ยนแปลงสถานะทุกตัว ให้วอร์มอัปและล็อกรีจิสทรีระหว่างบูต อย่าเรียก
register()ระหว่างจัดการคำขอโดยเด็ดขาด registerFromBinary()เขียนไบต์ฟอนต์ลงไฟล์ชั่วคราวก่อนการวิเคราะห์ ข้อมูลฟอนต์ที่ไม่น่าเชื่อถือเป็นพื้นผิวการโจมตีของตัววิเคราะห์ — ให้ควบคุมผ่านExternalResourcePolicyInterface(ดูได้ที่หน้า security-policy)TextPreprocessorต้องไม่เพิ่มการขึ้นบรรทัดใหม่ อักขระปัดแคร่ (carriage return) หรือแท็บ อักขระเหล่านี้เปลี่ยนเค้าโครงและทำให้อินแวเรียนต์ข้อแรกของสัญญาเสียหายTextSegment::$originalCharCountเป็นเพียงคำใบ้เรื่องความกว้างเท่านั้น การนำคำใบ้นี้ไปใช้อนุมานเนื้อหาต้นฉบับจะทำให้การปกปิดไร้ผลและละเมิดอินแวเรียนต์ข้อที่สามของสัญญาTextPreprocessResult::getDisplayText()คืนค่าสตริงว่างสำหรับเซกเมนต์แบบกล่องทึบดำตามที่ออกแบบไว้ อย่าถือว่าเซกเมนต์ว่างเป็นความล้มเหลวของการประมวลผลเบื้องต้น
ประสิทธิภาพ
หัวข้อที่มีชื่อว่า “ประสิทธิภาพ”การวิเคราะห์ฟอนต์เป็นภาระหลักในการใช้งานครั้งแรก รีจิสทรีจะเฉลี่ยต้นทุนนั้นให้เกิดเพียงครั้งเดียวต่อหนึ่งโพรเซส หลังการวอร์มอัป get() และ has() เป็นการค้นหาในแมปแบบ O(1) memoryUsage() คืนค่า MemoryReport เพื่อให้เวิร์กเกอร์ติดตามแคชฟอนต์เทียบกับงบประมาณของตนได้ การประมวลผลข้อความเบื้องต้นเป็นเชิงเส้นตามความยาวของอินพุต รายการเซกเมนต์เพิ่มโอเวอร์เฮดที่มีขอบเขตจำกัดตามจำนวนรายการที่ตรงกับการปกปิด performance_budget ที่ 1500 ms wall และ 64 MB peak ครอบคลุมการวอร์มอัปสำหรับชุดฟอนต์ทั่วไปและการเรนเดอร์เอกสาร ต้นทุนการทำซับเซ็ตปรับตามจำนวนกลิฟที่ใช้งานจริง ไม่ใช่ตามตารางกลิฟทั้งหมดของฟอนต์ ดังนั้นการทำซับเซ็ตจึงลดขนาดเอาต์พุตและต้นทุนการเรนเดอร์สำหรับเนื้อหา CJK
หมายเหตุด้านความปลอดภัย
หัวข้อที่มีชื่อว่า “หมายเหตุด้านความปลอดภัย”โดเมนงานตัวอักษรมีพื้นผิวที่เกี่ยวข้องกับความปลอดภัยสองส่วน ส่วนแรกคืออินพุตฟอนต์ registerFromBinary() วิเคราะห์ไบต์ใด ๆ ก็ตาม ข้อมูลฟอนต์ที่ไม่น่าเชื่อถือต้องผ่าน ExternalResourcePolicyInterface ที่จำกัดขนาดไฟล์และจำนวนกลิฟก่อนจะไปถึงตัววิเคราะห์ ส่วนที่สองคือการปกปิด TextPreprocessorInterface ทำงานก่อนการจัดวางกลิฟ การทำซับเซ็ตฟอนต์ ToUnicode CMap และต้นไม้โครงสร้าง เพื่อให้เนื้อหาที่ถูกปกปิดไม่เข้าสู่อาร์ทิแฟกต์ที่เรนเดอร์ออกมาเลย การปกปิดด้วยการวางทับขณะวาด (paint-time overlay) จะทำให้ข้อความต้นฉบับรั่วไหลออกมาใน content stream และในซับเซ็ต ตำแหน่งของสัญญานี้ช่วยป้องกันข้อบกพร่องประเภทนั้น คำใบ้ด้านการวัดบนเซกเมนต์ถูกออกแบบให้ย้อนกลับไม่ได้โดยตั้งใจ ให้ถือว่าฟอนต์หรือข้อความใด ๆ ที่จัดหามาจากภายนอกเป็นสิ่งที่ไม่น่าเชื่อถือ
ความสอดคล้องตามมาตรฐาน
หัวข้อที่มีชื่อว่า “ความสอดคล้องตามมาตรฐาน”| ข้อกล่าวอ้าง | มาตรฐาน | ข้อกำหนด | หลักฐาน |
|---|---|---|---|
| ฟอนต์ทุกตัวที่เอกสารใช้งานจะถูกฝังไว้ เพื่อให้เอกสารเรนเดอร์ได้โดยไม่ต้องพึ่งพาฟอนต์ของระบบ | ISO 32000-2 | §9 | |
| ฟอนต์ที่ฝังไว้จะถูกทำซับเซ็ตให้เหลือเฉพาะกลิฟที่เอกสารอ้างอิง | ISO 32000-2 | §9 |
ข้อกำหนดทั้งสองข้อเป็นการเรียบเรียงใหม่ NextPDF ไม่ได้คัดลอกข้อความเชิงบรรทัดฐานมาแสดงซ้ำ PDF/A-4 บังคับให้ฝังฟอนต์ทุกตัว ความสอดคล้องดังกล่าวมีบันทึกไว้ในหน้า extraction และ accessibility
ดูเพิ่มเติม
หัวข้อที่มีชื่อว่า “ดูเพิ่มเติม”- Contracts: 41 อินเทอร์เฟซสาธารณะ (SPI) — ภาพรวมของ service provider interface และระดับความเสถียร
- Contracts / Document — บทบาทของรีจิสทรีในวงจรชีวิตของเอกสาร
- Contracts / Security Policy —
ExternalResourcePolicyInterfaceควบคุมไบต์ฟอนต์ที่ไม่น่าเชื่อถือ - Typography — โมดูลการจัดรูปทรงข้อความและเค้าโครง
- Font — การวิเคราะห์ฟอนต์ การทำซับเซ็ต และการฝัง
- Text — เอาต์พุตข้อความที่ใช้ผลลัพธ์จากพรีโพรเซสเซอร์