In VCL
, I could load a font from resource and without saving it I could use it from memory.
Here is the code I use and it works in VCL
:
procedure TForm1.Button1Click(Sender: TObject);
var
ResStream : tResourceStream;
FontsCount : DWORD;
begin
ResStream := tResourceStream.Create(hInstance, 'MyResourceName', RT_RCDATA);
winapi.windows.AddFontMemResourceEx(ResStream.Memory, ResStream.Size, nil, @FontsCount);
ResStream.Free();
button1.Font.name := 'MySavedFontNameInResource';
end;
In Firemonkey I just changed button1.Font.name
to button1.Font.family
but unfortunately the font didn't change. So I think this code is not compatible with firemonkey.
So in Firemonkey, how can I load a font from resource and save it temporary to memory and use it directly from there?
Update:
I saw these pages: Install font in firemonkey, How to use external fonts?
According to Mr Ed 's answer, it seems that there is no solution for this problem in FMX. But maybe we could load the font if we install it before running the app. I tried almost everything but I still can't load the the font.
There is also StylesSettings.ssFamily : Boolean property in New Delphi and must be set to False to have custom font family working. The same with Size, Style and FontColor.
This may or may not help.
Disclaimer
This requires extra researching that I have not gotten around to yet, but I believe this to be a good starting point.
Link for the MSDN page :- Custom Font Collections
You need to use the WinAPI.D2D1 unit (you may need FMX.TextLayout and FMX.Canvas.D2D as well) to gain access to the DirectWrite API. You can use this to get at the DirectWrite factories which will allow you to define and load a font from disk.
Once you have the font loaded AFAIK it should then be available to the entire application and hopefully all of the firemonkey controls. Its entirely possible that firemonkey only enumerates fonts at application load though, so this may all be for naught.
As I said, this requires research that I have not gotten to yet, so may only work if you are also custom painting your control (which I will be) and might not be suitable as a result.
I think I have an answer, which was only possible because of a LOT of help by Roy Nelson of Embarcadero's support staff who pointed me in the right direction.
I have verified that this works with Berlin 10.1 (without the Anniversary Patch applied) on Windows 10, 64 bit but I don't guarantee that will will work on all compiler versions/Windows versions and any insight other people have to offer would be very interesting to hear.
First off, I think the (currently) insurmountable issue starts with trying to use AddFontMemResourceEx as that produces fonts that are not enumerable and for Firemonkey to convert an installed TrueType Font to a graphically rendered D2D font--which is what it actually uses--it has to first be able to find it.
Replacing AddFontMemResourceEx with AddFontResource with a temp font file you write from the resource solves that problem, but it's not enough. After it's installed you need to force the TextLayout rendering engine to rebuild its font list which you can do with calling two lines from the FMX.Canvas.D2D.pas unit.
UnregisterCanvasClasses; //this tells it to forget everything it knows
RegisterCanvasClasses; //this tells it to learn it again based on the current state of this system, which now includes our dynamically loaded font.
I've posted a test project on GitHub at https://github.com/TheOriginalBytePlayer/FireMonkey-Fonts for anyone who wants to try it out.
Basically you create a resource file with your fonts in it -- numbered from 0 to whatever -- replace the {$R assimilate.res} line in the FMXFontInstaller.pas, with the one you jut created, add this file to your project source and you theoretically should be good to go.