ฟอนต์แบบกำหนดเอง: สัญญาส่วนขยายสำหรับ FontRegistry
ภาพรวมโดยย่อ
หัวข้อที่มีชื่อว่า “ภาพรวมโดยย่อ”FontRegistryInterface กำหนดสัญญาที่มีอายุตลอดโปรเซสสำหรับการลงทะเบียนและค้นหาฟอนต์ ลงทะเบียนฟอนต์จากพาธไฟล์ ไดเรกทอรี หรือข้อมูลไบนารีดิบ แล้วล็อกรีจิสทรีเพื่อป้องกันไม่ให้เวิร์กเกอร์ในโปรดักชันแก้ไขได้
การติดตั้ง
หัวข้อที่มีชื่อว่า “การติดตั้ง”composer require nextpdf/core:^3ภาพรวมเชิงแนวคิด
หัวข้อที่มีชื่อว่า “ภาพรวมเชิงแนวคิด”font registry เป็น singleton ที่มีอายุนานกว่าอินสแตนซ์ Document แต่ละตัว โดยจัดเก็บเฉพาะข้อมูล PHP ล้วน ไม่มี resource handle หรือออบเจ็กต์ส่วนขยาย จึงแชร์ข้ามคำขอต่างๆในเวิร์กเกอร์ที่ทำงานต่อเนื่องยาวนานได้
ใช้วิธีลงทะเบียนได้หนึ่งในสามแบบต่อไปนี้:
- จากไฟล์
register()แยกวิเคราะห์ไฟล์.ttf,.otf,.ttc, หรือ.pfbแล้วคืนค่าเมทาดาตา สำหรับ TrueType Collection ให้ส่งดัชนี sub-font - จากไดเรกทอรี
addFontDirectory()เพิ่มพาธการค้นหาที่เอนจินจะสแกนเมื่อแปลงตระกูลฟอนต์จากชื่อ - จากข้อมูลไบนารี
registerFromBinary()แยกวิเคราะห์ไบต์ TrueType หรือ OpenType แบบดิบ ใช้วิธีนี้สำหรับบริดจ์@font-faceเมื่อฟอนต์มาจาก Uniform Resource Identifier (URI) แบบdata:หรือจากแหล่งระยะไกล
เพื่อลดความหน่วงของคำขอแรก ให้เรียก warmup() ตอนเริ่มต้นเวิร์กเกอร์เพื่อแยกวิเคราะห์ฟอนต์ชุดหนึ่งล่วงหน้า จากนั้นเรียก lock() หลังจาก lock() เมธอดแก้ไขทุกตัวจะโยน LogicException ได้แก่ register(), addFontDirectory(), warmup(), registerBase14(), และ registerFromBinary() เมธอดค้นหายังคงใช้งานได้: get(), has(), all(), และ getSearchDirectories() การล็อกนี้ช่วยปกป้องเวิร์กเกอร์ในโปรดักชันโดยรับประกันว่าไม่มีคำขอใดเปลี่ยนแปลงชุดฟอนต์ที่ใช้ร่วมกันได้
ในกรณีส่วนใหญ่ คุณไม่จำเป็นต้องอิมพลีเมนต์ FontRegistryInterface เอนจินจัดเตรียมการอิมพลีเมนต์ไว้ และคุณเพียงเรียกใช้เท่านั้น ให้อิมพลีเมนต์เองเฉพาะเมื่อต้องการกลยุทธ์การแปลงฟอนต์แบบกำหนดเอง เช่น กลยุทธ์ที่รองรับด้วยที่เก็บแบบกำหนดที่อยู่ตามเนื้อหา ไม่ว่ากรณีใด สัญญายังคงเป็นขอบเขต
ขอบเขต API
หัวข้อที่มีชื่อว่า “ขอบเขต API”NextPDF\Contracts\FontRegistryInterface (เสถียร ตั้งแต่ 1.7.0):
| เมธอด | คืนค่า | วัตถุประสงค์ |
|---|---|---|
register(string $fontFile, string $alias, int $fontIndex) | FontInfo | แยกวิเคราะห์และลงทะเบียนไฟล์ฟอนต์ โยนข้อยกเว้นเมื่อรีจิสทรีถูกล็อกหรือแยกวิเคราะห์ไฟล์ไม่ได้ |
registerFromBinary(string $fontData, string $alias) | FontInfo | ลงทะเบียนฟอนต์จากไบต์ TrueType หรือ OpenType แบบดิบ |
registerBase14(string $key, FontInfo $font) | void | ลงทะเบียนฟอนต์มาตรฐาน Base 14 ที่สร้างไว้ล่วงหน้า |
addFontDirectory(string $directory) | void | เพิ่มไดเรกทอรีสำหรับค้นหาฟอนต์ |
warmup(array $fontFiles) | void | แยกวิเคราะห์ชุดฟอนต์ล่วงหน้าตอนเริ่มต้นเวิร์กเกอร์ |
lock() | void | ตรึงรีจิสทรีเพื่อป้องกันการแก้ไขเพิ่มเติม |
isLocked() | bool | รายงานว่ารีจิสทรีถูกล็อกหรือไม่ |
get(string $family, string $style) | FontInfo | null | ค้นหาฟอนต์ตามตระกูลและสไตล์ |
has(string $key) | bool | ตรวจสอบว่ามีคีย์การลงทะเบียนอยู่หรือไม่ |
all() | array<string, FontInfo> | คืนค่าฟอนต์ทั้งหมดที่ลงทะเบียนไว้ |
getSearchDirectories() | list<string> | คืนค่าไดเรกทอรีสำหรับค้นหาตามลำดับ |
memoryUsage() | MemoryReport | รายงานการใช้หน่วยความจำของรีจิสทรีในปัจจุบัน |
ตัวอย่างโค้ด — การเริ่มต้นอย่างรวดเร็ว
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — การเริ่มต้นอย่างรวดเร็ว”<?php
declare(strict_types=1);
use NextPDF\Contracts\FontRegistryInterface;
/** @var FontRegistryInterface $fonts */$info = $fonts->register('/srv/fonts/Inter-Regular.ttf', 'Inter');
if (!$fonts->has('inter')) { throw new RuntimeException('Inter failed to register');}ตัวอย่างโค้ด — โปรดักชัน
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — โปรดักชัน”เมื่อเริ่มต้นเวิร์กเกอร์ ให้วอร์มชุดฟอนต์ ล็อกรีจิสทรี และติดตามการโหลดแต่ละครั้งเพื่อการติดตามสิทธิ์การใช้งาน ตัวอย่างนี้ใช้เฉพาะชนิดข้อมูลสาธารณะเท่านั้น
<?php
declare(strict_types=1);
use NextPDF\Contracts\FontRegistryInterface;use NextPDF\Event\Content\FontLoadedEvent;use NextPDF\Event\EventDispatcher;use NextPDF\Event\ListenerProvider;use Psr\Log\LoggerInterface;
final class FontWarmup{ /** @param list<string> $fontFiles */ public function __construct( private readonly FontRegistryInterface $fonts, private readonly LoggerInterface $logger, private readonly array $fontFiles, ) {}
public function boot(): EventDispatcher { $listeners = new ListenerProvider(); $listeners->addListener( FontLoadedEvent::class, function (FontLoadedEvent $event): void { $this->logger->info('font.loaded', [ 'family' => $event->family, 'style' => $event->style, 'type' => $event->fontType->name, ]); }, );
if (!$this->fonts->isLocked()) { $this->fonts->warmup($this->fontFiles); $this->fonts->lock(); }
return new EventDispatcher($listeners); }}กรณีขอบและข้อควรระวัง
หัวข้อที่มีชื่อว่า “กรณีขอบและข้อควรระวัง”- รีจิสทรีที่ถูกล็อก หลังจาก
lock()การแก้ไขใดๆจะโยนLogicExceptionตรวจสอบisLocked()ก่อนวอร์มแบบมีเงื่อนไขในเวิร์กเกอร์ที่ถูกนำกลับมาใช้ใหม่ - การลงทะเบียนแบบไบนารีไม่ถูกแคชตามคีย์
registerFromBinary()เขียนลงไฟล์ชั่วคราวแล้วแยกวิเคราะห์ไฟล์นั้น ใช้FontInfoที่คืนกลับมาเป็นแฮนเดิล - ดัชนีของ TrueType Collection (TTC) สำหรับ TrueType Collection อาร์กิวเมนต์ตัวที่สามของ
register()เป็นตัวเลือก sub-font ค่าเริ่มต้น0เลือกหน้าฟอนต์แรก - การแปลงตระกูลฟอนต์
get()คืนค่าnullสำหรับคู่ของตระกูลและสไตล์ที่ไม่รู้จัก อย่าสันนิษฐานเด็ดขาดว่าผลลัพธ์จะไม่เป็น null
ประสิทธิภาพ
หัวข้อที่มีชื่อว่า “ประสิทธิภาพ”warmup() ย้ายต้นทุนการแยกวิเคราะห์จากคำขอแรกไปยังขั้นเริ่มต้นเวิร์กเกอร์ เมธอดของรีจิสทรีใช้ข้อมูล PHP ล้วน และการค้นหาเป็นการอ่านแมปในเวลาคงที่ เรียก memoryUsage() เพื่อประเมินขนาดชุดฟอนต์ที่อยู่ในหน่วยความจำของเวิร์กเกอร์เทียบกับงบประมาณหน่วยความจำของคุณ
หมายเหตุด้านความปลอดภัย
หัวข้อที่มีชื่อว่า “หมายเหตุด้านความปลอดภัย”ฟอนต์ที่ลงทะเบียนแล้วสามารถฝังลงในเนื้อหา Portable Document Format (PDF) ได้ ตรวจสอบความถูกต้องของแหล่งที่มาของฟอนต์ก่อนลงทะเบียน อย่าลงทะเบียนข้อมูลไบนารีที่ผู้โจมตีควบคุมโดยไม่ตรวจสอบขนาดและรูปแบบ ใช้ฮุก FontLoadedEvent เพื่อบังคับใช้การปฏิบัติตามสิทธิ์การใช้งานฟอนต์ และบันทึกว่าเอกสารฝังหน้าฟอนต์ใดบ้าง
ความสอดคล้อง
หัวข้อที่มีชื่อว่า “ความสอดคล้อง”ไม่มีข้อกำหนดเชิงบรรทัดฐานด้านการลงนามหรือการจัดเก็บถาวรที่นำมาใช้ การฝังฟอนต์และการทำ subset สอดคล้องกับโมเดลฟอนต์ของ PDF 2.0 ตัวทำ subset ภายในเป็นผู้รับผิดชอบความสอดคล้องนั้น ไม่ใช่สัญญานี้
บริบทเชิงพาณิชย์
หัวข้อที่มีชื่อว่า “บริบทเชิงพาณิชย์”NextPDF Enterprise เพิ่มการรับรองสิทธิ์การใช้งานฟอนต์และนโยบายการทำ subset ที่ผ่านการตรวจสอบไว้บน FontRegistryInterface ตัวเดียวกัน โค้ดลงทะเบียนของคุณทำงานเหมือนกันในทุกรุ่นเพราะสัญญาเป็นขอบเขต
ดูเพิ่มเติม
หัวข้อที่มีชื่อว่า “ดูเพิ่มเติม”- ภาพรวมการสร้างส่วนขยาย
- ทริกเกอร์การกระทำและ event listener
- เค้าโครงแบบกำหนดเองและการดักจับข้อความ
- กฎความเสถียรของ SPI
สัญญาและโมดูลที่เกี่ยวข้อง
หัวข้อที่มีชื่อว่า “สัญญาและโมดูลที่เกี่ยวข้อง”- เอกสารอ้างอิงโมดูล Font — การอิมพลีเมนต์รีจิสทรี การแยกวิเคราะห์ และกลไกภายในของการทำ subset
- เอกสารอ้างอิงสัญญา Typography — รายการแคตาล็อกสำหรับ
FontRegistryInterface - ทริกเกอร์การกระทำและ event listener —
FontLoadedEventและ dispatcher - เค้าโครงแบบกำหนดเองและการดักจับข้อความ — สัญญากลยุทธ์ระดับเดียวกันที่ทำงานตอนเรนเดอร์
- กฎความเสถียรของ SPI — คำมั่นสัญญาของอินเทอร์เฟซที่อยู่เบื้องหลัง
FontRegistryInterface
อภิธานศัพท์ให้นิยามของ font registry, image registry, และ event listener ดูคำนิยามอย่างเป็นทางการได้ในอภิธานศัพท์ที่เผยแพร่