ترميز نص CJK مع مراعاة cmap
لمحة سريعة
قسم بعنوان «لمحة سريعة»تسجّل هذه الوصفة وجه خط TrueType صيني وياباني وكوري (CJK)، ثم ترمّز النص الصيني التقليدي عبر الواجهة التي تراعي cmap FontInfo::encodeText(). تُعيد الواجهة دفق بايتات CID ثنائية البايت بترميز Identity-H. تتبع الوصفة examples/35-cjk-cmap-demo.php. اقرأ ملاحظة النطاق قبل الاعتماد على هذا المسار.
النطاق والحالة (اقرأ أولًا)
قسم بعنوان «النطاق والحالة (اقرأ أولًا)»تُطرح بنية ترميز النص التي تراعي cmap على مراحل (ADR-013). اكتملت المرحلة 1: وُصلت الواجهة FontInfo::encodeText() واستراتيجية الترميز التي تراعي cmap، وأصبحتا متاحتين من مساحة المستخدم. المرحلة 2 قيد التنفيذ: تمرير أداة العرض والكاتب عبر الواجهة. المرحلتان 3 و4 معلّقتان: إصدار /ToUnicode و/CIDSystemInfo و/Encoding و/CIDToGIDMap لكل خط، ومُحلِّل الخط البديل، لم يُوصَّلا بعد إلى الكاتب.
خطّط مع مراعاة هذه التبعات:
- توضّح هذه الوصفة واجهة الترميز، وليست وضع كتابة عمودية مكتملًا. لا تملك واجهة المستند اليوم أي واجهة برمجة عامة لوضع الكتابة؛ فلا يوجد استدعاء
setWritingModeولا أداة ضبطvertical-rl. - المثال الداعم، وفق ترويسته نفسها، هو اختبار دخان تكاملي، وليس تجهيزة مطابقة. سيفشل التحقق من PDF/UA-2 وPDF/A-4 فشلًا سلبيًا للمخرجات المنتَجة بهذه الطريقة حتى تكتمل المرحلتان 3 و4. لا تذكر أن المخرجات من هذا المسار مطابقة. المدقّق هو من يقرّر المطابقة، وهذه المخرجات لن تجتازه بعد.
- توجد بنية مقاييس الكتابة العمودية لكنها داخلية. تشمل كائن القيمة
CjkVerticalMetricsومُصدِرَي/W2و/DW2. لا يكشف NextPDF عنها كاستدعاء “اكتب عموديًا” في مساحة المستخدم، ولا يُصدِر الكاتب قواميسها بعد.
التثبيت
قسم بعنوان «التثبيت»composer require nextpdf/core:^3يطابق القيد حزمة nextpdf/core. يعمل المثال على PHP 8.4. تجعل تجهيزة اختبار Noto Sans TC المرفقة هذه الوصفة مكتفية بذاتها.
نظرة عامة مفاهيمية
قسم بعنوان «نظرة عامة مفاهيمية»يصوغ ISO 32000-2 إخراج النص في ثلاث طبقات: نقطة ترميز Unicode، ورمز الحرف، ومعرّف المحرف الرسومي. بالنسبة إلى وجه خط TrueType من نوع CJK، يستخدم المحرّك خطًا مركّبًا من نوع Type 0 بترميز Identity-H. مع هذا الترميز، تستخدم السلسلة المعروضة أزواج بايتات تُفهرس CIDFont (ISO 32000-2).
يحلّل FontRegistry::register() وجه الخط. ثم يحدّد FontInfo::encodeText($unicodeText) استراتيجية الترميز عبر FontEncodingStrategyResolver. بالنسبة إلى وجه خط TrueType مسجّل من نوع CJK، يوجّه الطلب إلى TrueTypeCmapStrategy. يحمل EncodedGlyphRun المُعاد دفق بايتات Identity-H، ومُعامل سلسلة PDF، وعروض التقدّم لكل محرف رسومي، ونقاط الترميز المستخدَمة، وخريطة GID←Unicode. يستخدم تجزيء خطوط CJK نقاط الترميز وفق ADR-008. سيستخدم دفق /ToUnicode مستقبلًا خريطة GID←Unicode. الوضع المحدَّد هو EncodingMode::TwoByteCid.
يحدّد بناءان من بنى CIDFont الكتابة العمودية في PDF. الأول هو مصفوفة المقاييس العمودية لكل محرف رسومي /W2 (ISO 32000-2). والثاني هو المقاييس العمودية الافتراضية /DW2 (ISO 32000-2). يوفّر NextPDF كائن القيمة والمُصدِرات لكليهما عبر CjkVerticalMetrics::toW2Array() وtoW2RangeArray() وtoDw2Array(). هذه البنية داخلية، ولا يُصدِرها الكاتب بعد. راجع ملاحظة النطاق.
واجهة API
قسم بعنوان «واجهة API»FontRegistry::register(string $fontFile, string $alias = '', int $fontIndex = 0): FontInfo—NextPDF\Typography\FontRegistry.FontInfo::encodeText(string $unicodeText): EncodedGlyphRun—NextPDF\Typography\FontInfo. واجهة المرحلة 1.EncodedGlyphRun—NextPDF\Typography\Encoding\EncodedGlyphRun(byteStream,pdfStringOperand,mode,advanceWidths,toUnicodeMap,usedCodepoints,glyphCount()).EncodingMode—NextPDF\Typography\Encoding\EncodingMode(SingleByte,TwoByteCid).CjkVerticalMetrics—NextPDF\Typography\CjkVerticalMetrics. كائن قيمة داخلي للمقاييس العمودية. يُوثَّق للشفافية، وليس كمسار كتابة في مساحة المستخدم.
يُولَّد جدول PHPDoc الكامل من المصدر.
عيّنة الكود — بداية سريعة
قسم بعنوان «عيّنة الكود — بداية سريعة»<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Typography\Encoding\EncodingMode;use NextPDF\Typography\FontRegistry;
$registry = new FontRegistry();$font = $registry->register('/path/to/NotoSansTC-Regular.ttf', alias: 'NotoSansTC');
$encoded = $font->encodeText('PDF 2.0 引擎');
assert($encoded->mode === EncodingMode::TwoByteCid); // cmap-aware branch firedecho $encoded->glyphCount() . " glyph run entries\n";عيّنة الكود — الإنتاج
قسم بعنوان «عيّنة الكود — الإنتاج»هذه العيّنة قائمة بذاتها وقابلة للتشغيل ضمن إطار الاختبار. وهي تعكس examples/35-cjk-cmap-demo.php. أولًا، سجّل تجهيزة Noto Sans TC المرفقة. بعد ذلك، تأكّد من أن الواجهة التي تراعي cmap قابلة للوصول. ثم اعرض عبر DocumentFactory حتى يستخدم المستند السجل الذي ملأته.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\DocumentFactory;use NextPDF\Graphics\ImageRegistry;use NextPDF\Typography\Encoding\EncodingMode;use NextPDF\Typography\FontRegistry;
$cjkFontPath = dirname(__DIR__, 2) . '/fonts/test-fixtures/Noto Sans TC/NotoSansTC-Regular.ttf';if (!is_file($cjkFontPath)) { fwrite(STDERR, "Missing CJK font fixture: {$cjkFontPath}\n"); exit(1);}
$fontRegistry = new FontRegistry();$cjkFont = $fontRegistry->register($cjkFontPath, alias: 'NotoSansTC');
// Phase 1 facade: prove the cmap-aware path is reachable from userland.$cjkSample = 'PDF 2.0 引擎 — 使用 CMap 編碼';$encoded = $cjkFont->encodeText($cjkSample);
if ($encoded->mode !== EncodingMode::TwoByteCid) { fwrite(STDERR, "Expected TwoByteCid (TrueTypeCmapStrategy branch)\n"); exit(2);}
$imageRegistry = new ImageRegistry(maxCacheBytes: 0);$documentFactory = new DocumentFactory($fontRegistry, $imageRegistry);
$doc = $documentFactory->create();$doc->setTitle('NextPDF CJK CMap-Aware Encoding Demo');$doc->setLanguage('zh-Hant');$doc->addPage();
$doc->setFont('helvetica', 'B', 16);$doc->cell(0, 12, 'CJK cmap-aware encoding (Phase 1 facade)', newLine: true);$doc->setFont('helvetica', '', 10);$doc->cell(0, 6, 'Mode: ' . $encoded->mode->name . ' (Identity-H, 2-byte CIDs)', newLine: true);$doc->cell(0, 6, 'Glyphs: ' . $encoded->glyphCount() . ' run entries', newLine: true);$doc->cell(0, 6, 'Bytes: ' . strlen($encoded->byteStream) . ' encoded bytes', newLine: true);$doc->ln(4);
$doc->setFont('NotoSansTC', '', 18);$doc->cell(0, 12, $cjkSample, newLine: true);
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');$doc->save($out !== false ? $out : __DIR__ . '/cjk-vertical-writing.pdf');
echo "Wrote cjk-vertical-writing.pdf (Phase 1+2 dry-run; not a conformance fixture)\n";STDOUT المتوقّع:
Wrote cjk-vertical-writing.pdf (Phase 1+2 dry-run; not a conformance fixture)الحالات الحدّية والمزالق
قسم بعنوان «الحالات الحدّية والمزالق»- ليست تجهيزة مطابقة. وفق ترويسة المثال الداعم نفسها، هذه المخرجات اختبار دخان تكاملي. ستفشل فحوص PDF/UA-2 وPDF/A-4 لها حتى تكتمل المرحلتان 3 و4. لا تسجّلها كمرجع مطابقة ذهبي.
- لا توجد واجهة برمجة لوضع الكتابة. لا يوجد استدعاء عام يبدّل إلى الكتابة العمودية، بما يشمل
vertical-rlوvertical-lr. يوجد مُصدِرا/W2و/DW2داخليًا. وهما غير مكشوفين ولم يُكتبا بعد في قاموس الخط. - ملكية السجل. يبني
Document::createStandalone()سجله الخاص. استخدمDocumentFactoryحتى يقرأ المستند السجل الذي ملأته بوجه خط CJK. - مسار دفق البايتات النهائي. حتى تُغلق المرحلة 2، لا يزال دفق المحتوى المرئي يمرّ عبر مسار النص القديم. الجزء المثبَت والمتاح اليوم هو خطوة الترميز الأولية: البحث الأمامي في cmap إضافة إلى دفق بايتات Identity-H.
- تكلفة تجزيء خطوط CJK. تُجزَّأ أوجه خطوط CJK الكبيرة عبر عملية فرعية معزولة. لدى تلك العملية الفرعية بديل أصلي بلغة PHP ومهلة من ثانيتين (ADR-008).
الأداء
قسم بعنوان «الأداء»يُجري encodeText() تمريرة بحث أمامي واحدة في cmap على المُدخل. وهو خطّي في عدد نقاط الترميز، O(n). الميزانية هي wall_ms: 2000, peak_mb: 128. هذه الميزانية هي الأعلى في هذه المجموعة لأن أوجه خطوط CJK كبيرة، والتجزيء هو التكلفة الغالبة. يعزل ADR-008 ذلك العمل بحيث لا يستطيع حجب المستدعي.
ملاحظات أمنية
قسم بعنوان «ملاحظات أمنية»ملف خط CJK مُدخل ثنائي غير موثوق. يرفض المحلّل مسارات أغلفة الدفق وبايتات null. يعمل تجزيء خطوط CJK في عملية فرعية معزولة دون حالة موروثة (ADR-008). تحقّق من مصدر أوجه الخطوط التي يوفّرها المستخدم النهائي. يُعرَض محتوى نص CJK ولا يُفسَّر.
المطابقة
قسم بعنوان «المطابقة»| العبارة | المواصفة | البند | reference_id |
|---|---|---|---|
| بالنسبة إلى خط Type 0 بترميز Identity-H/Identity-V، تكون السلسلة المعروضة أزواج بايتات تُفهرس CIDFont. | ISO 32000-2 | iso32000_2_sec9#x1.x49.p90 | |
| تعطي مصفوفة W2 مقاييس الكتابة العمودية لكل محرف رسومي وتنطبق فقط على CIDFonts المستخدَمة للكتابة العمودية. | ISO 32000-2 | iso32000_2_sec9#x1.x44.p23 | |
| تعطي مصفوفة DW2 مقاييس الكتابة العمودية الافتراضية لـ CIDFont. | ISO 32000-2 | iso32000_2_sec9#x1.x44.p22 |
تُظهر هذه الوصفة أن واجهة ترميز CJK التي تراعي cmap قابلة للوصول من مساحة المستخدم (المرحلة 1). وهي لا تدّعي إخراج كتابة عمودية ولا مطابقة PDF/UA-2 / PDF/A-4 للملف المنتَج. إصدار /ToUnicode والمقاييس العمودية من جانب الكاتب (المرحلتان 3 و4) لا يزال معلّقًا، ولن تجتاز هذه المخرجات المدقّق اليوم.
السياق التجاري
قسم بعنوان «السياق التجاري»لا ينطبق.