THotPDF.AssignSyntheticCodepointForGID / GetSyntheticCodepointForGID

THotPDF allocator συνθετικών codepoints PUA (v2.119.68)

 

GSUB Engine  Auto Shaping Pipeline  Arabic Shaping

Κατανέμει και ερωτά συνθετικά codepoints Private Use Area (U+E000 - U+F8FF) για OpenType GSUB substitute GIDs που δεν έχουν φυσικό Unicode codepoint προσβάσιμο μέσω του cmap της γραμματοσειράς. Κλείνει το κενό producer-side εκπομπής σε επίπεδο GID που άφησαν τα v2.119.43-66 GSUB query και refinement APIs

 

Σύνταξη Delphi:

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

function GetSyntheticCodepointForGID(GID: Word): Word;

 

Γιατί υπάρχει το API

Η v2.119.32-67 producer-side automatic shaping pipeline (Arabic / Latin / Devanagari) απαιτεί τα substitute GIDs που επιστρέφει ο GSUB engine να είναι προσβάσιμα μέσω Unicode codepoint. Η υπάρχουσα hex-encoded text pipeline εκπέμπει codepoints, όχι GIDs, και ο consumer reader επιλύει το codepoint πίσω σε GID μέσω του ενσωματωμένου /CIDToGIDMap. Για substitute GIDs που έχουν φυσικό Unicode codepoint μέσω του cmap της γραμματοσειράς (Arabic Presentation Forms, Latin Standard Ligatures FB00-FB06), η υπάρχουσα pipeline λειτουργεί κανονικά

 

Όμως τα font-specific substitutes που καταλήγουν σε font-internal GIDs, όπως τα περισσότερα Devanagari cluster shapes, stylistic alternates που ο σχεδιαστής γραμματοσειράς παρέχει μόνο ως numbered GIDs, CJK ideographic variation sequences (IVS) και discretionary ligatures χωρίς αντίστοιχο Presentation Form, δεν έχουν καθόλου codepoint στο cmap της γραμματοσειράς. Πριν από το v2.119.68 αυτά τα GIDs δεν ήταν προσβάσιμα μέσω της producer-side hex pipeline. Το v2.119.68 κλείνει αυτό το κενό επιτρέποντας στους callers να κατανέμουν ένα συνθετικό codepoint στο Private Use Area για οποιοδήποτε GID

 

Σημασιολογία AssignSyntheticCodepointForGID

Κατανέμει το επόμενο διαθέσιμο PUA codepoint (ξεκινώντας από U+E000) για το παρεχόμενο GID και αντικατοπτρίζει την ανάθεση σε κάθε cache από την οποία εξαρτάται η υπάρχουσα producer-side hex pipeline + consumer-reader resolution chain:

 

1. FUnicodeCpToGid[SyntheticCP] := GID - ώστε η producer-side hex pipeline να εκπέμπει το SyntheticCP στον text-showing operator και ο consumer reader να επιλύει το SyntheticCP πίσω σε GID μέσω /CIDToGIDMap κατά το render

2. FAcroFormUnicodeAdvances[SyntheticCP] := em-fraction - ώστε ο v2.65 word-wrap calculator να βρίσκει το σωστό hmtx advance για το synthetic codepoint όταν εμφανίζεται σε AcroForm text-field content

3. FUnicodeSyntheticCpForGID[GID] := SyntheticCP - ο per-GID reverse-lookup table που χρησιμοποιεί το GetSyntheticCodepointForGID για να κάνει επαναλαμβανόμενες κλήσεις AssignSyntheticCodepointForGID idempotent (η δεύτερη κλήση με το ίδιο GID επιστρέφει το ήδη κατανεμημένο SyntheticCP)

 

Επιστρέφει True σε επιτυχία με το SyntheticCP ορισμένο στο κατανεμημένο codepoint. Επιστρέφει False (και αφήνει το SyntheticCP στο 0) σε οποιαδήποτε από αυτές τις αμυντικές συνθήκες: δεν έχει καταχωρηθεί γραμματοσειρά (RegisterUnicodeTTF δεν κλήθηκε ποτέ ή κλήθηκε με κενά ορίσματα για reset state), μη έγκυρο GID (μηδέν ή πέρα από το glyph count του cmap), εξάντληση PUA range (όλες οι 6400 θέσεις U+E000 - U+F8FF έχουν κατανεμηθεί), μη αρχικοποιημένη cache κατά την είσοδο

 

Σημασιολογία GetSyntheticCodepointForGID

Pure-functional query οποιασδήποτε υπάρχουσας ανάθεσης. Επιστρέφει το synthetic codepoint που έχει κατανεμηθεί για το GID αν το AssignSyntheticCodepointForGID(GID, ...) έχει κληθεί προηγουμένως. Διαφορετικά επιστρέφει 0 (που δεν είναι έγκυρο PUA codepoint, άρα λειτουργεί και ως sentinel "no assignment"). Δεν κατανέμει. Είναι ασφαλές να κληθεί πριν εκτελεστεί οποιοδήποτε AssignSyntheticCodepointForGID

 

Κύκλος ζωής allocator state

FUnicodeSyntheticCpForGID και ο next-available-PUA cursor (FUnicodeNextSyntheticCp) γίνονται lazy-allocated στην πρώτη κλήση AssignSyntheticCodepointForGID. Ο cursor ξεκινά στο 0 (μη αρχικοποιημένος) και μετακινείται στο $E000 στην πρώτη κατανομή. Οι επόμενες κατανομές τον μετακινούν μέσα από $E001, $E002, ..., $F8FF. Και τα δύο πεδία γίνονται reset σε empty / 0 σε κάθε RegisterUnicodeTTF('', nil) μαζί με το υπόλοιπο per-font subset state, ώστε callers που επαναχρησιμοποιούν μία παρουσία THotPDF σε πολλά έγγραφα να ξεκινούν κάθε έγγραφο με νέο PUA cursor

 

Τυπική ροή εργασίας (Devanagari cluster shape)

 

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;

 

Παράδειγμα idempotency

 

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)

 

Συμπεριφορά consumer reader

Ο consumer reader βλέπει το PUA codepoint στον text-showing operator και το επιλύει μέσω του ενσωματωμένου στο έγγραφο /CIDToGIDMap προς το target GID, έπειτα κάνει render εκείνο το GID χρησιμοποιώντας το ενσωματωμένο font program. Από την οπτική του reader δεν υπάρχει διαφορά ανάμεσα σε ένα "φυσικό" Unicode codepoint που το cmap δρομολογεί στο GID και ένα PUA synthetic codepoint που το /CIDToGIDMap δρομολογεί στο GID, αφού και τα δύο παράγουν το ίδιο rendered glyph

 

Συμπεριφορά copy / paste: τα PUA codepoints κάνουν round-trip ως έχουν μέσω copy / paste όταν το ToUnicode CMap τα δηλώνει ως identity mappings. Callers που θέλουν τα source Unicode characters (το input run που παρήγαγε το substitute) να κάνουν round-trip αντ' αυτού μπορούν να καταχωρήσουν reverse mapping με RegisterToUnicodeReverseMapping ή να συντάξουν ActualText marked-content sequence properties μέσω BeginTaggedContent και να εκπέμψουν τα synthetic codepoints μέσα στο bracketed content. Το HotPDF χρησιμοποιεί αυτόματα το ίδιο internal-CID pattern για AcroForm appearance streams βασισμένα σε RegisterUnicodeTTF που περιέχουν supplementary-plane Unicode characters

 

Κλείσιμο Phase 8 roadmap

Το v2.119.68 / Phase 8c.6 κλείνει το Phase 8 GSUB engine roadmap: κάθε LookupType 1-8 query API (Phase 1-6), το Script / LangSys selection API (Phase 7), το TTF subsetter closure entry point (Phase 9), το static post-pass ligature folding (v2.119.32 / 58 / 60 / 62), η opt-in automatic pipeline (v2.119.59), η automatic emission Arabic rlig + Latin liga / clig + rclt (Phase 8b / 8c.2 / 8b / GSUB 'rclt'), το ToUnicode reverse-mapping (v2.119.61 / 62 / 65), το advance query (v2.119.64), το Devanagari Indic reorder pre-pass (v2.119.67) και τώρα το PUA synthetic codepoint GID-level emit (v2.119.68) ενσωματώνονται όλα σε μία ενιαία producer-side shaping surface που χειρίζεται κάθε είδος substitute glyph που μπορεί να παράγει μια OpenType γραμματοσειρά

 

Δείτε επίσης: OpenType GSUB Substitution Engine, Automatic Shaping Pipeline (Phase 8), Arabic / Persian / Urdu Shaping Support, Syriac / Mongolian / Devanagari Shaping, THotPDF.BeginTaggedContent