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:
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];
The font-stretch property allows you to make text narrower (condensed) or wider (expanded). Note: Some fonts provide additional faces; condensed faces and expanded faces. For these fonts, you can use the font-stretch property to select a normal, condensed, or expanded font face.
You can set the UILabel transform property and scale the width:
[myLabel sizeToFit];
myLabel.transform = CGAffineTransformMakeScale(0.5, 1.0);
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With