Recent

Author Topic: [Solved:] SVG export broken in macOS  (Read 3247 times)

jwdietrich

  • Hero Member
  • *****
  • Posts: 1232
    • formatio reticularis
[Solved:] SVG export broken in macOS
« on: May 15, 2021, 07:46:40 pm »
Unlike in previous versions of Lazarus I am no longer able to create SVG images from my projects on macOS. Using the Cocoa widgetset the app either simply crashes or creates an invalid SVG file. With the Carbon widgetset, it delivers an error message that it doesn't find the font "default" (see figure in the attachment) and it either doesn't create a valid SVG file.

Inspecting the file with a text editor reveals:

Code: XML  [Select][+][-]
  1. <?xml version="1.0"?>
  2. <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
  3. "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">

So, the files seem to terminate early.

The error can be reproduced with the save demo file that comes with TAChart in Lazarus.
« Last Edit: May 22, 2021, 09:05:47 am by jwdietrich »
function GetRandomNumber: integer; // xkcd.com
begin
  GetRandomNumber := 4; // chosen by fair dice roll. Guaranteed to be random.
end;

http://www.formatio-reticularis.de

Lazarus 2.2.6 | FPC 3.2.2 | PPC, Intel, ARM | macOS, Windows, Linux

wp

  • Hero Member
  • *****
  • Posts: 11853
Re: SVG export broken in macOS
« Reply #1 on: May 16, 2021, 01:24:34 am »
Just checked the save demo on a VM with macOS Mojave 10.14.3 (laz trunk r65002 / fpc 3.0.4 - I don't use this VM often, so it's a bit out-dated) - no problem with svg.

Is fpvectorial available on your system, and is the TAChartFPVectorial package installed? (but I guess you cannot compile the demo without them).

Does it help when you replace the generic "default" font by a specific one on your machine? And maybe you should also replace the fontsize 0 by something like 10. Note that there are several fonts.

jwdietrich

  • Hero Member
  • *****
  • Posts: 1232
    • formatio reticularis
Re: SVG export broken in macOS
« Reply #2 on: May 16, 2021, 09:15:41 am »
Thanks for the feedback. I use the standard version of Lazarus 2.0.12 along with FPC 3.2.0 and Xcode 11.3.1 on macOS Mojave 10.14.6. I don't have fpvectorial or TAChartFPVectorial installed. Do I need these packages? I used the SVG drawer for TAChart since 2014, and I don't remember that I needed any additional packages. But I might be wrong, of course.
function GetRandomNumber: integer; // xkcd.com
begin
  GetRandomNumber := 4; // chosen by fair dice roll. Guaranteed to be random.
end;

http://www.formatio-reticularis.de

Lazarus 2.2.6 | FPC 3.2.2 | PPC, Intel, ARM | macOS, Windows, Linux

jwdietrich

  • Hero Member
  • *****
  • Posts: 1232
    • formatio reticularis
Re: SVG export broken in macOS
« Reply #3 on: May 16, 2021, 12:55:05 pm »
I have now tried it on another machine (running macOS 10.12) as well, but it doesn't work either (neither with the Carbon nor the Cocoa widgetset).

I don't think that it has to do with fpvectorial or TAChartFPVectorial, but rather with a bug in the initialisation of fonts. After inspecting the save demo of TAChart again, I found that there are two possible implementations of the SVG save handler hidden in the code. One is the standard form, which uses the SaveToSVGFile method of TChart:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.tbSaveAsSVGClick(Sender: TObject);
  2. begin
  3.   Chart1.SaveToSVGFile(GetFilename('svg'));
  4. end;
  5. { or ...
  6. var
  7.   fs: TFileStream;
  8.   id: IChartDrawer;
  9. begin
  10.   fs := TFileStream.Create(GetFileName('svg'), fmCreate);
  11.   try
  12.     id := TSVGDrawer.Create(fs, true);
  13.     with Chart1 do
  14.       Draw(id, Rect(0, 0, Width, Height));
  15.   finally
  16.     fs.Free;
  17.   end;
  18. end;   }
  19.  

The standard code can be commented out to enable another version that allows for more thorough investigations:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.tbSaveAsSVGClick(Sender: TObject);
  2. {begin
  3.   Chart1.SaveToSVGFile(GetFilename('svg'));
  4. end;
  5.  or ... }
  6. var
  7.   fs: TFileStream;
  8.   id: IChartDrawer;
  9. begin
  10.   fs := TFileStream.Create(GetFileName('svg'), fmCreate);
  11.   try
  12.     id := TSVGDrawer.Create(fs, true);
  13.     id.SetFont();
  14.     with Chart1 do
  15.       Draw(id, Rect(0, 0, Width, Height));
  16.   finally
  17.     fs.Free;
  18.   end;
  19. end;

However, it fails, too, with the default font.

I then changed it by explicitly assigning the font "Helvetica" (which is always installed on Macs since 1984) with:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.tbSaveAsSVGClick(Sender: TObject);
  2. {begin
  3.   Chart1.SaveToSVGFile(GetFilename('svg'));
  4. end;
  5.  or ...}
  6. var
  7.   fs: TFileStream;
  8.   id: IChartDrawer;
  9.   ft: TFPCustomFont;          // added
  10. begin
  11.   fs := TFileStream.Create(GetFileName('svg'), fmCreate);
  12.   ft := TFPCustomFont.Create; // added
  13.   ft.Name := 'Helvetica';     // added
  14.   try
  15.     id := TSVGDrawer.Create(fs, true);
  16.     id.SetFont(ft);           // added
  17.     with Chart1 do
  18.       Draw(id, Rect(0, 0, Width, Height));
  19.   finally
  20.     ft.free;                  // added
  21.     fs.Free;
  22.   end;
  23. end;

Unfortunately, this fails as well. The failure is caused by the fact that the TSVGDrawer.SetFont method is unable to load the font (the font is nil after calling LoadFont). LoadFont delivers nil, since it is unable again to assign the variable familyItem (which is of type TCustomFamilyCollectionItem).

This is where my knowledge ends. I simply don't know enough about the LazFreeTypeFontCollection to fix it, the more as this unit seems to be nearly undocumented.

In my opinion, the fact that the SVG export appears to work on some machines and crashes on other ones might result from an initialisation issue in the font handlers.
function GetRandomNumber: integer; // xkcd.com
begin
  GetRandomNumber := 4; // chosen by fair dice roll. Guaranteed to be random.
end;

http://www.formatio-reticularis.de

Lazarus 2.2.6 | FPC 3.2.2 | PPC, Intel, ARM | macOS, Windows, Linux

wp

  • Hero Member
  • *****
  • Posts: 11853
Re: SVG export broken in macOS
« Reply #4 on: May 16, 2021, 01:24:45 pm »
I don't have fpvectorial or TAChartFPVectorial installed. Do I need these packages?
You do need then, but since they come with Lazarus the IDE seems to know where they are as I found out. So, this does not seem to be an issue.

The failure is caused by the fact that the TSVGDrawer.SetFont method is unable to load the font (the font is nil after calling LoadFont).
There is a note in the svn commits for TAFonts.pas, r61240: "TAChart: Fix svg drawer not finding fonts on Mac (https://forum.lazarus.freepascal.org/index.php/topic,45461.msg321532.html)."

In this commit new entries are added to the font directory, IFDEF'ed for Cocoa and Carbon. Please open your tafonts.pas in the TAChart installation directory, and find the procedure PopulateFontDirList. You will see {$IFDEF WINDOWS} and {$IFDEF LINUX}. If there is no {$IFDEF LCLCarbon} and not {$IFDEF LCLCocoa} you should add the following lines to this procedure, immediately before the "end;":
Code: Pascal  [Select][+][-]
  1.  {$IFDEF LCLCarbon}
  2.   AList.Add('/Library/Fonts/');
  3.   AList.Add('/System/Library/Fonts/');
  4.   AList.Add('/Network/Library/Fonts/');
  5.   AList.Add('~/Library/Fonts/');
  6.  {$ENDIF}
  7.  {$IFDEF LCLCocoa}
  8.   AList.Add('/Library/Fonts/');
  9.   AList.Add('/System/Library/Fonts/');
  10.   AList.Add('/Network/Library/Fonts/');
  11.   AList.Add('~/Library/Fonts/');
  12.  {$ENDIF}

Please also have a look at https://forum.lazarus.freepascal.org/index.php/topic,45461.msg321564.html#msg321564 regarding an exception due to faulty font files.

P.S.
It's good to see that I'm not the only one who seems to forget about details of prior work.
« Last Edit: May 16, 2021, 01:28:17 pm by wp »

jwdietrich

  • Hero Member
  • *****
  • Posts: 1232
    • formatio reticularis
Re: SVG export broken in macOS
« Reply #5 on: May 17, 2021, 12:28:16 am »
Thanks. Seems to be groundhog day...  :D

function GetRandomNumber: integer; // xkcd.com
begin
  GetRandomNumber := 4; // chosen by fair dice roll. Guaranteed to be random.
end;

http://www.formatio-reticularis.de

Lazarus 2.2.6 | FPC 3.2.2 | PPC, Intel, ARM | macOS, Windows, Linux

jwdietrich

  • Hero Member
  • *****
  • Posts: 1232
    • formatio reticularis
Re: [Solved:] SVG export broken in macOS
« Reply #6 on: January 15, 2022, 09:38:15 am »
This issue seems to be permanently solved in Lazarus 2.2. Thanks again for your help and support.
function GetRandomNumber: integer; // xkcd.com
begin
  GetRandomNumber := 4; // chosen by fair dice roll. Guaranteed to be random.
end;

http://www.formatio-reticularis.de

Lazarus 2.2.6 | FPC 3.2.2 | PPC, Intel, ARM | macOS, Windows, Linux

 

TinyPortal © 2005-2018