Recent

Author Topic: resource as fonts  (Read 8850 times)

sam707

  • Guest
resource as fonts
« on: October 02, 2014, 12:42:23 am »
is there a SIMPLE way to embed  truetype free fonts in resources of an executable and load them at runtime for display?

I guess using lazUtils unit, freetype unit, streamed resource, etc. can help... and including a font in a laz resource file (.lrs) conditionally ...

I.e. :

suppose I have a fonts pack that is available for linux, mac, windows...

does something like below exist? or a simple way to achieve what it means...

{$ifdef Windows}
{$I myttfontsWin.lrs}
{$else}
{$I myttfontslinux.lrs}

myfont := TFont.Create;
myfont.LoadFromResource('biShaded.fnt'); // or from memorystream...

this behaviour should also be apreciated by fonts creators who do not want to distribute their fonts outside their executables... i especially think about games creators ...

thanks by advance
« Last Edit: October 02, 2014, 12:51:15 am by sam707 »

tr_escape

  • Sr. Member
  • ****
  • Posts: 432
  • sector name toys | respect to spectre
    • Github:
Re: resource as fonts
« Reply #1 on: October 02, 2014, 10:20:24 am »
You can use this function :

WriteComponentResFile('question_fnt.dat',frmAyarlar.FontDialog1);

for reading:

ReadComponentResFile('reminder_fnt.dat',frmAyarlar.FontDialog3);

I will save all properties which component saving to harddisk

I am using in my software...
« Last Edit: October 02, 2014, 10:22:35 am by tr_escape »

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: resource as fonts
« Reply #2 on: October 02, 2014, 10:31:27 am »
I'm not sure how to do it in Linux but for Windows I'll show you. Just loading the font in a TFont is not the way to use it in Windows itself. You'll need to use AddFontMemResourceEx to use it in your components at runtime.

Here I have a Kixcode-font (special barcode for post). I'll load the font from resource and assign the font to the text in the button. (all in memory):

font.rc:
Code: [Select]
KIX_FONT           RT_FONT "Kixbrg_.ttf"

Your unit:
Code: [Select]
{$R font.rc}

var
  hKixFontRes: LongWord;

const
  MM_MAX_NUMAXES = 16;

type
  LPDWORD = ^DWORD;

function AddFontMemResourceEx(pbFont: Pointer; cbFont: DWORD; pdv: Pointer; pcFonts: LPDWORD): LongWord; stdcall;
  external 'gdi32.dll' Name 'AddFontMemResourceEx';
function RemoveFontMemResourceEx(fh: LongWord): LongBool; stdcall;
  external 'gdi32.dll' Name 'RemoveFontMemResourceEx';

function CheckAndLoadKixcodeFont: boolean;
var
  ResS1: TResourceStream;
  FontCount1: cardinal;
  FontId: integer;
begin
  Result := true;
  FontId := Screen.Fonts.IndexOf('KIX_FONT'); // <- resource name
  if FontId > 0 then exit; // already loaded
  if hKixFontRes > 0 then exit; // already loaded
  Result := false;
  FontCount1 := 0;
  ResS1 := TResourceStream.Create(hInstance, 'KIX_FONT', 'RT_FONT'); // <- resource name
  try
    hKixFontRes := AddFontMemResourceEx(ResS1.Memory, ResS1.Size, nil, @FontCount1);
  finally
    ResS1.Free;
    Result := (FontCount1 = 1);
  end;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
  if CheckAndLoadKixcodeFont then
  begin
    Button1.Font.Name := 'KIX Barcode'; // <- internal font-name !!!
  end;
end;

initialization
  hKixFontRes := 0;

finalization
  if hKixFontRes <> 0 then // remove font from memory if it's loaded
    RemoveFontMemResourceEx(hKixFontRes);

« Last Edit: October 02, 2014, 10:33:52 am by rvk »

sam707

  • Guest
Re: resource as fonts
« Reply #3 on: October 02, 2014, 08:17:56 pm »
well guys thank you for your answers but I just read some papers and saw that in Delphi there is an "AddFontResource" function not planned to be implemented in lazarus... after what I found out that in Lazarus there is a Font list REGISTERED at startup in the Screen (TScreen) object comming from the platform where the application runs.

So, the 'simple' way to embed fonts inside resource can not be as simple as I thought lol  :o

I am going to embed fonts into .lrs file and extract them fromm my exe at runtime to make the platform register them and see how the Screen object is initialized to propagate font list ... problem stil ahead = I want the fonts to be deleted after my app execution ends...

http://lazarus-ccr.sourceforge.net/docs/lcl/forms/tscreen.html

see Fonts property [TStrings] ReadOnly  :(
« Last Edit: October 02, 2014, 08:34:55 pm by sam707 »

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: resource as fonts
« Reply #4 on: October 02, 2014, 09:35:40 pm »
... and saw that in Delphi there is an "AddFontResource" function not planned to be implemented in lazarus...
...
So, the 'simple' way to embed fonts inside resource can not be as simple as I thought lol  :o
AddFontMemResourceEx (and AddFontResource) are not Delphi specific. They are Windows specific. You can use them perfectly fine in Lazarus (under Windows). My code shows how to use AddFontMemResourceEx. It worked perfectly in Lazarus for assigning a font loaded from resource and the font only resides in memory. (I tested it before posting this code.) So at least for Windows you can use this method directly from memory. If you want a cross-platform solution you have to look at how to do this in Linux/MacOS.

If you want to save your fonts to disk and register them with the OS, I hope you make sure the user has the correct privileges to do so. It's just the mess of saving the font, registering them and not forgetting to UNREGISTER them and deleting the file which made me decide that i'd use the AddFontMemResourceEx-method. (I doubt your way would be 'simpler' than my example)

For unregistering and removing the font you could use the same method i used. The finalization-section of your program.

Edit:
I don't have a lot of Linux-GUI experience so you have to check the method below yourself. (I only used Linux as server with just the console). I searched a little for adding fonts in Linux "on the fly". I'm going to assume the user/program does not have privileges to install a system-font. You shouldn't either because otherwise your program will run into trouble if it runs unprivileged. Maybe you can add the font as file in $HOME/.fonts/ and run fc-cache --force. You'll have to check if after that you can assign the name of the font to any of your components in runtime. The method is described here.
If this method works you could write your own cross-platform routines which would use AddFontResource on Windows and $HOME/.fonts/ on Linux.
« Last Edit: October 02, 2014, 10:39:06 pm by rvk »

qdos

  • Full Member
  • ***
  • Posts: 112
Re: resource as fonts
« Reply #5 on: October 02, 2014, 11:10:07 pm »
I would probably not bother with embedding a TTF file inside the .exe, but installing the font so you can use it - means copying it to the fonts folder.

On Ubuntu at least that folder is:
/home/username/.fonts

See following link for info:
http://ubuntuforums.org/showthread.php?t=951250

sam707

  • Guest
Re: resource as fonts
« Reply #6 on: October 02, 2014, 11:53:08 pm »
correct! friends... I just wanted to know if lazarus had an easy way to use embeded fonts inside an application with lrs, because I'm sure such a behavior would interest game creators and netchats creators whom do not especially want to freely give their fonts to the OS except use them inside their apps.

actually i am building an "iRC like modified protocol" client server based on lNet library with fonts and graphics abilities ... I want all final clients to visualize and use some SHARED fonts .. that are known by my tchat client (cross platform) not necessary by the underlaying OS ...

a client change its font in his OS and broadcast a message to his friends on other OSes... I want them all receive the message with the same look and feel (bold italic strikeout and SAME crossplatform FONT, no placeholder!)
« Last Edit: October 03, 2014, 12:04:00 am by sam707 »

 

TinyPortal © 2005-2018