Recent

Author Topic: [SOLVED] Font question  (Read 1826 times)

Pe3s

  • Hero Member
  • *****
  • Posts: 533
[SOLVED] Font question
« on: March 26, 2023, 11:34:51 am »
Hello , I have a question about changing the font in the project . If I change the font to my own, compile the project and move it to another computer where this font is not installed, will the font be displayed or will it be replaced?

« Last Edit: March 26, 2023, 04:36:36 pm by Pe3s »

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: Font question
« Reply #1 on: March 26, 2023, 11:42:25 am »
1. If the font is not available, both on Linux and Windows an effort is made to replace it with a font from the same "font family". This can lead to disappointing results, though.
2. A better way is to include the font as a font resource, so the font is part of your application.

I often use 1), but if the font is really special, say, e.g. for music notation, I always use 2). In commercial software I only use 2) except if I use a font that is known to be part of the OS distribution and the application is restricted to that OS.
When in doubt, or X--platform, choose 2)

Adding a font resource is quite easy and I already gave an example sometime ago.

Note that many fonts are copyrighted or otherwise subject to licensing, so try to use a font without many restrictions, like "Creative Commons" versions. Many of the best fonts have such a license.

Of course if you have an interest in Typography/Typesetting you can also design your own font. There are many freeware font designers available. (Challenging, though, at least to me)
« Last Edit: March 26, 2023, 12:06:40 pm by Thaddy »
Specialize a type, not a var.

Pe3s

  • Hero Member
  • *****
  • Posts: 533
Re: Font question
« Reply #2 on: March 26, 2023, 12:38:40 pm »
@Thaddy, I found this code to read font from resources

Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. var
  3.   MyResStream: TResourceStream;
  4. begin
  5.   MyResStream:=TResourceStream.Create(hInstance, 'MYFONT', RT_RCDATA);
  6.   MyResStream.SavetoFile('Gen4.ttf');
  7.   AddFontResource(PChar('Gen4.ttf'));
  8.   SendMessage(HWND_BROADCAST,WM_FONTCHANGE,0,0);
  9.   Label1.Font.Charset:=SYMBOL_CHARSET;
  10.   Label1.Font.Size:=24;
  11.   Label1.Font.Name:='Gen4';
  12. end;
  13.  

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2007
  • Fifty shades of code.
    • Delphi & FreePascal
Re: Font question
« Reply #3 on: March 26, 2023, 12:40:19 pm »
Here you find my way  :P
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

Pe3s

  • Hero Member
  • *****
  • Posts: 533
Re: Font question
« Reply #4 on: March 26, 2023, 04:36:23 pm »
Thank you  :)

Pe3s

  • Hero Member
  • *****
  • Posts: 533
Re: [SOLVED] Font question
« Reply #5 on: March 26, 2023, 05:57:05 pm »
I have this thought, it is easier to load a font from disk than from resources

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2007
  • Fifty shades of code.
    • Delphi & FreePascal
Re: [SOLVED] Font question
« Reply #6 on: March 26, 2023, 07:02:19 pm »
I prefer using my class, easy in handling, works for me on Windows flawless.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: [SOLVED] Font question
« Reply #7 on: March 26, 2023, 07:36:13 pm »
I have this thought, it is easier to load a font from disk than from resources
There is not much difference in complexity.
What is different is that you do not have to provide the font as a separate file, which is important.
(KodeZwerg 's code is way over-compicated, but will do what you mean.)

The snippet you found is very close to what I published.
« Last Edit: March 26, 2023, 07:37:46 pm by Thaddy »
Specialize a type, not a var.

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2007
  • Fifty shades of code.
    • Delphi & FreePascal
Re: [SOLVED] Font question
« Reply #8 on: March 26, 2023, 07:47:31 pm »
(KodeZwerg 's code is way over-compicated, but will do what you mean.)
Code: Pascal  [Select][+][-]
  1. if FFonts.LoadResourceFont(HInstance, 1, RT_FONT) then
Total overcomplicated... I see and laugh out loud.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

Pe3s

  • Hero Member
  • *****
  • Posts: 533
Re: [SOLVED] Font question
« Reply #9 on: March 27, 2023, 05:23:33 pm »
Unable to load font from resource by way
Code: Pascal  [Select][+][-]
  1. var
  2.   Stream: TResourceStream;
  3. begin
  4.   Stream := TResourceStream.Create(HInstance, 'MyFont', RT_RCDATA);
  5.  

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2007
  • Fifty shades of code.
    • Delphi & FreePascal
Re: [SOLVED] Font question
« Reply #10 on: March 27, 2023, 06:09:06 pm »
Demo for my Class.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

Pe3s

  • Hero Member
  • *****
  • Posts: 533
Re: [SOLVED] Font question
« Reply #11 on: March 27, 2023, 07:39:06 pm »
Thank you, I will use your method

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2007
  • Fifty shades of code.
    • Delphi & FreePascal
Re: [SOLVED] Font question
« Reply #12 on: March 28, 2023, 01:42:59 pm »
Thank you, I will use your method
You are welcome. Not forget to check license for fonts if allowed to embed them in your applications.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

Pe3s

  • Hero Member
  • *****
  • Posts: 533
Re: [SOLVED] Font question
« Reply #13 on: March 29, 2023, 06:38:27 pm »
Just out of curiosity ,
this code works too, it loads the font from the resources.
Code: Pascal  [Select][+][-]
  1. uses: jwawingdi
  2. function LoadResourceFontByName(const ResourceName : string; ResType: PChar) : Boolean;
  3. var
  4.   ResStream : TResourceStream;
  5.   FontsCount : DWORD;
  6. begin
  7.   ResStream := TResourceStream.Create(hInstance, ResourceName, ResType);
  8.   try
  9.     Result := (AddFontMemResourceEx(ResStream.Memory, ResStream.Size, nil, @FontsCount) <> 0);
  10.   finally
  11.     ResStream.Free;
  12.   end;
  13. end;
  14.  
  15.  
  16. procedure TForm1.Button6Click(Sender: TObject);
  17. begin
  18.    if LoadResourceFontByName('MR', RT_RCDATA) then
  19.    Self.Font.Name := 'Montserrat-Regular';
  20. end;
  21.  

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2007
  • Fifty shades of code.
    • Delphi & FreePascal
Re: [SOLVED] Font question
« Reply #14 on: March 29, 2023, 07:38:34 pm »
Yes, under the hood every approach used to wrap around the WinAPI on its own way.
Code: Pascal  [Select][+][-]
  1. function TkzFonts.LoadResourceFont(const AInstance: THandle; const AResID: Integer; const AResTyp: {$IFDEF UNICODE}PWideChar{$ELSE UNICODE}PAnsiChar{$ENDIF UNICODE} = {$IFDEF UNICODE}PWideChar{$ELSE UNICODE}PAnsiChar{$ENDIF UNICODE}(RT_RCDATA)): Boolean;
  2. var
  3.   LRes: TResourceStream;
  4.   i, LCount: Integer;
  5.   LMyFont: TMyFont;
  6. begin
  7.   Result := False;
  8.   {$IFNDEF WINDOWS}
  9.     Exit;
  10.   {$ENDIF WINDOWS}
  11.   if ResourceExists(AInstance, AResID, AResTyp) then
  12.     begin
  13.       LRes := TResourceStream.CreateFromID(AInstance, AResID, PChar(AResTyp));
  14.       try
  15.         LMyFont.Handle := AddFontMemResourceEx(LRes.Memory, LRes.Size, nil, @LCount);
  16.         if ((LMyFont.Handle <> INVALID_HANDLE_VALUE) and (LMyFont.Handle <> 0)) then
  17.           Result := GetFontName(LRes, LMyFont);
  18.         if Result then
  19.           begin
  20.             i := Length(FMyFonts);
  21.             SetLength(FMyFonts, i + 1);
  22.             FMyFonts[i] := LMyFont;
  23.             FCount := Length(FMyFonts);
  24.             if (Assigned(FOnFontEvent)) then
  25.               FOnFontEvent(Self, FMyFonts[i].FontName, FMyFonts[i].Handle);
  26.           end;
  27.       finally
  28.         LRes.Free;
  29.       end;
  30.     end;
  31. end;
  32.  
  33. function TkzFonts.LoadResourceFont(const AInstance: THandle; const AResName: {$IFDEF UNICODE}WideString{$ELSE UNICODE}AnsiString{$ENDIF UNICODE}; const AResTyp: {$IFDEF UNICODE}PWideChar{$ELSE UNICODE}PAnsiChar{$ENDIF UNICODE} = {$IFDEF UNICODE}PWideChar{$ELSE UNICODE}PAnsiChar{$ENDIF UNICODE}(RT_RCDATA)): Boolean;
  34. var
  35.   LRes: TResourceStream;
  36.   i, LCount: Integer;
  37.   LMyFont: TMyFont;
  38. begin
  39.   Result := False;
  40.   {$IFNDEF WINDOWS}
  41.     Exit;
  42.   {$ENDIF WINDOWS}
  43.     if ResourceExists(AInstance, AResName, AResTyp) then
  44.     begin
  45.       LRes := TResourceStream.Create(AInstance, string(AResName), PChar(AResTyp));
  46.       try
  47.         LMyFont.Handle := AddFontMemResourceEx(LRes.Memory, LRes.Size, nil, @LCount);
  48.         if ((LMyFont.Handle <> INVALID_HANDLE_VALUE) and (LMyFont.Handle <> 0)) then
  49.           Result := GetFontName(LRes, LMyFont);
  50.         if Result then
  51.           begin
  52.             i := Length(FMyFonts);
  53.             SetLength(FMyFonts, i + 1);
  54.             FMyFonts[i] := LMyFont;
  55.             FCount := Length(FMyFonts);
  56.             if (Assigned(FOnFontEvent)) then
  57.               FOnFontEvent(Self, FMyFonts[i].FontName, FMyFonts[i].Handle);
  58.           end;
  59.       finally
  60.         LRes.Free;
  61.       end;
  62.     end;
  63. end;
In my case, I collect them in an easy to use array plus I do not need to know the actual Fontface name.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

 

TinyPortal © 2005-2018