- Imager::Font::BBox objects now have right_bearing() and display_width()
authorTony Cook <tony@develop=help.com>
Tue, 26 Apr 2005 08:55:35 +0000 (08:55 +0000)
committerTony Cook <tony@develop=help.com>
Tue, 26 Apr 2005 08:55:35 +0000 (08:55 +0000)
  methods.  Hopefully this and the advance_width() method fills out
  the Imager bounding box interface to a useful state.
  Implemented for FT2, FT1.x, T1Lib so far.

Changes
dynfilt/Makefile.PL
font.c
lib/Imager/Font.pm
t/t30t1font.t
t/t35ttfont.t
t/t36oofont.t

diff --git a/Changes b/Changes
index 09a5569..9591b7f 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1069,7 +1069,7 @@ Revision history for Perl extension Imager.
 - Imager::Font::BBox objects now have right_bearing() and display_width()
   methods.  Hopefully this and the advance_width() method fills out
   the Imager bounding box interface to a useful state.
-  Implemented for FT2 so far.
+  Implemented for FT2, FT1.x, T1Lib so far.
 
 =================================================================
 
index 2141dd9..11793e3 100644 (file)
@@ -92,6 +92,8 @@ pure_all ::
 }
 
 # EU::MM crashes without this when we define it in the base Makefile.PL
+# but then warns about redefinition, so delete the GLOB entry
+BEGIN { delete $MY::{metafile} }
 sub MY::metafile {
   '';
 }
diff --git a/font.c b/font.c
index 5099ee2..a979e7a 100644 (file)
--- a/font.c
+++ b/font.c
@@ -328,8 +328,10 @@ i_t1_bbox(int fontnum,float points,char *str,int len,int cords[6], int utf8,char
   cords[BBOX_ASCENT]=((float)bbox.ury*points)/1000;
 
   cords[BBOX_ADVANCE_WIDTH] = ((float)advance * points)/1000;
+  cords[BBOX_RIGHT_BEARING] = 
+    cords[BBOX_ADVANCE_WIDTH] - cords[BBOX_POS_WIDTH];
 
-  return BBOX_ADVANCE_WIDTH+1;
+  return BBOX_RIGHT_BEARING+1;
 }
 
 
@@ -1726,8 +1728,6 @@ i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, int len, int c
          - (gm->bbox.xMax - gm->bbox.xMin);
        /* fprintf(stderr, "font info last: %d %d %d %d\n", 
           gm->bbox.xMax, gm->bbox.xMin, gm->advance, rightb); */
-       if (rightb > 0)
-         rightb = 0;
       }
 
       ascent  = (ascent  >  casc ?  ascent : casc );
@@ -1737,13 +1737,16 @@ i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, int len, int c
   
   cords[BBOX_NEG_WIDTH]=start;
   cords[BBOX_GLOBAL_DESCENT]=gdescent;
-  cords[BBOX_POS_WIDTH]=width - rightb / 64;
+  cords[BBOX_POS_WIDTH]=width;
+  if (rightb < 0)
+    cords[BBOX_POS_WIDTH] -= rightb / 64;
   cords[BBOX_GLOBAL_ASCENT]=gascent;
   cords[BBOX_DESCENT]=descent;
   cords[BBOX_ASCENT]=ascent;
   cords[BBOX_ADVANCE_WIDTH] = width;
+  cords[BBOX_RIGHT_BEARING] = rightb / 64;
 
-  return BBOX_ADVANCE_WIDTH + 1;
+  return BBOX_RIGHT_BEARING + 1;
 }
 
 
index 6fb624d..dfc2bbc 100644 (file)
@@ -873,6 +873,15 @@ list.
 
 You need to modify this class to add new font types.
 
+The $pos_width member returned by the bounding_box() method has
+historically returned different values from different drivers.  The
+Freetype 1.x and 2.x, and the Win32 drivers return the max of the
+advance width and the right edge of the right-most glyph.  The Type 1
+driver always returns the right edge of the right-most glyph.
+
+The newer advance_width and right_bearing values allow access to any
+of the above.
+
 =head1 SEE ALSO
 
 Imager(3), Imager::Font::FreeType2(3), Imager::Font::Type1(3),
index a83ab1d..b36f5d4 100644 (file)
@@ -7,7 +7,7 @@
 # Change 1..1 below to 1..last_test_to_print .
 # (It may become useful if the test is moved to ./t subdirectory.)
 use strict;
-use Test::More tests => 41;
+use Test::More tests => 50;
 BEGIN { use_ok(Imager => ':all') }
 
 #$Imager::DEBUG=1;
@@ -22,13 +22,13 @@ my $fontname_afm=$ENV{'T1FONTTESTAFM'}||'./fontfiles/dcr10.afm';
 SKIP:
 {
   if (!(i_has_format("t1")) ) {
-    skip(40, "t1lib unavailable or disabled", 40);
+    skip("t1lib unavailable or disabled", 49);
   }
   elsif (! -f $fontname_pfb) {
-    skip("cannot find fontfile for type 1 test $fontname_pfb", 40);
+    skip("cannot find fontfile for type 1 test $fontname_pfb", 49);
   }
   elsif (! -f $fontname_afm) {
-    skip("cannot find fontfile for type 1 test $fontname_afm", 40);
+    skip("cannot find fontfile for type 1 test $fontname_afm", 49);
   }
 
   print "# has t1\n";
@@ -37,7 +37,7 @@ SKIP:
 
   my $fnum=Imager::i_t1_new($fontname_pfb,$fontname_afm); # this will load the pfb font
   unless (ok($fnum >= 0, "load font $fontname_pfb")) {
-    skip("without the font I can't do a thing", 39);
+    skip("without the font I can't do a thing", 48);
   }
 
   my $bgcolor=Imager::Color->new(255,0,0,0);
@@ -48,7 +48,7 @@ SKIP:
   i_line($overlay,0,50,100,50,$bgcolor,1);
 
   my @bbox=i_t1_bbox(0,50.0,'XMCLH',5);
-  ok(@bbox == 7, "i_t1_bbox");
+  is(@bbox, 8, "i_t1_bbox");
   print "# bbox: ($bbox[0], $bbox[1]) - ($bbox[2], $bbox[3])\n";
 
   open(FH,">testout/t30t1font.ppm") || die "cannot open testout/t35t1font.ppm\n";
@@ -73,9 +73,9 @@ SKIP:
   my $alttext = "A\xA1A";
   
   my @utf8box = i_t1_bbox($fnum, 50.0, $text, length($text), 1);
-  is(@utf8box, 7, "utf8 bbox element count");
+  is(@utf8box, 8, "utf8 bbox element count");
   my @base = i_t1_bbox($fnum, 50.0, $alttext, length($alttext), 0);
-  is(@base, 7, "alt bbox element count");
+  is(@base, 8, "alt bbox element count");
   my $maxdiff = $fontname_pfb eq $deffont ? 0 : $base[2] / 3;
   print "# (@utf8box vs @base)\n";
   ok(abs($utf8box[2] - $base[2]) <= $maxdiff, 
@@ -101,7 +101,7 @@ SKIP:
     ok(i_t1_cp($backgr, 80, 180, 1, $fnum, 32, $text, length($text), 1),
         "cp UTF8");
     @utf8box = i_t1_bbox($fnum, 50.0, $text, length($text), 0);
-    is(@utf8box, 7, "native utf8 bbox element count");
+    is(@utf8box, 8, "native utf8 bbox element count");
     ok(abs($utf8box[2] - $base[2]) <= $maxdiff, 
       "compare box sizes native $utf8box[2] vs $base[2] (maxerror $maxdiff)");
     eval q{$text = "A\xA1\xA2\x01\x1F\x{0100}A"};
@@ -158,7 +158,7 @@ SKIP:
   SKIP:
   {
     ok($font, "loaded OO font")
-      or skip("Could not load test font", 15);
+      or skip("Could not load test font", 24);
     my @exists = $font->has_chars(string=>"!A");
     is(@exists, 2, "return count from has_chars");
     ok($exists[0], "we have an exclamation mark");
@@ -199,6 +199,31 @@ SKIP:
     };
     is($@, "", "correct error handling");
     cmp_ok(Imager->errstr, '=~', qr/no string parameter/, "error message");
+
+    # test extended bounding box results
+    # the test font is known to have a shorter advance width for that char
+    @bbox = $font->bounding_box(string=>"/", size=>100);
+    is(@bbox, 8, "should be 8 entries");
+    isnt($bbox[6], $bbox[2], "different advance width");
+    my $bbox = $font->bounding_box(string=>"/", size=>100);
+    cmp_ok($bbox->pos_width, '>', $bbox->advance_width, "OO check");
+
+    cmp_ok($bbox->right_bearing, '<', 0, "check right bearing");
+
+    cmp_ok($bbox->display_width, '>', $bbox->advance_width,
+           "check display width (roughly)");
+
+    # check with a char that fits inside the box
+    $bbox = $font->bounding_box(string=>"!", size=>100);
+    print "# pos width ", $bbox->pos_width, "\n";
+
+    # they aren't the same historically for the type 1 driver
+    isnt($bbox->pos_width, $bbox->advance_width, 
+       "check backwards compatibility");
+    cmp_ok($bbox->left_bearing, '>', 0, "left bearing positive");
+    cmp_ok($bbox->right_bearing, '>', 0, "right bearing positive");
+    cmp_ok($bbox->display_width, '<', $bbox->advance_width,
+           "display smaller than advance");
   }
 }
 
index 133d030..258ee8e 100644 (file)
@@ -1,7 +1,7 @@
 #!perl -w
 use strict;
 use lib 't';
-use Test::More tests => 43;
+use Test::More tests => 49;
 
 BEGIN { use_ok(Imager => ':all') }
 require "t/testtools.pl";
@@ -32,7 +32,7 @@ SKIP:
   ok($ttraw, "create font");
 
   my @bbox = i_tt_bbox($ttraw,50.0,'XMCLH',5,0);
-  is(@bbox, 7, "bounding box");
+  is(@bbox, 8, "bounding box");
   print "#bbox: ($bbox[0], $bbox[1]) - ($bbox[2], $bbox[3])\n";
 
   ok(i_tt_cp($ttraw,$overlay,5,50,1,50.0,'XMCLH',5,1,0), "cp output");
@@ -71,9 +71,9 @@ SKIP:
   my $alttext = "A-A";
   
   my @utf8box = i_tt_bbox($ttraw, 50.0, $text, length($text), 1);
-  is(@utf8box, 7, "utf8 bbox element count");
+  is(@utf8box, 8, "utf8 bbox element count");
   my @base = i_tt_bbox($ttraw, 50.0, $alttext, length($alttext), 0);
-  is(@base, 7, "alt bbox element count");
+  is(@base, 8, "alt bbox element count");
   my $maxdiff = $fontname eq $deffont ? 0 : $base[2] / 3;
   print "# (@utf8box vs @base)\n";
   ok(abs($utf8box[2] - $base[2]) <= $maxdiff, 
@@ -100,7 +100,7 @@ SKIP:
     ok(i_tt_cp($ttraw, $backgr, 350, 80, 0, 14, $text, 0, 1, 0),
        "cp UTF8");
     @utf8box = i_tt_bbox($ttraw, 50.0, $text, length($text), 0);
-    is(@utf8box, 7, "native utf8 bbox element count");
+    is(@utf8box, 8, "native utf8 bbox element count");
     ok(abs($utf8box[2] - $base[2]) <= $maxdiff, 
        "compare box sizes native $utf8box[2] vs $base[2] (maxerror $maxdiff)");
     eval q{$text = "A\x{0905}\x{0906}\x{0103}A"}; # Devanagari
@@ -119,7 +119,7 @@ SKIP:
  SKIP:
   {
     ok($hcfont, "loading existence test font")
-      or skip("could not load test font", 14);
+      or skip("could not load test font", 20);
 
     # list interface
     my @exists = $hcfont->has_chars(string=>'!A');
@@ -150,11 +150,27 @@ SKIP:
 
     # the test font is known to have a shorter advance width for that char
     my @bbox = $hcfont->bounding_box(string=>"/", size=>100);
-    is(@bbox, 7, "should be 7 entries");
+    is(@bbox, 8, "should be 8 entries");
     isnt($bbox[6], $bbox[2], "different advance width from pos width");
     print "# @bbox\n";
     my $bbox = $hcfont->bounding_box(string=>"/", size=>100);
     isnt($bbox->pos_width, $bbox->advance_width, "OO check");
+
+    cmp_ok($bbox->right_bearing, '<', 0, "check right bearing");
+
+    cmp_ok($bbox->display_width, '>', $bbox->advance_width,
+           "check display width (roughly)");
+
+    # check with a char that fits inside the box
+    $bbox = $hcfont->bounding_box(string=>"!", size=>100);
+    print "# @$bbox\n";
+    print "# pos width ", $bbox->pos_width, "\n";
+    is($bbox->pos_width, $bbox->advance_width, 
+       "check backwards compatibility");
+    cmp_ok($bbox->left_bearing, '>', 0, "left bearing positive");
+    cmp_ok($bbox->right_bearing, '>', 0, "right bearing positive");
+    cmp_ok($bbox->display_width, '<', $bbox->advance_width,
+           "display smaller than advance");
   }
   undef $hcfont;
   
index cab30fe..6d374c9 100644 (file)
@@ -15,7 +15,7 @@ my $loaded;
 BEGIN { $| = 1; print "1..20\n"; }
 END {print "not ok 1\n" unless $loaded;}
 use Imager;
-require "t/testtools.pl";
+BEGIN { require "t/testtools.pl"; }
 $loaded=1;
 okx(1, "loaded");
 
@@ -46,7 +46,7 @@ if (i_has_format("t1") and -f $fontname_pfb) {
   my $text="LLySja";
   my @bbox=$font->bounding_box(string=>$text, 'x'=>0, 'y'=>50);
 
-  okx(@bbox == 7, "bounding box list length");
+  isx(@bbox, 8, "bounding box list length");
 
   $img->box(box=>\@bbox, color=>$green);
 
@@ -97,7 +97,7 @@ if (i_has_format("tt") and -f $fontname_tt) {
   my $text="LLySja";
   my @bbox=$font->bounding_box(string=>$text, 'x'=>0, 'y'=>50);
 
-  okx(@bbox == 7, "bbox list size");
+  isx(@bbox, 8, "bbox list size");
 
   $img->box(box=>\@bbox, color=>$green);