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

الخطوط المخصصة: عقد امتداد FontRegistry

يحدّد FontRegistryInterface عقد الامتداد طويل العمر على مستوى العملية لتسجيل الخطوط والبحث عنها. سجّل الخطوط من مسار ملف أو من دليل أو من بيانات ثنائية خام، ثم أقفل السجل حتى لا تتمكن عمليات الإنتاج من تعديله.

Terminal window
composer require nextpdf/core:^3

سجل الخطوط كائن مفرد يتجاوز عمره عمر كل مثيل Document. لا يخزّن إلا بيانات ⁨PHP⁩ خالصة، من دون مقابض موارد أو كائنات امتداد، بحيث يمكن مشاركته بين الطلبات في عملية طويلة الأمد.

استخدم أحد مسارات التسجيل الثلاثة:

  • من ملف. يحلّل register() ملف .ttf أو .otf أو .ttc أو .pfb ويُرجع بيانات وصفية. في حالة ⁨TrueType Collection⁩، مرّر فهرس الخط الفرعي.
  • من دليل. يضيف addFontDirectory() مسار بحث يفحصه المحرك عند تحليل عائلة خط بالاسم.
  • من بيانات ثنائية. يحلّل registerFromBinary() بايتات ⁨TrueType⁩ أو ⁨OpenType⁩ الخام. استخدم هذا المسار لربط @font-face عندما تأتي الخطوط من معرّف موارد موحّد (⁨URI⁩) من نوع data: أو من مصدر بعيد.

لتقليل زمن استجابة أول طلب، استدعِ warmup() عند إقلاع العملية لتحليل دفعة من الخطوط مسبقًا. ثم استدعِ lock(). بعد lock()، تطرح كل طريقة تعديل استثناء LogicException: register() وaddFontDirectory() وwarmup() وregisterBase14() وregisterFromBinary(). تبقى طرق البحث متاحة: get() وhas() وall() وgetSearchDirectories(). يحمي هذا القفل عمليات الإنتاج لأنه يمنع أي طلب من تغيير مجموعة الخطوط المشتركة.

في معظم الحالات، لا تحتاج إلى تنفيذ FontRegistryInterface. يوفّر المحرك التنفيذ، وأنت تستدعيه. لا تنفّذها إلا إذا احتجت إلى إستراتيجية مخصصة لتحليل الخطوط، مثل إستراتيجية مدعومة بمخزن معنوَن بالمحتوى. في كلتا الحالتين، يبقى العقد هو الحدّ الفاصل.

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() الخط الفرعي. القيمة الافتراضية 0 تحدّد الوجه الأول.
  • تحليل عائلة الخط. يُرجع get() القيمة null لزوج عائلة-ونمط غير معروف. لا تفترض أبدًا نتيجة غير فارغة.

ينقل warmup() تكلفة التحليل من أول طلب إلى إقلاع العملية. تستخدم طرق السجل بيانات ⁨PHP⁩ خالصة، وتكون عمليات البحث قراءات خريطة بزمن ثابت. استدعِ memoryUsage() لقياس حجم مجموعة الخطوط المقيمة في العملية مقابل ميزانية الذاكرة لديك.

يمكن تضمين الخط المسجّل في محتوى ⁨PDF⁩. تحقق من مصدر الخط قبل التسجيل. لا تسجّل بيانات ثنائية يتحكم فيها مهاجم من دون فحوص للحجم والتنسيق. استخدم خطّاف FontLoadedEvent لفرض الامتثال لتراخيص الخطوط وتسجيل الأوجه التي يضمّنها المستند.

لا تنطبق أي ادعاءات معيارية متعلقة بالتوقيع أو الأرشفة. يطابق تضمين الخطوط وتجزئتها نموذج خطوط ⁨PDF 2.0.⁩ وتقع تلك المطابقة على عاتق أداة التجزئة الداخلية، لا على هذا العقد.

يضيف ⁨NextPDF Enterprise⁩ إثبات تراخيص الخطوط وسياسة تجزئة مدقّقة فوق FontRegistryInterface نفسه. يعمل رمز التسجيل لديك بالطريقة نفسها عبر الإصدارات لأن العقد هو الحدّ الفاصل.

يعرّف المسرد سجل الخطوط وسجل الصور ومستمع الأحداث. راجع المسرد المنشور للحصول على التعريفات المرجعية.