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