How to render stretched text in iOS?

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:

enter image description here

  • iOS: is Core Graphics implemented on top of OpenGL?
  • drawing with clear color on UIView (cutting a hole) in static method
  • How to directly update pixels - with CGImage and direct CGDataProvider
  • Load PDF from documents directory - iPhone
  • How to render view into image faster?
  • Write PDF text to a PDFContext in iOS
    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];
    

    3 Solutions Collect From Internet About “How to render stretched text in iOS?”

    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.

    You can set the UILabel transform property and scale the width:

    [myLabel sizeToFit];
    myLabel.transform = CGAffineTransformMakeScale(0.5, 1.0);
    

    you can also try with the UILabel’s @property(nonatomic) BOOL adjustsFontSizeToFitWidth and @property minimumFontSize

    Initially you can set the much higher value for font property and also initialize the minimumFontSize with a minimum font value.