Re: CTFramesetterSuggestFrameSizeWithConstraints cuts off text
Re: CTFramesetterSuggestFrameSizeWithConstraints cuts off text
- Subject: Re: CTFramesetterSuggestFrameSizeWithConstraints cuts off text
- From: Quincey Morris <email@hidden>
- Date: Fri, 17 May 2013 10:25:09 -0700
On May 17, 2013, at 06:38 , Koen van der Drift <email@hidden> wrote:
> CGSize frameSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRangeMake(0, stringLength), NULL, CGSizeMake(self.bounds.size.width, CGFLOAT_MAX), &fitRange);
> self.frame = CGRectMake(0, 0, self.frame.size.width, frameSize.height); // <<<<==== frameSize.height is too small
I ran into this problem a while back, and after a lot of anguish I think I worked out what was going wrong. From an admittedly imperfect memory…
'CTFramesetterSuggestFrameSizeWithConstraints' sometimes returns a width that's *larger* than the width in the 'constraints' parameter -- wider than the view width in your case. So, with your existing code, when the string is eventually typeset and displayed, your view isn't wide enough for the text to line-wrap with exactly the same line breaks as it when you got the suggested frame size, and the text wraps with (generally) one extra line.
The extra width in the returned value comes from "hanging spaces" -- spaces at the end of a line that don't count in the line's wrap width. For example, if you specify a constraint width of 350 points, and the width metric for a space is 5 points (in the font size being used), then the longest possible typeset line is actually 355 points. There may also be other typesetting situations, such as hanging punctuation, which produce similar results.
This is correct behavior, because the non-space characters in the line are allowed to use all 350 points of the width. (Hanging punctuation may partially occupy some of the 350-point width, and partially extend past the end of the width.)
Note that the larger width isn't *always* returned -- it depends how close the non-hanging characters of the longest line come to the constraint width -- so the problem appears to be intermittent.
It's disputable, I guess, but I convinced myself it's correct to return a width >350, because the character that "oversets" the line may have a non-blank glyph -- even a space, when displaying text with a "show invisibles" option -- and so needs to be given a place to display.
Therefore, you need to use the *returned* width for your CTFrame, instead of your view width. This will mean that the CTFrame may overhang the view on the right. In most cases this won't matter, since in most cases the overhanging glyph will be a blank space.
Alternatively, you can pass a smaller width to 'CTFramesetterSuggestFrameSizeWithConstraints' -- for example: self.frame.size.width - (width of a space) -- to ensure that hanging characters have a place to display. But this is an awkward solution if you have a mix of fonts and point sizes in your attributed string.
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden