PageRenderTime 44ms CodeModel.GetById 15ms app.highlight 26ms RepoModel.GetById 1ms app.codeStats 0ms

/libs/FontLabel/FontLabel.m

http://github.com/kstenerud/ObjectAL-for-iPhone
Objective C | 186 lines | 145 code | 17 blank | 24 comment | 37 complexity | 504ddd4e16404cdc691a2b519e4feab9 MD5 | raw file
  1//
  2//  FontLabel.m
  3//  FontLabel
  4//
  5//  Created by Kevin Ballard on 5/8/09.
  6//  Copyright Š 2009 Zynga Game Networks
  7//
  8//
  9// Licensed under the Apache License, Version 2.0 (the "License");
 10// you may not use this file except in compliance with the License.
 11// You may obtain a copy of the License at
 12//
 13// http://www.apache.org/licenses/LICENSE-2.0
 14//
 15// Unless required by applicable law or agreed to in writing, software
 16// distributed under the License is distributed on an "AS IS" BASIS,
 17// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 18// See the License for the specific language governing permissions and
 19// limitations under the License.
 20//
 21
 22#import "FontLabel.h"
 23#import "FontManager.h"
 24#import "FontLabelStringDrawing.h"
 25#import "ZFont.h"
 26
 27@interface ZFont (ZFontPrivate)
 28@property (nonatomic, readonly) CGFloat ratio;
 29@end
 30
 31@implementation FontLabel
 32@synthesize zFont;
 33@synthesize zAttributedText;
 34
 35- (id)initWithFrame:(CGRect)frame fontName:(NSString *)fontName pointSize:(CGFloat)pointSize {
 36	return [self initWithFrame:frame zFont:[[FontManager sharedManager] zFontWithName:fontName pointSize:pointSize]];
 37}
 38
 39- (id)initWithFrame:(CGRect)frame zFont:(ZFont *)font {
 40	if ((self = [super initWithFrame:frame])) {
 41		zFont = [font retain];
 42	}
 43	return self;
 44}
 45
 46- (id)initWithFrame:(CGRect)frame font:(CGFontRef)font pointSize:(CGFloat)pointSize {
 47	return [self initWithFrame:frame zFont:[ZFont fontWithCGFont:font size:pointSize]];
 48}
 49
 50- (CGFontRef)cgFont {
 51	return self.zFont.cgFont;
 52}
 53
 54- (void)setCGFont:(CGFontRef)font {
 55	if (self.zFont.cgFont != font) {
 56		self.zFont = [ZFont fontWithCGFont:font size:self.zFont.pointSize];
 57	}
 58}
 59
 60- (CGFloat)pointSize {
 61	return self.zFont.pointSize;
 62}
 63
 64- (void)setPointSize:(CGFloat)pointSize {
 65	if (self.zFont.pointSize != pointSize) {
 66		self.zFont = [ZFont fontWithCGFont:self.zFont.cgFont size:pointSize];
 67	}
 68}
 69
 70- (void)setZAttributedText:(ZAttributedString *)attStr {
 71	if (zAttributedText != attStr) {
 72		[zAttributedText release];
 73		zAttributedText = [attStr copy];
 74		[self setNeedsDisplay];
 75	}
 76}
 77
 78- (void)drawTextInRect:(CGRect)rect {
 79	if (self.zFont == NULL && self.zAttributedText == nil) {
 80		[super drawTextInRect:rect];
 81		return;
 82	}
 83	
 84	if (self.zAttributedText == nil) {
 85		// this method is documented as setting the text color for us, but that doesn't appear to be the case
 86		if (self.highlighted) {
 87			[(self.highlightedTextColor ?: [UIColor whiteColor]) setFill];
 88		} else {
 89			[(self.textColor ?: [UIColor blackColor]) setFill];
 90		}
 91		
 92		ZFont *actualFont = self.zFont;
 93		CGSize origSize = rect.size;
 94		if (self.numberOfLines == 1) {
 95			origSize.height = actualFont.leading;
 96			CGPoint point = CGPointMake(rect.origin.x,
 97										rect.origin.y + roundf(((rect.size.height - actualFont.leading) / 2.0f)));
 98			CGSize size = [self.text sizeWithZFont:actualFont];
 99			if (self.adjustsFontSizeToFitWidth && self.minimumFontSize < actualFont.pointSize) {
100				if (size.width > origSize.width) {
101					CGFloat desiredRatio = (origSize.width * actualFont.ratio) / size.width;
102					CGFloat desiredPointSize = desiredRatio * actualFont.pointSize / actualFont.ratio;
103					actualFont = [actualFont fontWithSize:MAX(MAX(desiredPointSize, self.minimumFontSize), 1.0f)];
104					size = [self.text sizeWithZFont:actualFont];
105				}
106				if (!CGSizeEqualToSize(origSize, size)) {
107					switch (self.baselineAdjustment) {
108						case UIBaselineAdjustmentAlignCenters:
109							point.y += roundf((origSize.height - size.height) / 2.0f);
110							break;
111						case UIBaselineAdjustmentAlignBaselines:
112							point.y += (self.zFont.ascender - actualFont.ascender);
113							break;
114						case UIBaselineAdjustmentNone:
115							break;
116					}
117				}
118			}
119			size.width = MIN(size.width, origSize.width);
120			// adjust the point for alignment
121			switch (self.textAlignment) {
122				case UITextAlignmentLeft:
123					break;
124				case UITextAlignmentCenter:
125					point.x += (origSize.width - size.width) / 2.0f;
126					break;
127				case UITextAlignmentRight:
128					point.x += origSize.width - size.width;
129					break;
130			}
131			[self.text drawAtPoint:point forWidth:size.width withZFont:actualFont lineBreakMode:self.lineBreakMode];
132		} else {
133			CGSize size = [self.text sizeWithZFont:actualFont constrainedToSize:origSize lineBreakMode:self.lineBreakMode numberOfLines:self.numberOfLines];
134			CGPoint point = rect.origin;
135			point.y += roundf((rect.size.height - size.height) / 2.0f);
136			rect = (CGRect){point, CGSizeMake(rect.size.width, size.height)};
137			[self.text drawInRect:rect withZFont:actualFont lineBreakMode:self.lineBreakMode alignment:self.textAlignment numberOfLines:self.numberOfLines];
138		}
139	} else {
140		ZAttributedString *attStr = self.zAttributedText;
141		if (self.highlighted) {
142			// modify the string to change the base color
143			ZMutableAttributedString *mutStr = [[attStr mutableCopy] autorelease];
144			NSRange activeRange = NSMakeRange(0, attStr.length);
145			while (activeRange.length > 0) {
146				NSRange effective;
147				UIColor *color = [attStr attribute:ZForegroundColorAttributeName atIndex:activeRange.location
148							 longestEffectiveRange:&effective inRange:activeRange];
149				if (color == nil) {
150					[mutStr addAttribute:ZForegroundColorAttributeName value:[UIColor whiteColor] range:effective];
151				}
152				activeRange.location += effective.length, activeRange.length -= effective.length;
153			}
154			attStr = mutStr;
155		}
156		CGSize size = [attStr sizeConstrainedToSize:rect.size lineBreakMode:self.lineBreakMode numberOfLines:self.numberOfLines];
157		CGPoint point = rect.origin;
158		point.y += roundf((rect.size.height - size.height) / 2.0f);
159		rect = (CGRect){point, CGSizeMake(rect.size.width, size.height)};
160		[attStr drawInRect:rect withLineBreakMode:self.lineBreakMode alignment:self.textAlignment numberOfLines:self.numberOfLines];
161	}
162}
163
164- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines {
165	if (self.zFont == NULL && self.zAttributedText == nil) {
166		return [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];
167	}
168	
169	if (numberOfLines == 1) {
170		// if numberOfLines == 1 we need to use the version that converts spaces
171		CGSize size = [self.text sizeWithZFont:self.zFont];
172		bounds.size.width = MIN(bounds.size.width, size.width);
173		bounds.size.height = MIN(bounds.size.height, size.height);
174	} else {
175		if (numberOfLines > 0) bounds.size.height = MIN(bounds.size.height, self.zFont.leading * numberOfLines);
176		bounds.size = [self.text sizeWithZFont:self.zFont constrainedToSize:bounds.size lineBreakMode:self.lineBreakMode];
177	}
178	return bounds;
179}
180
181- (void)dealloc {
182	[zFont release];
183	[zAttributedText release];
184	[super dealloc];
185}
186@end