iOS上具有不对称形状的核心文本

时间:2013-12-09 17:21:45

标签: ios quartz-2d core-text

我想在可以占用任何形状的路径中书写文字。现在我可以在其中绘制翻转文本:

NSArray *coordinates = ...;

CGMutablePathRef pathRef = [self objectPathGivenCoordinates:coordinates];

... // Draw the shapes

// Now draw the text    
CGContextSetTextMatrix(context, CGAffineTransformIdentity);

NSAttributedString* attString = [[NSAttributedString alloc] initWithString:@"0,1,2..."];
CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attString);
CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, [attString length]), pathRef, NULL);
CTFrameDraw(frame, context);

这产生了这个:

Flipped text in Asymmetric Shape

我知道iOS有一个翻转坐标系。大多数解决方案在绘制之前添加这两行:

CGContextTranslateCTM(context, 0, rect.size.height);
CGContextScaleCTM(context, 1.0, -1.0);

但是这产生了这个:

Text is now written left-right right-side-up but out of path bounds

那么为什么这种技术不起作用?在我见过的每个例子中,当文本以对称,剪切或OS X呈现时,使用此技术。如果我们以对称形状绘制文本,则调用CGContextTranslateCTM()和{ {1}}有道理。拨打CGContextScaleCTM(),将第一个字母的原点移至顶部。对CGContextTranslateCTM(context, 0, rect.size.height)的调用会反转Y的方向。如果我们在对称形状上反转Y的方向,它就不会改变。可悲的是,我的形状并不对称。

这是我考虑过但放弃了

  • 以相同的比例绘制形状和数字(两者都是颠倒的),然后以某种方式翻转CGContextScaleCTM(context, 1, -1)(1)
  • 不要拨打电话来改变比例或翻译CTM。使用UIImageView翻转文本矩阵,以便从左到右,从下到上,并且正面朝上绘制文本。确定在确定形状的字符串后,形状中剩余多少个额外字符。翻转单词(现在它将从上到下,从右到左,右上方)。为每个额外的角色添加空格。现在为每个CGContextSetTextMatrix(),以某种方式再次反转单词(现在它将从上到下,从左到右,右上方)(2)

为什么我放弃了他们

(1)我无法翻转我的图像。他们总是需要正面朝上

(2)对于其他人知道的简单解决方案,这可能是过度的。

1 个答案:

答案 0 :(得分:6)

我确定了一个解决方案

// Flip the coordinates so that the object is drawn as if it were mirrored along the x-axis
// coordinates = @[CGPointMake(1, 2), CGPointMake(9, 17), CGPointMake(41, 3), ...]
NSArray *flippedCoordinates = [coordinates map:^id(id object) {
     CGPoint value;
     [object getValue:&value];
     CGPoint point = value;

     point.y = point.y * (-1) + rect.size.height;

     return [NSValue value:&point withObjCType:@encode(CGPoint)];
}];

// Generate a CGPathRef using the new coordinates
CGMutablePathRef pathRef = CGPathCreateMutable();
CGPathMoveToPoint(pathRef, NULL, [[flippedCoordinates objectAtIndex:0] CGPointValue].x + .5 [[flippedCoordinates objectAtIndex:0] CGPointValue].y + .5);
for(NSValue *arrayValue in flippedCoordinates) {
    CGPoint point = [arrayValue CGPointValue];
    CGPathAddLineToPoint(pathRef, NULL, point.x, point.y);
}
CGPathCloseSubpath(pathRef);

// Draw the object
// ...

// Draw the text as if it were on OS X
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
NSAttributedString* attString = [[NSAttributedString alloc] initWithString:@"0,1,2,..." attributes:@{(NSString *)kCTForegroundColorAttributeName : textColor}];
CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attString);
CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, [attString length]), pathRef, NULL);
CTFrameDraw(frame, context);

CFRelease(frame);
CFRelease(frameSetter);
CFRelease(pathRef);

// And, for the magic touch, flip the whole view AFTER everything is drawn
[self.layer setAffineTransform:CGAffineTransformMakeScale(1, -1)];

现在一切都是从上到下,从左到右,右上方绘制的

Core Text correctly laid out on asymmetric shape in iOS