View Issue Details

IDProjectCategoryView StatusLast Update
0035049FPCPackagespublic2019-03-05 12:25
ReporterDoyenneAssigned ToMichael Van Canneyt 
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
Product VersionProduct Build 
Target Version3.2.0Fixed in Version3.3.1 
Summary0035049: FPReport: HTML < b > and < i > can select wrong PostScript font name
DescriptionCurrent behaviour:
If (on Windows) a Memo uses the Arial font (PostScript name: ArialMT) and the memo uses the <b&;gt tag, an exception is raised: font ArialMT-Bold not found in font cache.

Cause:

If HTML < b > and/or < i > tags are used in a memo, the HTMLOnFoundText() procedure in FPReport.pp chooses the appropriate PostScript font name as follows (from line 4463 in current trunk version):

    lNewFontName := Font.Name;
    if [htBold, htItalic] <= FTextBlockState then // test if it is a sub-set of FTextBlockState
      lNewFontName := lNewFontName + '-BoldItalic'
    else if htBold in FTextBlockState then
      lNewFontName := lNewFontName + '-Bold'
    else if htItalic in FTextBlockState then
      lNewFontName := lNewFontName + '-Italic';
    FCurTextBlock.FontName := lNewFontName;

So this procedure assumes that PostScript font names follow a regular pattern, where the bold version of the font has '-Bold' appended to the name, and so on. This is true in some cases, e.g. LiberationSans -> LiberationSans-Bold. However, is it not true in all cases. On Windows, a standard font like Arial does not follow this pattern:

PostScript name regular font: ArialMT
PostScript name bold version: Arial-BoldMT (NOT ArialMT-Bold)

This procedure will also fail in a case where a memo uses a bold font (e.g. LiberationSans-Bold) and uses the < i > tag. This procedure will transform the name into LiberationSans-Bold-Italic, which should be LiberationSans-BoldItalic.

However, this can easily be solved, since the fpttf unit already contains procedures that select the correct PostScript font name from a font family.

The following code solves the problem:

    lNewFontName := gTTFontCache.Find(
        gTTFontCache.Find(Font.Name).FamilyName,
        htBold in FTextBlockState,
        htItalic in FTextBlockState).PostScriptName;
    FCurTextBlock.FontName := lNewFontName;

Note: this is not safe code, since the result of the inner gTTFontCache.Find() is not checked for nil values. This code is for illustrative purposes only.

It might be elegant to introduce a helper function (maybe in the fpttf unit) that 'converts' a PostScript font name to a new PostScript font name, based on bold and italic booleans. This helper function could then handle errors (by raising an exception or by not changing the font name).
TagsNo tags attached.
Fixed in Revision41592
FPCOldBugId
FPCTarget
Attached Files
  • fix-fontname-lookup.diff (2,149 bytes)
    Index: src/fpreport.pp
    ===================================================================
    --- src/fpreport.pp	(revision 41343)
    +++ src/fpreport.pp	(working copy)
    @@ -4439,7 +4439,9 @@
     
     procedure TFPReportCustomMemo.HTMLOnFoundText(Text: string);
     var
    -  lNewFontName: string;
    +  lFC,
    +  lNewFC: TFPFontCacheItem;
    +  lMissingFontName: string;
       lDescender: TFPReportUnits;
       lHasURL: boolean;
     begin
    @@ -4460,15 +4462,28 @@
         if FLastBGColor <> clNone then
           FCurTextBlock.BGColor := FLastBGColor;
     
    -    lNewFontName := Font.Name;
    -    if [htBold, htItalic] <= FTextBlockState then // test if it is a sub-set of FTextBlockState
    -      lNewFontName := lNewFontName + '-BoldItalic'
    -    else if htBold in FTextBlockState then
    -      lNewFontName := lNewFontName + '-Bold'
    -    else if htItalic in FTextBlockState then
    -      lNewFontName := lNewFontName + '-Italic';
    -    FCurTextBlock.FontName := lNewFontName;
    +    // find this memo's font
    +    lFC := gTTFontCache.FindFont(Font.Name);
    +    if not Assigned(lFC) then
    +      raise EReportFontNotFound.CreateFmt(SErrFontNotFound, [Font.Name]);
     
    +    // find corresponding font style (bold and/or italic)
    +    lNewFC := gTTFontCache.Find(lFC.FamilyName, htBold in FTextBlockState, htItalic in FTextBlockState);
    +    if not Assigned(lNewFC) then
    +    begin
    +      lMissingFontName := lFC.FamilyName;
    +      if [htBold, htItalic] <= FTextBlockState then // test if it is a sub-set of FTextBlockState
    +        lMissingFontName := lMissingFontName + '-BoldItalic'
    +      else if htBold in FTextBlockState then
    +        lMissingFontName := lMissingFontName + '-Bold'
    +      else if htItalic in FTextBlockState then
    +        lMissingFontName := lMissingFontName + '-Italic';
    +      raise EReportFontNotFound.CreateFmt(SErrFontNotFound, [lMissingFontName]);
    +    end;
    +
    +    // apply font style by setting new PostScriptName (it contains Bold, Italic info)
    +    FCurTextBlock.FontName := lNewFC.PostScriptName;
    +
         FCurTextBlock.Width := TextWidth(FCurTextBlock.Text);
         FCurTextBlock.Height := TextHeight(FCurTextBlock.Text, lDescender);
         FCurTextBlock.Descender := lDescender;
    
    fix-fontname-lookup.diff (2,149 bytes)
  • minor-typo.diff (542 bytes)
    Index: src/fpttf.pp
    ===================================================================
    --- src/fpttf.pp	(revision 41588)
    +++ src/fpttf.pp	(working copy)
    @@ -149,7 +149,7 @@
       rsNoSearchPathDefined = 'No search path was defined';
       rsNoFontFileName = 'The FileName property is empty, so we can''t load font data.';
       rsMissingFontFile = 'The font file <%s> can''t be found.';
    -  SErrFontNotFound = 'The font <%s> can can''t be found';
    +  SErrFontNotFound = 'The font <%s> can''t be found';
     
     var
       uFontCacheList: TFPFontCacheList;
    
    minor-typo.diff (542 bytes)

Activities

Doyenne

2019-02-09 16:07

reporter   ~0113989

I'm sorry, I did not realize that the bug description processes HTML tags. So I used < b > and < i > tags in the text and now it looks strange. It seems I cannot edit the bug title and description myself, maybe an administrator can correct it...

J. Gareth Moreton

2019-02-10 03:31

developer   ~0114000

Fixed the processed HTML tags in the description and title.

Doyenne

2019-02-18 21:34

reporter  

fix-fontname-lookup.diff (2,149 bytes)
Index: src/fpreport.pp
===================================================================
--- src/fpreport.pp	(revision 41343)
+++ src/fpreport.pp	(working copy)
@@ -4439,7 +4439,9 @@
 
 procedure TFPReportCustomMemo.HTMLOnFoundText(Text: string);
 var
-  lNewFontName: string;
+  lFC,
+  lNewFC: TFPFontCacheItem;
+  lMissingFontName: string;
   lDescender: TFPReportUnits;
   lHasURL: boolean;
 begin
@@ -4460,15 +4462,28 @@
     if FLastBGColor <> clNone then
       FCurTextBlock.BGColor := FLastBGColor;
 
-    lNewFontName := Font.Name;
-    if [htBold, htItalic] <= FTextBlockState then // test if it is a sub-set of FTextBlockState
-      lNewFontName := lNewFontName + '-BoldItalic'
-    else if htBold in FTextBlockState then
-      lNewFontName := lNewFontName + '-Bold'
-    else if htItalic in FTextBlockState then
-      lNewFontName := lNewFontName + '-Italic';
-    FCurTextBlock.FontName := lNewFontName;
+    // find this memo's font
+    lFC := gTTFontCache.FindFont(Font.Name);
+    if not Assigned(lFC) then
+      raise EReportFontNotFound.CreateFmt(SErrFontNotFound, [Font.Name]);
 
+    // find corresponding font style (bold and/or italic)
+    lNewFC := gTTFontCache.Find(lFC.FamilyName, htBold in FTextBlockState, htItalic in FTextBlockState);
+    if not Assigned(lNewFC) then
+    begin
+      lMissingFontName := lFC.FamilyName;
+      if [htBold, htItalic] <= FTextBlockState then // test if it is a sub-set of FTextBlockState
+        lMissingFontName := lMissingFontName + '-BoldItalic'
+      else if htBold in FTextBlockState then
+        lMissingFontName := lMissingFontName + '-Bold'
+      else if htItalic in FTextBlockState then
+        lMissingFontName := lMissingFontName + '-Italic';
+      raise EReportFontNotFound.CreateFmt(SErrFontNotFound, [lMissingFontName]);
+    end;
+
+    // apply font style by setting new PostScriptName (it contains Bold, Italic info)
+    FCurTextBlock.FontName := lNewFC.PostScriptName;
+
     FCurTextBlock.Width := TextWidth(FCurTextBlock.Text);
     FCurTextBlock.Height := TextHeight(FCurTextBlock.Text, lDescender);
     FCurTextBlock.Descender := lDescender;
fix-fontname-lookup.diff (2,149 bytes)

Doyenne

2019-02-18 21:39

reporter   ~0114248

Uploaded a .diff that corrects the bug (this code differs from the bug description - this time safe code including exceptions).

Michael Van Canneyt

2019-03-02 15:07

administrator   ~0114565

I implemented your suggestion of implementing a helper function in the font cache.

I used the Delphi convention of a pair of functions:
Find (no exception) and Get (exception if not found)

function FindPostScriptFontName(const AFontName: string; ABold: boolean; AItalic: boolean): String;
    // Same as Find, but raise exception when not found.
function GetPostScriptFontName(const AFontName: string; ABold: boolean; AItalic: boolean): String;

Doyenne

2019-03-04 21:04

reporter   ~0114645

Last edited: 2019-03-04 21:05

View 2 revisions

Thanks for the nice fix! Just a minor typo :)

(See attachment)

Doyenne

2019-03-04 21:05

reporter  

minor-typo.diff (542 bytes)
Index: src/fpttf.pp
===================================================================
--- src/fpttf.pp	(revision 41588)
+++ src/fpttf.pp	(working copy)
@@ -149,7 +149,7 @@
   rsNoSearchPathDefined = 'No search path was defined';
   rsNoFontFileName = 'The FileName property is empty, so we can''t load font data.';
   rsMissingFontFile = 'The font file <%s> can''t be found.';
-  SErrFontNotFound = 'The font <%s> can can''t be found';
+  SErrFontNotFound = 'The font <%s> can''t be found';
 
 var
   uFontCacheList: TFPFontCacheList;
minor-typo.diff (542 bytes)

Michael Van Canneyt

2019-03-05 12:25

administrator   ~0114659

Fixed typo, thanks!

Issue History

Date Modified Username Field Change
2019-02-09 16:04 Doyenne New Issue
2019-02-09 16:07 Doyenne Note Added: 0113989
2019-02-10 03:31 J. Gareth Moreton Note Added: 0114000
2019-02-10 03:31 J. Gareth Moreton Summary FPReport: HTML and can select wrong PostScript font name => FPReport: HTML < b > and < i > can select wrong PostScript font name
2019-02-10 03:31 J. Gareth Moreton Description Updated View Revisions
2019-02-10 03:32 J. Gareth Moreton Summary FPReport: HTML < b > and < i > can select wrong PostScript font name => FPReport: HTML and can select wrong PostScript font name
2019-02-10 03:32 J. Gareth Moreton Description Updated View Revisions
2019-02-10 03:33 J. Gareth Moreton Summary FPReport: HTML and can select wrong PostScript font name => FPReport: HTML < b > and < i > can select wrong PostScript font name
2019-02-10 03:33 J. Gareth Moreton Description Updated View Revisions
2019-02-17 10:17 Michael Van Canneyt Assigned To => Michael Van Canneyt
2019-02-17 10:17 Michael Van Canneyt Status new => assigned
2019-02-18 21:34 Doyenne File Added: fix-fontname-lookup.diff
2019-02-18 21:39 Doyenne Note Added: 0114248
2019-03-02 15:07 Michael Van Canneyt Fixed in Revision => 41554
2019-03-02 15:07 Michael Van Canneyt Note Added: 0114565
2019-03-02 15:07 Michael Van Canneyt Status assigned => resolved
2019-03-02 15:07 Michael Van Canneyt Fixed in Version => 3.3.1
2019-03-02 15:07 Michael Van Canneyt Resolution open => fixed
2019-03-02 15:07 Michael Van Canneyt Target Version => 3.2.0
2019-03-04 21:04 Doyenne Note Added: 0114645
2019-03-04 21:04 Doyenne Status resolved => feedback
2019-03-04 21:04 Doyenne Resolution fixed => reopened
2019-03-04 21:05 Doyenne File Added: minor-typo.diff
2019-03-04 21:05 Doyenne Note Edited: 0114645 View Revisions
2019-03-05 12:25 Michael Van Canneyt Fixed in Revision 41554 => 41592
2019-03-05 12:25 Michael Van Canneyt Note Added: 0114659
2019-03-05 12:25 Michael Van Canneyt Status feedback => resolved
2019-03-05 12:25 Michael Van Canneyt Resolution reopened => fixed