A szövegalakítás a PDFium komponensben egy telepíthető objektumon át megy. A ConfigureTextShaper telepíti azt az alakítót, amelyen át minden alakítási belépési pont irányul, lecserélve és felszabadítva azt, ami ott volt; az ActiveTextShaper visszaadja a telepítettet, és első használatkor létrehozza a platform alapértelmezését; az ActiveTextShaperName megmondja, melyik backend él; a ClearTextShaper eldobja a telepítést, és hagyja, hogy az alapértelmezés újból létrejöjjön. Windowson az alapértelmezés a TPdfUniscribeTextShaper. Free Pascal alatt van TPdfHarfBuzzTextShaper, amely futásidőben köti be a libharfbuzzot, tehát egy hiányzó függvénytár jelentett állapot, nem betöltési megbukás
Egy interfész, két backend, amelyek a munkát teljesen másképp osztják meg. Az aszimmetria megértése az, ami megakadályozza, hogy a hordozható út olyan szöveget állítson elő, amely helyesen van alakítva és rosszul van pozicionálva
Miért egy osztály a Windows backend és három darab a hordozható?
Mert a Uniscribe négy API, amely azt színleli, hogy egy. A ScriptItemize szkript szerint szegmentál egy karakterláncot, és feloldja a kétirányú szinteket; a ScriptShape karaktereket glífákra képez le; a ScriptPlace előrehaladásokat és offseteket számol; a ScriptLayout vizuális sorrendbe teszi a keletkező futamokat. Az arra épülő backendnek ezért nincs mit hozzáadnia, ami az ok, amiért a Windows alakító egyetlen osztály egyetlen metódussal
A HarfBuzz a középső kettőt fedi. Alakít és pozicionál egy futamot, amelynek irányát és szkriptjét a hívó már eldöntötte, és nincs véleménye arról, hogyan oszlik bekezdés futamokká, vagy milyen sorrendben jelennek meg azok. A hordozható backend ezért a többit szolgáltatja: a kétirányú algoritmus feloldja a beágyazási szinteket, a HarfBuzz Unicode függvényei szkript szerint szegmentálják a szöveget, és a futamok abban a vizuális sorrendben rakódnak le, amelyet a UAX #9 L2 szabály előállít. A kétirányú fele elég terjedelmes ahhoz, hogy saját egység legyen, amelyet a UAX #9 beágyazási szintek cikk ír le
Az alakító nem old fel betűket, és az szándékos
A Uniscribe a betű binárisát egy GDI eszközkontextusból olvassa. Annak nincs hordozható megfelelője, és egy ilyennek a kitalálása egy alakító egységen belül azt jelentené, hogy minden alkalmazás nevében dönt arról, hogy a betűk fontconfigból, CoreTextből, egy alkalmazás betűmappájából vagy adatbázisból jönnek. Ezért a HarfBuzz backend feloldót vesz: olyan visszahívást, amely egy betűnevet TrueType vagy OpenType bájtokra képez le. A False visszatérés elbuktatja az alakítási kérést ugyanúgy, ahogyan Windowson egy olvashatatlan GDI betű elbuktatja
uses
FPdfTextShaping
{$IFDEF FPC}
, FPdfTextShapingHb
{$ENDIF}
;
function TFontCatalogue.Resolve(const FontName: WideString;
out FontData: TBytes): Boolean;
var
Path: string;
begin
// Az Ön politikája: fontconfig, CoreText, alkalmazás betűmappa, adatbázis
Result := FLookup.TryGetValue(LowerCase(FontName), Path);
if Result then
FontData := TFile.ReadAllBytes(Path);
end;
procedure InstallShaper(Catalogue: TFontCatalogue);
begin
{$IFDEF FPC}
// A tulajdon az egységre száll át; hívja egyszer induláskor,
// mielőtt bármi szöveget alakítana
ConfigureTextShaper(TPdfHarfBuzzTextShaper.Create(Catalogue.Resolve));
{$ENDIF}
// Delphi alatt a platform alapértelmezése (Uniscribe) igény szerint
// jön létre, tehát egyáltalán nincs szükség telepítésre
LogInfo('shaping backend: ' + ActiveTextShaperName);
end;
A betűfelismerés alakítón kívül tartásának második haszna szervereken mutatkozik meg: ugyanaz a folyamat alakíthat olyan beágyazott betűkészlettel, amelynek semmi köze ahhoz, ami a gépre telepítve van, ami az, amit akkor akar, amikor a kimenetnek gépek között bájtonként újratermelhetőnek kell lennie. A komponens gazdagép-rendszer betűszolgáltatót is kitesz azokhoz az esetekhez, amikor mégis telepített betűket akar, amelyet a rendszer betűszolgáltató cikk tárgyal
Az eredményrekord backendsemleges, és a klaszterek az ok
Mindkét backend ugyanazt a TPdfShapedText-et tölti: a forrásszöveget, a betűnevet, a méretet, a betűbájtokat, futamtömböt, a teljes szélességet, a glífaszámot és a logikai karakterszámot. Minden TPdfShapedRun hordozza a szakaszát a forrásszövegben, a vizuális X pozícióját, a szélességét, a kétirányú szintjét és jobbról-balra jelzőjét, plusz a glífáit. Minden TPdfShapedGlyph hordoz glífaazonosítót, előrehaladást, X és Y offseteket, és azt a klasztert, amelyhez tartozik, kezdettel és hosszként a forrásszövegben
Azok a klasztermezők teszik a rekordot használhatóvá, nem csupán tájékoztatóvá. Az alakítás nem egy-az-egyhez leképezés: egy dévanágari szótag négy karakterből egy glífává válik, egy arab ligatúra kettőt egyesít, és egyetlen karakter több jelet is produkálhat. Klaszterszakaszok nélkül nem helyezhet kurzort, nem tesztelheti találatként a kattintást, nem emelhet ki kijelölést, mert nem mondhatja meg, mely karakterekhez tartozik egy glífa. Velük a számtan lokális, és ugyanaz a kód mindkét backendre működik
var
Shaped: TPdfShapedText;
R, G: Integer;
begin
if ShapePdfText(Line, 'Noto Sans Arabic', 14, ptdAuto, Shaped) then
for R := 0 to High(Shaped.Runs) do
begin
// A futamok már vizuális sorrendben érkeznek, kitöltött VisualX-szel
X := Shaped.Runs[R].VisualX;
for G := 0 to High(Shaped.Runs[R].Glyphs) do
begin
EmitGlyph(Shaped.Runs[R].Glyphs[G].GlyphID,
X + Shaped.Runs[R].Glyphs[G].OffsetX,
Shaped.Runs[R].Glyphs[G].OffsetY);
X := X + Shaped.Runs[R].Glyphs[G].Advance;
end;
end;
end;
A korlátok az opciórekordba valók
A TPdfTextShapingOptions irányt hordoz plusz három korlátot: maximális karakterek, maximális glífák és maximális futamok, egy Default osztályfüggvénnyel, amely ésszerű értékeket tölt. A korlátok nem paranoia a rosszul formált bemenet felől; számtanok. Az alakítás tágul: egy agresszív kontextusfüggő helyettesítéssel bíró betű több glífát bocsáthat ki, mint amennyi bemeneti karakter van, és egy bekezdés, amely néhány karakterenként váltja a szkripteket, váltásonként egy futamot produkál. Egy olyan dokumentum, amelyet mindkettő maximalizálására állítottak össze, egy szerény karakterláncot nagy foglalássá tesz, és egy, a nem megbízható PDF-ekből szöveget alakító szolgáltatásnak olyan korlát kell, amelyet ő választott, nem pedig olyan, amelyet a gép ró
Az irány explicit beállítása automatikus hagyása helyett megéri, akárhányszor már tudja. Az automatikus a bekezdésirány szabályait alkalmazza, hogy az első erős karakterből találgasson, ami a szabad szövegre helyes, és téves egy olyan űrlapmezőre, amelynek iránya a mező tulajdonsága, nem annak az értékéé, amelyet valaki belegépelt
Futásidejű bekötés, nem buildfüggőség
A HarfBuzz backend dinamikusan tölti a függvénytárat. Az olyan telepítési döntés, amelynek valós következményei vannak: egyetlen bináris fut egy HarfBuzz-szal bíró gépen és egy nélkülözőn is, a második esetben csökkentett képességet jelentve, indítási megbukás helyett. Más fejlesztőknek szállított függvénytár számára ez az egyetlen működőképes elrendezés, mert nem követelheti meg egy PDF-komponens minden fogyasztójától, hogy szerezzen és verzióegyeztessen egy olyan alakító függvénytárat, amelyre talán nincs is szüksége
A hívóknak megfelelő szabály az ellenőrzés. Az ActiveTextShaper nil-t ad vissza, amikor a platformnak nincs alapértelmezése, és egyet sem konfiguráltak, és az alakítási belépési pont azt elérhetetlen alakítóként jelenti, nem alakítási megbukásként. Ezek különböző problémák, és különböző üzeneteket érdemelnek: az egyik telepítési rés, a másik betű- vagy szövegprobléma
Telepítse egyszer, mielőtt bármi alakítana
A telepítés lecseréli és felszabadítja az előző alakítót, tehát ismételt hívása biztonságos, de céltalan, és olyan hívása, miközben másik szál alakít, egyáltalán nem biztonságos. Tegye induláskor. Ha később a platform alapértelmezésére kell esnie, adjon át nil-t, ami az a mód is, ahogyan egy tesztkettőst visszavon egy teszt végén
Amint egy backend települt, a mérés és a tördelés mindkét platformon ugyanúgy viselkedik, mivel azok a futam- és glífametrikákat fogyasztják, nem pedig közvetlenül hívják a platformot; a tördelési modellt a szövegmérési és sortörési cikk írja le. A komponens támogatott platformjai és eszközláncai a PDFium Delphi component terméklapon találhatók