CTFramesetter ignores paragraph spacing when using paths that are not just a single rectangle

Originator:amorya
Number:rdar://15140647 Date Originated:3/Oct/2013
Status:Duplicate of 10535951 (Open) Resolved:
Product:iOS SDK Product Version:7.0
Classification:Serious Bug Reproducible:Always
 
Summary:
On iOS 7, CTFramesetter ignores paragraph spacing if the framesetter's path is more complex than a single rectangle. This is a regression from iOS 6. The bug manifests even if you compile for iOS 6 SDK and then run on iOS 7.

Steps to Reproduce:
1. Run the attached Xcode project. The app should be run on iOS 7.

Expected Results:
There should be two rectangles on the screen containing text, with text flowing from one to the other. There should be spaces between the paragraphs of text.

Actual Results:
The two rectangles appear as desired, with text flowing between them. However, the paragraphs do not have spacing between them.

Version:
7.0

Notes:
Adding a clipping path can also trigger this bug.

Comments

Duplicate of 10535951 (Open)

Code from the sample project

For the benefit of OpenRadar users, here is the code that demonstrates the problem. This should be put in the drawRect method of a UIView.

[[UIColor whiteColor] set];
UIRectFill(self.bounds);

CGContextRef context = UIGraphicsGetCurrentContext();

// Flip the coordinate system
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);

NSString *text = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras vitae aliquam orci. Sed tincidunt massa vitae arcu aliquet ornare. Cras sodales pellentesque nulla, vel varius enim. Donec aliquet facilisis ipsum eget dictum. Quisque vestibulum quam id quam ultricies, nec pulvinar libero congue. In hac habitasse platea dictumst. Ut elit orci, consequat a dictum ut, luctus vitae nunc. Duis ac iaculis enim. \nDonec bibendum, diam quis porttitor malesuada, ligula sapien semper arcu, nec laoreet mauris ante at lorem. Morbi eu purus aliquam, suscipit nunc euismod, semper dolor. Fusce condimentum, magna sed consectetur blandit, nunc ipsum rutrum nunc, quis rutrum libero enim eu odio. Curabitur volutpat risus diam, et sagittis urna interdum id.\nFusce eget dui orci. Ut quis augue a tortor sodales vehicula at scelerisque elit. Donec eu sagittis felis, a tristique orci. Aenean ante nisl, sodales rhoncus dui in, malesuada iaculis lorem. Mauris quis turpis posuere, dictum est eleifend, tristique ligula. \nNulla quis diam arcu. Cras pharetra aliquet lorem et accumsan. Donec venenatis diam id velit iaculis, ut dapibus dolor sagittis. Integer lobortis odio elit, vel blandit orci porta eget. Vivamus porta felis venenatis, aliquam dui vitae, lacinia lacus. Suspendisse imperdiet posuere mollis. Suspendisse fermentum nibh vitae nunc semper, sed interdum enim tincidunt. Cras in justo a est pharetra ultrices. Quisque elementum porta massa. Cras at lacus at diam porta scelerisque eu vitae justo. Phasellus pretium ante tortor, et viverra odio auctor at.";

CGFloat paragraphSpacing = 30.0;

CTParagraphStyleSetting paragraphSpacingSetting;
paragraphSpacingSetting.spec = kCTParagraphStyleSpecifierParagraphSpacing;
paragraphSpacingSetting.valueSize = sizeof(CGFloat);
paragraphSpacingSetting.value = &paragraphSpacing;

CTParagraphStyleSetting settings[1] = {paragraphSpacingSetting};

CFIndex settingCount = 1;
CTParagraphStyleRef paragraphRef = CTParagraphStyleCreate(settings, settingCount);
NSDictionary *attributes = @{(__bridge id)kCTParagraphStyleAttributeName : (__bridge id)paragraphRef};

NSAttributedString *attrText = [[NSAttributedString alloc] initWithString:text attributes:attributes];

CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attrText);

CGMutablePathRef mpath = CGPathCreateMutable();
CGPathAddRect(mpath, NULL, CGRectMake(0, 0, 500, 200));

// Comment out the line below to demonstrate that a simple rectangular path does not exhibit this bug.
CGPathAddRect(mpath, NULL, CGRectMake(0, 800, 500, 200));

// Draw a background behind the paths so we can see where Core Text should be drawing.
CGContextSaveGState(context);
CGContextSetFillColorWithColor(context, [UIColor lightGrayColor].CGColor);
CGContextAddPath(context, mpath);
CGContextFillPath(context);
CGContextRestoreGState(context);


CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), mpath, NULL);
CTFrameDraw(frame, UIGraphicsGetCurrentContext());

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!