DirectWrite — это компонент Windows, предназначенный для улучшения качества и производительности отображения текста. Он предоставляет разработчикам широкие возможности для работы с шрифтами, в том числе и для использования пользовательских шрифтов, не зарегистрированных в системе.
Проблема
Разработчик столкнулся с проблемой при попытке зарегистрировать пользовательский загрузчик шрифтов для использования с API DirectWrite в среде Delphi. Проблема заключалась в ошибке доступа при выполнении метода RegisterFontFileLoader интерфейса IDWriteFactory. В коде использовался объект TLoader, который реализует интерфейс IDWriteFontFileLoader, но при попытке его регистрации происходил сбой.
Контекст
В контексте проблемы, разработчик сравнивал реализацию интерфейса IDWriteFactory в Delphi с аналогичной реализацией в C++. В C++ для передачи интерфейса используется указатель, тогда как в Delphi используется переменная. Это могло вызывать сомнения в корректности перевода интерфейса.
Пример кода
unit DirectWriteBugMain;
interface
uses
WinApi.Windows,
System.Types,
Vcl.Direct2D,
WinAPI.D2D1,
System.SysUtils;
type
TLoader = class(TInterfacedObject, IDWriteFontFileLoader)
public
function CreateStreamFromKey(
fontFileReferenceKey: Pointer;
fontFileReferenceKeySize: Cardinal;
out fontFileStream: IDWriteFontFileStream): HResult; stdcall;
end;
procedure main; { called from dpr, in a console app }
implementation
function TLoader.CreateStreamFromKey(
fontFileReferenceKey: Pointer;
fontFileReferenceKeySize: Cardinal;
out fontFileStream: IDWriteFontFileStream): HResult; stdcall;
begin
fontFileStream := nil;
result := E_FAIL;
end;
procedure main;
var
Loader: IDWriteFontFileLoader;
begin
try
Loader := TLoader.Create as IDWriteFontFileLoader;
DWriteFactory.RegisterFontFileLoader(Loader);
except
on E: Exception do
begin
Writeln(E.ClassName, ': ', E.Message);
ReadLn;
end;
end;
end;
end.
Подтвержденный ответ
После анализа кода и сравнения с C++ реализацией, было выяснено, что проблема заключается в неправильном переводе заголовков интерфейсов в Delphi. В частности, использование ключевого слова var в объявлении метода RegisterFontFileLoader было некорректным. Вместо этого следует использовать const.
Рекомендации
Для исправления ошибки необходимо удалить ключевое слово var и заменить его на const в объявлении метода RegisterFontFileLoader в модуле WinAPI.D2D1, а также в аналогичных местах, где используется var для интерфейсов IDWrite*.
Альтернативный ответ
В COM интерфейсы представлены в виде указателей на таблицы виртуальных функций. В Delphi это неявно, в C++ — явно. Следовательно, использование var в Delphi для интерфейсов некорректно. Необходимо использовать либо простой проход по значению, либо const.
Заключение
Работа с API DirectWrite в Delphi требует внимательного изучения документации и сравнения с реализациями на C++. Использование пользовательских загрузчиков шрифтов позволяет расширить функционал приложений, но требует корректной реализации интерфейсов и их правильной регистрации в системе.
Разработчик в Delphi столкнулся с проблемой при попытке зарегистрировать пользовательский загрузчик шрифтов для использования с API DirectWrite из-за ошибки в переводе интерфейсов, аналогичной C++ реализации.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS