- Imager::Font::BBox objects now have right_bearing() and display_width()
[imager.git] / lib / Imager / Font / BBox.pm
1 package Imager::Font::BBox;
2 use strict;
3
4 =head1 NAME
5
6 Imager::Font::BBox - objects representing the bounding box of a string.
7
8 =head1 SYNOPSIS
9
10   use Imager::Font;
11
12   # get the object
13   my $font = Imager::Font->new(...);
14   my $bbox = $font->bounding_box(string=>$text, size=>$size);
15
16   # methods
17   my $start = $bbox->start_offset;
18   my $left_bearing = $bbox->left_bearing;
19   my $right_bearing = $bbox->right_bearing;
20   my $end = $bbox->end_offset;
21   my $gdescent = $box->global_descent;
22   my $gascent = $bbox->global_ascent;
23   my $ascent = $bbox->ascent;
24   my $decent = $bbox->descent;
25   my $total_width = $bbox->total_width;
26   my $fheight = $bbox->font_height;
27   my $theight = $bbox->text_height;
28   my $display_width = $bbox->display_width;
29
30 =head1 DESCRIPTION
31
32 Objects of this class are returned by the Imager::Font bounding_box()
33 method when it is called in scalar context.
34
35 This will hopefully make the information from this method more
36 accessible.
37
38 =head1 METHODS
39
40 =over
41
42 =item start_offset()
43
44 Returns the horizonatal offset from the selected drawing location to
45 the left edge of the first character drawn.  If this is positive, the
46 first glyph is to the right of the drawing location.
47
48 The alias neg_width() is present to match the bounding_box()
49 documentation for list context.
50
51 The alias left_bearing() is present to match font terminology.
52
53 =cut
54
55 sub start_offset {
56   return $_[0][0];
57 }
58
59 sub neg_width {
60   return $_[0][0];
61 }
62
63 sub left_bearing {
64   return $_[0][0];
65 }
66
67 =item end_offset()
68
69 The offset from the selected drawing location to the right edge of the
70 last character drawn.  Should always be positive.
71
72 You can use the alias pos_width() if you are used to the
73 bounding_box() documentation for list context.
74
75 =cut
76
77 sub end_offset {
78   return $_[0][2];
79 }
80
81 sub pos_width {
82   return $_[0][2];
83 }
84
85 =item global_descent()
86
87 The lowest position relative to the font baseline that any character
88 in the font reaches in the character cell.  Normally negative.
89
90 At least one font we've seen has reported a positive number for this.
91
92 =cut
93
94 sub global_descent {
95   return $_[0][1];
96 }
97
98 =item global_ascent()
99
100 The highest position relative to the font baseline that any character
101 in the font reaches in the character cell.  Normally positive.
102
103 =cut
104
105 sub global_ascent {
106   return $_[0][3];
107 }
108
109 =item descent()
110
111 The lowest position relative to the font baseline that any character
112 in the supplied string reaches.  Negative when any character's glyph
113 reaches below the baseline.
114
115 =cut
116
117 sub descent {
118   return $_[0][4];
119 }
120
121 =item ascent()
122
123 The highest position relative to the font baseline that any character
124 in the supplied string reaches.  Positive if any character's glyph
125 reaches above the baseline.
126
127 =cut
128
129 sub ascent {
130   return $_[0][5];
131 }
132
133 =item advance_width()
134
135 The advance width of the string, if the driver supports that,
136 otherwise the same as end_offset.
137
138 =cut
139
140 sub advance_width {
141   my $self = shift;
142
143   @$self > 6 ? $self->[6] : $self->[2];
144 }
145
146 =item total_width()
147
148 The total displayed width of the string.
149
150 =cut
151
152 sub total_width {
153   my $self = shift;
154
155   $self->end_offset - $self->start_offset;
156 }
157
158 =item font_height()
159
160 The maximum displayed height of any string using this font.
161
162 =cut
163
164 sub font_height {
165   my $self = shift;
166   $self->global_ascent - $self->global_descent;
167 }
168
169 =item text_height()
170
171 The displayed height of the supplied string.
172
173 =cut
174
175 sub text_height {
176   my $self = shift;
177
178   $self->ascent - $self->descent;
179 }
180
181 =item right_bearing
182
183 The distance from the right of the last glyph to the end of the advance
184 point.
185
186 If the glyph overflows the right side of the advance width this value
187 is negative.
188
189 =cut
190
191 sub right_bearing {
192   my $self = shift;
193
194   @$self >= 8 && return $self->[7]; # driver gives it to us
195
196   # otherwise the closest we have is the difference between the 
197   # end_pos and advance_width
198   return $self->advance_width - $self->pos_width;
199 }
200
201 =item display_width
202
203 The distance from the left-most pixel of the left-most glyph to the
204 right-most pixel of the right-most glyph.
205
206 Equals advance_width - left_bearing - right_bearing (and implemented
207 that way.)
208
209 =cut
210
211 sub display_width {
212   my ($self) = @_;
213
214   $self->advance_width - $self->left_bearing - $self->right_bearing;
215 }
216
217 =back
218
219 =head1 INTERNAL FUNCTIONS
220
221 =over
222
223 =item new(...)
224
225 Called by Imager::Font->bounding_box() to create the object.
226
227 =cut
228
229 sub new {
230   my $class = shift;
231   return bless [ @_ ], $class;
232 }
233
234 =back
235
236 =head1 BUGS
237
238 Doesn't reproduce the functionality that you get using the x and y
239 parameters to Imager::Font->bounding_box().  I considered:
240
241   my ($left, $top, $right, $bottom) = $box->offset(x=>$x, y=>$y)
242
243 but this is about as clumsy as the original.
244
245 =head1 AUTHOR
246
247 Tony Cook <tony@develop-help.com>
248
249 =head1 SEE ALSO
250
251 Imager(3), Imager::Font(3)
252
253 =cut
254
255 1;
256