
Yes, I have seen Getting Font Metrics. However, on my planet, "bounding rectangle" means "the rectangle that completely encloses all ink that will be drawn by the character." It does not mean "a rectangle that is 'advancement' wide".
Here is some code. The image to the right is what it draws. Note that none of these rectangles could even remotely be considered a bounding box. How do I find the bounding box?
{
NSString *str = @"j";
NSFont *font = [NSFont fontWithName:@"Helvetica-BoldOblique" size:180];
NSDictionary *attr = [NSDictionary dictionaryWithObject:font
forKey:NSFontAttributeName];
NSSize bbox = [str sizeWithAttributes:attr];
NSRect frame = [self bounds];
NSPoint pos;
pos.x = (frame.origin.x + ((frame.size.width - bbox.width) / 2));
pos.y = (frame.origin.y + ((frame.size.height - bbox.height) / 2));
/* I can't believe we have to go through this bullshit just to
convert a 'char' to an NSGlyph!!
*/
NSGlyph g;
{
NSTextStorage *ts = [[NSTextStorage alloc] initWithString:str];
[ts setFont:font];
NSLayoutManager *lm = [[NSLayoutManager alloc] init];
NSTextContainer *tc = [[NSTextContainer alloc] init];
[lm addTextContainer:tc];
[tc release]; // lm retains tc
[ts addLayoutManager:lm];
[lm release]; // ts retains lm
g = [lm glyphAtIndex:0];
[ts release];
}
/* Clear window and draw the character.
*/
[[NSColor whiteColor] set];
NSRectFill([self bounds]);
[str drawAtPoint:pos withAttributes:attr];
/* Draw blue square marking origin.
*/
frame.origin = pos;
frame.origin.y -= [font descender];
frame.size.width = frame.size.height = 10;
[[NSColor blueColor] set];
NSRectFill (frame);
/* Draw blue baseline according to [NSFont descender].
*/
frame.origin.x = 0;
frame.origin.y = pos.y - [font descender];
frame.size.width = [self bounds].size.width;
frame.size.height = 1;
[[NSColor blueColor] set];
NSFrameRect (frame);
/* Draw blue line according to [NSFont advancementForGlyph].
*/
frame.origin.x = pos.x + [font advancementForGlyph:g].width;
frame.origin.y = 0;
frame.size.width = 1;
frame.size.height = [self bounds].size.height;
[[NSColor blueColor] set];
NSFrameRect (frame);
/* Draw red bounding box according to [NSString sizeWithAttributes].
*/
frame.origin = pos;
frame.size = bbox;
[[NSColor redColor] set];
NSFrameRect (frame);
/* Draw green bounding box according to [NSFont boundingRectForGlyph].
*/
NSRect bbox2 = [font boundingRectForGlyph: g];
frame.origin.x = pos.x + bbox2.origin.x;
frame.origin.y = pos.y - bbox2.origin.y;
frame.size = bbox2.size;
[[NSColor greenColor] set];
NSFrameRect (frame);
}
(Previously.)
Update: I did solve this eventually; if you want to see the working code, see the query_font() function in xscreensaver/OSX/jwxyz.m.