如何在 iOS 上旋转 Quartz 运行 中的文本以使原点不移动?

How do I rotate text in Quartz running on iOS so the origin does not move?

我正在尝试创建一个 PDF,它将 运行 在 iOS 台设备上(仅 iPad)。我已经创建了我的 PDF,并且可以在其中写入文本和图形。但是我很难写旋转文本,这样文本会旋转但原点将保持不变。这是我要实现的输出图像:

我这样创建我的 PDF:

  -(void)drawPDF:(NSString*)fileName
{
    self.pageSize = CGSizeMake(792, 612);

    // Create the PDF context using the default page size of 612 x 792.
    UIGraphicsBeginPDFContextToFile(fileName, CGRectZero, nil);

    // Mark the beginning of a new page.
    UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, pageSize.width, pageSize.height), nil);

    // Get the graphics context.
    context = UIGraphicsGetCurrentContext();

    CGContextSetTextMatrix(context, CGAffineTransformIdentity);    
    CGContextTranslateCTM(context, 0, 654);
    CGContextScaleCTM(context, 1.0, -1.0);

    UIFont *font = [UIFont fontWithName:@"Helvetica-Light" size:8];

    [self drawText:@"here is a really long line of text so we can see" withFrame:CGRectMake(400, 100, 50, 50) withFont:font rotation:-50];

    // Close the PDF context and write the contents out.
    UIGraphicsEndPDFContext();
}

然后我有了这个绘制文本的功能,我尝试了很多变体:

  -(void)drawText:(NSString *)text withFrame:(CGRect)rect withFont:(UIFont *)font rotation:(float)degrees
{
    float radians = [PDFMaker DegreesToRadians:degrees];

    NSDictionary *attribs = @{NSFontAttributeName:[UIFont fontWithName:@"Helvetica-Light" size:10.0]};

    CGContextSaveGState(context);

    CGPoint pos = CGPointMake(rect.origin.x, -50 - rect.origin.y);

    // Translate so we're drawing in the right coordinate space
    CGContextScaleCTM(context, 1.0, -1.0);

    CGSize stringSize = [text sizeWithAttributes:attribs];
    CGContextTranslateCTM(context, 0-stringSize.width/2, 0-stringSize.height/2);

    CGContextRotateCTM(context, radians);

    CGContextTranslateCTM(context, stringSize.width/2, stringSize.height/2);

    [text drawAtPoint:CGPointMake(pos.x, pos.y) withAttributes:attribs];

    CGContextRestoreGState(context);
}

但无论我如何使用翻译,文本都会跳来跳去,就好像绕着原点的轴旋转一样。我读过其他答案,在原点的中心旋转文本并尝试过,但这似乎不起作用(或者,可能更准确地说,我无法让它工作)。我怀疑问题可能与使用 PDF 上下文有关,但我真的不知道。任何帮助将不胜感激。

经过大量研究和实验,我明白了。我不确定是否可以回答我自己的问题,所以如果不行,请操作员告诉我,我会删除它。我确实认为答案和答案背后的原因可能对其他社区成员有价值。

这是工作代码:

-(void)drawText:(NSString *)text withFrame:(CGRect)rect withFont:(UIFont *)font
   rotation:(float)degrees alignment:(int)alignment center:(BOOL)center

{ // 透视矩形 rect = CGRectMake(rect.origin.x, rect.origin.y*-1, rect.size.width, rect.size.height);

float radians = [PDFMaker DegreesToRadians:degrees];

NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
paragraphStyle.alignment = alignment;

NSDictionary *attributes = @{ NSFontAttributeName: font,
                              NSParagraphStyleAttributeName: paragraphStyle,
                              NSForegroundColorAttributeName: [Util ColorFromHexString:@"FFFFFF"] };

CGContextSaveGState(context);

// Translate so we're drawing in the right coordinate space
CGContextScaleCTM(context, 1.0, -1.0);

// Save this is we want/need to offset by size
CGRect textSize = [text boundingRectWithSize:rect.size
                                          options:NSStringDrawingUsesLineFragmentOrigin
                                       attributes:attributes
                                          context:nil];

// Translate to origin, rotate, translate back
CGContextTranslateCTM(context, rect.origin.x, rect.origin.y);
CGContextRotateCTM(context, radians);
CGContextTranslateCTM(context, -rect.origin.x, -rect.origin.y);

// Center if necessary
if(center==YES)
{
    CGContextTranslateCTM(context, 0, (rect.size.height/2)-(textSize.size.height/2));
}

[text drawInRect:rect withAttributes:attributes];

CGContextRestoreGState

}

同样有趣或更有趣的是背后的原因。所有这些都写在其他问题和答案中,尽管通常是片段和许多代码,其他问答中的代码示例已被弃用。

所以原因:iOS 以原点在左上角的矩阵开始,如 Windows。但是 iOS 的文本渲染功能是从 OSX 继承的(从 NEXT 继承的),原点在左下角。 PDF 通常是从左下角开始编写的,但是编写转换是从左上角开始运行的标准做法。但由于这些是使用 Core Text 的文本渲染函数,我们再次翻转。因此,您需要考虑并正确转换,否则您的文本将上下颠倒或在屏幕外打印。

之后我们需要在原点旋转,至少按照我设置的方式,它现在位于左下角。如果我们不在原点旋转,我们的文本看起来会飞来飞去:离原点越远,它飞得越远。所以我们平移到原点,旋转,然后平移回来。这不是 PDF 独有的,适用于 Quartz 中的任何旋转。

最后,关于在 iOS 设备上制作 PDF 的编辑评论不容忽视:它可能很慢并且会消耗大量内存。当您想要高质量的矢量输出用于打印或嵌入到 Office 文档等内容中时,我认为对少量页面执行此操作很好;图表、图表、也许是游戏说明、可打印的门票……小东西。但是,如果您要打印大型报告或书籍之类的内容,最好在服务器上生成 PDF。