Recent

Author Topic: Something's broken in fpTTF : too many fonts causes Stream Read Error  (Read 2320 times)

paweld

  • Hero Member
  • *****
  • Posts: 1217
And did you even read the first post in the thread? TS uses fpttf - and that is quite different from System.Fonts.
Best regards / Pozdrawiam
paweld

jipété

  • Full Member
  • ***
  • Posts: 182
Here,
Code: Pascal  [Select][+][-]
  1. /etc/fonts/* =
  2. -rw-r--r-- 1 2808 15 mai    2020 fonts.conf
  3. drwxr-xr-x 2 4096 18 août   2022 conf.avail
  4. drwxr-xr-x 2 4096 17 mai   07:31 conf.d

cat fonts.conf shows sentences that I have no time to spend for tests
ls -al conf.avail shows 14 fonts' names
ls -al conf.d shows 46 links to conf files, dunno what to do with that.

Back to my problem : thanks to you but you forget that basic fact :
if I use /usr/share/fonts (1116 files) there is a problem with the 501th font, DOUR46W.TTF
if I use /usr/share/fonts/fonts_shared/from_Win2000/Polices/Machine (only 26 files) there is no problem !
So I take 20 files off, move them elsewhere and I restart the code : 1116 (files) becomes 1096, 602 (families) becomes 589 and there is no more problem, even with DOUR46W.TTF kept in this folder but at the 499th range.

Something very strange is the fact that a little procedure activated from a button hangs now at the 481th font ! (501 - 20 = 481...)
I have no time for that this week, see you on 15th of July.

jipété

  • Full Member
  • ***
  • Posts: 182
Hello,

I'm back, with good news!

I found the source of the problem, and it's inexplicable: it's a folder, just one, containing 9 .ttf files and 10 .otf files (but I have .otf elsewhere in the font tree, without problems...),  and I don't know how to explain it but there's only one file (the first .ttf file of the list from this folder) that is accepted by gTTFontCache.Items!
The others crash the program.
Well, I'll delete all that, I could live without them.

For your information, here are the culprits, extracted from the 960-line list:
Code: Text  [Select][+][-]
  1. ...
  2. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Bodoni/BODONI-1.TTF
  3. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/Garamond-EB-Pardo/EBGaramond-ExtraBold.ttf
  4. crash here-- /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/Garamond-EB-Pardo/EBGaramond-ExtraBoldItalic.otf
  5. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/Garamond-EB-Pardo/EBGaramond-SemiBold.ttf
  6. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/Garamond-EB-Pardo/EBGaramond-Regular.otf
  7. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/Garamond-EB-Pardo/EBGaramond-Regular.ttf
  8. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/Garamond-EB-Pardo/EBGaramond-Bold.ttf
  9. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/Garamond-EB-Pardo/EBGaramond-Medium.otf
  10. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/Garamond-EB-Pardo/EBGaramond-ExtraBold.otf
  11. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/Garamond-EB-Pardo/EBGaramond-Medium.ttf
  12. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/Garamond-EB-Pardo/EBGaramond-MediumItalic.ttf
  13. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/Garamond-EB-Pardo/EBGaramond-Italic.ttf
  14. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/Garamond-EB-Pardo/EBGaramond-MediumItalic.otf
  15. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/Garamond-EB-Pardo/EBGaramond-ExtraBoldItalic.ttf
  16. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/Garamond-EB-Pardo/EBGaramond-SemiBold.otf
  17. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/Garamond-EB-Pardo/EBGaramond-BoldItalic.otf
  18. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/Garamond-EB-Pardo/EBGaramond-Bold.otf
  19. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/Garamond-EB-Pardo/EBGaramond-SemiBoldItalic.ttf
  20. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/Garamond-EB-Pardo/EBGaramond-Italic.otf
  21. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/Garamond-EB-Pardo/EBGaramond-SemiBoldItalic.otf
  22. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/Garamond-EB-Pardo/EBGaramond-BoldItalic.ttf
  23. restart ok here-- /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/EBGaramond/08/EBGaramond08-Regular.otf
  24. /usr/share/fonts/fonts_shared/from_Win2000/Polices/Garamond/EBGaramond/08/EBGaramondSC08-Regular.otf
  25. ...

EDIT 30/july/24
Solved but incomprehensible!
Other problem, see my 30/july post /EDIT

Thanks, everybody  ;)
« Last Edit: July 30, 2024, 06:14:03 pm by jipété »

paweld

  • Hero Member
  • *****
  • Posts: 1217
It is likely that the font files are corrupted, so the parser did not cope with it. If you are making a program just for yourself then you can leave it like that, however, if you are going to share it further, in my opinion you should use the try...except block when trying to load/read each font item.
Best regards / Pozdrawiam
paweld

jipété

  • Full Member
  • ***
  • Posts: 182
in my opinion you should use the try...except block when trying to load/read each font item.
Something like that ? :
Code: Pascal  [Select][+][-]
  1. var
  2.   function ComputeField(aName: string): string;
  3.   begin  Result := Copy(ExtractFileName(aName), 1, length(aName)-4);  end;
  4. begin
  5.   gTTFontCache.SearchPath.Add('/usr/share/fonts');
  6.   gTTFontCache.BuildFontCache;
  7.   for i:= 0 to gTTFontCache.Count-1 do
  8.   try
  9.     with gTTFontCache do begin
  10.       if Items[i].HumanFriendlyName = '' then field1 := ComputeField(Items[i].FileName) else field1 := Items[i].HumanFriendlyName;
  11.       if Items[i].PostScriptName    = '' then field2 := ComputeField(Items[i].FileName) else field2 := Items[i].PostScriptName;
  12.       if Items[i].FamilyName        = '' then field3 := ComputeField(Items[i].FileName) else field3 := Items[i].FamilyName;
  13.       aLine := field1 +' ...'+  field2 +' ...'+  field3 +' ...'+ Items[i].FileName +' ***'; // *** used for end-of-line}
  14.       memoFontList.Lines.Add(aLine);
  15.     end;
  16.   except
  17.     memoFontList.Lines.Add('ERROR in '+ TFPFontCacheItem(gTTFontCache.Items[i]).FileName)
  18.   end;
  19. end;
  20.  
Never seen the error above...

jipété

  • Full Member
  • ***
  • Posts: 182
Hello,

The part that is wrong by design is the exception part: you should know beforehand if a font exists or not.
How do you do that ?

The other thing that is wrong is not choosing a font family, so there is at least a reasonable alternative.

Those two issues should really have been addressed a long time ago,  and it has been mentioned many times.
Will be happy to read that, thanks for the links.


« Last Edit: July 15, 2024, 05:31:56 pm by jipété »

paweld

  • Hero Member
  • *****
  • Posts: 1217
Quote from: jipété
Something like that ? :
yes
Quote from: jipété
How do you do that ?
you don't need to check it - such control is already provided by the method gTTFontCache.BuildFontCache;.
Best regards / Pozdrawiam
paweld

jipété

  • Full Member
  • ***
  • Posts: 182
Fonts, FpTTF and gTTFontCache, the nightmare

Hello,

I've been struggling with fonts for over a month now, with incomplete results. I've searched the entire internet, read hundreds of posts, and done dozens of code tests. In the end, out of 935 .ttf and .odt files, I have 17 that refuse to behave normally.
Cache analysis shows empty data for the three fields PostScriptName, FamilyName, and HumanFriendlyName, example with this little tool found this morning and adapted to my needs:
Code: Pascal  [Select][+][-]
  1. procedure TfrmMain.btnBasicTestClick(Sender: TObject);
  2. var // https://forum.lazarus.freepascal.org/index.php/topic,42163.msg293769.html#msg293769
  3.   F : Text;
  4.   i : Integer;
  5. begin
  6. (*  if gTTFontCache.SearchPath.Count=0 then
  7.     begin
  8.     {$IFDEF UNIX}
  9.       gTTFontCache.SearchPath.Add('/usr/share/fonts/truetype/dejavu/');
  10.     {$ENDIF}
  11.     end;    *)
  12.   //ShowMessage(inttostr(gTTFontCache.Count));
  13.   if (gTTFontCache.Count=0) then
  14.     gTTFontCache.ReadStandardFonts;
  15.   {$IFNDEF WINDOWS}
  16.   AssignFile(F,'/tmp/fonts.txt');
  17.   Rewrite(F);
  18.   For I:=0 to gTTFontCache.Count-1 do
  19.      Writeln(F,I,' ',gTTFontCache.Items[i].PostScriptName,' : ',gTTFontCache.Items[i].FamilyName,' : ',gTTFontCache.Items[i].HumanFriendlyName);
  20.   CloseFile(F);
  21.   {$ENDIF}
  22. end;
  23.  
extract from log file:
Code: Text  [Select][+][-]
  1. 194 Ondine Regular : Ondine : Ondine Regular
  2. 195 GenoaItalic : GenoaItalic : GenoaItalic
  3. 196  :  :
  4. 197  :  :
  5. 198  :  :
  6. 199  :  :
  7. 200 SpartaCapsSSK : SpartaCapsSSK : SpartaCapsSSK Regular
  8. 201 BlackadderITC-Regular : Blackadder ITC : Blackadder ITC
and yet, the concerned missing fonts here work correctly in the Windows environment.

By diving into the files, I still noticed that the ALMANAC.TTF font was among the missing ones and since I didn't like its name, I tried to modify the related fields with the good old Softy tool, like this:
img almanach_names

and amazement after saving and regenerating the cache, the font is still not detected!
By analyzing the file in depth, I was then able to see that there are two different areas where this data is saved, one accessible and modifiable (and ineffective) by the GUI, and the other of which we don't know what it is used for and how we could modify its data...
img font_without-with-dots.png

A final word: of these 17 fonts not recognized by FpTTF, at least 4 come from the official Windows world and worked well (from Win3.1 regarding Wingding).

And the question is: what can we do to correct these defects?
I would have liked to say more and diagnose more deeply but there is no way to step through FpTTF and fpparsettf, the compiler does not allow me to do that and I don't know why...

Linux Debian 11.9
Regards,

jipété

  • Full Member
  • ***
  • Posts: 182
Using the FontInfo tool (https://forum.lazarus.freepascal.org/index.php/topic,37329.msg250615.html) and the ALMANACH.TTF font (notice the "H" letter I've added), I see the following :

Code: Pascal  [Select][+][-]
  1. for I := 0 to NameRecordCount - 1 do begin
  2.   Stream.Read(TrueTypeNameRecord, SizeOf(TrueTypeNameRecord));
  3.   if EncodeWord(TrueTypeNameRecord.NameID) = 1 then begin
  4.     Len := EncodeWord(TrueTypeNameRecord.Length);
  5.     {Platform and Encoding stuff!!!}
  6.     if (EncodeWord(TrueTypeNameRecord.PlatformID) = 1) or (
  7.        (EncodeWord(TrueTypeNameRecord.PlatformID) = 3) and
  8.        (EncodeWord(TrueTypeNameRecord.EncodingID) = 0) )
  9.     then begin
  10.       {ANSI}
  11.       SetLength(Temp1, Len);
  12.       ...
And with step-by-step and the mouse on the "Len" word (line 4 here) I read "10", which is the length of "ALMANAC MT" without the "H", a string which exists in the second part of the previous image, not available to us, as I explained.

Maybe the useful data are there ?
How to get them ?

wp

  • Hero Member
  • *****
  • Posts: 12356
I would have liked to say more and diagnose more deeply but there is no way to step through FpTTF and fpparsettf, the compiler does not allow me to do that and I don't know why...
You must rebuild FPC with debug information.

jipété

  • Full Member
  • ***
  • Posts: 182
Thanks for this info (this is the first time I've had to recompile FPC...) I'll see about it a bit later, for now I'm focusing on the contents of the ALMANAC(H).TTF file.
I put parentheses around the H because the original file doesn't have this H, which doesn't change the fact that the new file, like others, is badly analyzed by gTTFontCache.

I made an image of the binary content of the file, we can clearly see that the data is duplicated, once with the letters that follow each other normally, another time they are separated by the value 00.

And we can see that the upper part of the image works with Almanac while the lower part uses Almanach, highlighted in red, and present thanks to Somfy.

From there I don't know what to do. Post a bug report?

In the meantime, I'm happy to post files that are not compatible with FpTTF, for testing, but I won't be able to correct the problem...

And regarding those who wrote on the previous page it was a broken font problem, I'm able to work with the font, using LO-Writer...

Its worth noting that the FontCache is substantially improved in FPC- fixes. If you are using FPC322, might be worth trying Fixes.
Dunno where to look for.

Regards,
« Last Edit: July 30, 2024, 06:26:41 pm by jipété »

jipété

  • Full Member
  • ***
  • Posts: 182
Re: Something's broken in fpTTF : too many fonts causes Stream Read Error
« Reply #26 on: August 06, 2024, 09:14:49 am »
Hello,

Here is the end of my torments.
I recap: I currently have 935 ttf and otf files, some dating back 30 years and having always worked well, in general and under Windows.
It was when switching to Linux that a problem appeared, when trying to use the option to know the location of the files, useful for their management, which generated a SIGSEGV exception for 17 of them, I mean the
Code: Pascal  [Select][+][-]
  1. function GetFontFile(fName:string): string;
  2. // https://forum.lazarus.freepascal.org/index.php?topic=48975.0
  3. var
  4.   lFC: TFPFontCacheItem;
  5. begin
  6.   lFC := gTTFontCache.FindFont(fName);
  7.   try
  8.     Result := lFC.FileName;
  9.   except
  10.     //
  11.   end;
  12. end;
function that relies on the fpTTF.pp unit and that I modified like this because I was tired of the complete shutdown of the program in the event of a problem with one or more fonts:
Code: Pascal  [Select][+][-]
  1. function GetFontFile(fName:string): string;
  2. // https://forum.lazarus.freepascal.org/index.php?topic=48975.0
  3. var
  4.   lFC: TFPFontCacheItem;
  5. begin
  6.   lFC := gTTFontCache.FindFont(fName);
  7.   if lFC <> nil
  8.   then Result := lFC.FileName
  9.   else begin
  10.     Result := '';
  11.     ShowMessage('Problem with font '+fName);
  12.   end;
  13. end;
And I quickly realized that when FindFont didn't return anything, it was because the string fields HumanFriendlyName, PostScriptName and FamilyName were empty!
These 3 fields (as well as the FileName field, which is never empty since it defines the current file) are in the fpTTF.TFPFontCacheItem object, public section.

So I had 935 True/OpenType files, 17 of which were not present in the Family list of a tool being created, and I should point out right away that these 17 files are perfectly usable in the Windows world, exactly like the other 918. In the Linux world, it's random...

I then started to examine the inside of the 17 files with a Perl tool (ttftable from the Font-TTF-Scripts-1.06 library + installation of the libfont-ttf-perl package [read: http://scripts.sil.org/FontUtils, download: https://github.com/silnrsi/font-ttf-scripts.git]) which extracts the "name" tag in a binary file to examine with a hex editor in which I was able to see that the fields returned empty by the FreePascal tool were indeed present in the 17 files!
Usage:
Code: C  [Select][+][-]
  1. ttftable -export "name=try" /path/fontname.ttf
will generate a file in the folder opened to launch the script, a script that I was not able to automate with TProcess, too bad, but since there were only 17 files, I wasted less time processing them one by one by hand.

A confirmation by another tool from the FontForge suite (showttf.c, download: https://github.com/fontforge/fontforge/blob/master/contrib/fonttools/showttf.c then a small modification to have access to the values ​​of the fields [addition of an option "-n" like "name":
add at the very top under "static int head_check = false;" the line
Code: C  [Select][+][-]
  1. static int copyright_check = false;
then add in "readit" under block "if ( head_check ) {" the block
Code: C  [Select][+][-]
  1.     if ( copyright_check ) {
  2.         if ( info.copyright_start!=0 )
  3.             readttfname(ttf,util,&info);
  4. return;
  5.     }
and at the very bottom in the main, after "head_check = true;", add
Code: C  [Select][+][-]
  1. else if ( strcmp(pt,"n")==0 || strcmp(pt,"checkcopyright")==0 ) // to add in main
  2.     copyright_check = true;
Recompile and bingo!
Code: C  [Select][+][-]
  1. $ ./showttf -n /filepath/afile.ttf
  2. blablabla
  3. ...
])
and for me the case is closed: all the fields necessary and useful for the proper functioning of the fonts are present in the files and used by the appropriate tools EXCEPT those that rely on FreePascal's fpTTF, which may have random behavior.

What made me persist in all this was the fact of noticing that these famous fields absent in FreePascal were indeed present with an old Windows tool, I named Softy.exe, which allowed me to generate this magnificent image where we notice that there are only 16 thumbnails because, for a reason that I do not know, the Windows wingding.ttf font (about 30 years old!) violently crashes Softy and since we do not have its code, it will stay like that especially since under Linux with showttf and my addition I have my information:
Code: C  [Select][+][-]
  1. $ ./showttf -n /data/17ttf/wingding.ttf
  2. NAME table (at 532)
  3.         format=0
  4.         nrecords=39
  5.         taboff=474
  6.          platform=1 plat spec encoding=0 language=0 name=0 Copyright
  7.          strlen=112  stroff=0      Copyright � 1992-1995 Microsoft Corp. All Rights Reserved.
  8.                                              � 1990-1991 Type Solutions, Inc. All Rights Reserved.
  9.          platform=1 plat spec encoding=0 language=0 name=1 Family
  10.          strlen=9  stroff=116      Wingdings
  11.          platform=1 plat spec encoding=0 language=0 name=2 Subfamily
  12.          strlen=7  stroff=1566     Regular
  13.          platform=1 plat spec encoding=0 language=0 name=3 UniqueID
  14.          strlen=27  stroff=1556    Wingdings Regular: MS: 1995
  15.          platform=1 plat spec encoding=0 language=0 name=4 FullName
  16.          strlen=9  stroff=116      Wingdings
  17.          platform=1 plat spec encoding=0 language=0 name=5 Version
  18.          strlen=12  stroff=1583    Version 2.55
  19.          platform=1 plat spec encoding=0 language=0 name=6 Postscript
  20.          strlen=17  stroff=1595    Wingdings-Regular
  21.          platform=1 plat spec encoding=0 language=0 name=7 Trademark
  22.          strlen=57  stroff=1612    The Windows logo is a trademark of Microsoft Corporation.
  23.          platform=1 plat spec encoding=0 language=0 name=8 Manufacturer
  24.          strlen=20  stroff=1669    Microsoft Typography
  25.          platform=1 plat spec encoding=0 language=0 name=9 Designer
  26.          strlen=31  stroff=149     Kris Holmes and Charles Bigelow
  27.          platform=1 plat spec encoding=0 language=0 name=10 Descriptor
  28.          strlen=1444  stroff=112           The Wingdings fonts were designed blabla...

The most observant will notice that in the image there is twice the same font: in the second line the first two thumbnails show the same data, however coming from two different files but it is not visible there and I do not know why I had fun making a modification of I do not know what... Do not take it into account, this large image is mainly there to show that these 16 files are accessible under Windows with a tool dating back to Windows 3.1 while the last of the FreePascal/Lazarus couple is not capable of it, alas.

The only thing that remains pending and bothers me is that I have not found why these 17 files only and not the others generate an error.
We can get around it but it is "not finished".

That's all.
Have a nice day,
« Last Edit: August 06, 2024, 09:19:13 am by jipété »

 

TinyPortal © 2005-2018