From: Tony Cook Date: Sun, 24 Apr 2005 11:28:01 +0000 (+0000) Subject: - Imager::Font::BBox objects now have right_bearing() and display_width() X-Git-Tag: Imager-0.48^2~175 X-Git-Url: http://git.imager.perl.org/imager.git/commitdiff_plain/dc35bde9992a36677aa424d8ee2aa52d51eacc15 - 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. --- diff --git a/Changes b/Changes index fde12b6b..09a55698 100644 --- 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. ================================================================= diff --git a/datatypes.h b/datatypes.h index 9270d2c0..f4925651 100644 --- a/datatypes.h +++ b/datatypes.h @@ -235,6 +235,7 @@ enum bounding_box_index_t { BBOX_DESCENT, BBOX_ASCENT, BBOX_ADVANCE_WIDTH, + BBOX_RIGHT_BEARING, BOUNDING_BOX_COUNT }; diff --git a/freetyp2.c b/freetyp2.c index 66d9dd36..687e2685 100644 --- a/freetyp2.c +++ b/freetyp2.c @@ -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; } /* diff --git a/lib/Imager/Font.pm b/lib/Imager/Font.pm index 3fa10ad2..6fb624df 100644 --- a/lib/Imager/Font.pm +++ b/lib/Imager/Font.pm @@ -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: diff --git a/lib/Imager/Font/BBox.pm b/lib/Imager/Font/BBox.pm index 4fe8ddfd..dd58f7ab 100644 --- a/lib/Imager/Font/BBox.pm +++ b/lib/Imager/Font/BBox.pm @@ -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 diff --git a/t/t38ft2font.t b/t/t38ft2font.t index 59118309..c08f2d15 100644 --- a/t/t38ft2font.t +++ b/t/t38ft2font.t @@ -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()) {