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 — відповідник бекенда Uniscribe у FPdfTextShaping для цілей, де немає usp10.dll. Інтерфейс компілюється лише під Free Pascal, адже Delphi націлена на Windows, де застосовується бекенд Uniscribe
Два бекенди поділяють роботу по-різному. Uniscribe розбиває на елементи, шейпить, розміщує й перевпорядковує за один прохід, тоді як HarfBuzz шейпить один прохід, чий напрям і писемність уже відомі. Цей модуль дає решту: FPdfBidi розв'язує рівні вкладеності, юнікодна писемність кожного символу розбиває текст на проходи, а проходи розкладаються у візуальний порядок, який дає правило L2 з UAX #9. Символи писемностей common, inherited і unknown продовжують прохід, у якому перебувають, тож цифра чи пробіл не розриває слово
libharfbuzz прив'язується під час виконання через DynLibs, тож це не залежність збірки, а її відсутність повідомляється, а не стає фатальною. HarfBuzzAvailable повідомляє, чи бібліотеку знайдено та розв'язано потрібні точки входу, а HarfBuzzVersionString повертає версію завантаженої бібліотеки
Шейпер не шукає шрифти. Uniscribe читає двійковий код шрифта з контексту пристрою GDI, у якого немає переносимого еквівалента, тож хост передає до Create TPdfFontDataResolver, який відображає ім'я шрифта на байти TrueType чи OpenType. Це тримає перелік шрифтів — fontconfig, CoreText чи власна тека шрифтів застосунку — поза модулем, який не має жодного стосунку до такої політики
| Function | Description |
|---|---|
HarfBuzzAvailable | True, коли libharfbuzz знайдено та розв'язано потрібні точки входу; перший виклик виконує прив'язування |
HarfBuzzVersionString | Версія завантаженої бібліотеки у форматі "major.minor.micro" або порожній рядок, коли бібліотека недоступна |
| Type | Description |
|---|---|
TPdfFontDataResolver | Посилання на метод, яке відображає FontName на байти файлу шрифта в FontData; повернення False змушує шейпер провалити запит так само, як нечитабельний шрифт GDI на Windows |
EPdfHarfBuzzError | Виняток, що породжується, коли розв'язувача не налаштовано, libharfbuzz недоступна або не вдається створити blob, face, font чи буфер HarfBuzz |
TPdfHarfBuzzTextShaper | Реалізація TPdfTextShaper на HarfBuzz, з Create, Destroy і Shape |
| Member | Description |
|---|---|
Create(Resolver) | Створює шейпер і зберігає TPdfFontDataResolver, який використовуватиме для кожного пошуку шрифта |
Destroy | Вивільняє кешовані face і blob HarfBuzz, а потім успадкований деструктор |
Shape(Text, FontName, FontSize, Options, Shaped) | Розв'язує рівні вкладеності, розбиває текст за рівнем і писемністю, шейпить кожен прохід через HarfBuzz і повертає проходи у візуальному порядку в Shaped; False, коли текст не дає гліфів |
HarfBuzzAvailable пробує libharfbuzz-0.dll і harfbuzz.dll на Windows, libharfbuzz.0.dylib і libharfbuzz.dylib на macOS, а libharfbuzz.so.0 і libharfbuzz.so в інших місцяхShape породжує EPdfTextShapingError для порожнього тексту, порожнього імені шрифта, непозитивного розміру шрифта, недійсних лімітів Options, тексту понад MaxCharacters, гліфів понад MaxGlyphs або даних шрифта, які розв'язувач не зміг постачатиShape породжує EPdfHarfBuzzError, коли TPdfFontDataResolver не налаштовано, libharfbuzz недоступна або об'єкт HarfBuzz неможливо створитиOptions.MaxRuns, а Options.Direction відображає ptdLeftToRight і ptdRightToLeft на фіксований напрям абзацу, а все інше розв'язується автоматичноShaped.FontData містить байти, які повернув розв'язувач, — саме це потрібно TPdf.AddShapedText для побудови шрифта CID