Incorrect emoji string size returned by CTFramesetterSuggestFrameSizeWithConstraints method
| Originator: | LvChaoShuai | ||
| Number: | rdar://29235932 | Date Originated: | 09-16-2015 |
| Status: | Resolved | Resolved: | 06-05-2017 |
| Product: | iOS SDK | Product Version: | iOS 9+ |
| Classification: | Reproducible: | Yes |
Summary:
We are advised in Apple API Reference (https://developer.apple.com/reference/coretext/1478566-ctframesettersuggestframesizewit?language=objc) that to use CTFramesetterSuggestFrameSizeWithConstraints to determine how much space is needed to display a string.
And before iOS 9, this method works as expected as it always returns the correct value. Since iOS 9 came out, we find the method returns a lot of incorrect size for emoji only strings, which breaks our rendering component.
For example, given an constraint of maxWidth = 288, and a font = 40.0pt, (each emoji's size can be estimated as 45pt). However, for some string with 7 emojis in total, it renders 5 emojis in the first line and 2 emojis in the second line (Incorrect). And for the rest strings, it renders 6 emojis in the first line and 1 emoji in the second line (Correct).
An incorrect emoji string example: @"\U0001F611\U0001F611\U0001F606\U0001F606\U0001F609\U0001F60C\U0001F601"
A correct emoji string example: @"\U0001F611\U0001F611\U0001F606\U0001F606\U0001F609\U0001F60C\u263A"
Since (45 * 5 = 225) < (45 * 6 = 270) < 288 always holds, we believe the method is somehow broken after iOS 9. And the issue didn't get fixed in iOS 10 as well as latest Xcode 8.1.
Steps to Reproduce:
1. Initialize an attributedString with content: @"\U0001F611\U0001F611\U0001F606\U0001F606\U0001F609\U0001F60C\U0001F601", line spacing = 1.0; font size = 40.0pt, MinimumLineHeight = setMaximumLineHeight = 40.0pt.
2. Use CTFramesetterCreateWithAttributedString method to create a CTFramesetterRef, then use CTFramesetterSuggestFrameSizeWithConstraints with constraints={288, CGFLOAT_MAX}.
3. See the value returned was {225, 81}, while the correct value should be {270, 81}.
Redo step 1-3 with string: @"\U0001F611\U0001F611\U0001F606\U0001F606\U0001F609\U0001F60C\u263A", see the returned value was {270, 81}.
Expected Results:
For both string @"\U0001F611\U0001F611\U0001F606\U0001F606\U0001F609\U0001F60C\U0001F601" and @"\U0001F611\U0001F611\U0001F606\U0001F606\U0001F609\U0001F60C\u263A", the returned value should be {270, 81} given font size = 40.0pt and constraint = {288, CGFLOAT_MAX}
Actual Results:
For string @"\U0001F611\U0001F611\U0001F606\U0001F606\U0001F609\U0001F60C\U0001F601" the returned value should be {225, 81} given font size = 40.0pt and constraint = {288, CGFLOAT_MAX}. (Correct)
For string @"\U0001F611\U0001F611\U0001F606\U0001F606\U0001F609\U0001F60C\u263A", the returned value should be {270, 81} given font size = 40.0pt and constraint = {288, CGFLOAT_MAX}. (Incorrect)
Version:
iOS 10.1.1 [14B100]
Notes:
The issue is identified after iOS 9.0, and all the experiments were done in latest Xcode with Version 8.1 (8B62), tested in both iOS simulator (iPhone 7 Plus) and iPhone device.
Configuration:
iPhone 7, 128 GB
Attachments:
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!