buggins / dlangui

Cross Platform GUI for D programming language
Boost Software License 1.0
805 stars 120 forks source link

How to load font from resources? #652

Open bagomot opened 1 year ago

bagomot commented 1 year ago

I have the example.ttf font in my resources, how can I use it in a text widget? The font is not installed on my OS.

I use FreeType. This is how I can get the font file from the directory, but it's still not an embedded resource:

FreeTypeFontManager fontManager = cast(FreeTypeFontManager) FreeTypeFontManager.instance;
fontManager.registerFont("path_from_file");
GrimMaple commented 1 year ago

It appears that you can only register a font that is a physical file. Can't do that from an embedded resource.

bagomot commented 1 year ago

It's a pity. I'll make a file cache in that case.

GrimMaple commented 1 year ago

It's a pity. I'll make a file cache in that case.

If you want to invest your time into this, you can just add loading fonts from embedded resource. I'll beglad to accept a PR

bagomot commented 1 year ago

If you want to invest your time into this, you can just add loading fonts from embedded resource. I'll beglad to accept a PR

On my first try, I didn't come up with a way to do this. If I figure out a way, I'll do it.

bagomot commented 1 year ago

I did it for FreeType, I still need it for WinAPI. I want to finish one of these days to make an PR.

GrimMaple commented 1 year ago

I did it for FreeType, I still need it for WinAPI. I want to finish one of these days to make an PR.

That's impressive! I think a general architecture overview for FontManager is going to be needed in some future

bagomot commented 1 year ago

I think a general architecture overview for FontManager is going to be needed in some future

There's a lot of chaos there. For example, I found that for Windows fonts, loading from the specified file is not implemented. Currently only system fonts.

bagomot commented 1 year ago

I have done font registration from file and from memory for winapi. But there is one problem. Currently registering from memory works by creating a temporary file and registering the font from it. This is because winapi does not provide font information when using the AddFontMemResourceEx function. This means parsing the bytes of a font looking for information about it. This is the task of a separate library, such as FreeType, but we do not use it here.

Also, I found a serious problem with Win32FontManager: it doesn't support loading fonts with the same name but different styles and weights. This is because the list stores fonts by name. This manager needs to be completely reworked. But I don't have time for that yet.

I can make a PR or provide the code here so that those interested can rework the Win32FontManager. What to do?

For USE_FREETYPE I wrote and everything works as it should. I will make a separate PR for this.

GrimMaple commented 1 year ago

Can't you use GetFontData to get the font data after loading? Another thing I can suggest is enumerating system fonts, adding a font from memory, then enumerating fonts again -- the difference should be your added fonts.

As for Win32FontManager, can't we just use a "better" string for the map, like "Name-weight-size" instead of just face name?

bagomot commented 1 year ago

Can't you use GetFontData to get the font data after loading?

This function gets its data directly from the font file. Not suitable for an embedded font.

Another thing I can suggest is enumerating system fonts, adding a font from memory, then enumerating fonts again -- the difference should be your added fonts.

A font loaded from memory using AddFontMemResourceEx is not registered as a system font and is only available inside the application with the specified handle. Therefore, it cannot be enumerated using EnumFontFamiliesEx.

As for Win32FontManager, can't we just use a "better" string for the map, like "Name-weight-size" instead of just face name?

Yes. I think so too. We need to add this, but this will not solve the problem with obtaining font data during the registration stage for embedded fonts. Yes. I think so too. We need to add this, but this will not solve the problem for embedded fonts with obtaining font data during the registration stage.

I think it is necessary to bring font managers to the same view as much as possible so that they correspond to interface (as you wrote above). But first you need to deal with the embedded fonts.

GrimMaple commented 1 year ago

OK, so for adding font from a temporary file -- I think it's OK, provided you leave the comment that it's a hack and should be fixed if that causes problems. Also, that fon't should go to an appropriate temporary directory.

For the rewriting font manager, I think a struct named FontDescription is needed to unify storage. Not sure how it should be designed.

Any PRs are welcome :)