تخطَّ إلى المحتوى

الخط: أنواع القيم والتضمين والاحتياطي

في ⁨NextPDF⁩، الخط هو كائن القيمة غير القابل للتغيير FontInfo ونوع التقنية الذي يخبر المحرك بكيفية تضمينه. يضمّن المحرك كل خط يستخدمه. ويُعالَج أي مرجع قديم إلى ⁨Base 14⁩ ببديل مرفق متوافق في المقاييس.

Terminal window
composer require nextpdf/core:^3

FontInfo هو كائن القيمة غير القابل للتغيير الذي يزوّد المحرك بكل ما يحتاجه لتضمين خط: العائلة والنمط، واسم ⁨PostScript⁩، وأعلام الواصف، والمقاييس المُحجَّمة إلى مربع ⁨em⁩ بحجم 1000 وحدة، وعروض المحارف، وخريطة الرسم إلى ⁨Unicode⁩، وخريطة المحارف الأمامية (⁨cmap⁩، من ⁨Unicode⁩ إلى مُعرِّف الرسم)، وبايتات الخط الخام، وعند توفّرها محاور التباين والنُّسخ المُسمّاة ومُحدِّدات التباين وأزواج التقنين والمقاييس الرأسية. وهو final readonly. توقيع مُنشئه وخصائصه العامة مُجمَّدة، لذلك يبقى الخط المُحلَّل حقيقة ثابتة قابلة للمشاركة. FontInfo::encodeText() هي الطريقة الوحيدة التي تتضمن سلوكًا. تمرّ عبر مُحلِّل الترميز وتُعيد EncodedGlyphRun.

FontType يُعدِّد التقنيات التي يضمّنها المحرك: TrueType (ترميز أحادي البايت)، وTrueTypeUnicode (ترميز مُعرِّف المحرف (⁨CID⁩) متعدد البايتات للنصوص الغنية بمحارف ⁨Unicode⁩)، وOpenType (مخططات ⁨Compact Font Format⁩)، وType1 (⁨PostScript Type 1⁩، مُسجَّل من زوج ⁨Printer Font Binary⁩ (⁨PFB⁩) و⁨Adobe Font Metrics⁩ (⁨AFM⁩))، وCidFont0 (خط ⁨CID⁩ قائم على ⁨PostScript⁩). يحدد النوع الذي يُسنِده المُحلِّل شكل قاموس الخط الذي يُصدِره الكاتب.

للحفاظ على استقلال العرض عن خطوط النظام المُثبَّتة، يضمّن المحرك برنامج الخط — ⁨ISO 32000-2⁩ §9. يُضمَّن برنامج ⁨TrueType⁩ عبر مُدخل واصف الخط FontFile2 ويجب أن يتضمن جداول glyf وhead وhhea وhmtx وloca وmaxp — ⁨ISO 32000-2⁩ §9.6.5 (مُوجَز ⁨RAG⁩ مُقتطَع بسبب حدّ الترخيص؛ مُسجَّل في _downgraded-claims-o3.md). ويُضمَّن برنامج ⁨OpenType⁩ الذي يحتوي على جدول مخططات ⁨Compact Font Format⁩ عبر FontFile3 — ⁨ISO 32000-2⁩ §9.6.5 (مُوجَز ⁨RAG⁩ مُقتطَع؛ انظر السجل ذاته). يُعيد المُجزِّئ بناء مجموعة الجداول المطلوبة هذه كاملةً، لذلك تبقى المجموعة الفرعية المُضمَّنة برنامجًا مطابقًا.

يغطي الاحتياطي حالة ⁨Base 14⁩ القديمة. يطابق Base14SubstituteFonts مفتاح ⁨Base 14⁩ مُسوَّى — helvetica وhelveticab وtimes وcourier والبقية — مع ملف ⁨Liberation Fonts⁩ مرفق. تتوافق مقاييس ⁨Liberation Sans⁩ و⁨Serif⁩ و⁨Mono⁩ مع ⁨Helvetica⁩ أو ⁨Arial⁩ و⁨Times Roman⁩ و⁨Courier.⁩ كل منها وجه ⁨TrueType⁩ مضمَّن، لذلك يعرض ذخيرة ⁨WinAnsiEncoding⁩ ‏(⁨Windows-1252⁩) اللاتينية الكاملة التي يتطلّبها مرجع ⁨standard-14⁩ — اللاتينية المُشكَّلة، وعلامة اليورو، وعلامات الترقيم الطباعية الشائعة (⁨ISO 32000-2 Annex D.2⁩). لا يتوفر لـ Symbol وZapfDingbats بديل متوافق في المقاييس بترخيص متساهل، لذلك لا يستبدلهما ⁨NextPDF⁩ عمدًا؛ ويجب على أي مستند يحتاج إلى أحد هذين الخطين أن يُسجِّل خطًا قابلاً للتضمين. لا يُحدِث المُحلِّل أي آثار جانبية: فهو يعيد الملف الذي يطابقه مفتاح ما ولا شيء آخر. يبقى المُستدعي مسؤولاً عن التسجيل في السجلّ، مع الحفاظ على دلالات القفل وخط أنابيب الإحماء.

النوعالصنفالأعضاء الرئيسيونالاستقرارمنذ
FontInfoصنف ⁨final readonly⁩$family, $style, $type, $unitsPerEm, $widths, $unicodeMap, $cmapForward, $fileData, $variationAxes, $kernPairs, getKey(), encodeText()مستقر1.0.0
FontTypeتعداد (نصّي)TrueType, TrueTypeUnicode, OpenType, Type1, CidFont0مستقر1.0.0
Base14SubstituteFontsصنف ⁨final⁩ (داخلي)مفتاح ⁨Base 14⁩ مُسوَّى إلى مسار ملف ⁨Liberation⁩ مرفقمستقر2.7.0
ShaperFactoryصنف ⁨final⁩default(), create(), wouldUseRealShaper()مستقر3.2.0
ShapingResultصنف ⁨final readonly⁩$glyphRuns, $originalText, $script, $direction, $shaperImplمستقر3.2.0

Base14SubstituteFonts هو @internal: مخصص للاستخدام داخل إطار العمل فقط، ولا يقدم أي ضمان للتوافق العكسي لواجهته.

examples/35-cjk-cmap-demo.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Typography\FontRegistry;
use NextPDF\Typography\FontType;
$registry = new FontRegistry();
$font = $registry->register('/path/to/NotoSansTC-Regular.ttf', alias: 'NotoSansTC');
// FontInfo is the immutable parsed fact about the face.
echo $font->family, ' / ', $font->type->value, "\n"; // e.g. "Noto Sans TC / TrueTypeUnicode"
assert($font->type === FontType::TrueTypeUnicode);

يملأ المُحلِّل FontInfo ويُسنِد FontType. يصبح وجه ⁨TrueType⁩ الذي يحتوي على خريطة محارف ⁨Unicode⁩ TrueTypeUnicode، ويُصدِره الكاتب كخط مُركَّب من النوع ⁨Type 0.⁩

examples/font/base14-fallback.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Typography\Base14SubstituteFonts;
use NextPDF\Typography\FontRegistry;
final readonly class Base14EmbeddingResolver
{
public function __construct(private FontRegistry $registry) {}
/**
* Register an embeddable substitute for a legacy Base 14 key so the
* output document embeds every font (PDF/A-4 and PDF/UA-2 require it).
*/
public function ensureEmbeddable(string $base14Key): void
{
$path = Base14SubstituteFonts::resolve($base14Key);
if ($path === null) {
// Symbol / ZapfDingbats have no permissive substitute — the
// caller must supply its own embeddable font.
throw new \RuntimeException("No bundled substitute for {$base14Key}");
}
if (!$this->registry->has($base14Key)) {
$this->registry->register($path, alias: $base14Key);
}
}
}

لا يُحدِث المُحلِّل أي آثار جانبية. يبقى التسجيل صريحًا، لذلك تظل عقود القفل والإحماء في السجلّ سارية. لا يُعيد Symbol وZapfDingbats أي مسار بحكم التصميم.

  • لا يُستبدَل Symbol وZapfDingbats عمدًا. النتيجة الفارغة (⁨null⁩) لتلك المفاتيح هي السلوك المُوثَّق، وليست عطلاً ناتجًا عن خط مفقود.
  • FontInfo هو final readonly. تعامَل مع الخط المُحلَّل كقيمة: لا تتوقع أبدًا تعديل العروض أو المقاييس في موضعها؛ أعِد التسجيل إذا تغيّر المصدر.
  • يحتاج خط ⁨Type 1⁩ إلى مخطط ⁨PFB⁩ ومقاييس ⁨AFM⁩ معًا. يأخذ FontRegistry::registerType1() الزوج؛ ويشتقّ الاكتشاف التلقائي مسار ⁨AFM⁩ من مسار ⁨PFB⁩ حسب الامتداد.
  • يُميّز FontType::TrueType وFontType::TrueTypeUnicode الفرق بين أحادي البايت ومتعدد البايتات. يستخدم مُحلِّل الترميز خريطة المحارف الأمامية المملوءة، لا اسم العائلة، لذلك يُوجَّه وجه ⁨TrueType⁩ بنظام ⁨Unicode⁩ إلى مسار ⁨Identity-H⁩ تلقائيًا.
  • تُحلَّل محاور الخطوط المتغيّرة والنُّسخ المُسمّاة إلى FontInfo عند توفّرها، لكن المثال المُطبَّق على الصينية واليابانية والكورية (⁨CJK⁩) يستخدم الوجه الثابت عمدًا للحفاظ على حتمية FontInfo بعد التحليل.

يُخصِّص السجلّ FontInfo مرة واحدة لكل خط في كل عملية، ثم يشاركه بالمرجع. تُهيمن بايتات الخط الخام على تكلفة الذاكرة. أحمِ فقط الخطوط التي يحتاجها العامل وتتبَّع memoryUsage(). يُجري مُحلِّل بدائل ⁨Base 14⁩ بحثًا في خريطة بزمن ثابت دون ⁨input/output⁩ (⁨I/O⁩) حتى يُسجِّل المُستدعي الملف المُحلَّل. يغطّي performance_budget البالغ 1500 ⁨ms⁩ زمنًا و64 ⁨MB⁩ ذروةً إحماء مجموعة خطوط نموذجية بالإضافة إلى العرض. حتى يعمل المُجزِّئ، يتناسب أثر الذاكرة لكل خط مع حجم ملف الخط، لا مع عدد الرسوم.

FontInfo نفسه خامل: بيانات مُحلَّلة بلا سلوك يتجاوز التحويل النقي encodeText(). يقع سطح الهجوم في الطبقة الأعلى، وقت التحليل، عندما تصل بايتات خط عشوائية إلى مُحلِّل ⁨TrueType⁩ أو ⁨Type 1.⁩ تفحص المُحلِّلات حدود كل إزاحة ثنائية وترفض مُغلِّفات الدفق وبايتات ⁨null⁩ في المسارات. قبل التسجيل، يجب أن يجتاز إدخال الخط غير الموثوق سياسة موارد خارجية تحدّ من الحجم وعدد الرسوم. بدائل ⁨Liberation⁩ المرفقة أصول موثوقة تُشحَن مع الحزمة، لذلك لا يُدخِل مسار الاحتياطي أي إدخال جديد غير موثوق.

الادعاءالمعيارالبندالدليل
كل خط يستخدمه المستند مُضمَّن بحيث يُعرَض المستند دون الاعتماد على خطوط النظام.⁨ISO 32000-2⁩§9
يُضمَّن برنامج ⁨TrueType⁩ عبر FontFile2 مع جداول glyf وhead وhhea وhmtx وloca وmaxp.⁨ISO 32000-2⁩§9.6.5مُوجَز ⁨RAG⁩ مُقتطَع بسبب حدّ الترخيص؛ البادئة 7b26f37996239b2a، انظر _downgraded-claims-o3.md
يُضمَّن برنامج ⁨OpenType⁩ (⁨CFF⁩) عبر FontFile3.⁨ISO 32000-2⁩§9.6.5مُوجَز ⁨RAG⁩ مُقتطَع بسبب حدّ الترخيص؛ البادئة 801549ee00623baf، انظر _downgraded-claims-o3.md

البند الأول مُثبَّت بالمُوجَز ومُعزَّز بـ ⁨B1.⁩ بندا ⁨FontFile2⁩ و⁨FontFile3⁩ صياغتان معاد تحريرهما. لم تُعَد المُوجزات الكاملة لـ ⁨RAG⁩ لتلك البنود (اقتطاع بسبب حدّ الترخيص)، لذلك يُعزَّز الدليل أيضًا بـ FontSubsetter (الذي يُعيد بناء مجموعة glyf/head/hhea/hmtx/loca/maxp كاملةً) وتعداد FontType. لا يُعيد ⁨NextPDF⁩ إنتاج النص المعياري. في المصدر، يستشهد Base14SubstituteFonts بـ ⁨ISO 32000-2⁩ §9.6.2.2 (معالجة خط ⁨Type 1⁩ القياسي)، و⁨ISO 14289-2⁩:2024 §8.4.5.5.1 (تضمين خط ⁨PDF/UA-2⁩)، و⁨ISO 19005-4⁩:2020 §6.3.5 (تضمين خط ⁨PDF/A-4⁩). تحمل صفحتا إمكانية الوصول والمطابقة بيان السمات الكامل.

تبني حزمة ترخيص الخطوط التجارية وخدمة التجزئة الديناميكية على FontInfo في ⁨Core⁩ والسجلّ. تُضمِّن وحدة خطوط ⁨Core⁩ وتُجزِّئ وتوفر احتياطيًا دون ترخيص. حذف رابط التحويل مقصود.