Of course you can do it. However, with iOS 7, you don’t have to go all the way to Core Text. NSLayoutManager can handle it in many cases. See CurvyText Demo I wrote for iOS: PTL . You can drag all the control points and see the layout of the text along the curve.
To see how fast this layout can get in pure Core Text and Core Animation, see the PinchText Rich Text demo , the main text . This shows how to adjust the layout of the main text to respond to multi-touch, so the text seems to be bent towards your fingers. It includes examples of how to animate using Core Animation to get smooth settings (and even a little splash effect when you remove your finger).
I don’t quite understand what you mean by “the whole picture into contextual nonsense that slows everything down”. I draw them in context very, very fast (and Core Animation also draws a lot in contexts).
Bending text around a circle is easier than any of these demos. The trick is to compute points along your circle and use these points to translate and rotate your context before asking the layout manager to draw a glyph. Here is a drawText example from a CurvyTextView (which draws along a Bezier curve).
- (void)drawText { if ([self.attributedString length] == 0) { return; } NSLayoutManager *layoutManager = self.layoutManager; CGContextRef context = UIGraphicsGetCurrentContext(); NSRange glyphRange; CGRect lineRect = [layoutManager lineFragmentRectForGlyphAtIndex:0 effectiveRange:&glyphRange]; double offset = 0; CGPoint lastGlyphPoint = self.P0; CGFloat lastX = 0; for (NSUInteger glyphIndex = glyphRange.location; glyphIndex < NSMaxRange(glyphRange); ++glyphIndex) { CGContextSaveGState(context); CGPoint location = [layoutManager locationForGlyphAtIndex:glyphIndex]; CGFloat distance = location.x - lastX;
The “magic” of this is to compute the transformations you need, which is done in offsetAtDistance:fromPoint:andOffset: pointForOffset: and angleForOffset: These procedures are much easier to write for a circle than the general Bezier curve, so this is probably a very good starting point. Please note that this code is not particularly optimized. It was designed for readability more than speed, but it still works very quickly on the iPad 3. If you need it to be faster, there are several methods , including a lot of preliminary calculation that can be done.
The PinchText demo is in pure Core Text and Core Animation, and it's quite a bit more complicated as it does all of its math acceleration (and really needs). I doubt you need this, because the layout problem is not that complicated. Some simple C can probably calculate everything you need in a lot of time. But the PinchText daemon shows how to let Core Animation manage transitions more nicely. Take a look at addTouches:inView:scale: ::
- (void)addTouches:(NSSet *)touches inView:(UIView *)view scale:(CGFloat)scale { for (UITouch *touch in touches) { TouchPoint *touchPoint = [TouchPoint touchPointForTouch:touch inView:view scale:scale]; NSString *keyPath = [self touchPointScaleKeyPathForTouchPoint:touchPoint]; CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:keyPath]; anim.duration = kStartTouchAnimationDuration; anim.fromValue = @0; anim.toValue = @(touchPoint.scale); anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; [self addAnimation:anim forKey:keyPath]; [self.touchPointForIdentifier setObject:touchPoint forKey:touchPoint.identifier]; } }
What happens here is that it animates the model data (the "scale" here is "how much it affects the layout, it has nothing to do with transformations"). needsDisplayForKey: indicates that when changing the data structure of the model, this layer must be redrawn. And he completely redefines and redraws himself in the context of each frame. Done correctly, it can be incredibly fast.
This code will hopefully help you get started. Don't push the book too much, but the demo version of CurvyText is widely discussed in iOS's “Pressing Constraints” in Chapter 21.