bounding_box() for t1 driver fonts was treating spaces as empty space
authorTony Cook <tony@develop=help.com>
Thu, 20 Jul 2006 13:42:04 +0000 (13:42 +0000)
committerTony Cook <tony@develop=help.com>
Thu, 20 Jul 2006 13:42:04 +0000 (13:42 +0000)
when calculating the bounds, which they are, but this is inconsistent
with other drivers.  This was especially a problem for strings
containing only spaces where the left bound would end up far to the
right of the right bound, and similarly for the ascent and descent.

calculating the bounding box for an empty string invoked special
behaviour in t1lib, making it unreliable.

Fixes: http://rt.cpan.org/Ticket/Display.html?id=20555
MANIFEST
font.c
fontfiles/ExistenceTest.afm
fontfiles/ExistenceTest.pfb
fontfiles/ExistenceTest.sfd
fontfiles/SpaceTest.afm [new file with mode: 0644]
fontfiles/SpaceTest.pfb [new file with mode: 0644]
fontfiles/SpaceTest.sfd [new file with mode: 0644]
t/t30t1font.t

index 6cfee799277f139ee6cea78b7380e4c414496ad0..1b2c7ae3dc8787ca82b5aae5146f8e72ec7673f3 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -92,6 +92,8 @@ fontfiles/ExistenceTest.ttf     generated using pfaedit
 fontfiles/ImUgly.ttf
 fontfiles/MMOne.pfb            multiple master test font
 fontfiles/NameTest.ttf          test glyph_names() - see t38ft2font.t
+fontfiles/SpaceTest.afm
+fontfiles/SpaceTest.pfb                test bounding box with spaces in t30t1font.t
 fontfiles/dcr10.afm
 fontfiles/dcr10.pfb
 fontfiles/dodge.ttf
diff --git a/font.c b/font.c
index e228fbab859812813c4797d1ceac246868823379..6f72710e3d122d83a8d5e61e208b068d23675dd9 100644 (file)
--- a/font.c
+++ b/font.c
@@ -298,6 +298,17 @@ i_t1_cp(i_img *im,int xb,int yb,int channel,int fontnum,float points,char* str,i
   return 1;
 }
 
+static void
+t1_fix_bbox(BBox *bbox, const char *str, int len, int advance, 
+           int space_position) {
+  /* never called with len == 0 */
+  if (str[0] == space_position && bbox->llx > 0)
+    bbox->llx = 0;
+  if (str[len-1] == space_position && bbox->urx < advance)
+    bbox->urx = advance;
+  if (bbox->lly > bbox->ury)
+    bbox->lly = bbox->ury = 0; 
+}
 
 /*
 =item i_t1_bbox(handle, fontnum, points, str, len, cords)
@@ -320,20 +331,32 @@ i_t1_bbox(int fontnum,float points,const char *str,int len,int cords[6], int utf
   BBox gbbox;
   int mod_flags = t1_get_flags(flags);
   int advance;
+  int space_position = T1_GetEncodingIndex(fontnum, "space");
   
   mm_log((1,"i_t1_bbox(fontnum %d,points %.2f,str '%.*s', len %d)\n",fontnum,points,len,str,len));
   T1_LoadFont(fontnum);  /* FIXME: Here a return code is ignored - haw haw haw */ 
-  if (utf8) {
-    int worklen;
-    char *work = t1_from_utf8(str, len, &worklen);
-    bbox = T1_GetStringBBox(fontnum,work,worklen,0,mod_flags);
-    myfree(work);
+
+  if (len == 0) {
+    /* len == 0 has special meaning to T1lib, but it means there's
+       nothing to draw, so return that */
+    bbox.llx = bbox.lly = bbox.urx = bbox.ury = 0;
+    advance = 0;
   }
   else {
-    bbox = T1_GetStringBBox(fontnum,(char *)str,len,0,mod_flags);
+    advance = T1_GetStringWidth(fontnum, (char *)str, len, 0, mod_flags);
+    if (utf8) {
+      int worklen;
+      char *work = t1_from_utf8(str, len, &worklen);
+      bbox = T1_GetStringBBox(fontnum,work,worklen,0,mod_flags);
+      t1_fix_bbox(&bbox, work, worklen, advance, space_position);
+      myfree(work);
+    }
+    else {
+      bbox = T1_GetStringBBox(fontnum,(char *)str,len,0,mod_flags);
+      t1_fix_bbox(&bbox, str, len, advance, space_position);
+    }
   }
   gbbox = T1_GetFontBBox(fontnum);
-  advance = T1_GetStringWidth(fontnum, (char *)str, len, 0, mod_flags);
   
   mm_log((1,"bbox: (%d,%d,%d,%d)\n",
          (int)(bbox.llx*points/1000),
index 7dd627c270a59c374f9b6c24ab1504804c1ec5b7..5200705ae6309dca7297066e9bb760db698da142 100644 (file)
@@ -1,6 +1,6 @@
 StartFontMetrics 2.0
 Comment Generated by pfaedit
-Comment Creation Date: Sat Dec 28 17:06:43 2002
+Comment Creation Date: Thu Jul 20 21:57:23 2006
 FontName ExistenceTest
 FullName ExistenceTest
 FamilyName ExistenceTest
@@ -13,7 +13,8 @@ UnderlineThickness 50
 Version 001.000
 EncodingScheme AdobeStandardEncoding
 FontBBox -60 -55 819 775
-StartCharMetrics 2
+StartCharMetrics 3
+C 0 ; WX 487 ; N uniFFFD ; B 72 87 414 396 ;
 C 33 ; WX 310 ; N exclam ; B 51 0 207 738 ;
 C 47 ; WX 761 ; N slash ; B -60 -55 819 775 ;
 EndCharMetrics
index 46a987458c6f48aad53ec22ef1f13fe363111f90..88863ad502d7f6f0a2fbd5364633b0c16ee2f3c2 100644 (file)
Binary files a/fontfiles/ExistenceTest.pfb and b/fontfiles/ExistenceTest.pfb differ
index 012568a49b2c02e6cc8ddf7d76eda9cce0c654ca..c76b93fb0acf3afeae211669911496881b442de2 100644 (file)
@@ -11,6 +11,7 @@ UnderlinePosition: -100
 UnderlineWidth: 50
 Ascent: 800
 Descent: 200
+NeedsXUIDChange: 1
 FSType: 12
 PfmFamily: 17
 TTFWeight: 500
@@ -18,17 +19,42 @@ TTFWidth: 5
 Panose: 2 0 6 3 0 0 0 0 0 0
 LineGap: 90
 VLineGap: 0
-
-Encoding: adobestandard
-DisplaySize: -24
+OS2WinAscent: 0
+OS2WinAOffset: 1
+OS2WinDescent: 0
+OS2WinDOffset: 1
+HheadAscent: 0
+HheadAOffset: 1
+HheadDescent: 0
+HheadDOffset: 1
+Encoding: AdobeStandard
+UnicodeInterp: none
+DisplaySize: -48
 AntiAlias: 1
-BeginChars: 256 95
-StartChar: space
-Encoding: 32 32
-Width: 1000
+FitToEm: 1
+WinInfo: 0 16 4
+BeginChars: 256 5
+StartChar: uniFFFD
+Encoding: 0 65533 65535
+Width: 487
+Flags: HW
+HStem: 87 45<117 414> 342 54<72 363>
+VStem: 72 45<87 342> 363 51<132 396>
+Fore
+117 342 m 1
+ 117 132 l 1
+ 363 132 l 1
+ 363 342 l 1
+ 117 342 l 1
+72 396 m 1
+ 414 396 l 1
+ 414 87 l 1
+ 72 87 l 1
+ 72 396 l 1
+EndSplineSet
 EndChar
 StartChar: exclam
-Encoding: 33 33
+Encoding: 33 33 1
 Width: 310
 Flags: W
 HStem: 0 126<99 163> 180 558<99 147>
@@ -55,56 +81,8 @@ Fore
 EndSplineSet
 MinimumDistance: x2,-1 
 EndChar
-StartChar: quotedbl
-Encoding: 34 34
-Width: 1000
-EndChar
-StartChar: numbersign
-Encoding: 35 35
-Width: 1000
-EndChar
-StartChar: dollar
-Encoding: 36 36
-Width: 1000
-EndChar
-StartChar: percent
-Encoding: 37 37
-Width: 1000
-EndChar
-StartChar: ampersand
-Encoding: 38 38
-Width: 1000
-EndChar
-StartChar: parenleft
-Encoding: 40 40
-Width: 1000
-EndChar
-StartChar: parenright
-Encoding: 41 41
-Width: 1000
-EndChar
-StartChar: asterisk
-Encoding: 42 42
-Width: 1000
-EndChar
-StartChar: plus
-Encoding: 43 43
-Width: 1000
-EndChar
-StartChar: comma
-Encoding: 44 44
-Width: 1000
-EndChar
-StartChar: hyphen
-Encoding: 45 45
-Width: 1000
-EndChar
-StartChar: period
-Encoding: 46 46
-Width: 1000
-EndChar
 StartChar: slash
-Encoding: 47 47
+Encoding: 47 47 14
 Width: 761
 Flags: W
 DStem: 783.882 774.221 818.118 737.779 -59.1182 -17.7793 -24.8818 -54.2207
@@ -116,324 +94,12 @@ Fore
  -59.1182 -17.7793 l 1
 EndSplineSet
 EndChar
-StartChar: zero
-Encoding: 48 48
-Width: 1000
-EndChar
-StartChar: one
-Encoding: 49 49
-Width: 1000
-EndChar
-StartChar: two
-Encoding: 50 50
-Width: 1000
-EndChar
-StartChar: three
-Encoding: 51 51
-Width: 1000
-EndChar
-StartChar: four
-Encoding: 52 52
-Width: 1000
-EndChar
-StartChar: five
-Encoding: 53 53
-Width: 1000
-EndChar
-StartChar: six
-Encoding: 54 54
-Width: 1000
-EndChar
-StartChar: seven
-Encoding: 55 55
-Width: 1000
-EndChar
-StartChar: eight
-Encoding: 56 56
-Width: 1000
-EndChar
-StartChar: nine
-Encoding: 57 57
-Width: 1000
-EndChar
-StartChar: colon
-Encoding: 58 58
-Width: 1000
-EndChar
-StartChar: semicolon
-Encoding: 59 59
-Width: 1000
-EndChar
-StartChar: less
-Encoding: 60 60
-Width: 1000
-EndChar
-StartChar: equal
-Encoding: 61 61
-Width: 1000
-EndChar
-StartChar: greater
-Encoding: 62 62
-Width: 1000
-EndChar
-StartChar: question
-Encoding: 63 63
-Width: 1000
-EndChar
-StartChar: at
-Encoding: 64 64
-Width: 1000
-EndChar
-StartChar: A
-Encoding: 65 65
-Width: 1000
-EndChar
-StartChar: B
-Encoding: 66 66
-Width: 1000
-EndChar
-StartChar: C
-Encoding: 67 67
-Width: 1000
-EndChar
-StartChar: D
-Encoding: 68 68
-Width: 1000
-EndChar
-StartChar: E
-Encoding: 69 69
-Width: 1000
-EndChar
-StartChar: F
-Encoding: 70 70
-Width: 1000
-EndChar
-StartChar: G
-Encoding: 71 71
-Width: 1000
-EndChar
-StartChar: H
-Encoding: 72 72
-Width: 1000
-EndChar
-StartChar: I
-Encoding: 73 73
-Width: 1000
-EndChar
-StartChar: J
-Encoding: 74 74
-Width: 1000
-EndChar
-StartChar: K
-Encoding: 75 75
-Width: 1000
-EndChar
-StartChar: L
-Encoding: 76 76
-Width: 1000
-EndChar
-StartChar: M
-Encoding: 77 77
-Width: 1000
-EndChar
-StartChar: N
-Encoding: 78 78
-Width: 1000
-EndChar
-StartChar: O
-Encoding: 79 79
-Width: 1000
-EndChar
-StartChar: P
-Encoding: 80 80
-Width: 1000
-EndChar
-StartChar: Q
-Encoding: 81 81
-Width: 1000
-EndChar
-StartChar: R
-Encoding: 82 82
-Width: 1000
-EndChar
-StartChar: S
-Encoding: 83 83
-Width: 1000
-EndChar
-StartChar: T
-Encoding: 84 84
-Width: 1000
-EndChar
-StartChar: U
-Encoding: 85 85
-Width: 1000
-EndChar
-StartChar: V
-Encoding: 86 86
-Width: 1000
-EndChar
-StartChar: W
-Encoding: 87 87
-Width: 1000
-EndChar
-StartChar: X
-Encoding: 88 88
-Width: 1000
-EndChar
-StartChar: Y
-Encoding: 89 89
-Width: 1000
-EndChar
-StartChar: Z
-Encoding: 90 90
-Width: 1000
-EndChar
-StartChar: bracketleft
-Encoding: 91 91
-Width: 1000
-EndChar
-StartChar: backslash
-Encoding: 92 92
-Width: 1000
-EndChar
-StartChar: bracketright
-Encoding: 93 93
-Width: 1000
-EndChar
-StartChar: asciicircum
-Encoding: 94 94
-Width: 1000
-EndChar
-StartChar: underscore
-Encoding: 95 95
-Width: 1000
-EndChar
-StartChar: a
-Encoding: 97 97
-Width: 1000
-EndChar
-StartChar: b
-Encoding: 98 98
-Width: 1000
-EndChar
-StartChar: c
-Encoding: 99 99
-Width: 1000
-EndChar
-StartChar: d
-Encoding: 100 100
-Width: 1000
-EndChar
-StartChar: e
-Encoding: 101 101
-Width: 1000
-EndChar
-StartChar: f
-Encoding: 102 102
-Width: 1000
-EndChar
-StartChar: g
-Encoding: 103 103
-Width: 1000
-EndChar
-StartChar: h
-Encoding: 104 104
-Width: 1000
-EndChar
-StartChar: i
-Encoding: 105 105
-Width: 1000
-EndChar
-StartChar: j
-Encoding: 106 106
-Width: 1000
-EndChar
-StartChar: k
-Encoding: 107 107
-Width: 1000
-EndChar
-StartChar: l
-Encoding: 108 108
-Width: 1000
-EndChar
-StartChar: m
-Encoding: 109 109
-Width: 1000
-EndChar
-StartChar: n
-Encoding: 110 110
-Width: 1000
-EndChar
-StartChar: o
-Encoding: 111 111
-Width: 1000
-EndChar
-StartChar: p
-Encoding: 112 112
-Width: 1000
-EndChar
-StartChar: q
-Encoding: 113 113
-Width: 1000
-EndChar
-StartChar: r
-Encoding: 114 114
-Width: 1000
-EndChar
-StartChar: s
-Encoding: 115 115
-Width: 1000
-EndChar
-StartChar: t
-Encoding: 116 116
-Width: 1000
-EndChar
-StartChar: u
-Encoding: 117 117
-Width: 1000
-EndChar
-StartChar: v
-Encoding: 118 118
-Width: 1000
-EndChar
-StartChar: w
-Encoding: 119 119
-Width: 1000
-EndChar
-StartChar: x
-Encoding: 120 120
-Width: 1000
-EndChar
-StartChar: y
-Encoding: 121 121
-Width: 1000
-EndChar
-StartChar: z
-Encoding: 122 122
-Width: 1000
-EndChar
-StartChar: braceleft
-Encoding: 123 123
-Width: 1000
-EndChar
-StartChar: bar
-Encoding: 124 124
-Width: 1000
-EndChar
-StartChar: braceright
-Encoding: 125 125
-Width: 1000
-EndChar
-StartChar: asciitilde
-Encoding: 126 126
-Width: 1000
-EndChar
 StartChar: quotesingle
-Encoding: 169 39
+Encoding: 169 39 93
 Width: 1000
 EndChar
 StartChar: grave
-Encoding: 193 96
+Encoding: 193 96 94
 Width: 1000
 EndChar
 EndChars
diff --git a/fontfiles/SpaceTest.afm b/fontfiles/SpaceTest.afm
new file mode 100644 (file)
index 0000000..bdac656
--- /dev/null
@@ -0,0 +1,21 @@
+StartFontMetrics 2.0
+Comment Generated by pfaedit
+Comment Creation Date: Thu Jul 20 21:51:08 2006
+FontName SpaceTest
+FullName SpaceTest
+FamilyName SpaceTest
+Weight Medium
+Notice (Created by Tony Cook,,, with FontForge 1.0 (http://fontforge.sf.net))
+ItalicAngle 0
+IsFixedPitch false
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.000
+EncodingScheme AdobeStandardEncoding
+FontBBox 72 -24 414 684
+StartCharMetrics 3
+C 0 ; WX 487 ; N uniFFFD ; B 72 87 414 396 ;
+C 32 ; WX 500 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 451 ; N exclam ; B 156 -24 312 684 ;
+EndCharMetrics
+EndFontMetrics
diff --git a/fontfiles/SpaceTest.pfb b/fontfiles/SpaceTest.pfb
new file mode 100644 (file)
index 0000000..38cdc89
Binary files /dev/null and b/fontfiles/SpaceTest.pfb differ
diff --git a/fontfiles/SpaceTest.sfd b/fontfiles/SpaceTest.sfd
new file mode 100644 (file)
index 0000000..abeea3a
--- /dev/null
@@ -0,0 +1,80 @@
+SplineFontDB: 1.0
+FontName: SpaceTest
+FullName: SpaceTest
+FamilyName: SpaceTest
+Weight: Medium
+Copyright: Created by Tony Cook,,, with FontForge 1.0 (http://fontforge.sf.net)
+Comments: 2006-7-20: Created.
+Version: 001.000
+ItalicAngle: 0
+UnderlinePosition: -100
+UnderlineWidth: 50
+Ascent: 800
+Descent: 200
+NeedsXUIDChange: 1
+XUID: [1021 918 1786090884 13370659]
+FSType: 8
+PfmFamily: 17
+TTFWeight: 500
+TTFWidth: 5
+Panose: 2 0 6 3 0 0 0 0 0 0
+LineGap: 90
+VLineGap: 0
+OS2WinAscent: 0
+OS2WinAOffset: 1
+OS2WinDescent: 0
+OS2WinDOffset: 1
+HheadAscent: 0
+HheadAOffset: 1
+HheadDescent: 0
+HheadDOffset: 1
+Encoding: AdobeStandard
+UnicodeInterp: none
+DisplaySize: -48
+AntiAlias: 1
+FitToEm: 1
+WinInfo: 0 16 4
+BeginChars: 256 3
+StartChar: uniFFFD
+Encoding: 0 65533 65535
+Width: 487
+Flags: HW
+Fore
+117 342 m 1
+ 117 132 l 1
+ 363 132 l 1
+ 363 342 l 1
+ 117 342 l 1
+72 396 m 1
+ 414 396 l 1
+ 414 87 l 1
+ 72 87 l 1
+ 72 396 l 1
+EndSplineSet
+EndChar
+StartChar: space
+Encoding: 32 32 65535
+Width: 500
+Flags: W
+EndChar
+StartChar: exclam
+Encoding: 33 33 65535
+Width: 451
+Flags: WO
+HStem: -24 156<221.497 237>
+VStem: 183 102<177 684>
+Fore
+156 54 m 0
+ 156 97.056 190.944 132 234 132 c 0
+ 277.056 132 312 97.056 312 54 c 0
+ 312 10.944 277.056 -24 234 -24 c 0
+ 190.944 -24 156 10.944 156 54 c 0
+183 684 m 1
+ 285 684 l 1
+ 285 177 l 1
+ 183 177 l 1
+ 183 684 l 1
+EndSplineSet
+EndChar
+EndChars
+EndSplineFont
index 9d8a01072cb058a1347a0decb51de6400842daf0..4331e649b624ae15b9d5700d0ea8eb45befe1370 100644 (file)
@@ -8,7 +8,7 @@
 # (It may become useful if the test is moved to ./t subdirectory.)
 use strict;
 use lib 't';
-use Test::More tests => 64;
+use Test::More tests => 76;
 BEGIN { use_ok(Imager => ':all') }
 
 #$Imager::DEBUG=1;
@@ -23,13 +23,13 @@ my $fontname_afm=$ENV{'T1FONTTESTAFM'}||'./fontfiles/dcr10.afm';
 SKIP:
 {
   if (!(i_has_format("t1")) ) {
-    skip("t1lib unavailable or disabled", 63);
+    skip("t1lib unavailable or disabled", 75);
   }
   elsif (! -f $fontname_pfb) {
-    skip("cannot find fontfile for type 1 test $fontname_pfb", 63);
+    skip("cannot find fontfile for type 1 test $fontname_pfb", 75);
   }
   elsif (! -f $fontname_afm) {
-    skip("cannot find fontfile for type 1 test $fontname_afm", 63);
+    skip("cannot find fontfile for type 1 test $fontname_afm", 75);
   }
 
   print "# has t1\n";
@@ -252,6 +252,46 @@ SKIP:
     }
     ok($im->write(file=>'testout/t30align.ppm'), "save align image");
   }
+
+ SKIP:
+  {
+    # see http://rt.cpan.org/Ticket/Display.html?id=20555
+    print "# bounding box around spaces\n";
+    # SpaceTest contains 3 characters, space, ! and .undef
+    # only characters that define character zero seem to illustrate
+    # the problem we had with spaces
+    my $space_fontfile = "fontfiles/SpaceTest.pfb";
+    my $font = Imager::Font->new(file => $space_fontfile, type => 't1');
+    ok($font, "loaded $deffont")
+      or skip("failed to load $deffont" . Imager->errstr, 13);
+    my $bbox = $font->bounding_box(string => "", size => 36);
+    print "# empty string bbox: @$bbox\n";
+    is($bbox->start_offset, 0, "empty string start_offset");
+    is($bbox->end_offset, 0, "empty string end_offset");
+    is($bbox->advance_width, 0, "empty string advance_width");
+    is($bbox->ascent, 0, "empty string ascent");
+    is($bbox->descent, 0, "empty string descent");
+
+    # a single space
+    my $bbox_space = $font->bounding_box(string => " ", size => 36);
+    print "# space bbox: @$bbox_space\n";
+    is($bbox_space->start_offset, 0, "single space start_offset");
+    is($bbox_space->end_offset, $bbox_space->advance_width, 
+       "single space end_offset");
+    cmp_ok($bbox_space->ascent, '>=', $bbox_space->descent,
+          "single space ascent/descent");
+
+    my $bbox_bang = $font->bounding_box(string => "!", size => 36);
+    print "# '!' bbox: @$bbox_bang\n";
+
+    # space ! space
+    my $bbox_spbangsp = $font->bounding_box(string => " ! ", size => 36);
+    print "# ' ! ' bbox: @$bbox_spbangsp\n";
+    my $exp_advance = $bbox_bang->advance_width + 2 * $bbox_space->advance_width;
+    is($bbox_spbangsp->advance_width, $exp_advance, "sp ! sp advance_width");
+    is($bbox_spbangsp->start_offset, 0, "sp ! sp start_offset");
+    is($bbox_spbangsp->end_offset, $exp_advance, "sp ! sp end_offset");
+  }
 }
 
 #malloc_state();