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

จัดเตรียมฟอนต์ในการใช้งานจริง

PDF ของคุณเรนเดอร์ถูกต้องบนแล็ปท็อป แล้วส่งไปยังคอนเทนเนอร์และออกมาเป็นแถวกล่องว่าง — glyph แบบ “tofu” — หรือมีสระและอักขระที่ไม่ใช่ละตินหายไป สาเหตุแทบจะเหมือนกันเสมอ คือ ฟอนต์ที่คุณเลือกไม่มีอยู่ใน image ที่ deploy ออกไป

เอนจิน NextPDF แบบเนทีฟภายในกระบวนการแก้ฟอนต์จาก ไฟล์ฟอนต์ ที่ font registry อ่านได้ มันไม่ค้นพบฟอนต์ของ OS หรือ fontconfig โดยอัตโนมัติ — ไฟล์ฟอนต์ที่ติดตั้ง โดย OS จะช่วยได้ก็ต่อเมื่อคุณลงทะเบียนไฟล์เหล่านั้นอย่างชัดเจน หรือเพิ่มไดเรกทอรีที่ บรรจุไฟล์เหล่านั้นลงในพาธค้นหาของ FontRegistry คอนเทนเนอร์ที่ build จาก base image แบบบางไม่มีฟอนต์ที่ติดตั้งด้วย apt/apk และแม้แต่เมื่อมี เอนจินเนทีฟก็ เพิกเฉยต่อมันเว้นแต่คุณจะชี้ registry ไปยังไฟล์ของมัน วิธีแก้คือบันเดิลไฟล์ฟอนต์ จริงไว้ในแอปพลิเคชันหรือ image ของคุณ และลงทะเบียนมันกับเอนจิน registry อ่านไฟล์ TrueType (.ttf), OpenType (.otf) และ TrueType Collection (.ttc) ส่วน Type1 (.pfb) แบบ legacy ก็รับได้แต่ไม่ค่อยจำเป็นสำหรับงานใหม่

ก่อนเริ่ม ให้ยืนยันว่าชิ้นส่วนเหล่านี้พร้อมแล้ว

  • ติดตั้ง NextPDF core แล้ว
  • คุณมีไฟล์ฟอนต์จริงที่ตั้งใจจะใช้ และคุณได้รับอนุญาตให้ฝังมัน สิทธิ์การฝังเป็น ความรับผิดชอบของคุณ — ดู ฝังและทำ subset ฟอนต์ TrueType
  • build ของคุณสามารถคัดลอกไฟล์เหล่านั้นลงใน artifact ที่ deploy ได้

นี่คือ how-to ด้านการปฏิบัติการ โค้ดมีน้อยที่สุด งานอยู่ที่ build และเลย์เอาต์ของ ระบบไฟล์ สำหรับกลไกระดับ API ของการลงทะเบียนและทำ subset หน้าฟอนต์เดียว ให้อ่าน สูตร embed-and-subset ที่ลิงก์ไว้ด้านบน หน้านี้ครอบคลุมการนำไฟล์ ขึ้นไปบนเครื่อง และชี้เอนจินไปยังมัน

ทำไมเอนจินเนทีฟจึงไม่พบฟอนต์ของ OS โดยอัตโนมัติ

หัวข้อที่มีชื่อว่า “ทำไมเอนจินเนทีฟจึงไม่พบฟอนต์ของ OS โดยอัตโนมัติ”

มีเส้นทางการเรนเดอร์ที่แตกต่างกันสองเส้นทาง และเรื่องของฟอนต์ต่างกันระหว่างทั้งสอง

  • เอนจินเนทีฟภายในกระบวนการ (ค่าเริ่มต้น Document / writeHtml): เอนจิน ไม่เรียกเข้าระบบฟอนต์ของระบบปฏิบัติการหรือ fontconfig เพื่อการค้นหา มันแก้ หน้าฟอนต์ผ่าน font registry ซึ่งอ่านไฟล์ฟอนต์ที่คุณลงทะเบียนไว้ หรือค้นหา ไฟล์หนึ่งภายในไดเรกทอรีที่คุณกำหนดเป็นพาธค้นหา การติดตั้งฟอนต์ด้วย apt-get install fonts-noto หรือการรัน fc-cache ไม่ได้ทำอะไรด้วยตัวมันเอง — เอนจินเนทีฟเห็นไฟล์เหล่านั้นก็ต่อเมื่อคุณลงทะเบียนมันหรือเพิ่มไดเรกทอรีของมัน ลงในพาธค้นหาของ registry
  • Chrome bridge (ตัวเรนเดอร์ HTML-to-PDF ที่ขับเบราว์เซอร์แบบ headless): เส้นทางนี้ ใช้ ฟอนต์ที่ติดตั้งของโฮสต์ผ่านการค้นหาฟอนต์ปกติของเบราว์เซอร์ ดังนั้นแพ็กเกจฟอนต์ apt/apk และ fontconfig จึงมีความสำคัญที่นั่น

หากคุณอ่านคำแนะนำทั่วไปว่า “ติดตั้งแพ็กเกจฟอนต์ของระบบเหล่านี้ใน Dockerfile ของคุณ” มันใช้กับ Chrome bridge ไม่ใช่ กับเอนจินเนทีฟที่ครอบคลุมในหน้านี้ สำหรับการ สร้างแบบเนทีฟ ให้บันเดิลไฟล์และลงทะเบียนมัน

วางไฟล์ฟอนต์ไว้ในแผนผังแอปพลิเคชันของคุณเพื่อให้มันมีการกำหนดเวอร์ชันและส่งไปกับ ทุก build ตำแหน่งตามแบบแผนคือไดเรกทอรี resources/fonts/

your-app/
├── resources/
│ └── fonts/
│ ├── DejaVuSans.ttf
│ ├── DejaVuSans-B.ttf
│ └── NotoSansCJK-Regular.ttc
└── src/

ตั้งชื่อไฟล์เพื่อให้การค้นหาไดเรกทอรีของเอนจินหาไฟล์ได้ตามตระกูลและสไตล์ เมื่อคุณ ลงทะเบียน ไดเรกทอรี (แทนที่จะเป็นไฟล์ที่ระบุ) แล้วเรียก setFont('DejaVuSans', 'B', 12) ในภายหลัง เอนจินจะมองหาไฟล์เช่น DejaVuSans-B.ttf, DejaVuSansB.ttf หรือ DejaVuSans.ttf ในแต่ละไดเรกทอรีที่ กำหนดค่าไว้ การค้นหาไดเรกทอรีสร้างชื่อผู้เข้าชิงเหล่านั้นจาก รหัสสไตล์ตัวอักษร เดียวที่คุณส่งให้ setFont (B สำหรับตัวหนา, I สำหรับตัวเอียง, BI สำหรับ ตัวหนาเอียง) ไม่ใช่คำที่สะกดเต็ม — ดังนั้นรูปแบบที่เชื่อถือได้คือ Family-<StyleCode>.ttf (ตัวอย่างเช่น DejaVuSans-B.ttf หรือ DejaVuSans-BI.ttf) ไม่ใช่ Family-Bold.ttf ไฟล์ที่ชื่อ DejaVuSans-Bold.ttf จะไม่มีวันถูกพบโดยการค้นหาไดเรกทอรี หากต้องการใช้ไฟล์ เช่นนั้น ให้ลงทะเบียนมันอย่างชัดเจนด้วย register() — ซึ่งแยกวิเคราะห์ฟอนต์และ จัดทำดัชนีมันภายใต้ตระกูลและสไตล์ที่อ่านจาก name table ของไฟล์เอง ดังนั้นชื่อไฟล์ ที่สะกดเต็มจึงไม่สำคัญอีกต่อไป (ดูขั้นที่ 2)

คุณมีสองวิธีที่เทียบเท่ากันในการทำให้ไฟล์มองเห็นได้ ทั้งสองผ่าน NextPDF\Typography\FontRegistry ซึ่ง implement NextPDF\Contracts\FontRegistryInterface

ลงทะเบียนไฟล์ที่ระบุภายใต้ alias เมื่อคุณควบคุมหน้าฟอนต์ที่แน่นอน

use NextPDF\Typography\FontRegistry;
$registry = new FontRegistry();
$registry->register(__DIR__ . '/../resources/fonts/DejaVuSans.ttf', alias: 'DejaVuSans');

register(string $fontFile, string $alias = '', int $fontIndex = 0) รับไฟล์ .ttf, .otf และ .ttc รวมถึง Type1 .pfb แบบ legacy (ซึ่งโหลด metrics .afm คู่กันจากพาธเดียวกัน) $fontIndex เลือก sub-font ภายใน TrueType Collection (.ttc) register() แยกวิเคราะห์ไฟล์และจัดทำดัชนีหน้าฟอนต์ตามตระกูล และสไตล์ที่อ่านจาก name table ของมันเอง ดังนั้นชื่อไฟล์ทางกายภาพจึงไม่เกี่ยวข้อง เมื่อลงทะเบียนแล้ว $alias ที่เป็นทางเลือกเป็นเพียงชื่อค้นหาเพิ่มเติมสำหรับ หน้าฟอนต์ — มันไม่ใช่รหัสสไตล์และไม่เปลี่ยนสไตล์ที่ไฟล์ให้ ส่งมันเมื่อคุณต้องการ เรียก setFont() ด้วยชื่ออื่นนอกเหนือจากชื่อตระกูลที่ฝังของฟอนต์ มันคืน FontInfo ที่แยกวิเคราะห์แล้ว

ลงทะเบียนไดเรกทอรี เมื่อคุณต้องการให้เอนจินแก้หน้าฟอนต์ตามชื่อจากโฟลเดอร์ที่ คุณควบคุม

$registry = new FontRegistry('/var/www/app/resources/fonts');
// or, equivalently, after construction:
$registry->addFontDirectory('/var/www/app/resources/fonts');

constructor ของ FontRegistry รับไดเรกทอรีนั้นเป็น argument แรก และ addFontDirectory() เพิ่มพาธค้นหาเพิ่มเติม Document เปล่าๆ ก็เปิดเผย addFontDirectory() สำหรับกรณี standalone ด้วย

หากต้องการใช้ registry ที่คุณ populate เอง ให้สร้างเอกสารผ่าน DocumentFactory ซึ่งเชื่อม registry นั้นเข้ากับทุกเอกสารที่มันสร้าง

use NextPDF\Core\DocumentFactory;
use NextPDF\Graphics\ImageRegistry;
$factory = new DocumentFactory($registry, new ImageRegistry(maxCacheBytes: 0));
$doc = $factory->create();
$doc->addPage();
$doc->setFont('DejaVuSans', '', 12);
$doc->cell(0, 10, 'Réndéred wîth a bundled face — no tofu.', newLine: true);
$doc->save('/tmp/out.pdf');

Document::createStandalone() สร้าง registry ภายใน ของตัวเอง ดังนั้น หน้าฟอนต์ที่คุณลงทะเบียนบน FontRegistry แยกต่างหากจึงมองไม่เห็น ในการใช้งานจริง ให้ผ่าน DocumentFactory (หรือ factory ของเฟรมเวิร์กของคุณ) เพื่อให้ registry ที่ populate แล้วเป็นตัวที่ใช้งานอยู่

แต่ละ integration ของเฟรมเวิร์กเปิดเผยแนวคิดสองอย่างเดียวกันเป็นการกำหนดค่า ดังนั้น คุณจึงแทบไม่ต้องแตะ registry โดยตรง ในไฟล์ nextpdf.php ของแพ็กเกจ Laravel fonts_path (ค่าเริ่มต้น NEXTPDF_FONTS_PATH ที่ fallback ไปยัง resource_path('fonts')) คือไดเรกทอรีค้นหา และ preload_fonts คือรายการพาธไฟล์ ฟอนต์แบบสัมบูรณ์ที่แยกวิเคราะห์ ณ เวลา boot ของ worker ชี้ fonts_path ไปยัง ไดเรกทอรีที่คุณบันเดิล แล้วหน้าฟอนต์ที่คุณลงทะเบียนจะแก้ได้อัตโนมัติ

ในคอนเทนเนอร์ ไฟล์ฟอนต์ต้องเป็นส่วนหนึ่งของเลเยอร์ image คัดลอกเข้ามา ณ เวลา build เนื่องจากโค้ดแอปพลิเคชันและฟอนต์ส่งไปด้วยกันเมื่อคุณบันเดิลมันไว้ใต้ resources/fonts/ คำสั่ง COPY . . ปกติจึงนำมันไปด้วยอยู่แล้ว หากคุณเก็บฟอนต์ไว้ นอก build context ให้คัดลอกมันอย่างชัดเจนและตรวจสอบให้แน่ใจว่าพาธที่คุณลงทะเบียน ตรงกับพาธภายใน image

# Native engine: NO system font packages are required.
# The native engine does not discover OS-installed fonts automatically; install OS
# font packages (`apt-get install fonts-*`) only if you also register them or point
# the font registry's search directory at their files.
FROM php:8.4-cli
WORKDIR /var/www/app
# Bundle the application, including resources/fonts/, into the image.
COPY . /var/www/app
# Make the bundled directory the engine's font search path.
ENV NEXTPDF_FONTS_PATH=/var/www/app/resources/fonts
CMD ["php", "bin/generate.php"]

บน ระบบไฟล์ที่เปลี่ยนแปลงไม่ได้หรืออ่านอย่างเดียว (คอนเทนเนอร์ readOnlyRootFilesystem, image แบบ serverless หรือโฮสต์ที่เสริมความแข็งแกร่ง) ไฟล์ฟอนต์ถูกอ่าน ณ เวลาสร้างและไม่เคยถูกเขียน ดังนั้น mount แบบอ่านอย่างเดียวจึง ใช้ได้ การเขียนเดียวที่เอนจินอาจต้องการคือ cache ของฟอนต์ที่แยกวิเคราะห์แล้ว: ให้ ไดเรกทอรีนั้นเป็น writable volume ขนาดเล็ก หรือ warm และ lock registry ณ เวลา boot (หัวข้อถัดไป) เพื่อไม่ให้มีการพยายามเขียนหรือลงทะเบียน ณ runtime

ใน worker ที่ทำงานยาวนาน ให้แยกวิเคราะห์ทุกหน้าฟอนต์หนึ่งครั้ง ณ เวลา boot จากนั้น lock registry เพื่อไม่ให้มีการลงทะเบียนต่อคำขอเกิดขึ้น และให้การกำหนดค่าผิด ล้มเหลวอย่างชัดเจนแทนที่จะ fallback เงียบๆ

$registry = new FontRegistry('/var/www/app/resources/fonts');
$registry->warmup([
'/var/www/app/resources/fonts/DejaVuSans.ttf',
'/var/www/app/resources/fonts/DejaVuSans-B.ttf',
]);
$registry->lock();

หลัง lock() แล้ว register(), addFontDirectory() และ warmup() จะ throw ซึ่งเปลี่ยนความผิดพลาด “พาธผิดใน image” ให้เป็นการล้มเหลวที่ boot แบบเด็ดขาด แทนที่ จะเป็นหน้า tofu ในการใช้งานจริง

เพิ่มการตรวจสอบ smoke ของการ deploy ที่เรนเดอร์หนึ่งหน้าด้วยแต่ละหน้าฟอนต์ที่ต้องการ การตรวจสอบส่วนหัวด้านล่างยืนยันเพียงว่าเอกสาร สร้างเอาต์พุต เท่านั้น — มันไม่ พิสูจน์ว่าฟอนต์แยกวิเคราะห์ ฝัง หรือแม้แต่แก้ได้ หน้าฟอนต์ที่เอนจินหาไม่พบอาจ fallback ไปยัง base font มาตรฐาน (และภายใต้พฤติกรรม non-strict ปัจจุบัน conformance profile อาจให้ตัวแทนที่บันเดิลไว้แทน) ในขณะที่ยังส่งออก PDF ที่ถูกต้อง และไม่ว่างเปล่า — ดังนั้นแม้ในจุดที่ fallback นั้นเกิดขึ้น การตรวจสอบนี้เพียงอย่าง เดียวก็จะไม่จับการเสื่อมถอยเงียบๆ ได้ อย่าพึ่งพาว่า fallback จะรับประกันหรือเงียบ ในทุกเส้นทาง ให้ตรวจสอบโปรแกรมที่ฝังโดยตรง ดังที่แสดงด้านล่าง

$doc = $factory->create();
$doc->addPage();
$doc->setFont('DejaVuSans', '', 12);
$doc->cell(0, 10, 'warmup check', newLine: true);
$pdf = $doc->getPdfData();
// `getPdfData()` would normally throw on a real failure; this header check only
// confirms serialization returned PDF bytes, not that any specific font resolved.
if (!str_starts_with($pdf, '%PDF')) {
throw new RuntimeException('Font warmup smoke check produced no PDF output.');
}

หากต้องการให้การ deploy ล้มเหลวจริงเมื่อหน้าฟอนต์หายไป ให้ตรวจสอบ PDF ที่ส่งออก หาโปรแกรมฟอนต์ที่ฝัง หน้าฟอนต์ที่ลงทะเบียนแล้วที่แก้ได้นำพา font dictionary ของตัวเองพร้อมโปรแกรมที่ฝัง ดังนั้นการยืนยันการมีอยู่ของมันจึงจับกรณีที่หน้าฟอนต์ ที่ร้องขอไม่เคยแก้ได้ (ไม่ว่าเอนจินจะ fallback ไปยังอะไร) ที่การตรวจสอบส่วนหัวพลาด ไป คีย์ใดถือโปรแกรมขึ้นอยู่กับรูปแบบ outline: outline แบบ TrueType (.ttf, .ttc) ใช้ /FontFile2, outline แบบ CFF/OpenType (.otf ที่มี outline PostScript) ใช้ /FontFile3 และ Type1 (.pfb) แบบ legacy ใช้ /FontFile

หากสิ่งที่คุณต้องการคือสัญญาณ “มีโปรแกรมฟอนต์ฝังอยู่บ้าง” แบบไม่ขึ้นกับรูปแบบ ให้ทดสอบหา /FontFile เพียงตัวเดียว — เพราะ /FontFile เป็นสตริงย่อยของทั้ง /FontFile2 และ /FontFile3 การตรวจสอบสตริงย่อยเปล่าๆ จึงตรงกับทุกประเภท outline อยู่แล้ว และการเพิ่ม /FontFile2//FontFile3 เป็นกิ่ง || เพิ่มเติมจึงซ้ำซ้อน

if (!str_contains($pdf, '/FontFile')) {
throw new RuntimeException('No embedded font program found — face fell back.');
}

อย่างไรก็ตาม สตริงย่อย /FontFile เปล่าๆ ไม่สามารถแยกประเภท outline ออกจากกันได้ หากต้องการแยกแยะมัน ให้จับคู่กับโทเคนที่แน่นอนพร้อม word boundary เพื่อให้ /FontFile ไม่ทำงานบน /FontFile2 หรือ /FontFile3 ด้วย

$isTrueType = preg_match('~/FontFile2\b~', $pdf) === 1; // TrueType (.ttf/.ttc)
$isCffOtf = preg_match('~/FontFile3\b~', $pdf) === 1; // CFF/OpenType (.otf)
$isType1 = preg_match('~/FontFile(?![23])\b~', $pdf) === 1; // Type1 (.pfb)
if (!$isTrueType && !$isCffOtf && !$isType1) {
throw new RuntimeException('No embedded font program found — face fell back.');
}

ไม่ว่าจะวิธีใด ให้จัดการกับสิ่งนี้เป็น ฮิวริสติกแบบหยาบเท่านั้น ไม่ใช่ deploy gate ที่เชื่อถือได้ การค้นหาไบต์ดิบบน PDF ที่ serialize แล้วไม่แม่นยำด้วยหลายเหตุผล โปรแกรมฟอนต์อาจอยู่ภายใน compressed object stream (ที่ /FontFile* ไม่เคย ปรากฏเป็นไบต์ธรรมดา), incremental update สามารถต่อท้ายหรือแทนที่วัตถุ, ฟอนต์ที่ไม่ฝังหรือ standard-14 ไม่นำพาโปรแกรมฟอนต์เลยโดยชอบธรรม และ ความแตกต่างของ serialization (ลำดับวัตถุ, whitespace, การเข้ารหัสชื่อ) สามารถย้ายหรือซ่อนโทเคนได้ อย่างดีที่สุดมันยืนยันว่าหน้าฟอนต์ บางส่วน ฝังโปรแกรม ไว้ — ไม่ใช่ว่าหน้าฟอนต์ ที่ระบุ ที่คุณต้องการแก้ได้

สำหรับ deploy gate จริง อย่าพึ่งพาการค้นหาไบต์ แยกวิเคราะห์ PDF ที่ส่งออกด้วย parser หรือตัวตรวจสอบวัตถุ PDF ที่เหมาะสม และยืนยันว่าวัตถุฟอนต์สำหรับหน้าฟอนต์ เป้าหมายของคุณนำพาโปรแกรม /FontFile//FontFile2//FontFile3 ที่ฝังไว้ หรือใช้ การยืนยันการแก้ฟอนต์ที่ผลิตภัณฑ์จัดให้หากมีให้ใน integration ของคุณ regex ที่ ตระหนักถึงโทเคนด้านบนมีประโยชน์สำหรับการตรวจสอบความสมเหตุสมผลในเครื่องอย่างรวดเร็ว แต่การตรวจสอบเชิงโครงสร้างคือสิ่งที่ควรทำให้การ deploy ล้มเหลว โครงสร้างการฝังและ font dictionary อธิบายไว้ใน ฝังและทำ subset ฟอนต์ TrueType

  • createStandalone() มี registry ของตัวเอง หน้าฟอนต์ที่ลงทะเบียนบน FontRegistry แยกต่างหากจะมองไม่เห็นโดยเอกสาร standalone ใช้ DocumentFactory (หรือ factory ของเฟรมเวิร์ก) เพื่อให้ registry ของคุณเป็นตัวที่ทำงานอยู่
  • ไฟล์สไตล์ต้องมีอยู่จริงเป็นไฟล์ เอนจินไม่สังเคราะห์ตัวหนาหรือตัวเอียงจาก หน้าฟอนต์ปกติ หากคุณเรียก setFont('DejaVuSans', 'B') การค้นหาไดเรกทอรีมองหา DejaVuSans-B.ttf, DejaVuSansB.ttf หรือ DejaVuSans.ttf (ตัวพิมพ์เล็กและ รูปแบบ .otf ด้วย) — มันสร้างผู้เข้าชิงจากรหัสสไตล์ B ตามตัวอักษร ดังนั้นจึง ไม่เคยมองหา DejaVuSans-Bold.ttf ไฟล์ที่มีชื่อสะกดเต็มเช่น DejaVuSans-Bold.ttf จะแก้ได้ก็ต่อเมื่อคุณลงทะเบียนมันอย่างชัดเจนด้วย register() ซึ่งจัดทำดัชนีมัน ตามตระกูลและสไตล์ที่อ่านจาก name table ของไฟล์เองโดยไม่คำนึงถึงชื่อไฟล์ การพึ่งพา การค้นหาไดเรกทอรีเพื่อหามันทำให้พลาด หลังจากนั้นเอนจินอาจ fallback ไปยัง base font (ไม่ใช่เส้นทางที่รับประกันหรือเงียบเสมอ) — การเสื่อมถอยที่หน้านี้เตือนถึง
  • พาธ stream-wrapper และพาธรีโมตถูกปฏิเสธ registry ปฏิเสธพาธที่มี URI scheme หรือ null byte ลงทะเบียนเฉพาะไฟล์ในเครื่อง สำหรับฟอนต์ที่ดึง ณ runtime ให้ใช้ registerFromBinary() พร้อมไบต์ดิบ
  • registry ที่ lock แล้วเปลี่ยนแปลงไม่ได้ เมื่อคุณเรียก lock() แล้ว register(), addFontDirectory() หรือ warmup() ใดในภายหลังจะ throw เมธอด การค้นหายังคงใช้ได้ ลงทะเบียนและ warm up ทุกอย่างก่อน lock
  • CJK collection มีขนาดใหญ่ ลงทะเบียน sub-font ที่ถูกต้องของ .ttc ด้วย $fontIndex และเผื่อสำหรับ subset ที่ฝังขนาดใหญ่กว่า ดูหมายเหตุ CJK ในสูตร embed-and-subset
  • ไฟล์ฟอนต์เป็นอินพุตไบนารีที่ไม่น่าเชื่อถือ บันเดิลเฉพาะฟอนต์จากแหล่งที่คุณเชื่อถือ และตรวจสอบที่มาของหน้าฟอนต์ใดก็ตามที่รับจากผู้ใช้ปลายทาง
  • การ lock registry หลัง warmup ลบพื้นผิวการกลายพันธุ์ ณ runtime และทำให้ ความผิดพลาดของพาธล้มเหลวที่ boot แทนที่จะเสื่อมเอาต์พุตเงียบๆ
  • อย่าแทรกอินพุตของผู้ใช้ลงในพาธไฟล์ที่ลงทะเบียน ลงทะเบียนชุดของหน้าฟอนต์ที่บันเดิล ตายตัว อย่าให้คำขอเลือกพาธของระบบไฟล์ตามอำเภอใจ

คู่มือนี้ไม่อ้างเรื่องมาตรฐานเชิงบรรทัดฐาน ทุกสัญลักษณ์ที่แสดงเป็นพื้นผิวสาธารณะที่ ตรวจสอบแล้ว: NextPDF\Typography\FontRegistry (register(), addFontDirectory(), warmup(), lock(), argument constructor ของไดเรกทอรี), contract NextPDF\Contracts\FontRegistryInterface ของมัน, NextPDF\Core\DocumentFactory::create() และ NextPDF\Core\Document::setFont() / addFontDirectory() คีย์ fonts_path และ preload_fonts ของ Laravel คือ การกำหนดค่าที่บันทึกไว้ของแพ็กเกจ nextpdf/laravel พฤติกรรมการฝังและ subset-tag พร้อมการอ้างอิง ISO 32000-2 ของมัน บันทึกไว้ในสูตร embed-and-subset ที่ลิงก์ไว้ ใต้ดูเพิ่มเติม