API 0.9.5
AppKit/CPFont.j
Go to the documentation of this file.
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
 All Classes Files Functions Variables Defines