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

استكشاف الأخطاء وإصلاحها: الخطوط والاقتصار والوسم

تتناول هذه المداخل حالات فشل العثور على الخطوط وتحليلها التي تُثار عبر NextPDF\Exception\FontNotFoundException وNextPDF\Exception\FontParsingException. وتغطي أيضًا تشخيصات تغطية الصينية واليابانية والكورية (⁨CJK⁩) ومشكلات شجرة البنية التي تؤثر في المخرجات الموسومة. يذكر كل مدخل الاستثناء أو الاختبار الدقيق حتى تتمكن من التحقق من السبب.

  • العَرَض. FontNotFoundException برسالة بصيغة Font "<name>" not found. Searched: [<paths>].
  • السبب المحتمل. عائلة الخط المطلوبة أو مسار الملف غير موجود، أو غير قابل للقراءة، أو يقع في دليل خطوط يتعذر على وقت التشغيل الوصول إليه. قد تكون بيانات الخط صالحة، لكن المحرك لا يزال غير قادر على الوصول إليها.
  • الدليل / التشخيص. تُرجِع getContext() القيم font_name وsearch_paths وfallback_attempted. استخدم search_paths لمراجعة كل موقع جرّبه المحرك. استخدم fallback_attempted للتأكد مما إذا كان المحرك قد حاول استخدام خط احتياطي بالفعل.
  • الحل.
    1. طابق font_name المطلوب مع ملف الخط الموجود فعليًا.
    2. أضف الدليل الذي يحتوي على الخط إلى دليل الخطوط المُهيّأ، أو صحّح المسار الذي مرّرته.
    3. تحقق من قدرة مستخدم وقت التشغيل على قراءة الملف.
    4. أعد تنفيذ الاستدعاء.
  • ذو صلة. مرجع الاستثناءات.

مدخل: فشل تحليل ملف الخط بنيويًا

قسم بعنوان «مدخل: فشل تحليل ملف الخط بنيويًا»
  • العَرَض. FontParsingException برسالة بصيغة Failed to parse font file "<file>": <reason>.
  • السبب المحتمل. عثر المحرك على ملف الخط، لكنه تعذّر عليه استخدام محتواه: ترويسة مبتورة، أو دليل جداول غير صالح، أو جدول إلزامي مفقود مثل head أو hhea أو OS/2.
  • الدليل / التشخيص. تُرجِع getContext() القيمتين font_file وparse_error. توضّح parse_error المشكلة البنيوية.
  • الحل.
    1. اقرأ parse_error لتحديد الخلل البنيوي.
    2. استبدل ملف الخط بنسخة سليمة معروفة من الوجه نفسه.
    3. أعد تشغيل الاستدعاء.
  • ذو صلة. مرجع الاستثناءات.

مدخل: فشل الاقتصار بسبب جدول خط مشوّه

قسم بعنوان «مدخل: فشل الاقتصار بسبب جدول خط مشوّه»
  • العَرَض. FontParsingException بقيمة font_file تساوي font-subset وparse_error مثل Invalid head table: too short أو Invalid hhea table: too short أو Invalid maxp table: too short أو Failed to unpack font data.
  • السبب المحتمل. اجتاز الخط التحميل الأولي، لكن جدولًا مطلوبًا للاقتصار مبتور أو يتعذر فك حزمه. يرفض المُقتصِر الخط بدلًا من إصدار مجموعة جزئية تالفة.
  • الدليل / التشخيص. عندما يكون جدول head أو hhea أو maxp قصيرًا جدًا أو تفشل عملية فك حزمه، يُطلِق src/Typography/FontSubsetter.php الاستثناء FontParsingException مع الرمز الحرفي font-subset بوصفه اسم الملف. يدلّك هذا الرمز على أن الفشل وقع أثناء الاقتصار، لا أثناء التحميل الأولي.
  • الحل.
    1. استبدل خط المصدر بنسخة كاملة وغير مبتورة من الوجه نفسه.
    2. إذا كانت أداة البناء تولّد الخط، فأعد توليده وتحقق من اكتمال جداول head وhhea وmaxp.
    3. أعد تشغيل البناء.
  • ذو صلة. التحقق من ⁨PDF/A⁩ و⁨PDF/UA⁩.

مدخل: نص ⁨CJK⁩ يُعرَض بمحارف رسومية مفقودة

قسم بعنوان «مدخل: نص ⁨CJK⁩ يُعرَض بمحارف رسومية مفقودة»
  • العَرَض. يُعرَض النص الصيني أو الياباني أو الكوري على هيئة مربعات فارغة أو محارف مفقودة، وتكون تغطية الخط لـ ⁨CJK⁩ غير مؤكدة.
  • السبب المحتمل. الخط المحدد لا يغطي كتل ⁨Unicode⁩ التي يتطلبها النظام الكتابي. يتطلب كل نظام كتابي من أنظمة ⁨CJK⁩ كتلًا محددة بالإضافة إلى كتل الأيديوغرافات المشتركة.
  • الدليل / التشخيص. يوفّر src/Typography/CjkFontValidator.php الدالة validateCoverage(FontInfo $font, CjkScript $script). تُرجِع CjkCoverageResult مع نسبة التغطية المئوية وأي كتل دون عتبة الإبلاغ البالغة %50. يأخذ المدقق عينات من نقاط الترميز. إنها أداة تشخيص ولا تعدّل تحميل الخطوط.
  • الحل.
    1. شغّل CjkFontValidator::validateCoverage() للخط والنظام الكتابي المستهدف.
    2. اقرأ missingRanges لمعرفة الكتل غير المغطاة، على سبيل المثال، ⁨Bopomofo⁩ للصينية التقليدية، و⁨Hiragana⁩ و⁨Katakana⁩ لليابانية، و⁨Hangul Syllables⁩ للكورية.
    3. حدّد خطًا يغطي تلك الكتل، أو أضف خطًا احتياطيًا يغطيها.
    4. أعد تنفيذ العرض وأعد فحص التغطية.
  • ذو صلة. مرجع الاستثناءات.

مدخل: خريطة ⁨CMap⁩ المعرّفة مسبقًا لا تطابق نظام ⁨CJK⁩ الكتابي

قسم بعنوان «مدخل: خريطة ⁨CMap⁩ المعرّفة مسبقًا لا تطابق نظام ⁨CJK⁩ الكتابي»
  • العَرَض. يُربَط نص ⁨CJK⁩ بمحارف رسومية غير صحيحة، أو يستخدم المستند خريطة ⁨CMap⁩ معرّفة مسبقًا لا تطابق لغته.
  • السبب المحتمل. يحدد النظام الكتابي المكتشَف اسم خريطة ⁨CMap⁩ المعرّفة مسبقًا من ⁨Adobe.⁩ الخط الذي يغطي كتلة الأيديوغرافات المشتركة فقط، دون كتلة خاصة بنظام كتابي، يُكتشَف بوصفه صينية مبسّطة بحسب التصميم.
  • الدليل / التشخيص. تُرجِع CjkFontValidator::detectScript() النظام الكتابي المكتشَف، وتربطه resolvePredefinedCMapName(): الصينية المبسّطة بـ UniGB-UTF16-H، والصينية التقليدية بـ UniCNS-UTF16-H، واليابانية بـ UniJIS-UTF16-H، والكورية بـ UniKS-UTF16-H. إذا لم تكن هناك كتلة خاصة بنظام كتابي، يعود الاكتشاف إلى الصينية المبسّطة.
  • الحل.
    1. تأكّد من أن الخط يتضمن الكتلة الخاصة بالنظام الكتابي: ⁨Bopomofo⁩ للصينية التقليدية، و⁨Hiragana⁩ أو ⁨Katakana⁩ لليابانية، و⁨Hangul⁩ للكورية.
    2. إذا كان المستند بالصينية التقليدية لكن الخط لا يحتوي على كتلة ⁨Bopomofo⁩، فحدد خطًا يتضمنها حتى يستقر الاكتشاف على النظام الكتابي المقصود.
    3. أعد تنفيذ العرض.
  • ذو صلة. مرجع الاستثناءات.

مدخل: المحتوى الموسوم لا يُنتِج شجرة بنية قابلة للاستخدام

قسم بعنوان «مدخل: المحتوى الموسوم لا يُنتِج شجرة بنية قابلة للاستخدام»
  • العَرَض. لا يُنتِج البناء الموسوم أي بنية، أو يُبلِغ فحص لاحق للإتاحة عن شجرة بنية فارغة أو مفقودة.
  • السبب المحتمل. أخرج البناء المحتوى خارج مسار الوسم، فلم يُنشئ أي عناصر بنية. تبقى شجرة البنية فارغة.
  • الدليل / التشخيص. يبني src/Accessibility/StructureTree.php وsrc/Accessibility/TaggedContentEmitter.php شجرة البنية من المحتوى الموسوم. يؤكد الاختبار tests/Integration/Accessibility/EmptyTaggedPdfDoesNotAdvertisePdfUa2Test.php أن شجرة البنية الفارغة لا تُعلن التوافق مع ⁨PDF/UA-2.⁩
  • الحل.
    1. تأكّد من أن المحتوى يُخرَج عبر مسار الوسم حتى تُنشأ عناصر البنية.
    2. تحقق من أن كل تسلسل محتوى موسوم يرتبط بعنصر بنية.
    3. أعد تنفيذ البناء وافحص شجرة البنية.
  • ذو صلة. التحقق من ⁨PDF/A⁩ و⁨PDF/UA⁩.

مدخل: رفض وسم لغة عنصر البنية

قسم بعنوان «مدخل: رفض وسم لغة عنصر البنية»
  • العَرَض. يفشل البناء لأن قيمة اللغة على عنصر بنية أو على المستند ليست وسمًا صالحًا.
  • السبب المحتمل. اللغة المُقدَّمة ليست وسمًا صالحًا من ⁨BCP 47⁩. يرفض المدقق الوسوم المشوّهة بدلًا من إصدارها.
  • الدليل / التشخيص. يتحقق src/Accessibility/Bcp47Validator.php من الوسم. يُطلِق الوسم غير الصالح src/Accessibility/InvalidBcp47TagException.php. يختبر tests/Unit/Conformance/PdfUa2Section844LangStrictTest.php متطلب اللغة الصارم في ⁨PDF/UA-2.⁩
  • الحل.
    1. استبدل قيمة اللغة بوسم صالح من ⁨BCP 47⁩، مثل en-US أو de-DE أو zh-Hant-TW.
    2. عيّن اللغة على عنصر البنية المحدد عندما يختلف مقطع عن لغة المستند.
    3. أعد تنفيذ البناء.
  • ذو صلة. التحقق من ⁨PDF/A⁩ و⁨PDF/UA⁩.
  • يُبلِغ FontNotFoundException وFontParsingException عن حالات فشل مختلفة. يعني “غير موجود” أنه تعذّر الوصول إلى الملف. ويعني التحليل البنيوي أنه جرى الوصول إلى الملف، لكن وحدات بايت محتواه غير قابلة للاستخدام. اقرأ اسم الصنف لتحديد أي فشل وقع.
  • font-subset في font_file علامة مقصودة لمرحلة الاقتصار، وليس مسارًا فعليًا. لا تبحث عن ملف باسم font-subset.
  • يأخذ CjkFontValidator عينات من نقاط الترميز بدلًا من فحص كل واحدة، لذا فإن رقم التغطية فيه تقدير يساعد على اختيار الخط، وليس تدقيقًا دقيقًا على مستوى البايت.
  • يُبلَّغ عن شجرة البنية الفارغة بوصفها غير متوافقة مع ⁨PDF/UA-2⁩ بحسب التصميم. هذا هو سلوك المحرك الموثّق، وليس خللًا.

المسرد: اقتصار الخطوط · تغطية ⁨CJK⁩ · شجرة البنية