- Imager::Font::BBox objects now have right_bearing() and display_width()
authorTony Cook <tony@develop=help.com>
Sun, 24 Apr 2005 11:28:01 +0000 (11:28 +0000)
committerTony Cook <tony@develop=help.com>
Sun, 24 Apr 2005 11:28:01 +0000 (11:28 +0000)
  methods.  Hopefully this and the advance_width() method fills out
  the Imager bounding box interface to a useful state.
  Implemented for FT2 so far.

Changes
datatypes.h
freetyp2.c
lib/Imager/Font.pm
lib/Imager/Font/BBox.pm
t/t38ft2font.t

diff --git a/Changes b/Changes
index fde12b6..09a5569 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1066,6 +1066,10 @@ Revision history for Perl extension Imager.
   checking the end of string when calculating the right side bearing
   used to adjust pos_width for glyphs that overlap the right side of the
   advance width.
+- 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.
 
 =================================================================
 
index 9270d2c..f492565 100644 (file)
@@ -235,6 +235,7 @@ enum bounding_box_index_t {
   BBOX_DESCENT,
   BBOX_ASCENT,
   BBOX_ADVANCE_WIDTH,
+  BBOX_RIGHT_BEARING,
   BOUNDING_BOX_COUNT
 };
 
index 66d9dd3..687e268 100644 (file)
@@ -389,20 +389,24 @@ i_ft2_bbox(FT2_Fonthandle *handle, double cheight, double cwidth,
        handle the case where the right the of the character overlaps the 
        right*/
       rightb = (gm->horiAdvance - gm->horiBearingX - gm->width)/64;
-      if (rightb > 0)
-        rightb = 0;
+      /*if (rightb > 0)
+        rightb = 0;*/
     }
   }
 
   bbox[BBOX_NEG_WIDTH] = start;
   bbox[BBOX_GLOBAL_DESCENT] = handle->face->size->metrics.descender / 64;
-  bbox[BBOX_POS_WIDTH] = width - rightb;
+  bbox[BBOX_POS_WIDTH] = width;
+  if (rightb < 0)
+    bbox[BBOX_POS_WIDTH] -= rightb;
   bbox[BBOX_GLOBAL_ASCENT] = handle->face->size->metrics.ascender / 64;
   bbox[BBOX_DESCENT] = descent;
   bbox[BBOX_ASCENT] = ascent;
   bbox[BBOX_ADVANCE_WIDTH] = width;
+  bbox[BBOX_RIGHT_BEARING] = rightb;
+  mm_log((1, " bbox=> negw=%d glob_desc=%d pos_wid=%d glob_asc=%d desc=%d asc=%d adv_width=%d rightb=%d\n", bbox[0], bbox[1], bbox[2], bbox[3], bbox[4], bbox[5], bbox[6], bbox[7]));
 
-  return BBOX_ADVANCE_WIDTH + 1;
+  return BBOX_RIGHT_BEARING + 1;
 }
 
 /*
index 3fa10ad..6fb624d 100644 (file)
@@ -326,7 +326,8 @@ Imager::Font - Font handling for Imager.
    $global_ascent,
    $descent,
    $ascent,
-   $advance_width) = $font->bounding_box(string=>"Foo");
+   $advance_width,
+   $right_bearing) = $font->bounding_box(string=>"Foo");
 
   $logo = $font->logo(text   => "Slartibartfast Enterprises",
                      size   => 40,
@@ -415,7 +416,8 @@ Returns the bounding box for the specified string.  Example:
       $global_ascent,
       $descent,
       $ascent,
-      $advance_width) = $font->bounding_box(string => "A Fool");
+      $advance_width,
+      $right_bearing) = $font->bounding_box(string => "A Fool");
 
   my $bbox_object = $font->bounding_box(string => "A Fool");
 
@@ -453,6 +455,12 @@ start at, this is often the same as C<$pos_width>, but can be
 different if the final character overlaps the right side of its
 character cell.
 
+=item C<$right_bearing>
+
+The distance from the right side of the final glyph to the end of the
+advance width.  If the final glyph overflows the advance width this
+value is negative.
+
 =back
 
 Obviously we can stuff all the results into an array just as well:
index 4fe8ddf..dd58f7a 100644 (file)
@@ -15,6 +15,8 @@ Imager::Font::BBox - objects representing the bounding box of a string.
 
   # methods
   my $start = $bbox->start_offset;
+  my $left_bearing = $bbox->left_bearing;
+  my $right_bearing = $bbox->right_bearing;
   my $end = $bbox->end_offset;
   my $gdescent = $box->global_descent;
   my $gascent = $bbox->global_ascent;
@@ -23,6 +25,7 @@ Imager::Font::BBox - objects representing the bounding box of a string.
   my $total_width = $bbox->total_width;
   my $fheight = $bbox->font_height;
   my $theight = $bbox->text_height;
+  my $display_width = $bbox->display_width;
 
 =head1 DESCRIPTION
 
@@ -45,6 +48,8 @@ first glyph is to the right of the drawing location.
 The alias neg_width() is present to match the bounding_box()
 documentation for list context.
 
+The alias left_bearing() is present to match font terminology.
+
 =cut
 
 sub start_offset {
@@ -55,6 +60,10 @@ sub neg_width {
   return $_[0][0];
 }
 
+sub left_bearing {
+  return $_[0][0];
+}
+
 =item end_offset()
 
 The offset from the selected drawing location to the right edge of the
@@ -169,6 +178,42 @@ sub text_height {
   $self->ascent - $self->descent;
 }
 
+=item right_bearing
+
+The distance from the right of the last glyph to the end of the advance
+point.
+
+If the glyph overflows the right side of the advance width this value
+is negative.
+
+=cut
+
+sub right_bearing {
+  my $self = shift;
+
+  @$self >= 8 && return $self->[7]; # driver gives it to us
+
+  # otherwise the closest we have is the difference between the 
+  # end_pos and advance_width
+  return $self->advance_width - $self->pos_width;
+}
+
+=item display_width
+
+The distance from the left-most pixel of the left-most glyph to the
+right-most pixel of the right-most glyph.
+
+Equals advance_width - left_bearing - right_bearing (and implemented
+that way.)
+
+=cut
+
+sub display_width {
+  my ($self) = @_;
+
+  $self->advance_width - $self->left_bearing - $self->right_bearing;
+}
+
 =back
 
 =head1 INTERNAL FUNCTIONS
index 5911830..c08f2d1 100644 (file)
@@ -1,6 +1,7 @@
 #!perl -w
 use strict;
-use Test::More tests => 138;
+use Test::More tests => 144;
+++$|;
 # Before `make install' is performed this script should be runnable with
 # `make test'. After `make install' it should work as `perl test.pl'
 
@@ -37,7 +38,7 @@ SKIP:
   my @bbox=Imager::Font::FreeType2::i_ft2_bbox($ttraw, 50.0, 0, 'XMCLH', 0);
   print "#bbox @bbox\n";
   
-  is(@bbox, 7, "i_ft2_bbox() returns 7 values");
+  is(@bbox, 8, "i_ft2_bbox() returns 8 values");
 
   ok(Imager::Font::FreeType2::i_ft2_cp($ttraw,$overlay,5,50,1,50.0,50, 'XMCLH',1,1, 0, 0), "drawn to channel");
   i_line($overlay,0,50,100,50,$bgcolor,1);
@@ -187,7 +188,7 @@ SKIP:
   @bbox = $oof->bounding_box(string=>"hello", size=>30);
   my $bbox = $oof->bounding_box(string=>"hello", size=>30);
 
-  is(@bbox, 7, "list bbox returned 7 items");
+  is(@bbox, 8, "list bbox returned 8 items");
   ok($bbox->isa('Imager::Font::BBox'), "scalar bbox returned right class");
   ok($bbox->start_offset == $bbox[0], "start_offset");
   ok($bbox->end_offset == $bbox[2], "end_offset");
@@ -223,14 +224,30 @@ SKIP:
   SKIP:
   {
     ok($exfont, "loaded existence font") or
-      skip("couldn't load test font", 5);
+      skip("couldn't load test font", 11);
+
     # the test font is known to have a shorter advance width for that char
     my @bbox = $exfont->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");
     my $bbox = $exfont->bounding_box(string=>"/", size=>100);
     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
+    my $bbox = $exfont->bounding_box(string=>"!", size=>100);
+    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");
+
     # name tests
     # make sure the number of tests on each branch match
     if (Imager::Font::FreeType2::i_ft2_can_face_name()) {