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