Mailing Lists: Apple Mailing Lists

Image of Mac OS face in stamp
 
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Core Text line height




On Mar 17, 2008, at 11:02 AM, Luigi Castelli wrote:

For reasons that I am not going to explain I can't/don't want to use the image bounds of the line.
So, in order to retrieve the line metrics I am using the CTLineGetTypographicBounds function.

I ran into this problem in my own code where I couldn't use the typographic bounds because I didn't have a CGContext handy at the time.  What I did to work around that was to create a small, one pixel CGBitmapContext and use that as the context that I would render into.  Of course, in my case the text in question was to be drawn on the screen so I could be reasonably certain that a bitmap context and the screen would use text that was the same size. Those measurements might be inaccurate if you were, say, going to draw the text into a printing context.

Now, I understand that different fonts have different ways of adhering to the standard font metric rules. (some probably don't) However is there a more accurate way to get the correct line height to vertically center text, or is what I am after like a moving target ?

Here's the routine that I use to measure the height of the text in a frame using CoreText.  I like the results it gives. You are welcome to use it, if it solves your problem, but I make no warranties as to its correctness.  The only odd part is the bit at the very end about rounding up the size of the frame to a full point.  I found that if I measured the text via typographic bounds, then tried to draw into a frame that was that exact size, that sometimes the last line would wrap out of the frame.  As I said, I was drawing to the screen so this may have been due to the demands of the pixel grid or antialiasing or something. The fix as given below seems to work for all the cases I've tried.

Here's the code:

- (CGSize) measureFrame: (CTFrameRef) frame forContext: (CGContext *) cgContext
{
CGPathRef framePath = CTFrameGetPath(frame);
CGRect frameRect = CGPathGetBoundingBox(framePath);

CFArrayRef lines = CTFrameGetLines(frame);
CFIndex numLines = CFArrayGetCount(lines);

CGFloat maxWidth = 0;
CGFloat textHeight = 0;

// Now run through each line determining the maximum width of all the lines.
// We special case the last line of text. While we've got it's descent handy,
// we'll use it to calculate the typographic height of the text as well.
CFIndex lastLineIndex = numLines - 1;
for(CFIndex index = 0; index < numLines; index++)
{
CGFloat ascent, descent, leading, width;
CTLineRef line = (CTLineRef) CFArrayGetValueAtIndex(lines, index);
width = CTLineGetTypographicBounds(line, &ascent,  &descent, &leading);

if(width > maxWidth)
{
maxWidth = width;
}

if(index == lastLineIndex)
{
// Get the origin of the last line. We add the descent to this
// (below) to get the bottom edge of the last line of text.
CGPoint lastLineOrigin;
CTFrameGetLineOrigins(frame, CFRangeMake(lastLineIndex, 1), &lastLineOrigin);

// The height needed to draw the text is from the bottom of the last line
// to the top of the frame.
textHeight =  CGRectGetMaxY(frameRect) - lastLineOrigin.y + descent;
}
}

// For some text the exact typographic bounds is a fraction of a point too
// small to fit the text when it is put into a context. We go ahead and round
// the returned drawing area up to the nearest point.  This takes care of the
// discrepencies.
return CGSizeMake(ceil(maxWidth), ceil(textHeight));
}

 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Quartz-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/quartz-dev/email@hidden

This email sent to email@hidden

References: 
 >Core Text line height (From: Luigi Castelli <email@hidden>)



Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2007 Apple Inc. All rights reserved.