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 je protějšek backendu Uniscribe z FPdfTextShaping pro cíle, které nemají usp10.dll. Rozhraní se kompiluje pouze pod Free Pascalem, protože Delphi cílí na Windows, kde platí backend Uniscribe
Oba backendy si práci dělí jinak. Uniscribe segmentuje, tvaruje, umisťuje a přeřazuje v jednom průchodu, zatímco HarfBuzz tvaruje jediný běh, jehož směr a písmo jsou už známé. Zbytek dodává tato jednotka: FPdfBidi vyřeší úrovně vnoření, Unicode písmo každého znaku rozdělí text na běhy a běhy se vyskládají do vizuálního pořadí, které dává pravidlo L2 z UAX #9. Znaky common, inherited a neznámého písma zůstávají v běhu, ve kterém právě jsou, takže číslice ani mezera nerozdělí slovo
libharfbuzz se váže za běhu přes DynLibs, takže není build závislostí a jeho absence se nahlásí místo toho, aby byla fatální. HarfBuzzAvailable hlásí, zda byla knihovna nalezena a požadované vstupní body vyřešeny, a HarfBuzzVersionString vrací verzi nahrané knihovny
Shaper si fonty sám nehledá. Uniscribe čte binární data fontu z GDI device contextu, což nemá přenositelný ekvivalent, takže hostitel předá Create resolver TPdfFontDataResolver, který mapuje název fontu na bajty TrueType nebo OpenType. Vyjmenovávání fontů - fontconfig, CoreText nebo vlastní složka fontů aplikace - tak zůstává mimo jednotku, která do té politiky nic nemá
| Function | Description |
|---|---|
HarfBuzzAvailable | True, když byl libharfbuzz nalezen a požadované vstupní body vyřešeny; první volání provede vazbu |
HarfBuzzVersionString | Verze nahrané knihovny jako "major.minor.micro", nebo prázdný řetězec, když knihovna není k dispozici |
| Type | Description |
|---|---|
TPdfFontDataResolver | Method reference mapující FontName na bajty souboru fontu v FontData; vrácení False donutí shaper ukončit požadavek jako neúspěšný stejně jako nečitelný GDI font ve Windows |
EPdfHarfBuzzError | Výjimka vyvolaná, když není nakonfigurován žádný resolver, když není libharfbuzz k dispozici, nebo když nelze vytvořit HarfBuzz blob, face, font ani buffer |
TPdfHarfBuzzTextShaper | Implementace TPdfTextShaper postavená na HarfBuzz, s Create, Destroy a Shape |
| Member | Description |
|---|---|
Create(Resolver) | Vytvoří shaper a uloží TPdfFontDataResolver, který použije při každém hledání fontu |
Destroy | Uvolní cachovanou HarfBuzz face a blob, poté zavolá zděděný destruktor |
Shape(Text, FontName, FontSize, Options, Shaped) | Vyřeší úrovně vnoření, rozdělí text podle úrovně a písma, vytvaruje každý běh přes HarfBuzz a vrátí běhy ve vizuálním pořadí v Shaped; False, když text neposkytne žádné glyfy |
HarfBuzzAvailable zkouší libharfbuzz-0.dll a harfbuzz.dll na Windows, libharfbuzz.0.dylib a libharfbuzz.dylib na macOS a libharfbuzz.so.0 a libharfbuzz.so jindeShape vyvolá EPdfTextShapingError pro prázdný text, prázdný název fontu, nekladnou velikost fontu, neplatné limity Options, text přes MaxCharacters, glyfy přes MaxGlyphs nebo data fontu, která resolver nedodalShape vyvolá EPdfHarfBuzzError, když není nakonfigurován žádný TPdfFontDataResolver, když není libharfbuzz k dispozici, nebo když nelze vytvořit HarfBuzz objektOptions.MaxRuns a Options.Direction mapuje ptdLeftToRight a ptdRightToLeft na pevný směr odstavce, cokoli jiného se vyřeší automatickyShaped.FontData drží bajty, které resolver vrátil; přesně to TPdf.AddShapedText potřebuje k sestavení CID fontu