![]() |
API 0.9.5
|
00001 /* 00002 * CPFont.j 00003 * AppKit 00004 * 00005 * Created by Francisco Tolmasky. 00006 * Copyright 2008, 280 North, Inc. 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 00023 00024 00025 CPFontDefaultSystemFontFace = @"Arial, sans-serif"; 00026 CPFontDefaultSystemFontSize = 12; 00027 00028 var _CPFonts = {}, 00029 _CPFontSystemFontFace = CPFontDefaultSystemFontFace, 00030 _CPFontSystemFontSize = 12, 00031 _CPFontFallbackFaces = CPFontDefaultSystemFontFace.split(", "), 00032 _CPFontStripRegExp = new RegExp("(^\\s*[\"']?|[\"']?\\s*$)", "g"); 00033 00034 00035 #define _CPFontNormalizedNames(aName) _CPFontNormalizedNameArray(aName).join(", ") 00036 #define _CPCachedFont(aName, aSize, isBold, isItalic) _CPFonts[_CPFontCreateCSSString(_CPFontNormalizedNames(aName), aSize, isBold, isItalic)] 00037 00069 @implementation CPFont : CPObject 00070 { 00071 CPString _name; 00072 float _size; 00073 float _ascender; 00074 float _descender; 00075 float _lineHeight; 00076 BOOL _isBold; 00077 BOOL _isItalic; 00078 00079 CPString _cssString; 00080 } 00081 00082 + (void)initialize 00083 { 00084 var systemFontFace = [[CPBundle mainBundle] objectForInfoDictionaryKey:@"CPSystemFontFace"]; 00085 00086 if (!systemFontFace) 00087 systemFontFace = [[CPBundle bundleForClass:[CPView class]] objectForInfoDictionaryKey:@"CPSystemFontFace"]; 00088 00089 if (systemFontFace) 00090 [self setSystemFontFace:systemFontFace]; 00091 00092 var systemFontSize = [[CPBundle mainBundle] objectForInfoDictionaryKey:@"CPSystemFontSize"]; 00093 00094 if (!systemFontSize) 00095 systemFontSize = [[CPBundle bundleForClass:[CPView class]] objectForInfoDictionaryKey:@"CPSystemFontSize"]; 00096 00097 if (systemFontSize) 00098 _CPFontSystemFontSize = systemFontSize; 00099 } 00100 00104 + (CPString)systemFontFace 00105 { 00106 return _CPFontSystemFontFace; 00107 } 00108 00112 + (CPString)setSystemFontFace:(CPString)aFace 00113 { 00114 _CPFontSystemFontFace = _CPFontNormalizedNames(aFace); 00115 } 00116 00120 + (float)systemFontSize 00121 { 00122 return _CPFontSystemFontSize; 00123 } 00124 00128 + (float)setSystemFontSize:(float)size 00129 { 00130 if (size > 0) 00131 _CPFontSystemFontSize = size; 00132 } 00133 00140 + (CPFont)fontWithName:(CPString)aName size:(float)aSize 00141 { 00142 return _CPCachedFont(aName, aSize, NO, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:NO italic:NO]; 00143 } 00144 00152 + (CPFont)fontWithName:(CPString)aName size:(float)aSize italic:(BOOL)italic 00153 { 00154 return _CPCachedFont(aName, aSize, NO, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:NO italic:italic]; 00155 } 00156 00163 + (CPFont)boldFontWithName:(CPString)aName size:(float)aSize 00164 { 00165 return _CPCachedFont(aName, aSize, YES, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:YES italic:NO]; 00166 } 00167 00175 + (CPFont)boldFontWithName:(CPString)aName size:(float)aSize italic:(BOOL)italic 00176 { 00177 return _CPCachedFont(aName, aSize, NO, NO) || [[CPFont alloc] _initWithName:aName size:aSize bold:YES italic:italic]; 00178 } 00179 00185 + (CPFont)systemFontOfSize:(CPSize)aSize 00186 { 00187 return _CPCachedFont(_CPFontSystemFontFace, aSize, NO, NO) || [[CPFont alloc] _initWithName:_CPFontSystemFontFace size:aSize bold:NO italic:NO]; 00188 } 00189 00195 + (CPFont)boldSystemFontOfSize:(CPSize)aSize 00196 { 00197 return _CPCachedFont(_CPFontSystemFontFace, aSize, YES, NO) || [[CPFont alloc] _initWithName:_CPFontSystemFontFace size:aSize bold:YES italic:NO]; 00198 } 00199 00200 /* FIXME Font Descriptor 00201 @ignore 00202 */ 00203 - (id)_initWithName:(CPString)aName size:(float)aSize bold:(BOOL)isBold 00204 { 00205 return [self _initWithName:aName size:aSize bold:isBold italic:NO]; 00206 } 00207 00208 - (id)_initWithName:(CPString)aName size:(float)aSize bold:(BOOL)isBold italic:(BOOL)isItalic 00209 { 00210 self = [super init]; 00211 00212 if (self) 00213 { 00214 _name = _CPFontNormalizedNames(aName); 00215 _size = aSize; 00216 _ascender = 0; 00217 _descender = 0; 00218 _lineHeight = 0; 00219 _isBold = isBold; 00220 _isItalic = isItalic; 00221 00222 _cssString = _CPFontCreateCSSString(_name, _size, _isBold, _isItalic); 00223 00224 _CPFonts[_cssString] = self; 00225 } 00226 00227 return self; 00228 } 00229 00233 - (float)ascender 00234 { 00235 if (!_ascender) 00236 [self _getMetrics]; 00237 00238 return _ascender; 00239 } 00240 00245 - (float)descender 00246 { 00247 if (!_descender) 00248 [self _getMetrics]; 00249 00250 return _descender; 00251 } 00252 00258 - (float)defaultLineHeightForFont 00259 { 00260 if (!_lineHeight) 00261 [self _getMetrics]; 00262 00263 return _lineHeight; 00264 } 00265 00269 - (float)size 00270 { 00271 return _size; 00272 } 00273 00277 - (CPString)cssString 00278 { 00279 return _cssString; 00280 } 00281 00285 - (CPString)familyName 00286 { 00287 return _name; 00288 } 00289 00290 - (BOOL)isEqual:(id)anObject 00291 { 00292 return [anObject isKindOfClass:[CPFont class]] && [anObject cssString] === _cssString; 00293 } 00294 00295 - (CPString)description 00296 { 00297 return [CPString stringWithFormat:@"%@ %@", [super description], [self cssString]]; 00298 } 00299 00300 - (id)copy 00301 { 00302 return [[CPFont alloc] _initWithName:_name size:_size bold:_isBold italic:_isItalic]; 00303 } 00304 00305 - (void)_getMetrics 00306 { 00307 var metrics = [CPString metricsOfFont:self]; 00308 00309 _ascender = [metrics objectForKey:@"ascender"]; 00310 _descender = [metrics objectForKey:@"descender"]; 00311 _lineHeight = [metrics objectForKey:@"lineHeight"]; 00312 } 00313 00314 @end 00315 00316 var CPFontNameKey = @"CPFontNameKey", 00317 CPFontSizeKey = @"CPFontSizeKey", 00318 CPFontIsBoldKey = @"CPFontIsBoldKey", 00319 CPFontIsItalicKey = @"CPFontIsItalicKey"; 00320 00321 @implementation CPFont (CPCoding) 00322 00328 - (id)initWithCoder:(CPCoder)aCoder 00329 { 00330 var fontName = [aCoder decodeObjectForKey:CPFontNameKey], 00331 size = [aCoder decodeFloatForKey:CPFontSizeKey], 00332 isBold = [aCoder decodeBoolForKey:CPFontIsBoldKey], 00333 isItalic = [aCoder decodeBoolForKey:CPFontIsItalicKey]; 00334 00335 return [self _initWithName:fontName size:size bold:isBold italic:isItalic]; 00336 } 00337 00342 - (void)encodeWithCoder:(CPCoder)aCoder 00343 { 00344 [aCoder encodeObject:_name forKey:CPFontNameKey]; 00345 [aCoder encodeFloat:_size forKey:CPFontSizeKey]; 00346 [aCoder encodeBool:_isBold forKey:CPFontIsBoldKey]; 00347 [aCoder encodeBool:_isItalic forKey:CPFontIsItalicKey]; 00348 } 00349 00350 @end 00351 00352 00353 // aName must be normalized 00354 var _CPFontCreateCSSString = function(aName, aSize, isBold, isItalic) 00355 { 00356 var properties = (isItalic ? "italic " : "") + (isBold ? "bold " : "") + aSize + "px "; 00357 00358 return properties + _CPFontConcatNameWithFallback(aName); 00359 }; 00360 00361 var _CPFontConcatNameWithFallback = function(aName) 00362 { 00363 var names = _CPFontNormalizedNameArray(aName), 00364 fallbackFaces = _CPFontFallbackFaces.slice(0); 00365 00366 // Remove the fallback names used in the names passed in 00367 for (var i = 0; i < names.length; ++i) 00368 { 00369 for (var j = 0; j < fallbackFaces.length; ++j) 00370 { 00371 if (names[i].toLowerCase() === fallbackFaces[j].toLowerCase()) 00372 { 00373 fallbackFaces.splice(j, 1); 00374 break; 00375 } 00376 } 00377 00378 if (names[i].indexOf(" ") > 0) 00379 names[i] = '"' + names[i] + '"'; 00380 } 00381 00382 return names.concat(fallbackFaces).join(", "); 00383 }; 00384 00385 var _CPFontNormalizedNameArray = function(aName) 00386 { 00387 var names = aName.split(","); 00388 00389 for (var i = 0; i < names.length; ++i) 00390 names[i] = names[i].replace(_CPFontStripRegExp, ""); 00391 00392 return names; 00393 }; 00394 00395 @implementation CPFont (CPSynthesizedAccessors) 00396 00400 - (BOOL)isBold 00401 { 00402 return _isBold; 00403 } 00404 00408 - (BOOL)isItalic 00409 { 00410 return _isItalic; 00411 } 00412 00413 @end