THotPDF.AssignSyntheticCodepointForGID / GetSyntheticCodepointForGID

THotPDF PUA synthetic codepoint allocator (v2.119.68)

 

GSUB Engine  Auto Shaping Pipeline  Arabic Shaping

Cấp phát và truy vấn các mã điểm tổng hợp trong Private Use Area (U+E000 - U+F8FF) cho những GID thay thế của OpenType GSUB không có mã Unicode tự nhiên nào có thể truy cập qua cmap của phông. Điều này khép lại khoảng trống phát ra ở mức GID phía producer do các API truy vấn và tinh chỉnh GSUB v2.119.43-66 để lại

 

Cú pháp Delphi:

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

function GetSyntheticCodepointForGID(GID: Word): Word;

 

Vì sao API này tồn tại

Chuỗi tạo hình tự động phía producer v2.119.32-67 (Arabic / Latin / Devanagari) yêu cầu các GID thay thế do bộ máy GSUB trả về phải đi tới được qua một mã điểm Unicode - pipeline văn bản mã hex hiện có phát ra codepoint chứ không phải GID, và trình đọc phía tiêu thụ sẽ giải mã codepoint trở lại GID thông qua /CIDToGIDMap nhúng. Với các GID thay thế có sẵn mã điểm Unicode tự nhiên qua cmap của phông (Arabic Presentation Forms, Latin Standard Ligatures FB00-FB06), pipeline hiện tại hoạt động tốt

 

Nhưng các thay thế riêng của phông rơi vào những GID nội bộ của phông - phần lớn các cụm Devanagari, các biến thể kiểu chữ mà nhà thiết kế chỉ phát hành dưới dạng GID đánh số, các chuỗi biến thể ideograph CJK (IVS), các ligature tùy chọn không có Presentation Form tương ứng - thì không có codepoint nào trong cmap của phông. Trước v2.119.68, các GID này không thể đi qua pipeline hex phía producer; v2.119.68 khép lại khoảng trống đó bằng cách cho phép bên gọi cấp phát một codepoint tổng hợp trong Private Use Area cho bất kỳ GID nào

 

Ngữ nghĩa của AssignSyntheticCodepointForGID

Cấp phát codepoint PUA tiếp theo còn trống (bắt đầu từ U+E000) cho GID được cung cấp và ghi lại phép gán vào mọi cache mà chuỗi pipeline hex phía producer + giải mã phía consumer đang phụ thuộc vào:

 

1. FUnicodeCpToGid[SyntheticCP] := GID - để pipeline hex phía producer phát SyntheticCP vào toán tử hiển thị văn bản và trình đọc phía consumer giải mã SyntheticCP ngược về GID thông qua /CIDToGIDMap lúc kết xuất

2. FAcroFormUnicodeAdvances[SyntheticCP] := em-fraction - để bộ tính word-wrap v2.65 tìm được advance hmtx đúng cho codepoint tổng hợp khi nó xuất hiện trong nội dung trường văn bản AcroForm

3. FUnicodeSyntheticCpForGID[GID] := SyntheticCP - bảng tra ngược theo từng GID do GetSyntheticCodepointForGID dùng để làm cho các lời gọi lặp lại AssignSyntheticCodepointForGID trở nên idempotent (lần gọi thứ hai với cùng GID sẽ trả về SyntheticCP đã được cấp phát trước đó)

 

Trả về True khi thành công và đặt SyntheticCP thành codepoint đã cấp phát. Trả về False (và để SyntheticCP ở 0) trong các điều kiện phòng thủ sau: không có phông nào được đăng ký (RegisterUnicodeTTF chưa bao giờ được gọi hoặc được gọi với đối số rỗng để đặt lại trạng thái), GID không hợp lệ (0 hoặc vượt quá số glyph trong cmap), hết dải PUA (đã cấp phát toàn bộ 6400 ô U+E000 - U+F8FF), cache chưa được khởi tạo khi đi vào

 

Ngữ nghĩa của GetSyntheticCodepointForGID

Truy vấn thuần túy đối với một phép gán đã tồn tại. Trả về codepoint tổng hợp đã cấp phát cho GID nếu AssignSyntheticCodepointForGID(GID, ...) đã được gọi trước đó; ngược lại trả về 0 (không phải codepoint PUA hợp lệ, nên đồng thời đóng vai trò sentinel "chưa gán"). Không cấp phát gì thêm. An toàn khi gọi trước khi AssignSyntheticCodepointForGID nào chạy

 

Vòng đời trạng thái bộ cấp phát

FUnicodeSyntheticCpForGID và con trỏ PUA khả dụng tiếp theo (FUnicodeNextSyntheticCp) chỉ được cấp phát trễ ở lần gọi AssignSyntheticCodepointForGID đầu tiên Con trỏ bắt đầu ở 0 (chưa khởi tạo) rồi nhảy lên $E000 ở lần cấp phát đầu tiên; các lần cấp phát tiếp theo sẽ lần lượt đi qua $E001, $E002, ..., $F8FF Cả hai trường đều được đặt lại rỗng / 0 trong mọi lần RegisterUnicodeTTF('', nil) cùng với phần còn lại của trạng thái subset theo phông, nên các caller tái sử dụng một thể hiện THotPDF qua nhiều tài liệu sẽ bắt đầu mỗi tài liệu với một con trỏ PUA mới

 

Quy trình điển hình (hình dạng cụm Devanagari)

 

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 example

 

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)

 

Hành vi của reader phía consumer

Trình đọc phía consumer thấy codepoint PUA trong toán tử hiển thị văn bản và giải mã nó qua /CIDToGIDMap nhúng trong tài liệu về GID đích, rồi render GID đó bằng chương trình phông nhúng. Từ góc nhìn của reader, không có khác biệt giữa một codepoint Unicode "tự nhiên" mà cmap dẫn tới GID và một codepoint PUA tổng hợp mà /CIDToGIDMap dẫn tới GID - cả hai đều cho ra cùng một glyph được render

 

Hành vi copy / paste: codepoint PUA sẽ round-trip đúng chính nó qua copy / paste khi ToUnicode CMap khai báo chúng là ánh xạ đồng nhất. Bên gọi muốn các ký tự Unicode nguồn (dải đầu vào đã tạo ra substitute) round-trip thay vào đó có thể đăng ký ánh xạ ngược bằng RegisterToUnicodeReverseMapping hoặc tự tạo các thuộc tính sequence marked-content ActualText thông qua BeginTaggedContent và phát các codepoint tổng hợp bên trong nội dung đặt trong ngoặc vuông. HotPDF tự động dùng cùng mẫu internal-CID này cho các luồng appearance AcroForm dựa trên RegisterUnicodeTTF có chứa ký tự Unicode ở plane bổ sung

 

Khép lại lộ trình Phase 8

v2.119.68 / Phase 8c.6 khép lại lộ trình máy GSUB Phase 8: mọi API truy vấn LookupType 1-8 (Phase 1-6), API chọn Script / LangSys (Phase 7), điểm vào closure của bộ cắt con TTF (Phase 9), bước gộp ligature hậu xử lý tĩnh (v2.119.32 / 58 / 60 / 62), pipeline tự động opt-in (v2.119.59), phát tự động Arabic rlig + Latin liga / clig + rclt (Phase 8b / 8c.2 / 8b / GSUB 'rclt'), ánh xạ ngược ToUnicode (v2.119.61 / 62 / 65), truy vấn advance (v2.119.64), bước tiền xử lý đảo thứ tự Devanagari Indic (v2.119.67) và giờ là phát codepoint tổng hợp PUA ở mức GID (v2.119.68) đều hội tụ thành một bề mặt shaping phía producer duy nhất xử lý mọi loại glyph thay thế mà phông OpenType có thể tạo ra

 

See also: OpenType GSUB Substitution Engine, Automatic Shaping Pipeline (Phase 8), Arabic / Persian / Urdu Shaping Support, Syriac / Mongolian / Devanagari Shaping, THotPDF.BeginTaggedContent