Műszaki cikk

Arab és RTL szövegalakítás Delphi PDF-ekben a HotPDF használatával

Adja át a يوضح ملف PDF arab kifejezést a TextOut-nak, és nyissa meg az eredményt. A betűk rossz irányba futnak, és mindegyik elszigetelt formájában ül, látható réssel a következő előtt, mintha valaki angolul gépelt volna visszafelé, és minden karakter között szóközt ütött volna. Nem történt kivétel. Nem jelent meg figyelmeztetés. A kimenet egyszerűen rossz, és azért rossz, mert két különálló transzformáció, amelyektől az arab nyelv függ, soha nem történt meg. Annak ismerete, hogy mi ez a két transzformáció, és melyik hívás hajtja végre őket, a legtöbb, amire a komplex szkript PDF-kimenet visszavezethető

A HotPDF egy natív VCL PDF komponens a Delphi és a C++Builder számára, és a jobbról balra végzett munkát egy külön híváson keresztül végzi el Ön helyett. Néhány konkrét helyen meg is áll, amelyekről tudni szeretne, mielőtt elkötelezné magát egy területi beállítás mellett, így ez a cikk feltérképezi a fogalmakat és a valós határokat; magának a hívásnak a gyakorlati beállítása a RtLTextOut referenciacikkben található

Miért nyomtatódik még mindig rosszul egy helyes karakterlánc

A Unicode logikai sorrendben tartja a szöveget, abban a sorrendben, ahogyan begépeli és hangosan felolvassa. A renderelőnek vizuális sorrendben kell letennie a glifákat. A balról jobbra haladó írásmódoknál ezek a sorrendek egybeesnek, és senki sem gondol rá. Az arab és a héber esetében azonban nem, és ha egyetlen sor keveri az irányokat, mondjuk egy arab mondat, amely a „PDF” latin tokent hordozza, vagy egy számjegyekkel írt ár, a Unicode Bidirectional Algorithm (UAX #9) pontosan eldönti, hogy a balról jobbra haladó töredékek hogyan ágyazódnak be a jobbról balra haladó sorba. Ez az első transzformáció, az átrendezés, és ennek kihagyása fordítja meg a sort

A második a kontextuális alakítás. Az arab betűk másként vannak megrajzolva attól függően, hogy hol helyezkednek el egy szóban: kezdeti, középső, végső vagy önálló. A kódpont mindvégig ugyanaz marad; csak a glifa változik. Egy olyan folyamat, amely minden kódpontot egyenesen az alapértelmezett glifájához ad át, pontosan a nyitó bekezdésből származó, szétkapcsolt, elszigetelt formájú kimenetet állítja elő. A héber kihagyja ezt a lépést, mivel a betűi nem kapcsolódnak össze, de továbbra is szüksége van az átrendezésre. Az arabnak mindkettőre szüksége van, és ezért az arab, nem pedig a héber az a karakterlánc, amellyel tesztel

Az asztali gépen mindez nem az Ön problémája. Amikor egy VCL űrlap arab nyelvet fest egy TEdit-be, az operációs rendszer szövegverme csendesen átrendezi és formázza azt, pontosan ez az oka annak, hogy a képernyőn tökéletesnek tűnő karakterlánc törötten jön ki egy naiv PDF-ben. A tartalomfolyam nem tárol szerkeszthető szöveget. Pozícionált glifákat tárol, így aki kibocsátja a folyamot, örökli az alakítási feladatot, amelyet az operációs rendszer korábban kezelt. A RtLTextOut az a hívás, amely visszaveszi ezt a feladatot

Mit alakít az RtLTextOut Ön helyett

A HotPDF két különböző módszerként tartja meg a latin útvonalat és a komplex szkript útvonalat. A TextOut azt nyomtatja, amit megad neki, abban a sorrendben, ahogyan megadja. A RtLTextOut először mindkét transzformációt elvégzi – kétirányú átrendezés az egész sorban, kontextuális elemzés a csatlakozó szkriptekhez –, majd nyomtat. Az, hogy melyik szkript szabályai érvényesek, a betűtípus karakterkészletén keresztül érkezik, nem pedig magán a híváson keresztül, így az irány kifejezett választás minden hívási helyen, ahelyett, hogy a karakterekből találgatnánk. A paraméterenkénti beállítás, a karakterkészlet értékei, a betűtípus-regisztráció lépései és egy teljes lefordítható példa mind megtalálhatók a RtLTextOut referenciacikkben; ez a darab annál marad, amit a transzformációk jelentenek, hol állnak meg, és hogyan lehet bizonyítani, hogy működtek

Egy használati szabály még ezen a magasságon is számít: a bemenetnek logikai sorrendben kell lennie, mert az RtLTextOut maga hajtja végre a megfordítást, és egy kézzel már megfordított karakterlánc kétszeresen megfordítva jön ki – a referenciacikk végigmegy ezen a csapdán és annak megtisztításán. Amiért a csapda említést érdemel itt, az az, hogy miért éli túl a tesztelést. Egy kétszeresen megfordított tisztán arab karakterlánc tökéletesen helyesnek tűnhet, és csak akkor esik szét, amikor egy sor latin szót vagy számot hordoz, mert azok a beágyazott futások már nem az UAX #9 által diktált módon ágyazódnak be. A hiba nem a renderelésben van; abban van, hogy az algoritmust olyan szöveggel táplálják, amely már félig fel volt dolgozva

Ugyanez a vegyes irányú viselkedés jobban megbotránkoztatja az értékelőket, mint a kódot. Egy jobbról balra haladó soron belül a számjegyek és a beágyazott latin szavak továbbra is balról jobbra olvashatók. Valaki, aki nem dolgozott kétirányú elrendezéssel, megnéz egy renderelt számlát, látja, hogy a számlaszám a „rossz” irányba olvasható a körülötte lévő arabhoz képest, és hibaként írja fel. Ez a specifikációnak megfelelő eredmény. Egy rövid megjegyzés az elfogadási kritériumokban, amelyet az első anyanyelvi átadás előtt írnak, megtakarítja ezt a kitérőt

Amikor az átrendezés és az összekapcsolás elegendő, és amikor nem

Az arab és héber folyószövegeknél – jelentések, számlák, szerződések, levelek – az átrendezés plusz kontextuális összekapcsolás az egész munka, és a RtLTextOut egyedül viszi. A határ ott jelenik meg, amikor a tipográfia többet kér az összekapcsolásnál. A HotPDF válasza az arab oldalon egy opt-in produceroldali alakító: állítsa be az AutoShapeArabic := True értéket, és a komponens átírja a logikai sorrendű futást Unicode prezentációs formákká a kétirányú áthaladás előtt, így a csatlakozó formákat a logikai szomszédokkal szemben számítják ki, és a ligatúra hajtásokat belevonják a kódpontokba, amelyeket a PDF ténylegesen hordoz, ahelyett, hogy a megtekintőre hagynák a feloldást. A kapcsoló alapértelmezés szerint ki van kapcsolva, és a kimenet bájtstabil, amikor kikapcsolva marad, így a bekapcsolása szándékos döntés dokumentumfolyamatonként, nem pedig globális frissítés. Ugyanez az opt-in modell kiterjed a többi csatlakozó jobbról balra haladó szkriptre is, amelyeket a HotPDF alakít: a szír, az N'Ko, az adlam és a hanifi rohingya mindegyike rendelkezik saját auto-shape jelzővel, amely tükrözi az arabot

Az opcionális OpenType funkciók ismét egy másik mechanizmus. A diszkrecionális ligatúrák és hasonló egyszeres helyettesítő funkciók a GetSingleSubstituteGlyph(GID, 'liga')-n mennek keresztül, amely egyszerre egy helyettesítést old meg – először a bemeneti glifa azonosítóját, másodszor a funkció címkéjét –, és változatlanul adja vissza a bemeneti glifát, ha a funkció nem alkalmazható. Ez elég egy ismert, véges ligatúralista vezérléséhez, amelyet Ön tart fenn. Ez nem egy teljes GSUB motor, és a különbség pontosan az, ahol az ambiciózus nyelvi tervek rosszul sülnek el: egy alakító folyamat, amely hibátlanul kezeli az arabot, csak az átrendezést és az összekapcsolást bizonyította, semmi mást

Lefedettség a szkriptek között

Az arab mindkét transzformációt gyakorolja, amiért is ezzel a karakterlánccal kell tesztelni, és amiért az arab menet a legerősebb bizonyíték a folyamat működésére. A hébernek szüksége van az átrendezésre, de az összekapcsolásra nem, mivel a betűi önállóak; ha a héber helyesen renderel, de az arab szétkapcsolva jelenik meg, akkor a kétirányú fele rendben van, és a kontextuális fele soha nem futott le. A perzsa és az urdu az arab írásmódon lovagol, és örökli annak viselkedését, bár az urdu preferenciája a Nasztalík stílus iránt egy betűtípus-döntés, amelynek olvashatósági következményei vannak, és amelyet egy anyanyelvi olvasónak kell megítélnie

A thai a vonal másik oldalán ül teljesen. Balról jobbra halad, így nincs szüksége kétirányú munkára, és a betűi nem kapcsolódnak össze, így nincs szüksége kontextuális elemzésre; a thai karakterláncok a szokásos TextOut útvonalon haladnak át, mint a latin. Amivel a thai rendelkezik, azok a halmozott jelek – magánhangzók és tónusjelek az alapmássalhangzó felett és alatt –, és hogy ezek helyesen ülnek-e, attól függ, hogy a betűtípus alakító motor segítsége nélkül építi-e fel a kombináló jeleit a halmozáshoz. A legtöbb dedikált thai betűtípus így tesz. Teszteljen pontosan azzal a betűtípussal, amelyet be fog ágyazni, nem pedig egy hasonmással

A dévanágari és a többi indiai család az őszinte, kemény megállás. Magánhangzóik átrendeződnek a mássalhangzóklaszterek körül, és kötőjeleik kontextusfüggő helyettesítések láncolatán keresztül jönnek létre, ami a teljes GSUB területe, túl az átrendezésen és az összekapcsoláson. Ha egy indiai területi beállítás szerepel az ütemtervben, futtasson egy valódi kísérletet eredeti ügyfél-karakterláncokon, mielőtt megígérné – az arab működése nem bizonyíték arra, hogy a dévanágari is fog. A CJK karakterláncok, a vietnámi a halmozott diakritikus jelekkel és a vegyes európai szövegek mind a szokásos útvonalat követik, kétirányú elemzés nélkül, és érdemes fizikailag elkülöníteni a két útvonalat a jelentés kódjában, egy rutin az RTL futásokhoz és egy minden máshoz, hogy a területi beállítás logikája látható legyen a hívás helyén, ahelyett, hogy egy olyan jelző mögé rejtőzne, amelyet valaki elfelejt beállítani

A glifák lefedettsége már az alakítás futása előtt eldől

Az alakítás kiválasztja a glifákat a betűtípusból. Ha a betűtípus nem hordozza azokat, nincs mit kiválasztani, ezért a klasszikus telepítési hiba – hibátlan a fejlesztő gépén, üres dobozok az ügyfél szerverén egy csendes betűtípus-helyettesítés után – lefedettségi probléma, nem alakítási probléma. A gyakorlati gyógymódot, egy szállított betűtípus regisztrálását ahelyett, hogy bízna abban, amit egy gépre telepítettek, lépésről lépésre bemutatja a referenciacikk. A koncepcionális pont az, hogy a lefedettséget még azelőtt meg kell állapítani, hogy bármilyen alakítási kérdés értelmes lenne, és hogy ezt programozottan meg lehet állapítani ahelyett, hogy a kimenetet szemrevételeznénk

// After RegisterUnicodeTTF, audit coverage for the
// codepoints your data actually uses
GID := Pdf.GetUnicodeGlyphForCodepoint($0628);  // U+0628 ARABIC LETTER BEH
LogGlyphAudit($0628, GID);

Maga a regisztráció két korlátozást hordoz magában – a PDF 1.5 alapot a beágyazott Unicode kezeléshez és a betűtípus beágyazási engedély bitjeit –, mindkettő megtalálható a beállítási lépésekkel együtt a RtLTextOut referenciacikkben. Ide tartozik az auditálási szokás: a GetUnicodeGlyphForCodepoint az Ön korai figyelmeztető rendszere. Járja végig azokat a kódpont-tartományokat, amelyeket az adatai ténylegesen használnak a szolgáltatás indulásakor, és naplózza, hogy milyen glifa azonosítók jönnek vissza. Egy lefedettségi hézag ekkor egy sorként jelenik meg az indítási naplóban a bevezetés során, nem pedig hiányzó karakterként egy számlán, amely már elért egy ügyfélhez

Az olvasási sorrend a dokumentumhoz tartozik, nem a glifákhoz

A glifák helyesbítése még mindig hagy egy megoldatlan dolgot. Az ISO 32000-1 12.2 bekezdése meghatároz egy /Direction nevű megjelenítői preferenciát, amely megadja a dokumentum általános olvasási sorrendjét. Ez nem érint semmilyen glifát. Amit tesz, az az, hogy megmondja a megjelenítőnek, hogyan rendezze el a kétoldalas felbontásokat, melyik oldalról kelljen indulnia egy szemközti oldalas elrendezésnek, és melyik irányba dőljön az olvasási felület. Ezek egyike sem látszik egyetlen oldalon, pontosan ezért felejtik el

// Declare right-to-left reading order at the document level
Pdf.Direction := RightToLeft;  // adds vpDirection to ViewerPreferences

A Direction beállítása az egész feladat: a tulajdonság beállítója hozzáadja a vpDirection-t a dokumentum ViewerPreferences-éhez, így egy sor beviszi a preferenciát a fájlba. Ha a szöveg az RtLTextOut-on keresztül megy ki, ezt ingyen megkapja, mert a hívás mellékhatásként megfordítja a dokumentum irányát – a referenciacikk kitér arra, hogy mikor kell ezt visszavonni egy vegyes dokumentumnál. Abban az esetben, ha Önnek kell beállítania, egy olyan jobbról balra dokumentumról van szó, amelyet más módon állítottak elő, például felülről előre megformázott bemenetből, amelyet a szokásos úton rajzoltak. Hagyja ki, és az egyoldalas bizonyíték, amit néz, mindkét esetben ugyanúgy néz ki; majd valaki kinyomtat egy duplex füzetet, a felbontások tükröződve jönnek ki, és az ok egy hiányzó egysoros kód hetekkel korábbról

A formázott kimenet ellenőrzése

Ellenőrizze az elejétől a végéig, mert egy oldal tűnhet helyesnek, és mégis használhatatlan lehet a folyamat további részében. Három ellenőrzés találja meg a legtöbb problémát. Másolja ki a szöveget az Acrobatból, és hasonlítsa össze a kódpontokat a forrás-karakterláncával. Futtassa le a megjelenítő dokumentumon belüli keresését egy olyan szóra, amelyet lát az oldalon. És nyissa meg a kimenetet egy olyan gépen, amelyen nincsenek meg a fejlesztői betűtípusai, a legvalószínűbb gépen, amely feltárja a helyettesítést. Mindez nem helyettesíti egy anyanyelvi olvasó egy valódi dokumentumra vetett pillantását, amely olyan dolgokat is elkap, amelyeket egyetlen szintetikus korpusz sem. Tegye be ezt az áttekintést a naptárba, mielőtt a formátum megjelenik

Válassza ki a tesztkarakterláncokat szándékosan, ahelyett, hogy újrahasznosítaná azt, amit egy fordító tavaly küldött. A használható minimum területi beállításonként: egy tisztán szkript mondat, egy mondat beágyazott latin márkanevekkel, egy sor, amely számjegyeket és valutát hordoz, valamint diakritikus vagy kombináló jelekkel ellátott nevek. A valódi ügyfélnevek megdöntik azokat a feltételezéseket, amelyeket a kitöltő szöveg érintetlenül hagy, így a regressziós készlet minden alkalommal egy karakterlánccal bővüljön, amikor egy támogatási eset olyan mintát tár fel, amelyet korábban nem látott

A betűtípus-regisztrációt, a részhalmazképzést és a mindennapi szövegrajzolási API-t a HotPDF jelentéskimenetéről, betűtípusairól és képeiről szóló cikk tárgyalja. Amikor ugyanezeknek a dokumentumoknak meg kell felelniük a hozzáférhetőségi profiloknak is, a PDF/A és PDF/UA érvényesítési cikkben szereplő nyelvi címkézési és strukturálási szabályok az itt bemutatott alakítási munkára épülnek

A fent leírt jobbról balra és Unicode betűtípus API-k a Delphi és C++Builder számára készült HotPDF Componenttel együtt kerülnek szállításra; a termékoldal összekapcsolja a teljes szövegkimeneti referenciát