THotPDF.AssignSyntheticCodepointForGID / GetSyntheticCodepointForGID

تخصیص‌دهنده کدپوینت مصنوعی PUA برای THotPDF (نسخه ۲.۱۱۹.۶۸)

 

موتور GSUB  خط لوله شکل‌دهی خودکار  شکل‌دهی عربی

کدپوینت‌های مصنوعی محدوده Private Use Area (U+E000 - U+F8FF) را برای GIDهای جایگزین OpenType GSUB که هیچ کدپوینت Unicode طبیعیِ قابل دسترسی از طریق cmap فونت ندارند اختصاص می‌دهد و پرس‌وجو می‌کند. این API شکاف صدور در سطح GID را که در APIهای پرس‌وجو و اصلاح GSUB نسخه v2.119.43-66 باقی مانده بود می‌بندد

 

Delphi syntax:

function AssignSyntheticCodepointForGID(GID: Word; out SyntheticCP: Word): Boolean;

function GetSyntheticCodepointForGID(GID: Word): Word;

 

چرا این API وجود دارد

خط لوله شکل‌دهی خودکار سمت تولید در نسخه v2.119.32-67 (Arabic / Latin / Devanagari) ایجاب می‌کند GIDهای جایگزینی که موتور GSUB برمی‌گرداند از طریق یک کدپوینت Unicode قابل دسترسی باشند - خط لوله متنی hex-encoded موجود کدپوینت صادر می‌کند، نه GID، و خواننده مصرف‌کننده کدپوینت را از طریق /CIDToGIDMap توکار دوباره به GID برمی‌گرداند. برای GIDهای جایگزینی که از طریق cmap فونت یک کدپوینت Unicode طبیعی دارند (Arabic Presentation Forms، Latin Standard Ligatures FB00-FB06)، خط لوله موجود درست کار می‌کند

 

اما جایگزین‌های وابسته به فونت که به GIDهای داخلی فونت می‌رسند - بیشتر شکل‌های خوشه‌ای Devanagari، جایگزین‌های سبکی که طراح فونت فقط به‌صورت GID شماره‌دار ارائه می‌کند، دنباله‌های تنوع ایدئوگرافیک CJK (IVS)، لیگاتورهای اختیاری بدون Presentation Form متناظر - اصلاً هیچ کدپوینتی در cmap فونت ندارند. پیش از v2.119.68 این GIDها از طریق خط لوله hex سمت تولید قابل دسترس نبودند؛ v2.119.68 این شکاف را با اجازه دادن به فراخواننده برای تخصیص یک کدپوینت مصنوعی در Private Use Area برای هر GID می‌بندد

 

معنای AssignSyntheticCodepointForGID

نخستین کدپوینت آزاد PUA را از U+E000 به بعد برای GID داده‌شده تخصیص می‌دهد و این تخصیص را در همهٔ cacheهایی که خط لولهٔ hex سمت تولیدکننده و زنجیرهٔ resolve سمت reader مصرف‌کننده به آن‌ها تکیه دارند بازتاب می‌دهد:

 

1. FUnicodeCpToGid[SyntheticCP] := GID - تا خط لولهٔ hex سمت تولیدکننده SyntheticCP را در text-showing operator صادر کند و reader مصرف‌کننده در زمان رندر، SyntheticCP را از طریق /CIDToGIDMap دوباره به GID resolve کند

2. FAcroFormUnicodeAdvances[SyntheticCP] := em-fraction - تا محاسبه‌گر word-wrap نسخهٔ v2.65 هنگام دیده‌شدن این کدپوینت مصنوعی در محتوای فیلد متنی AcroForm، advance درست hmtx را پیدا کند

3. FUnicodeSyntheticCpForGID[GID] := SyntheticCP - جدول reverse-lookup هر GID که GetSyntheticCodepointForGID از آن استفاده می‌کند تا فراخوانی‌های تکراری AssignSyntheticCodepointForGID idempotent بمانند (فراخوانی دوم با همان GID همان SyntheticCP از پیش تخصیص‌یافته را برمی‌گرداند)

 

در صورت موفقیت True برمی‌گرداند و SyntheticCP را روی کدپوینت تخصیص‌یافته می‌گذارد. در هر یک از حالت‌های دفاعی زیر False برمی‌گرداند و SyntheticCP را روی 0 می‌گذارد: فونتی ثبت نشده باشد (RegisterUnicodeTTF هرگز فراخوانی نشده یا با آرگومان خالی برای بازنشانی state فراخوانی شده باشد)، GID نامعتبر باشد (صفر یا فراتر از تعداد glyphهای cmap)، محدودهٔ PUA تمام شده باشد (همهٔ 6400 slot بین U+E000 و U+F8FF تخصیص یافته باشند)، cache هنگام ورود مقداردهی نشده باشد

 

معنای GetSyntheticCodepointForGID

یک پرس‌وجوی کاملاً خواندنی از هر تخصیص موجود است. اگر AssignSyntheticCodepointForGID(GID, ...) قبلاً فراخوانی شده باشد، کدپوینت مصنوعی تخصیص‌یافته برای GID را برمی‌گرداند؛ در غیر این صورت 0 را برمی‌گرداند (که کدپوینت معتبر PUA نیست و بنابراین به‌عنوان sentinelِ «بدون تخصیص» هم عمل می‌کند). هیچ تخصیصی انجام نمی‌دهد و قبل از هر فراخوانی AssignSyntheticCodepointForGID هم امن است

 

چرخهٔ حیات state تخصیص‌دهنده

FUnicodeSyntheticCpForGID و cursorِ PUA بعدی (FUnicodeNextSyntheticCp) در نخستین فراخوانی AssignSyntheticCodepointForGID به‌صورت lazy تخصیص می‌یابند. این cursor از 0 شروع می‌شود (مقداردهی‌نشده) و با نخستین تخصیص به $E000 می‌رسد؛ تخصیص‌های بعدی آن را از $E001، $E002، ...، $F8FF عبور می‌دهند. هر دو فیلد در هر RegisterUnicodeTTF('', nil) همراه با بقیهٔ state مربوط به subset هر فونت به مقدار خالی / 0 بازنشانی می‌شوند، بنابراین فراخواننده‌هایی که از یک نمونهٔ THotPDF در چند سند استفادهٔ مجدد می‌کنند، هر سند را با یک cursor تازهٔ PUA آغاز می‌کنند

 

گردش‌کار معمول (شکل خوشهٔ دواناگری)

 

PDF.RegisterUnicodeTTF('NotoDeva', 'NotoSansDevanagari-Regular.ttf');

PDF.ShapingFeatures := [sfIndicShaping];

PDF.SetGSUBScript('deva');

 

// Get a font-internal cluster GID through the GSUB engine

ClusterGID := PDF.GetSingleSubstituteGlyph(BaseGID, 'nukt');

if ClusterGID <> BaseGID then

begin

  // Check if cmap reaches the substitute - usually no for Indic

  // clusters, since cluster GIDs are font-internal

  // Allocate a synthetic codepoint that the producer-side

  // hex pipeline can emit

  if PDF.AssignSyntheticCodepointForGID(ClusterGID, SyntheticCP) then

  begin

    // SyntheticCP is now in the U+E000-F8FF range; emit it

    // through UnicodeTextOut just like a normal codepoint

    PDF.CurrentPage.UnicodeTextOut(X, Y, 0, UnicodeChar(SyntheticCP));

    PDF.MarkUnicodeGlyphUsed(ClusterGID);

  end;

end;

 

نمونهٔ هم‌ارزی

 

PDF.AssignSyntheticCodepointForGID(150, CP1);  // CP1 = $E000

PDF.AssignSyntheticCodepointForGID(151, CP2);  // CP2 = $E001

PDF.AssignSyntheticCodepointForGID(150, CP3);  // CP3 = $E000 (idempotent)

CP4 := PDF.GetSyntheticCodepointForGID(150);  // CP4 = $E000

CP5 := PDF.GetSyntheticCodepointForGID(999);  // CP5 = 0 (no assignment)

 

رفتار خوانندهٔ مصرف‌کننده

خوانندهٔ مصرف‌کننده کدپوینت PUA را در text-showing operator می‌بیند و آن را از طریق /CIDToGIDMap تعبیه‌شده در سند به GID هدف resolve می‌کند، سپس همان GID را با برنامهٔ فونت تعبیه‌شده رندر می‌کند. از دید خواننده تفاوتی میان یک کدپوینت Unicode «طبیعی» که cmap آن را به GID می‌برد و یک کدپوینت مصنوعی PUA که /CIDToGIDMap آن را به GID می‌برد وجود ندارد - هر دو همان glyph رندرشده را تولید می‌کنند

 

رفتار copy / paste: کدپوینت‌های PUA وقتی ToUnicode CMap آن‌ها را به‌صورت identity mapping اعلام کند، در copy / paste به همان شکل رفت‌وبرگشت می‌کنند. فراخواننده‌هایی که می‌خواهند به‌جای آن نویسه‌های Unicode مبدأ (run ورودی که substitute را تولید کرده) برگردند، می‌توانند یک reverse mapping با RegisterToUnicodeReverseMapping ثبت کنند یا ویژگی‌های ActualText برای marked-content sequence را از طریق BeginTaggedContent بنویسند و کدپوینت‌های مصنوعی را داخل محتوای براکت‌شده صادر کنند. HotPDF برای جریان‌های appearanceِ AcroForm مبتنی بر RegisterUnicodeTTF که نویسه‌های Unicode در planeهای بالاتر دارند، همان الگوی internal-CID را به‌صورت خودکار به کار می‌برد

 

بستن نقشهٔ راه Phase 8

v2.119.68 / Phase 8c.6 نقشهٔ راه موتور GSUB فاز 8 را می‌بندد: تمام APIهای پرس‌وجوی LookupType 1-8 (Phase 1-6)، API انتخاب Script / LangSys (Phase 7)، نقطهٔ ورود بستن subsetterِ TTF (Phase 9)، fold لیگاتور در post-pass ایستا (v2.119.32 / 58 / 60 / 62)، خط لولهٔ خودکار opt-in (v2.119.59)، صدور خودکار Arabic rlig + Latin liga / clig + rclt (Phase 8b / 8c.2 / 8b / GSUB 'rclt')، reverse-mapping در ToUnicode (v2.119.61 / 62 / 65)، پرس‌وجوی advance (v2.119.64)، pre-pass بازآرایی Indic دواناگری (v2.119.67)، و اکنون صدور کدپوینت مصنوعی PUA در سطح GID (v2.119.68) همگی در یک سطح شکل‌دهی سمت تولیدکننده ادغام می‌شوند که هر نوع glyph جایگزینی را که یک فونت OpenType می‌تواند تولید کند پوشش می‌دهد

 

همچنین ببینید: موتور جایگزینی OpenType GSUB, خط لولهٔ شکل‌دهی خودکار (Phase 8), پشتیبانی شکل‌دهی عربی / فارسی / اردو, شکل‌دهی سریانی / مغولی / دواناگری, THotPDF.BeginTaggedContent