2011-07-29 10:15:10 +08:00
|
|
|
//
|
|
|
|
// FontLabel.m
|
|
|
|
// FontLabel
|
|
|
|
//
|
|
|
|
// Created by Kevin Ballard on 5/8/09.
|
|
|
|
// Copyright © 2009 Zynga Game Networks
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
//
|
|
|
|
|
|
|
|
#import "FontLabel.h"
|
|
|
|
#import "FontManager.h"
|
|
|
|
#import "FontLabelStringDrawing.h"
|
|
|
|
#import "ZFont.h"
|
|
|
|
|
|
|
|
@interface ZFont (ZFontPrivate)
|
|
|
|
@property (nonatomic, readonly) CGFloat ratio;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation FontLabel
|
|
|
|
@synthesize zFont;
|
|
|
|
@synthesize zAttributedText;
|
|
|
|
|
|
|
|
- (id)initWithFrame:(CGRect)frame fontName:(NSString *)fontName pointSize:(CGFloat)pointSize {
|
2012-04-19 14:35:52 +08:00
|
|
|
return [self initWithFrame:frame zFont:[[FontManager sharedManager] zFontWithName:fontName pointSize:pointSize]];
|
2011-07-29 10:15:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
- (id)initWithFrame:(CGRect)frame zFont:(ZFont *)font {
|
2012-04-19 14:35:52 +08:00
|
|
|
if ((self = [super initWithFrame:frame])) {
|
|
|
|
zFont = [font retain];
|
|
|
|
}
|
|
|
|
return self;
|
2011-07-29 10:15:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
- (id)initWithFrame:(CGRect)frame font:(CGFontRef)font pointSize:(CGFloat)pointSize {
|
2012-04-19 14:35:52 +08:00
|
|
|
return [self initWithFrame:frame zFont:[ZFont fontWithCGFont:font size:pointSize]];
|
2011-07-29 10:15:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
- (CGFontRef)cgFont {
|
2012-04-19 14:35:52 +08:00
|
|
|
return self.zFont.cgFont;
|
2011-07-29 10:15:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setCGFont:(CGFontRef)font {
|
2012-04-19 14:35:52 +08:00
|
|
|
if (self.zFont.cgFont != font) {
|
|
|
|
self.zFont = [ZFont fontWithCGFont:font size:self.zFont.pointSize];
|
|
|
|
}
|
2011-07-29 10:15:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
- (CGFloat)pointSize {
|
2012-04-19 14:35:52 +08:00
|
|
|
return self.zFont.pointSize;
|
2011-07-29 10:15:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setPointSize:(CGFloat)pointSize {
|
2012-04-19 14:35:52 +08:00
|
|
|
if (self.zFont.pointSize != pointSize) {
|
|
|
|
self.zFont = [ZFont fontWithCGFont:self.zFont.cgFont size:pointSize];
|
|
|
|
}
|
2011-07-29 10:15:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setZAttributedText:(ZAttributedString *)attStr {
|
2012-04-19 14:35:52 +08:00
|
|
|
if (zAttributedText != attStr) {
|
|
|
|
[zAttributedText release];
|
|
|
|
zAttributedText = [attStr copy];
|
|
|
|
[self setNeedsDisplay];
|
|
|
|
}
|
2011-07-29 10:15:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)drawTextInRect:(CGRect)rect {
|
2012-04-19 14:35:52 +08:00
|
|
|
if (self.zFont == NULL && self.zAttributedText == nil) {
|
|
|
|
[super drawTextInRect:rect];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (self.zAttributedText == nil) {
|
|
|
|
// this method is documented as setting the text color for us, but that doesn't appear to be the case
|
|
|
|
if (self.highlighted) {
|
|
|
|
[(self.highlightedTextColor ?: [UIColor whiteColor]) setFill];
|
|
|
|
} else {
|
|
|
|
[(self.textColor ?: [UIColor blackColor]) setFill];
|
|
|
|
}
|
|
|
|
|
|
|
|
ZFont *actualFont = self.zFont;
|
|
|
|
CGSize origSize = rect.size;
|
|
|
|
if (self.numberOfLines == 1) {
|
|
|
|
origSize.height = actualFont.leading;
|
|
|
|
CGPoint point = CGPointMake(rect.origin.x,
|
|
|
|
rect.origin.y + roundf(((rect.size.height - actualFont.leading) / 2.0f)));
|
|
|
|
CGSize size = [self.text sizeWithZFont:actualFont];
|
|
|
|
if (self.adjustsFontSizeToFitWidth && self.minimumFontSize < actualFont.pointSize) {
|
|
|
|
if (size.width > origSize.width) {
|
|
|
|
CGFloat desiredRatio = (origSize.width * actualFont.ratio) / size.width;
|
|
|
|
CGFloat desiredPointSize = desiredRatio * actualFont.pointSize / actualFont.ratio;
|
|
|
|
actualFont = [actualFont fontWithSize:MAX(MAX(desiredPointSize, self.minimumFontSize), 1.0f)];
|
|
|
|
size = [self.text sizeWithZFont:actualFont];
|
|
|
|
}
|
|
|
|
if (!CGSizeEqualToSize(origSize, size)) {
|
|
|
|
switch (self.baselineAdjustment) {
|
|
|
|
case UIBaselineAdjustmentAlignCenters:
|
|
|
|
point.y += roundf((origSize.height - size.height) / 2.0f);
|
|
|
|
break;
|
|
|
|
case UIBaselineAdjustmentAlignBaselines:
|
|
|
|
point.y += (self.zFont.ascender - actualFont.ascender);
|
|
|
|
break;
|
|
|
|
case UIBaselineAdjustmentNone:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
size.width = MIN(size.width, origSize.width);
|
|
|
|
// adjust the point for alignment
|
|
|
|
switch (self.textAlignment) {
|
|
|
|
case UITextAlignmentLeft:
|
|
|
|
break;
|
|
|
|
case UITextAlignmentCenter:
|
|
|
|
point.x += (origSize.width - size.width) / 2.0f;
|
|
|
|
break;
|
|
|
|
case UITextAlignmentRight:
|
|
|
|
point.x += origSize.width - size.width;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
[self.text drawAtPoint:point forWidth:size.width withZFont:actualFont lineBreakMode:self.lineBreakMode];
|
|
|
|
} else {
|
|
|
|
CGSize size = [self.text sizeWithZFont:actualFont constrainedToSize:origSize lineBreakMode:self.lineBreakMode numberOfLines:self.numberOfLines];
|
|
|
|
CGPoint point = rect.origin;
|
|
|
|
point.y += roundf((rect.size.height - size.height) / 2.0f);
|
|
|
|
rect = (CGRect){point, CGSizeMake(rect.size.width, size.height)};
|
|
|
|
[self.text drawInRect:rect withZFont:actualFont lineBreakMode:self.lineBreakMode alignment:self.textAlignment numberOfLines:self.numberOfLines];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ZAttributedString *attStr = self.zAttributedText;
|
|
|
|
if (self.highlighted) {
|
|
|
|
// modify the string to change the base color
|
|
|
|
ZMutableAttributedString *mutStr = [[attStr mutableCopy] autorelease];
|
|
|
|
NSRange activeRange = NSMakeRange(0, attStr.length);
|
|
|
|
while (activeRange.length > 0) {
|
|
|
|
NSRange effective;
|
|
|
|
UIColor *color = [attStr attribute:ZForegroundColorAttributeName atIndex:activeRange.location
|
|
|
|
longestEffectiveRange:&effective inRange:activeRange];
|
|
|
|
if (color == nil) {
|
|
|
|
[mutStr addAttribute:ZForegroundColorAttributeName value:[UIColor whiteColor] range:effective];
|
|
|
|
}
|
|
|
|
activeRange.location += effective.length, activeRange.length -= effective.length;
|
|
|
|
}
|
|
|
|
attStr = mutStr;
|
|
|
|
}
|
|
|
|
CGSize size = [attStr sizeConstrainedToSize:rect.size lineBreakMode:self.lineBreakMode numberOfLines:self.numberOfLines];
|
|
|
|
CGPoint point = rect.origin;
|
|
|
|
point.y += roundf((rect.size.height - size.height) / 2.0f);
|
|
|
|
rect = (CGRect){point, CGSizeMake(rect.size.width, size.height)};
|
|
|
|
[attStr drawInRect:rect withLineBreakMode:self.lineBreakMode alignment:self.textAlignment numberOfLines:self.numberOfLines];
|
|
|
|
}
|
2011-07-29 10:15:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines {
|
2012-04-19 14:35:52 +08:00
|
|
|
if (self.zFont == NULL && self.zAttributedText == nil) {
|
|
|
|
return [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (numberOfLines == 1) {
|
|
|
|
// if numberOfLines == 1 we need to use the version that converts spaces
|
|
|
|
CGSize size;
|
|
|
|
if (self.zAttributedText == nil) {
|
|
|
|
size = [self.text sizeWithZFont:self.zFont];
|
|
|
|
} else {
|
|
|
|
size = [self.zAttributedText size];
|
|
|
|
}
|
|
|
|
bounds.size.width = MIN(bounds.size.width, size.width);
|
|
|
|
bounds.size.height = MIN(bounds.size.height, size.height);
|
|
|
|
} else {
|
|
|
|
if (numberOfLines > 0) bounds.size.height = MIN(bounds.size.height, self.zFont.leading * numberOfLines);
|
|
|
|
if (self.zAttributedText == nil) {
|
|
|
|
bounds.size = [self.text sizeWithZFont:self.zFont constrainedToSize:bounds.size lineBreakMode:self.lineBreakMode];
|
|
|
|
} else {
|
|
|
|
bounds.size = [self.zAttributedText sizeConstrainedToSize:bounds.size lineBreakMode:self.lineBreakMode];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return bounds;
|
2011-07-29 10:15:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)dealloc {
|
2012-04-19 14:35:52 +08:00
|
|
|
[zFont release];
|
|
|
|
[zAttributedText release];
|
|
|
|
[super dealloc];
|
2011-07-29 10:15:10 +08:00
|
|
|
}
|
|
|
|
@end
|