diff options
Diffstat (limited to 'libs/FontLabel/FontLabel.m')
-rwxr-xr-x | libs/FontLabel/FontLabel.m | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/libs/FontLabel/FontLabel.m b/libs/FontLabel/FontLabel.m new file mode 100755 index 0000000..58975b1 --- /dev/null +++ b/libs/FontLabel/FontLabel.m | |||
@@ -0,0 +1,195 @@ | |||
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; | ||
172 | if (self.zAttributedText == nil) { | ||
173 | size = [self.text sizeWithZFont:self.zFont]; | ||
174 | } else { | ||
175 | size = [self.zAttributedText size]; | ||
176 | } | ||
177 | bounds.size.width = MIN(bounds.size.width, size.width); | ||
178 | bounds.size.height = MIN(bounds.size.height, size.height); | ||
179 | } else { | ||
180 | if (numberOfLines > 0) bounds.size.height = MIN(bounds.size.height, self.zFont.leading * numberOfLines); | ||
181 | if (self.zAttributedText == nil) { | ||
182 | bounds.size = [self.text sizeWithZFont:self.zFont constrainedToSize:bounds.size lineBreakMode:self.lineBreakMode]; | ||
183 | } else { | ||
184 | bounds.size = [self.zAttributedText sizeConstrainedToSize:bounds.size lineBreakMode:self.lineBreakMode]; | ||
185 | } | ||
186 | } | ||
187 | return bounds; | ||
188 | } | ||
189 | |||
190 | - (void)dealloc { | ||
191 | [zFont release]; | ||
192 | [zAttributedText release]; | ||
193 | [super dealloc]; | ||
194 | } | ||
195 | @end | ||