我正在尝试使用Delphi在Firemonkey(FMX)应用程序中的OSX上加载内存流中的字体。
这是我尝试过的代码:
procedure LoadFontFromStream(SourceStream:TStream);
var cfData:CFDataRef;
fontBuffer:TBytes;
fontRef: CGFontRef;
provider: CGDataProviderRef;
currentStrRef: CFStringRef;
currentStr: string;
streamSize: Int64;
ctFontReference : CTFontRef;
ctAscent, ctDescent, ctCapHeight: CGFloat;
begin
streamSize := SourceStream.Size;
SetLength(fontBuffer, streamSize);
SourceStream.Read(fontBuffer[0], streamSize);
cfData := CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, @fontBuffer[0],
streamSize, kCFAllocatorNull);
provider := CGDataProviderCreateWithCFData(cfData);
CFRelease(cfData);
fontRef := CGFontCreateWithDataProvider(provider);
CGDataProviderRelease(provider);
if fontRef <> nil then
begin
ctFontReference := CTFontCreateWithGraphicsFont(fontRef,0.0, nil, nil);
if ctFontReference <> nil then
begin
ctCapHeight := CTFontGetCapHeight(ctFontReference);
ctAscent := CTFontGetAscent(ctFontReference);
ctDescent := CTFontGetDescent(ctFontReference);
end;
currentStrRef := CTFontCopyFamilyName(ctFontReference);
currentStr := CFToDelphiString(currentStrRef);
Log.d('Family name: %s',[currentStr]);
CFRelease(currentStrRef);
currentStrRef := CTFontCopyPostscriptName(ctFontReference);
currentStr := CFToDelphiString(currentStrRef);
Log.d('Postscript name: %s',[currentStr]);
CFRelease(currentStrRef);
currentStrRef := CTFontCopyDisplayName(ctFontReference);
currentStr := CFToDelphiString(currentStrRef);
Log.d('Display name: %s',[currentStr]);
CFRelease(currentStrRef);
end;
end;
在调试器上显示的姓氏,postscript名称和显示名称都是正确的。但是,我的表单上没有加载/显示字体。我在运行代码后尝试枚举所有字体系列,似乎我的字体(Open Sans)不存在。以下是我枚举字体系列的方法:
procedure ListFonts();
var fontFamilyArray: CFArrayRef;
i : CFIndex;
NumFamilies: CFIndex;
family: CFStringRef;
familyStr: string;
foundOpenSans: Boolean;
begin
foundOpenSans := False;
fontFamilyArray := CTFontManagerCopyAvailableFontFamilyNames();
NumFamilies := CFArrayGetCount(fontFamilyArray);
for i := 0 to NumFamilies-1 do
begin
family := CFArrayGetValueAtIndex(fontFamilyArray, i);
familyStr := CFToDelphiString(family);
if familyStr.StartsWith('Open') then
begin
foundOpenSans := true;
Log.d('Found %s', [familyStr]);
end;
end;
if not foundOpenSans then
Log.d('Open Sans not found');
CFRelease(fontFamilyArray);
end;
我知道通过在info.plist文件中设置ATSApplicationFontsPath并将文件放在包含我的文件夹的文件夹中,可以加载自定义字体。我试过了,这很有效。但是,我需要从内存流中加载字体。
为什么代码不加载字体的任何想法?我正在运行代码以在我的应用程序中创建任何表单之前加载字体。
答案 0 :(得分:0)
我没有看到你用字体管理器注册该字体。看看CTFontManagerRegisterGraphicsFont。 文档明确提到了这个函数,用于注册从内存构造的字体。
答案 1 :(得分:0)
问题与我使用的缓冲区有关。以下是我解决它的方法。
procedure LoadFontFromStream(SourceStream:TStream);
var cfData:CFDataRef;
fontBuffer:TBytes;
fontRef: CGFontRef;
provider: CGDataProviderRef;
streamSize: Int64;
theError: CFErrorRef;
errorDescription : CFStringRef;
errorDescriptionString : string;
registerFontValue: Integer;
begin
streamSize := SourceStream.Size;
SetLength(fontBuffer, streamSize);
SourceStream.Read(fontBuffer[0], streamSize);
cfData := CFDataCreate(kCFAllocatorDefault, @fontBuffer[0],streamSize);
provider := CGDataProviderCreateWithCFData(cfData);
CFRelease(cfData);
fontRef := CGFontCreateWithDataProvider(provider);
CGDataProviderRelease(provider);
if fontRef <> nil then
begin
theError := nil;
registerFontValue :=CTFontManagerRegisterGraphicsFont(fontRef, @theError);
if theError <> nil then
begin
errorDescription := CFErrorCopyDescription(theError);
errorDescriptionString := CFToDelphiString(errorDescription);
Log.d('Error loading font: %s', [errorDescriptionString]);
CFRelease(errorDescription);
end;
end;
end;
但是,这仅适用于OSX 10.8及更高版本,因为CTFontManagerRegisterGraphicsFont在OSX 10.7上不可用。有关OSX 10.7上可用的方法的任何想法吗?