Arabic / Persian / Urdu Shaping Support

Producer-side shaping pipeline (v2.85.0 - v2.119.68)

 

OpenType GSUB Engine  CFF / OpenType Subsetting

HotPDF chạy pipeline shaping phía producer, chuyển các run Unicode đầu vào tiếng Ả Rập, Ba Tư và Urdu sang Arabic Presentation Forms trong lúc phát văn bản PDF, để trình đọc phía tiêu thụ nhận sẵn các glyph vị trí / ligature có thể render mà không cần một shaper kiểu Harfbuzz riêng

 

Pipeline làm gì

Shaping vị trí (v2.85.0): mỗi chữ cái gốc trong tiếng Ả Rập có tối đa bốn dạng vị trí - isolated (isol), initial (init), medial (medi), final (fina). HotPDF kiểm tra join class của từng ký tự Ả Rập và của các ký tự lân cận trực tiếp, rồi ánh xạ codepoint đầu vào sang glyph Arabic Presentation Forms-B (U+FE70 - U+FEFC) phù hợp trước khi xuất ra. Các chữ không nối, ký tự nối, ký tự trong suốt (combining mark), và Tatweel kashida đều được xử lý theo thuật toán Unicode Arabic Shaping

 

Ligature bắt buộc LAM-ALEF (v2.119.32): đặc tả Unicode Arabic Shaping yêu cầu mọi LAM (U+0644) theo ngay sau một ALEF (U+0627 dạng thường, U+0622 có madda ở trên, U+0623 có hamza ở trên, U+0625 có hamza ở dưới) phải gộp thành một glyph ligature duy nhất (U+FEFB - U+FEFC các dạng isolated / final với biến thể hamza / madda tương ứng). Đây là một trong số rất ít ligature không thể bỏ qua trong kiểu chữ Ả Rập và là điều kiện để hiển thị đúng; nếu tách chúng thành các glyph riêng, văn bản sẽ lập tức bị trình đọc gốc nhận ra là sai dạng. HotPDF thực hiện phép gộp ngay trong lúc xuất ra nên bên gọi không cần một shaper kiểu Harfbuzz trong luồng mã của mình

 

9 chữ cái lõi của Persian / Urdu (v2.119.35): Persian và Urdu mở rộng tiếng Ả Rập bằng các chữ không có trong khối Arabic Presentation Forms-B (U+FE70 - U+FEFC). 9 chữ dùng nhiều nhất trong nhóm này - gồm PEH (U+067E), TCHEH (U+0686), JEH (U+0698), KEH (U+06A9 / U+06AF), GAF (U+06AF), NOON GHUNNA (U+06BA), HEH DOACHASHMEE (U+06BE), YEH BARREE (U+06D2), và HEH GOAL (U+06C1) - có dạng trình bày trong Arabic Presentation Forms-A (U+FB50 - U+FDFF). HotPDF giờ ánh xạ các chữ này sang glyph Forms-A thích hợp trong lúc shaping vị trí, nên văn bản Persian và Urdu hiển thị đúng các dạng init / medi / fina / isol trong mọi trình đọc

 

Arabic Extended-A + Supplement (v2.119.52, v2.119.56): bảng join class giờ bao phủ các ký tự Arabic Extended-A còn lại (ALEF WASLA / NOON GHUNNA / các biến thể HEH), Arabic Supplement U+0750-U+077F, và dải Arabic Extended-A cao hơn U+08A0-U+08FF. Các ký tự có mã hóa Presentation Forms-A tĩnh được ánh xạ qua bộ shaper 4 vị trí hiện có; các ký tự không có ánh xạ đó (phần lớn Extended-A) chỉ nhận phân loại join class để các ký tự lân cận vẫn shaping đúng ngay cả khi chính ký tự đó được truyền qua nguyên vẹn. v2.119.56 đã sửa hai ánh xạ Forms-A sai được đưa vào bởi v2.119.52 (U+06C2 / U+06C3)

 

Phủ kín Persian / Urdu Form-B (v2.119.57): bảng join class được mở rộng để bao trùm toàn bộ dải U+0672-U+06D5 (khoảng 80 ký tự bao gồm các biến thể REH / DAL / SEEN / SAD / TAH / AIN / FEH / QAF / KAF / GAF / LAM / NOON / HEH / WAW / YEH), đồng thời thêm 26 ánh xạ Presentation Forms-A mới (15 dạng 4-form của lớp D + 11 dạng 2-form của lớp R). Đáng chú ý, HEH DOACHASHMEE chuẩn của Urdu (U+06BE → FBAA-FBAD) và YEH BARREE ở cuối từ của Urdu (U+06D2 → FBAE-FBAF) giờ đã được ánh xạ đúng vào các ô Forms-A từng bị bản sửa tạm ALEF WASLA / NOON GHUNNA ở v2.119.52 sử dụng sai. Mức phủ Forms-A tĩnh giờ bao trùm hơn 40 ký tự nguồn

 

Hậu xử lý ligature YEH-HAMZA + nguyên âm (v2.119.58): một post-pass thêm vào _ApplyArabicShaping sau shaping vị trí bao phủ 8 cặp ligature trong khối Forms-A U+FBEA-U+FBFB - YEH-HAMZA + ALEF / AE / WAW / U / OE / YU / E / ALEF MAKSURA. Mỗi cặp xuất ra dạng isolated (FBEA / FBEC / FBEE / FBF0 / FBF2 / FBF4 / FBF6 / FBF9) cộng với dạng final base+1. Các ô dạng đầu / giữa FBF8 / FBFB được để cho GSUB engine xử lý thông qua tùy chọn sfArabicGSUB. Được xây trên cùng bộ khung với LAM-ALEF v2.119.32

 

Ligature Allah (v2.119.60): chuỗi bốn ký tự ALEF + LAM + LAM + HEH gộp thành U+FDF2 ARABIC LIGATURE ALLAH ISOLATED FORM. Được triển khai như một post-pass tĩnh ở mức codepoint sau LAM-ALEF v2.119.32 và YEH-HAMZA v2.119.58 trong chuỗi _ApplyArabicShaping

 

Ligature cụm Bismillah (v2.119.62): cụm Bismillah chuẩn gồm 22 codepoint "بسم الله الرحمن الرحيم" gộp thành một glyph duy nhất U+FDFD ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM. Chạy như pre-pass đầu tiên trong _ApplyArabicShaping (trước LAM-ALEF), nên glyph Bismillah đã gộp đi vào phần còn lại của pipeline như một codepoint duy nhất và không bị các phép thay thế phía sau chạm lại

 

Public Query Helpers

GetArabicJoiningClass trả về join class Unicode mà bộ shaper Ả Rập tĩnh sử dụng. GetArabicPosition đưa một ký tự trong run về vị trí isolated, initial, medial, hoặc final để bên gọi có thể kiểm tra hoặc mô phỏng cùng quyết định shaping trước khi xuất văn bản

 

Cách gọi

Pipeline shaping chạy tự động bên trong các method phát văn bản Unicode - không cần một lời gọi riêng kiểu "shape this". Hãy truyền chuỗi Arabic / Persian / Urdu đầu vào Unicode vào THPDFPage.UnicodeTextOut hoặc THPDFPage.RtLTextOut và HotPDF sẽ ánh xạ từng codepoint đầu vào sang dạng trình bày của nó trước khi ghi toán tử hiển thị văn bản PDF. Các byte Unicode gốc cũng được ghi vào FUnicodeUsedCps để sinh ToUnicode CMap, nhờ vậy thao tác copy / paste phía người đọc và screen reader vẫn thấy payload Unicode gốc

 

Yêu cầu về font

Font được đăng ký qua RegisterUnicodeTTF phải chứa glyph cho cả khối Arabic Presentation Forms-B (U+FE70 - U+FEFC) và, với Persian / Urdu, dải Arabic Presentation Forms-A liên quan (U+FB50 - U+FDFF). Các font được khuyến nghị và có đủ bộ:

 

Noto Sans Arabic (Latin + Arabic; Forms-A + Forms-B + Arabic Extended-A)

Noto Naskh Arabic, Noto Naskh Arabic UI

Amiri (Naskh truyền thống, phủ đầy đủ Forms-A + Forms-B)

Scheherazade New (SIL, thiết kế cho các ngôn ngữ của thế giới Hồi giáo)

Microsoft Arabic Typesetting / Tahoma / Times New Roman (đi kèm Windows, phủ đầy đủ Forms-B; một số font có Forms-A)

 

Khi font đã đăng ký không có glyph cho một dạng trình bày được suy ra, HotPDF sẽ rơi về codepoint Unicode gốc và xuất nó nguyên trạng; khi đó trình đọc phía tiêu thụ có thể tự shaping tiếp (Acrobat, Foxit) hoặc render .notdef

 

Quy trình thường dùng

 

PDF.RegisterUnicodeTTF('NotoArab', 'NotoSansArabic-Regular.ttf');

PDF.BeginDoc;

PDF.CurrentPage.SetFont('NotoArab', [], 14);

PDF.CurrentPage.RtLTextOut(100, 700, 0,

  UnicodeString(#$0645#$0631#$062D#$0628#$0627));  // "marhaba" (hello)

PDF.EndDoc;

 

Tích hợp pipeline giai đoạn 8 tự động (v2.119.59 - v2.119.68)

v2.119.59 giới thiệu property tùy chọn ShapingFeatures: THPDFShapingFeatures và enum THPDFShapingFeature, đưa pipeline shaping vượt khỏi việc gộp tĩnh sau cùng để chuyển sang thay thế font cụ thể do GSUB điều khiển tự động. Đặt PDF.ShapingFeatures := [sfArabicGSUB] để áp dụng các lookup Arabic gốc của font đã đăng ký cho init, medi, fina, isol, rlig, calt, và rclt rồi xuất các contextual glyph ID thu được; thêm sfCursiveAttachment để áp các anchor cursive entry / exit GPOS lên run đã shaping đó; thêm sfStandardLigatures cho Latin Standard Ligatures (FB00-FB06 ff / fi / fl / ffi / ffl / ſt / st qua ApplyLatinLigatureRefinement của v2.119.65); thêm sfIndicShaping để bật bước sắp xếp lại pre-pass của Devanagari (v2.119.67). Giá trị mặc định [] giữ nguyên đầu ra y hệt byte cho bên gọi phụ thuộc vào pipeline tĩnh

 

Khi bật sfArabicGSUB, bộ shaper Unicode Presentation Forms tĩnh sẽ bị bỏ qua để nhường chỗ cho các luật GSUB của chính font. HotPDF xuất các contextual glyph ID gốc thông qua synthetic codepoint khi các glyph đó không truy cập được từ cmap của font, giữ cho embedded subset luôn khép kín, và ghi các ánh xạ ngược ToUnicode cho thao tác copy và paste. Bên gọi muốn bộ shaper tĩnh tiếp tục xử lý các codepoint nằm ngoài phạm vi GSUB mà font khai báo thì nên để sfArabicGSUB tắt và dựa vào chuỗi post-pass tĩnh

 

CMap ToUnicode Adobe-Identity-UCS được xuất bởi RegisterUnicodeTTF đi kèm các mục ánh xạ ngược bfchar cho mọi codepoint ligature mà chuỗi post-pass có thể tạo ra. v2.119.61 thêm 27 mục (8 LAM-ALEF + 18 họ YEH-HAMZA + 1 Allah); v2.119.62 thêm Bismillah (U+FDFD); v2.119.65 thêm 7 mục Latin Standard Ligature (FB00-FB06). Khi người dùng copy / paste ở phía trình đọc, mọi glyph ligature đều được giải ngược về chuỗi codepoint nguồn, nên PDF được render vẫn thân thiện với trợ năng

 

AssignSyntheticCodepointForGID(GID; out CP): Boolean + GetSyntheticCodepointForGID(GID): Word cho phép mã phía producer phát ra các substitute GID của GSUB không có codepoint Unicode tự nhiên nào truy cập được qua cmap của font. Bộ cấp phát phát codepoint trong Private Use Area (U+E000 - U+F8FF, 6400 vị trí) và sao chép phép gán sang FUnicodeCpToGid (để /CIDToGIDMap giải synthetic CP về đúng GID mục tiêu ở trình đọc), FAcroFormUnicodeAdvances (để word-wrap ở v2.65 tìm được đúng em-fraction), và một bảng tra ngược theo từng GID (để các yêu cầu gán lặp lại mang tính idempotent). Hãy dùng cơ chế này cho dạng cụm Devanagari, alternate kiểu dáng, và các chuỗi biến thể biểu tượng Hán tự mà GSUB tạo ra nhưng cmap không với tới

 

Quan hệ với OpenType GSUB engine

Bộ shaper post-pass tĩnh mô tả ở trên (v2.85.0 + v2.119.32 / 58 / 60 / 62) mặc định độc lập với OpenType GSUB engine. Khi bật sfArabicGSUB thông qua ShapingFeatures, GSUB engine trở thành một phần của đường phát ra phía producer: HotPDF tra cmap để dựng mảng GID cơ sở, áp các lookup GSUB vị trí và ngữ cảnh gốc của tiếng Ả Rập lên run glyph đó, gán synthetic codepoint cho các substitute glyph ID không có Unicode Presentation Form, và gọi MarkUnicodeGlyphUsed để giữ các glyph thay thế bên trong embedded font subset

 

Với các substitute glyph không có codepoint Unicode, bên gọi kết hợp ShapingFeatures với bộ cấp phát synthetic codepoint PUA của v2.119.68 để substitute GID vẫn truy cập được qua pipeline hex chuẩn. Chuỗi post-pass tĩnh vẫn là đường dự phòng mặc định cho các codepoint mà khai báo GSUB của font không bao phủ

 

Phạm vi và giới hạn

Thuật toán BiDi nằm ngoài trang này: bên gọi vẫn phải tự sắp xếp các run LTR và RTL trộn lẫn hoặc dùng một thư viện BiDi riêng. Hỗ trợ GPOS, Indic/Tibetan/Mongolian, Hebrew, N'Ko, Adlam, Thai/Lao, và Javanese hiện nằm trên các trang cờ shaping và API tùy chọn riêng, nên trang này chỉ tập trung vào shaping tiếng Ả Rập bằng cơ chế tĩnh và GSUB

 

Xem thêm: OpenType GSUB Substitution Engine, Automatic Shaping Pipeline (Phase 8), Syriac / Mongolian / Devanagari Shaping, THotPDF.AssignSyntheticCodepointForGID, THPDFPage.RtLTextOut, THPDFPage.UnicodeTextOut, CFF / OpenType Font Subsetting