# UILabel斜体字体裁剪

• 借助CoreText和 CGSize CTFramesetterSuggestFrameSizeWithConstraints ( CTFramesetterRef framesetter, CFRange stringRange, CFDictionaryRef frameAttributes, CGSize constraints, CFRange *fitRange );
• 借助NSAttributedString和 - (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context
• 借助NSString和 - (CGSize)sizeWithAttributes:(NSDictionary<NSString *,id> *)attrs
• 使用临时UITextView和sizeThatFits´ andfitToSize

Here is sample code on Github.

Even I don't have the time to test it, I'm pretty sure that the problem is that the label size is calculated from the advances. The advance is the amount of movement from one character's base point to the next ones. Typically for an italic font the advance can be smaller than the bounds. Therefore adding the advances will cut the end of the layout.

I.e. Baskerville-Italic H:

(lldb) p bounds[0].size
(CGSize) $6 = (width=33.53515625, height=26.484375) (lldb) p advances[0] (CGSize)$7 = (width=30, height=0)


So I think that you have to add the difference between advance and bounding box of the last character, if the text is layout in an ideal way (no compression and so on).

To get both values, you have to call some CT functions:

// What you probably have
CTFontRef font = …;
CFStringRef string = …;
CFAAttributedStringRef attrString = CFAttributedStringCreate(kCFAllocatorDefault, string, attributes);

// Get the character and glyph
CFIndex count = CFStringGetLength(string); // The length of the string
UniChar character;
CFStringGetCharacters( string, CFMakeRange( count-1, 1), &character );
CGGlyph glyph;
CTStringGetGlyphsForCharacters( font, &character, &glyph,1  );

// Get the bounds
CGRect bounds;
CTFontGetAdvancesForGlyphs( font, 0, &glyph, &bounds, 1);
`

Typed in Safari.

0条评论