9

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.

Community
  • 1
  • 1
Sky
  • 4,244
  • 7
  • 54
  • 83
  • I presume your function succeeds in both VCL and FMX cases? – Free Consulting Jan 29 '14 at 17:18
  • Sure, it compiles, because is syntactically correct. Question is, does it return success status in both cases or not? Please check for errors whenever possible. – Free Consulting Jan 29 '14 at 19:18
  • @FreeConsulting in both `VCL` and `FMX`, the function returns `true`. I don't know but I think something is wrong with `FontsCount : integer;` I changed `integer` to `DWORD` but nothing happened (http://msdn.microsoft.com/en-us/library/windows/desktop/dd183325(v=vs.85).aspx) – Sky Jan 29 '14 at 19:45
  • `pcFonts` parameter isnt important, it merely receives number of fonts added from the resource (should be `>= 1` upon return). – Free Consulting Jan 29 '14 at 23:34
  • I ran out of ideas, sorry. But I'd like to point out for any future readers what loading font resource works ok (see [revisions](http://stackoverflow.com/posts/21433459/revisions)) and problem might exist in some FMX typeface string handling (perhaps **not enumerable** font causes some influence). – Free Consulting Jan 29 '14 at 23:40
  • Might be related: http://stackoverflow.com/a/18413827/205376 – Free Consulting Jan 29 '14 at 23:59
  • Did anyone find a solution or workaround? - I can use custom fonts on iOS and OS X, but not on Windows because of this problem. – Hans Sep 17 '14 at 09:46
  • @Hans I think there's still no solution by far in FM :( – Sky Sep 17 '14 at 15:08
  • @Sky Have you found a solution to this for Windows. I was able to find solutions for OSX, iOS and Android but not Windows... – Alain Thiffault Sep 27 '16 at 20:24
  • @lowrider No. I haven't :( – Sky Sep 28 '16 at 05:10

3 Answers3

1

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.

1

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.

0

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.

  • 1
    Oh, by the way, I think this is an extremely inelegant way of doing this and I'm pushing that Embarcadero make this automatic for any font you install in the Images/Resources of a Project. Both for Mac and Windows. And you can upvote the original bug report if you agree https://quality.embarcadero.com/browse/RSP-17030. – Byte Player Mar 24 '17 at 09:40
  • Hmmm.. I tested this on a Windows 7 64 bit machine and it didn't work. Anyone have any thoughts? (Other than "oh, crap.") – Byte Player Mar 24 '17 at 23:22