LazFreeType: Font names and file names lazarus / 39-Graphics ---------------------------------------------------------------------- wp · 2016-06-01 13:07 I am trying to add FreeType support to the OpenGL drawer of TAChart, but I am stuck at how fpc/Laz handles the fonts there. Accessing a font in FreeType is file-based, i.e. I need to know the filename of a font including path in order to open a font in FreeType. The filenames, however, are different from the font names as used in the LCL TFont.Name property. My questions: If some text control uses a font "Times New Roman" how can I find out its file name (times.ttf)? How can I find out the path to the font in a platform-independent way? This is easy on Windows, but how on Linux/Unix/Mac etc? How to handle other font files for bold and/or italic within the same font family? In contrast to the fcl routines, the LazFreeType units seem to support UTF8. Correct?Do LazFreeType and the related drawers (e.g. TLazFreeTypeFPImageDrawer) support BiDi (right-to-left)?Since the OpenGL drawer of TAChart should be independent of LCL I cannot use any LCL functions. ---------------------------------------------------------------------- marcov · 2016-06-01 14:22 Quote from: wp on June 01, 2016, 03:07:19 pmIf some text control uses a font "Times New Roman" how can I find out its file name (times.ttf)? Afaik a TFont is a Windows (H)font under the hood. It seems with gettext*metrics functions you can query more info: http://stackoverflow.com/questions/11387564/get-a-font-filepath-from- name-and-style-in-c-windows Quote   How can I find out the path to the font in a platform- independent way? This is easy on Windows, but how on Linux/Unix/Mac etc? Linux and other open source *nix rarely have APIs for such things, usually you are already lucky if there is a way by executing a command and interpreting its output; a fragile process: http://unix.stackexchange.com/questions/123511/find-font-file-from- font-name-on-linux Quote   How to handle other font files for bold and/or italic within the same font family? In contrast to the fcl routines, the LazFreeType units seem to support UTF8. Correct?Do LazFreeType and the related drawers (e.g. TLazFreeTypeFPImageDrawer) support BiDi (right-to- left)?Since the OpenGL drawer of TAChart should be independent of LCL I cannot use any LCL functions. No idea about these. But fonts crossplatforms are nearly always a problem. ---------------------------------------------------------------------- engkin · 2016-06-02 04:33 fc-list, fc-scan and fc-match mentioned in Marco's link are part of Fontconfig. Find all the fonts using Fontconfig directly, or its XML configuration file /etc/fonts/fonts.conf: Quote This element contains a directory name which will be scanned for font files to include in the set of available fonts. Quote from: wp on June 01, 2016, 03:07:19 pmDo LazFreeType and the related drawers (e.g. TLazFreeTypeFPImageDrawer) support BiDi (right- to-left)? No, they don't. Not without some help. ---------------------------------------------------------------------- wp · 2016-06-02 11:27 Thanks for your ideas. But it was not quite what I was looking for. After some digging in the source files that come with Lazarus I found freetype gems in "components/lazutils". It is possible, with just a few lines of code, to collect all ttf files in a given folder, extract their font families and the styles belonging to this family. This helps me a lot: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program fontcollection_demo; {$mode objfpc}{$H+} uses  {$IFDEF UNIX}{$IFDEF UseCThreads}  cthreads,  {$ENDIF}{$ENDIF}  Classes, SysUtils, LazFileUtils, EasyLazFreeType, LazFreeTypeFontCollection; var  FontDirList: TStringList;  Font: TFreeTypeFont; procedure CreateFontDirList;var  s: String;begin  FontDirList := TStringList.Create; {$IFDEF WINDOWS}  s := SHGetFolderPathUTF8(20); // CSIDL_FONTS = 20  if s <> '' then    FontDirList.Add(s); {$ENDIF} {$IFDEF linux}  FontDirList.Add('/usr/share/cups/fonts/');  FontDirList.Add('/usr/share/fonts/truetype/');  FontDirList.Add('/usr/local/lib/X11/fonts/');  FontDirList.Add(GetUserDir + '.fonts/'); {$ENDIF}end; procedure InstallFonts;var  i: Integer;begin  for i:=0 to FontDirList.Count-1 do    FontCollection.AddFolder(FontDirList[i]);end; procedure ListFontFamily(AFamilyName: String);var  familyItem: TCustomFamilyCollectionItem;  i: Integer;  font: TFreeTypeFont;begin  WriteLn('Font family "', AFamilyName, '":');  familyItem := FontCollection.Family[AFamilyName];  if familyItem = nil then    WriteLn('  not found.')  else begin  WriteLn('  Font count: ', familyItem.FontCount);  for i:=0 to familyItem.FontCount-1 do begin  WriteLn('  Font #', i+1, ':');    WriteLn('                Filename: ', familyItem.Font[i].Filename);    WriteLn('                  styles: ', familyItem.Font[i].Styles);    WriteLn('                    bold: ', BoolToStr(familyItem.Font[i].Bold, 'true', 'false'));    WriteLn('                italic: ', BoolToStr(familyItem.Font[i].Italic, 'true', 'false'));    font := familyItem.Font[i].Createfont;    try    font.SizeInPoints := 12;      WriteLn('     TextWidth(''M'')@12pt: ', FloatToStr(font.TextWidth('M')));      font.SizeInPoints := 48;    WriteLn('     TextWidth(''M'')@48pt: ', FloatToStr(font.TextWidth('M')));    finally      font.Free;    end;  WriteLn;  end;  end;  WriteLn('-------------------------------------- --------------------------------');end; begin  CreateFontDirList;  FontCollection := TFreeTypeFontCollection.Create;  InstallFonts;   FontCollection.AddFile('c:\Windows\Fonts\arial.ttf');   WriteLn('Font files   : ', FontCollection.FontFileCount);  WriteLn('Family count : ', FontCollection.FamilyCount);  WriteLn('---------------------------- ------------------------------------------');   ListFontFamily('arial');            // case is ignored  ListFontFamily('TimesNewRoman');    // <-- does not exist  ListFontFamily('Times New Roman');  // <-- does exist   FontCollection.Free;  FontDirList.Free;   ReadLn;end. (Not perfect, yet, because the demo hangs if the same folder is added twice). It seems that these "LazFreeType"-related units do not require the freetype.dll (unlike the fcl units freetype and ftfont) ---------------------------------------------------------------------- circular · 2016-06-02 20:44 Indeed, LazFreeType is an actual implementation of FreeType fonts. However there is room for improvement (some fonts are distorted, right-to-left is not handled...) ---------------------------------------------------------------------- Graeme · 2016-06-03 14:47 Quote from: wp on June 01, 2016, 03:07:19 pmMy questions: ...snip... I've just written such a class for FPC. It is currently in FPC Trunk only, but is 100% backwards compatible with FPC 2.6.4 too. Simply copy the units from FPC Trunk if need be. Take a look at the src/packages/fcl-pdf/src/fpttf.pp unit. Usage is as simple as: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   // specify what directories should be used to find TrueType fonts  gTTFontCache.SearchPath.Add(ExtractFilePath(ParamStr(0)) + 'fonts/');  // ask to generate the font cache  gTTFontCache.BuildFontCache;  Now you can do fontname, font file paths and metric lookups using the gTTFontCache instance. There are some more improvements coming to that unit, which are required for the upcoming fpReport (FPC reporting engine) release coming time soon. If you didn't want to use fpTTF, then you need to call OS specific API's. Win32 includes what you want for Windows. FontConfig includes what you want for Linux and FreeBSD platforms. I don't know what is used under OSX. ---------------------------------------------------------------------- engkin · 2016-06-04 02:07 I just gave fpTTF a try. It seems that it only supports Windows fonts with Unicode BMP (UCS-2) CMAP tables (PlatformID=3, EncodingID=1): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TTFFileInfo.ParseCmap(AStream : TStream);....  While (UE>=0) and ((FSubtables[UE].PlatformID<>3) or (FSubtables[UE].EncodingID<> 1)) do    Dec(UE);  if (UE=-1) then    Raise ETTF.Create('No Format 4 map (unicode) table found <'+FFileName + ' - ' + PostScriptName+'>');..... When it fails it raises an exception which interrupts BuildFontCache. This could happen with symbolic fonts, like Windows webdings.ttf. ---------------------------------------------------------------------- Graeme · 2016-06-04 09:31 Quote from: engkin on June 04, 2016, 04:07:47 amI just gave fpTTF a try. It seems that it only supports Windows fonts with Unicode BMP (UCS-2) CMAP tables (PlatformID=3, EncodingID=1): Not sure why you say that, or mention "Windows fonts". I've tested with loads of different fonts, and the unit tests are written against the LiberationSans (metric equivalent to Helvetica) and the DejaVuSans fonts. QuoteThis could happen with symbolic fonts, like Windows webdings.ttf. Symbol fonts are still on the todo list - I haven't looked at them at all. ---------------------------------------------------------------------- engkin · 2016-06-04 18:28 Quote from: Graeme on June 04, 2016, 11:31:55 amQuote from: engkin on June 04, 2016, 04:07:47 amI just gave fpTTF a try. It seems that it only supports Windows fonts with Unicode BMP (UCS-2) CMAP tables (PlatformID=3, EncodingID=1): Not sure why you say that, or mention "Windows fonts". Correct me if am wrong, PlatformID=3 is for Windows