TPdfFontDataResolver = function(const FontName: WideString;
out FontData: TBytes): Boolean of object;
EPdfHarfBuzzError = class(Exception);
TPdfHarfBuzzTextShaper = class(TPdfTextShaper)
constructor Create(const Resolver: TPdfFontDataResolver);
destructor Destroy; override;
function Shape(const Text, FontName: WideString; FontSize: Single;
const Options: TPdfTextShapingOptions;
out Shaped: TPdfShapedText): Boolean; override;
end;
function HarfBuzzAvailable: Boolean;
function HarfBuzzVersionString: string;
FPdfTextShapingHb jest odpowiednikiem zaplecza Uniscribe z FPdfTextShaping dla celów pozbawionych usp10.dll. Interfejs jest kompilowany wyłącznie pod Free Pascal, ponieważ Delphi celuje w Windows, gdzie obowiązuje zaplecze Uniscribe
Oba zaplecza dzielą pracę inaczej. Uniscribe itemizuje, shape'uje, pozycjonuje i przestawia w jednym przebiegu, podczas gdy HarfBuzz shape'uje pojedynczy run o już znanym kierunku i piśmie. Ten moduł dostarcza reszty: FPdfBidi rozstrzyga poziomy osadzania, pismo Unicode każdego znaku segmentuje tekst na runy, a runy są układane w kolejności wizualnej, którą daje reguła L2 z UAX #9. Znaki pisma Common, Inherited i nieznanego kontynuują run, w którym się znajdują, więc cyfra ani spacja nie rozbijają słowa
libharfbuzz jest wiązany w czasie działania przez DynLibs, więc nie jest zależnością czasu budowania, a jego brak jest raportowany zamiast kończyć się katastrofą. HarfBuzzAvailable raportuje, czy biblioteka została znaleziona, a wymagane punkty wejścia rozwiązane, a HarfBuzzVersionString zwraca wersję załadowanej biblioteki
Shaper sam nie wyszukuje fontów. Uniscribe czyta binarną postać fonta z kontekstu urządzenia GDI, który nie ma przenośnego odpowiednika, więc host przekazuje do Create TPdfFontDataResolver mapujący nazwę fonta na bajty TrueType lub OpenType. Dzięki temu wyliczanie fontów - fontconfig, CoreText albo własny folder fontów aplikacji - zostaje poza modułem, który nie ma prawa rozstrzygać tej polityki
| Function | Description |
|---|---|
HarfBuzzAvailable | True, gdy libharfbuzz został znaleziony, a wymagane punkty wejścia rozwiązane; pierwsze wywołanie wykonuje wiązanie |
HarfBuzzVersionString | Wersja załadowanej biblioteki jako "major.minor.micro", albo pusty ciąg, gdy biblioteka jest niedostępna |
| Type | Description |
|---|---|
TPdfFontDataResolver | Referencja metody mapująca FontName na bajty pliku fonta w FontData; zwrócenie False sprawia, że shaper odrzuca żądanie tak samo, jak nieczytelny font GDI na Windows |
EPdfHarfBuzzError | Wyjątek zgłaszany, gdy nie skonfigurowano resolvera, gdy libharfbuzz jest niedostępny albo gdy nie da się utworzyć bloba, face, fonta ani bufora HarfBuzz |
TPdfHarfBuzzTextShaper | Implementacja TPdfTextShaper oparta na HarfBuzz, z Create, Destroy i Shape |
| Member | Description |
|---|---|
Create(Resolver) | Tworzy shaper i zapamiętuje TPdfFontDataResolver, który będzie używany przy każdym wyszukiwaniu fonta |
Destroy | Zwalnia cache'owany face i blob HarfBuzz, po czym wywołuje destruktor dziedziczony |
Shape(Text, FontName, FontSize, Options, Shaped) | Rozstrzyga poziomy osadzania, segmentuje tekst według poziomu i pisma, shape'uje każdy run przez HarfBuzz i zwraca runy w kolejności wizualnej w Shaped; False, gdy tekst nie produkuje żadnych glifów |
HarfBuzzAvailable sprawdza libharfbuzz-0.dll i harfbuzz.dll na Windows, libharfbuzz.0.dylib i libharfbuzz.dylib na macOS oraz libharfbuzz.so.0 i libharfbuzz.so wszędzie indziejShape zgłasza EPdfTextShapingError dla pustego tekstu, pustej nazwy fonta, niedodatniego rozmiaru fonta, nieprawidłowych limitów Options, tekstu ponad MaxCharacters, glifów ponad MaxGlyphs albo danych fonta, których resolver nie mógł dostarczyćShape zgłasza EPdfHarfBuzzError, gdy nie skonfigurowano TPdfFontDataResolver, gdy libharfbuzz jest niedostępny albo gdy nie da się utworzyć obiektu HarfBuzzOptions.MaxRuns, a Options.Direction mapuje ptdLeftToRight i ptdRightToLeft na sztywny kierunek akapitu, przy czym wszystko inne jest rozstrzygane automatycznieShaped.FontData przechowuje bajty zwrócone przez resolver, czyli to, czego TPdf.AddShapedText potrzebuje, aby zbudować font CID