Recent

Author Topic: Help Needed: Cross Platform Third Party Fonts  (Read 2242 times)

lainz

  • Hero Member
  • *****
  • Posts: 4593
  • Web, Desktop & Android developer
    • https://lainz.github.io/
Help Needed: Cross Platform Third Party Fonts
« on: February 02, 2023, 04:08:47 pm »
Hi, seems that's possible to use third party fonts on Windows, Linux and macOS.

Solutions in this thread

for Windows
https://forum.lazarus.freepascal.org/index.php/topic,62134.msg469606.html#msg469606

for Linux
https://forum.lazarus.freepascal.org/index.php/topic,62134.msg469714.html#msg469714

Unfortunatelly my Linux VM's are failing sometimes with Lazarus, and my macOS version is old, failing lazarus as well.

But I have the links:

macOS, how to bundle Fonts and use
https://stackoverflow.com/a/2444772/8852689

Maybe a script can be created to put the font in the bundle, and register it too...

Windows, how to embed Fonts and use
https://forum.lazarus.freepascal.org/index.php/topic,21032.msg252219.html#msg252219

The code is already there, maybe pack it into a single unit...
Edit: and to test it in Windows 11, we had problems with this or other similar code, the app won't start with this code or something like that...

Maybe just installing the font in the system with a dll call?

Linux
https://itsfoss.com/install-fonts-ubuntu/

Basically on Ubuntu / Mint one can create HOME/.fonts directory and put the fonts there, maybe that can be done easily from an FPC program... extracting the fonts from the binary, or using a folder where then we copy it to the hidden fonts folder.

Anyone interested with all the systems, to make a definitive solution for this endless problem?

Thanks.
« Last Edit: February 03, 2023, 10:08:21 pm by lainz »

Thaddy

  • Hero Member
  • *****
  • Posts: 15663
  • Censorship about opinions does not belong here.
Re: Help Needed: Cross Platform Third Party Fonts
« Reply #1 on: February 02, 2023, 04:18:36 pm »
1. The definitive solution for Lazarus and/or FPC is including the font as a resource. (Also works on Mac)
2. Linux has /usr/shared/fonts subs. ~/.fonts. The latter is local.
3. Windows has \Windows\Fonts

In case of problems, use 1. Accessing resource fonts does not require unpacking.

Note that 1. should work, but today I have only access to FPC main/trunk, which can call fpcres inline (transparent), which in turn can use rc and res on one line.
« Last Edit: February 02, 2023, 04:27:43 pm by Thaddy »
If I smell bad code it usually is bad code and that includes my own code.

lainz

  • Hero Member
  • *****
  • Posts: 4593
  • Web, Desktop & Android developer
    • https://lainz.github.io/
Re: Help Needed: Cross Platform Third Party Fonts
« Reply #2 on: February 03, 2023, 12:54:26 am »
@Thaddy what if the HOME/.fonts can't be created. I have a Linux system with the HOME folder blocked.

Or they refer as HOME as HOME/username?

domasz

  • Hero Member
  • *****
  • Posts: 529
Re: Help Needed: Cross Platform Third Party Fonts
« Reply #3 on: February 03, 2023, 12:58:34 am »
3. Windows has \Windows\Fonts

That's not a good solution. User might not want to have the fonts installed for every running application. The better solution:
Code: Pascal  [Select][+][-]
  1.  procedure TForm1.FormCreate(Sender: TObject) ;
  2.  begin
  3.    AddFontResource('c:FONTSMyFont.TTF') ;
  4.    SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0) ;
  5.  end;
  6.  {Remove font again on program termination}
  7.  procedure TForm1.FormDestroy(Sender: TObject; var Action: TCloseAction) ;
  8.  begin
  9.    RemoveFontResource('C:FONTSMyFont.TTF') ;
  10.    SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0) ;
  11.  end;

lainz

  • Hero Member
  • *****
  • Posts: 4593
  • Web, Desktop & Android developer
    • https://lainz.github.io/
Re: Help Needed: Cross Platform Third Party Fonts
« Reply #4 on: February 03, 2023, 03:37:49 am »
3. Windows has \Windows\Fonts

That's not a good solution. User might not want to have the fonts installed for every running application. The better solution:
Code: Pascal  [Select][+][-]
  1.  procedure TForm1.FormCreate(Sender: TObject) ;
  2.  begin
  3.    AddFontResource('c:FONTSMyFont.TTF') ;
  4.    SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0) ;
  5.  end;
  6.  {Remove font again on program termination}
  7.  procedure TForm1.FormDestroy(Sender: TObject; var Action: TCloseAction) ;
  8.  begin
  9.    RemoveFontResource('C:FONTSMyFont.TTF') ;
  10.    SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0) ;
  11.  end;

Thanks this code looks easy to use hope it works on Windows 11?

lainz

  • Hero Member
  • *****
  • Posts: 4593
  • Web, Desktop & Android developer
    • https://lainz.github.io/
Re: Help Needed: Cross Platform Third Party Fonts
« Reply #5 on: February 03, 2023, 02:30:42 pm »
3. Windows has \Windows\Fonts

That's not a good solution. User might not want to have the fonts installed for every running application. The better solution:
Code: Pascal  [Select][+][-]
  1.  procedure TForm1.FormCreate(Sender: TObject) ;
  2.  begin
  3.    AddFontResource('c:FONTSMyFont.TTF') ;
  4.    SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0) ;
  5.  end;
  6.  {Remove font again on program termination}
  7.  procedure TForm1.FormDestroy(Sender: TObject; var Action: TCloseAction) ;
  8.  begin
  9.    RemoveFontResource('C:FONTSMyFont.TTF') ;
  10.    SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0) ;
  11.  end;

Tested and works on Windows 11. Just cast to
Code: Pascal  [Select][+][-]
  1. Pchar('C:\FONTS\MyFont.TTF')
and you're good to go.

Unfortunately the wide version didn't work...

Code: Pascal  [Select][+][-]
  1. RemoveFontRresourceW(PWideChar(...));

Maybe casting PWideChar directly to a String is not working...

domasz

  • Hero Member
  • *****
  • Posts: 529
Re: Help Needed: Cross Platform Third Party Fonts
« Reply #6 on: February 03, 2023, 02:50:33 pm »
Tested and works on Windows 11.
I don't have Win11 but on Windows7 and Windows 10 it works. It also works in Delphi. So seems like a solid solution.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5672
  • Compiler Developer
Re: Help Needed: Cross Platform Third Party Fonts
« Reply #7 on: February 03, 2023, 03:40:28 pm »
3. Windows has \Windows\Fonts

That's not a good solution. User might not want to have the fonts installed for every running application. The better solution:
Code: Pascal  [Select][+][-]
  1.  procedure TForm1.FormCreate(Sender: TObject) ;
  2.  begin
  3.    AddFontResource('c:FONTSMyFont.TTF') ;
  4.    SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0) ;
  5.  end;
  6.  {Remove font again on program termination}
  7.  procedure TForm1.FormDestroy(Sender: TObject; var Action: TCloseAction) ;
  8.  begin
  9.    RemoveFontResource('C:FONTSMyFont.TTF') ;
  10.    SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0) ;
  11.  end;

You should not do this as part of OnCreate and OnDestroy of the form as a form might be created multiple times (you might not do so now, but you might have a reason for it later on). Instead do this at the start of the main program and the end of the main program.

Linux
https://itsfoss.com/install-fonts-ubuntu/

Basically on Ubuntu / Mint one can create HOME/.fonts directory and put the fonts there, maybe that can be done easily from an FPC program... extracting the fonts from the binary, or using a folder where then we copy it to the hidden fonts folder.

There is no guarantee that FontConfig is configured that way. It's very likely that it is, but the system administrator might decide that users don't get to install their own fonts.

@Thaddy what if the HOME/.fonts can't be created. I have a Linux system with the HOME folder blocked.

Or they refer as HOME as HOME/username?

Thaddy didn't write anything about HOME, he wrote ~/.fonts which is the .fonts directory in the user's folder (e.g. /home/pascaldragon/.fonts). If you can't create this as long as your application is running as the same user then something is seriously wrong, because a user always is supposed to have write access in their own home directory.

Bogen85

  • Hero Member
  • *****
  • Posts: 612
Re: Help Needed: Cross Platform Third Party Fonts
« Reply #8 on: February 03, 2023, 04:00:34 pm »
@Thaddy what if the HOME/.fonts can't be created. I have a Linux system with the HOME folder blocked.

Or they refer as HOME as HOME/username?

Not completely on topic, but...
(keep in mind, the following are just cursory details, there is a bit more involved...)

By HOME I assume you mean the environment variable. Which is set by your login environment and points to your home directory.

This is usually /home/username (both case sensitive) but that is not always the case.

Tilde / (~/) is expanded by the command shell (bash as least, not sure about others) to $HOME/ which might by /home/username/, but might be some other location that does have have home or your username in it.

As @PascalDragon pointed out, you should have write access on most Linux setups to what $HOME/ expands to, if you don't, that is almost always a problem.
If this is a normal desktop Linux install (not some highly custom one for some specific appliance or device) you will always have write access to your $HOME/.
« Last Edit: February 03, 2023, 04:03:54 pm by Bogen85 »

Bogen85

  • Hero Member
  • *****
  • Posts: 612
Re: Help Needed: Cross Platform Third Party Fonts
« Reply #9 on: February 03, 2023, 04:11:49 pm »
@Thaddy what if the HOME/.fonts can't be created. I have a Linux system with the HOME folder blocked.

Or they refer as HOME as HOME/username?

In what context are you referencing HOME/.fonts?

Per my previous reply, $HOME/ and ~/ expansion will only be in your shell, or in some other environment that understands how to do that expansion.

lainz

  • Hero Member
  • *****
  • Posts: 4593
  • Web, Desktop & Android developer
    • https://lainz.github.io/
Re: Help Needed: Cross Platform Third Party Fonts
« Reply #10 on: February 03, 2023, 04:14:01 pm »
I'm not Linux expert, for that I ask. AFAIK our custom Linux might have support for that .fonts directory, that was not removed AFAIK. Is based on Mint.

I have HOME folder and that's not writable, but yes HOME/username is writable.

So I need to create the folder in HOME/username/.fonts/

How I can do that with FPC?

Edit: Say I have the fonts in my program directory I access with this function:
Code: Pascal  [Select][+][-]
  1. DirectorioAplicacion + 'myfont.ttf'
I want to copy to HOME/username/.fonts/myfont.ttf
« Last Edit: February 03, 2023, 04:16:18 pm by lainz »

Bogen85

  • Hero Member
  • *****
  • Posts: 612
Re: Help Needed: Cross Platform Third Party Fonts
« Reply #11 on: February 03, 2023, 04:25:40 pm »
I have HOME folder and that's not writable, but yes HOME/username is writable.

Just to be clear, you mean /home on your system is not writable by you, but what might be /home/lainz (assumption of username for case of this discussion) is writable.

That is a normal setup.

I'm not Linux expert, for that I ask. AFAIK our custom Linux might have support for that .fonts directory, that was not removed AFAIK. Is based on Mint.

In this context I would call Mint completely standard and non custom (Mint is not a deviation from mainstream on the vast majority of how it does things, I don't really know if ever deviates, but "mainstream" can be and is very broad/fuzzy term)
It is unlikely that something based on Mint would (or even could) deviate to this degree, but could be wrong. (anything is possible...)

« Last Edit: February 03, 2023, 04:27:44 pm by Bogen85 »

Bogen85

  • Hero Member
  • *****
  • Posts: 612
Re: Help Needed: Cross Platform Third Party Fonts
« Reply #12 on: February 03, 2023, 04:29:47 pm »
So I need to create the folder in HOME/username/.fonts/

How I can do that with FPC?

Edit: Say I have the fonts in my program directory I access with this function:
Code: Pascal  [Select][+][-]
  1. DirectorioAplicacion + 'myfont.ttf'
I want to copy to HOME/username/.fonts/myfont.ttf

I'm thinking about how you can do this...
Not sure if would be considered the normal way.
Usually fonts would be in standard location, and you would just indicate in your application the details of the font you are using.

EDIT: Unless you mean when your program runs, it needs to update a standard location? (copy a font that is next to application to the standard location?)
« Last Edit: February 03, 2023, 04:31:37 pm by Bogen85 »

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Re: Help Needed: Cross Platform Third Party Fonts
« Reply #13 on: February 03, 2023, 04:33:12 pm »
For Windows I've created a simple class to help using embedded Fonts, maybe that help you too?
You can use it like:
Code: Pascal  [Select][+][-]
  1. var
  2.   FFont: TkzFonts;
  3. begin
  4.   FFont := TkzFonts.Create;
  5.   if FFont.LoadResourceFont(HInstance, 1) then
  6.     AnyControl.Font.Name := string(FFont.Index[0].FontName);
In that case a font with a resource identifier of "1" would be loaded and added to an internal array of fonts what you easy can access like shown.
« Last Edit: February 03, 2023, 04:34:54 pm by KodeZwerg »
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

lainz

  • Hero Member
  • *****
  • Posts: 4593
  • Web, Desktop & Android developer
    • https://lainz.github.io/
Re: Help Needed: Cross Platform Third Party Fonts
« Reply #14 on: February 03, 2023, 04:35:30 pm »
So I need to create the folder in HOME/username/.fonts/

How I can do that with FPC?

Edit: Say I have the fonts in my program directory I access with this function:
Code: Pascal  [Select][+][-]
  1. DirectorioAplicacion + 'myfont.ttf'
I want to copy to HOME/username/.fonts/myfont.ttf

I'm thinking about how you can do this...
Not sure if would be considered the normal way.
Usually fonts would be in standard location, and you would just indicate in your application the details of the font you are using.

EDIT: Unless you mean when your program runs, it needs to update a standard location? (copy a font that is next to application to the standard location?)

Exactly, I  have say

home/username/myprogram/myfont.ttf

and I want to copy it to

home/username/.fonts/myfont.ttf at runtime, so it's available, only once, if exists don't copy it again... and create the folder if don't exists, all by code

 

TinyPortal © 2005-2018