axmol/cocos2dx/platform/ios/FontLabel/FontLabel.m

196 lines
7.8 KiB
Objective-C

//
// 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 {
return [self initWithFrame:frame zFont:[[FontManager sharedManager] zFontWithName:fontName pointSize:pointSize]];
}
- (id)initWithFrame:(CGRect)frame zFont:(ZFont *)font {
if ((self = [super initWithFrame:frame])) {
zFont = [font retain];
}
return self;
}
- (id)initWithFrame:(CGRect)frame font:(CGFontRef)font pointSize:(CGFloat)pointSize {
return [self initWithFrame:frame zFont:[ZFont fontWithCGFont:font size:pointSize]];
}
- (CGFontRef)cgFont {
return self.zFont.cgFont;
}
- (void)setCGFont:(CGFontRef)font {
if (self.zFont.cgFont != font) {
self.zFont = [ZFont fontWithCGFont:font size:self.zFont.pointSize];
}
}
- (CGFloat)pointSize {
return self.zFont.pointSize;
}
- (void)setPointSize:(CGFloat)pointSize {
if (self.zFont.pointSize != pointSize) {
self.zFont = [ZFont fontWithCGFont:self.zFont.cgFont size:pointSize];
}
}
- (void)setZAttributedText:(ZAttributedString *)attStr {
if (zAttributedText != attStr) {
[zAttributedText release];
zAttributedText = [attStr copy];
[self setNeedsDisplay];
}
}
- (void)drawTextInRect:(CGRect)rect {
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];
}
}
- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines {
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;
}
- (void)dealloc {
[zFont release];
[zAttributedText release];
[super dealloc];
}
@end