Re: CTFramesetterSuggestFrameSizeWithConstraints cuts off text
On 17/05/2013, at 11:38 PM, Koen van der Drift wrote: > // calculate the size it occupies > >CTFramesetterRef framesetter = > CTFramesetterCreateWithAttributedString(attrString); > [] > // draw the string: > > [] >CTFramesetterRef framesetter = > CTFramesetterCreateWithAttributedString((CFAttributedStringRef) attrString); Don't create the framesetter object twice. I'm not sure it has a bearing on your issue, but it would make sense that the framesetter used to calculate the frame should be the exact same one that draws the frame. It might be that creating it and calculating the size performs some caching that speeds up the second use. In any case it will use less memory if you only use one. --Graham ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: CTFramesetterSuggestFrameSizeWithConstraints cuts off text
Yep, I saw it as well. But IIRC it was in rare occasions. Rare in my point of view, because we do use "normal" alphabet. the problem was in special characters, emoji, symbols, ... In these times I tried every possible combination/available method/property/calculation/... without success. Also tried 3rd party labels, later I tried DTCoreText from Cocoanetics with the same output - wrong height. I also asked Apple engineers and then I gave up. Not sure, but I did suspect them that they use private API or dunno what, because their apps didn't have problems. I'm pretty happy with attributed string and auto layout for now. It's enough for almost all needs and I'm glad that I'm not forced to dive into this "mess" again. On Friday, 17. May 2013 at 23:42, Quincey Morris wrote: > On May 17, 2013, at 11:20 , Robert Vojta (mailto:rob...@tapmates.com)> wrote: > > > Height was wrong even if returned width <= constrained width. > Once I took proper account of the returned width, I got no more "wrong" > heights. > > However, IIRC, there was a separate issue that fractional line heights didn't > work correctly. Maybe you ran into that problem as well. > ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: CTFramesetterSuggestFrameSizeWithConstraints cuts off text
Thanks all for the insightful responses. In my case I am using a monospaced font, and everything looks pretty square. The thing I did wrong as it turned out was that I had a little padding on the top, making my CTView to slightly shift down, and therefore making the final string disappear. My code looks like this now: CGSize frameSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRangeMake(0, 0), NULL, CGSizeMake(self.bounds.size.width, CGFLOAT_MAX), &fitRange); self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, frameSize.height + PADDING_TOP); <<=== correction for padding Cheers, - Koen. On Fri, May 17, 2013 at 5:42 PM, Quincey Morris < quinceymor...@rivergatesoftware.com> wrote: > On May 17, 2013, at 11:20 , Robert Vojta wrote: > > Height was wrong even if returned width <= constrained width. > > > Once I took proper account of the returned width, I got no more "wrong" > heights. > > However, IIRC, there was a separate issue that fractional line heights > didn't work correctly. Maybe you ran into that problem as well. > > ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: CTFramesetterSuggestFrameSizeWithConstraints cuts off text
On May 17, 2013, at 11:20 , Robert Vojta wrote: > Height was wrong even if returned width <= constrained width. Once I took proper account of the returned width, I got no more "wrong" heights. However, IIRC, there was a separate issue that fractional line heights didn't work correctly. Maybe you ran into that problem as well. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: CTFramesetterSuggestFrameSizeWithConstraints cuts off text
I ran into this few years ago and didn't find correct solution. Correct means nice & clean. Ended with adding 1/2 of line height, which causes another issues like wrong vertical alignment of elements. It was pre NSAttributedString era on iOS. Height was wrong even if returned width <= constrained width. Did spend on this couple of weeks and finally gave up. On Friday, 17. May 2013 at 19:25, Quincey Morris wrote: > On May 17, 2013, at 06:38 , Koen van der Drift > 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 (Cocoa-dev@lists.apple.com) > > 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: > https://lists.apple.com/mailman/options/cocoa-dev/robert%40tapmates.com > > This email sent to rob...@tapmates.com ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: CTFramesetterSuggestFrameSizeWithConstraints cuts off text
On May 17, 2013, at 06:38 , Koen van der Drift 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 (Cocoa-dev@lists.apple.com) 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: CTFramesetterSuggestFrameSizeWithConstraints cuts off text
Thanks Fritz, After trying out various values, this worked for me: CGSize frameSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRangeMake(0, 0), NULL, CGSizeMake(self.bounds.size.width, CGFLOAT_MAX), &fitRange); CGFloat lineHeight = CTFontGetSize( ctFont ) * 2.0; frameSize.height += lineHeight; I'm using CGFLOAT_MAX, since the text can be longer than the bounds of the view. - Koen. On May 17, 2013, at 10:37 AM, Fritz Anderson wrote: > Also, I had another app that didn't need the kludge. I don't have time to > experiment, but I think the operative line was: > >// boundingRect.size was {columwidth, CGFLOAT_MAX} >suggestion = CTFramesetterSuggestFrameSizeWithConstraints(setter, > CFRangeMake(0, > 0), > NULL, > > boundingRect.size, > &actualRange); > > Note the range of {0,0}, which allows the framesetter to run until it runs > out of space or string. That app worked properly. > > — F > > > -- > Fritz Anderson > Xcode 4 Unleashed: 4.5 supplement for free! > http://www.informit.com/store/xcode-4-unleashed-9780672333279 > ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: CTFramesetterSuggestFrameSizeWithConstraints cuts off text
Also, I had another app that didn't need the kludge. I don't have time to experiment, but I think the operative line was: // boundingRect.size was {columwidth, CGFLOAT_MAX} suggestion = CTFramesetterSuggestFrameSizeWithConstraints(setter, CFRangeMake(0, 0), NULL, boundingRect.size, &actualRange); Note the range of {0,0}, which allows the framesetter to run until it runs out of space or string. That app worked properly. — F -- Fritz Anderson Xcode 4 Unleashed: 4.5 supplement for free! http://www.informit.com/store/xcode-4-unleashed-9780672333279 ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: CTFramesetterSuggestFrameSizeWithConstraints cuts off text
On 17 May 2013, at 8:38 AM, Koen van der Drift wrote: > CTFramesetterSuggestFrameSizeWithConstraints I ran into this problem and had to resort to an ad-hoc kludge (though I guess all kludges are ad-hoc: lineHeight = CTFontGetSize(self.ctDefaultFont)*1.2; ... frameSize = CTFramesetterSuggestFrameSizeWithConstraints(ctFramesetter... ... // I wish I had a principled reason why this is necessary, or the best solution. // It looks good from a cursory examination, but surely this fails in some cases, // or with some combination of styles. frameSize.height += lineHeight / 2.0; — F -- Fritz Anderson Xcode 4 Unleashed: 4.5 supplement for free! http://www.informit.com/store/xcode-4-unleashed-9780672333279 ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
CTFramesetterSuggestFrameSizeWithConstraints cuts off text
I'm using Core Text to layout text in an UIView but am having troubles with getting the correct size that the text needs, so I can set the contentSize of the UIScrollView that it is embedded in. I know it is the wrong size, because the last line is not showing. I've done some spitting around, and it seems that CTFramesetterSuggestFrameSizeWithConstraints may not always work properly. However I haven't found a solution that works for me. I've pasted my code below, maybe I am overlooking something? Thanks, - Koen. == // create the string: NSString *testString = @"This is a not so very long but at least long enough test string to cover more than one line."; CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0); CFAttributedStringReplaceString (attrString, CFRangeMake(0, 0), (CFStringRef) testString ); CFIndex stringLength = CFStringGetLength((CFStringRef) attrString); // give it a font UIFont* uiFont = [UIFont fontWithName: @"Courier" size: 22.0]; CTFontRef ctFont = CTFontCreateWithName((__bridge CFStringRef) uiFont.fontName, uiFont.pointSize, NULL); CFAttributedStringSetAttribute(attrString, CFRangeMake(0, stringLength), kCTFontAttributeName, ctFont); // calculate the size it occupies CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString); CFRange fitRange; 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 // draw the string: CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetTextMatrix(context, CGAffineTransformIdentity); CGContextTranslateCTM(context, 0, self.bounds.size.height); CGContextScaleCTM(context, 1.0, -1.0); CGMutablePathRef path = CGPathCreateMutable(); CGPathAddRect(path, NULL, self.frame); CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef) attrString); CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, stringLength), path, NULL); CTFrameDraw(frameRef, context); ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com