如何在iOS中渲染拉伸文本? [英] How to render stretched text in iOS?

查看:180
本文介绍了如何在iOS中渲染拉伸文本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定一个矩形区域,我想使用特定的字体渲染一些文本,并使渲染的文本填充矩形。如下图所示:




  1. 这与改变字体大小并不相同。
  2. 将其渲染为位图,然后缩放它是不是一个选项(它看起来很可怕)

  3. 矢量图形是做到这一点的方式



解决方案



我想出了以下这些似乎适用于我的目的。代码绘制一行文本缩放来填充边界。子类 UIView 并替换 drawRect ,如下所示。

   - (void)drawRect:(CGRect)rect 
{
[self drawScaledString:@Abcde ];

$ b - (void)drawScaledString:(NSString *)string
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetTextMatrix(context,CGAffineTransformIdentity);

NSAttributedString * attrString = [self generateAttributedString:string]; (CFMutableAttributedStringRef)attrString,CFRangeMake(0,string.length),
kCTForegroundColorAttributeName,[UIColor redColor] .CGColor);

CFAttributedStringSetAttribute

CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)attrString);

// CTLineGetTypographicBounds不会给出正确的值,
//使用GetImageBounds而不是
CGRect imageBounds = CTLineGetImageBounds(line,context);
CGFloat width = imageBounds.size.width;
CGFloat height = imageBounds.size.height;

CGFloat padding = 0;

width + = padding;
height + = padding;

float sx = self.bounds.size.width / width;
float sy = self.bounds.size.height / height;

CGContextSetTextMatrix(context,CGAffineTransformIdentity);

CGContextTranslateCTM(context,1,self.bounds.size.height);
CGContextScaleCTM(context,1,-1);
CGContextScaleCTM(context,sx,sy);

CGContextSetTextPosition(context,-imageBounds.origin.x + padding / 2,-imageBounds.origin.y + padding / 2);

CTLineDraw(line,context);
CFRelease(line);

$ b - (NSAttributedString *)generateAttributedString:(NSString *)string
{

CTFontRef helv = CTFontCreateWithName(CFSTR(Helvetica-Bold ),20,NULL);
CGColorRef color = [UIColor blackColor] .CGColor;

NSDictionary * attributesDict = [NSDictionary dictionaryWithObjectsAndKeys:
(id)helv,(NSString *)kCTFontAttributeName,
color,(NSString *)kCTForegroundColorAttributeName,
nil];

NSAttributedString * attrString = [[[[NSMutableAttributedString alloc]
initWithString:string
attributes:attributesDict] autorelease];

return attrString;



$ b

示例:




  CGRect rect = CGRectMake(0,0,50,280); 
MyCTLabel * label = [[MyCTLabel alloc] initWithFrame:rect];
label.backgroundColor = [UIColor whiteColor];
[self addSubview:label];


解决方案

您可以尝试CoreText。得到一个 CTFramesetter ,计算它的矩形,然后计算将该矩形压缩到所需边界所需的仿射变换,并将其设置为CTM。然后当你画出文字时,应该以完整的质量适当地拉伸。


Given a rectangular area, I want to render some text using a specific font and have the rendered text fill out the rectangle. As in the image below:

  1. This is not the same as just changing font size
  2. Rendering it as a bitmap and then scale it is not an option (it looks horrible)
  3. Vector graphics is the way to do it

Solution

I came up with the following which seems to work for my purposes. The code draws a single line of text scaling to fill the bounds. Subclass UIView and replace drawRect as follows.

- (void)drawRect:(CGRect)rect 
{
    [self drawScaledString:@"Abcde"]; 
}

- (void)drawScaledString:(NSString *)string
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);

    NSAttributedString *attrString = [self generateAttributedString:string];

    CFAttributedStringSetAttribute((CFMutableAttributedStringRef)attrString, CFRangeMake(0, string.length), 
                                   kCTForegroundColorAttributeName, [UIColor redColor].CGColor);

    CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef) attrString);

    // CTLineGetTypographicBounds doesn't give correct values, 
    // using GetImageBounds instead
    CGRect imageBounds = CTLineGetImageBounds(line, context);
    CGFloat width = imageBounds.size.width;
    CGFloat height = imageBounds.size.height;

    CGFloat padding = 0;

    width += padding;
    height += padding;

    float sx = self.bounds.size.width / width;
    float sy = self.bounds.size.height / height;

    CGContextSetTextMatrix(context, CGAffineTransformIdentity);

    CGContextTranslateCTM(context, 1, self.bounds.size.height);
    CGContextScaleCTM(context, 1, -1);
    CGContextScaleCTM(context, sx, sy);

    CGContextSetTextPosition(context, -imageBounds.origin.x + padding/2, -imageBounds.origin.y + padding/2);

    CTLineDraw(line, context);
    CFRelease(line);
}

- (NSAttributedString *)generateAttributedString:(NSString *)string
{

    CTFontRef helv = CTFontCreateWithName(CFSTR("Helvetica-Bold"),20, NULL);
    CGColorRef color = [UIColor blackColor].CGColor;

    NSDictionary *attributesDict = [NSDictionary dictionaryWithObjectsAndKeys:
                                    (id)helv, (NSString *)kCTFontAttributeName,
                                    color, (NSString *)kCTForegroundColorAttributeName,
                                    nil];

    NSAttributedString *attrString = [[[NSMutableAttributedString alloc]
                                   initWithString:string
                                        attributes:attributesDict] autorelease];

    return attrString;
}

Example usage:

CGRect rect = CGRectMake(0, 0, 50, 280);
MyCTLabel *label = [[MyCTLabel alloc] initWithFrame:rect];
label.backgroundColor = [UIColor whiteColor]; 
[self addSubview:label];

解决方案

You could try CoreText. Get a CTFramesetter, calculate its rect, then calculate the affine transform necessary to compress that rect into the bounds you want and set that as the CTM. Then when you draw the text, it should stretch it appropriately at full quality.

这篇关于如何在iOS中渲染拉伸文本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆