From 9cd57b731ab1c666d4a1cb725538fdc137763d12 Mon Sep 17 00:00:00 2001 From: Starla Insigna Date: Sat, 30 Jul 2011 11:19:14 -0400 Subject: Initial commit (version 0.2.1) --- libs/FontLabel/ZFont.m | 170 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100755 libs/FontLabel/ZFont.m (limited to 'libs/FontLabel/ZFont.m') diff --git a/libs/FontLabel/ZFont.m b/libs/FontLabel/ZFont.m new file mode 100755 index 0000000..793b13a --- /dev/null +++ b/libs/FontLabel/ZFont.m @@ -0,0 +1,170 @@ +// +// ZFont.m +// FontLabel +// +// Created by Kevin Ballard on 7/2/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 "ZFont.h" + +@interface ZFont () +@property (nonatomic, readonly) CGFloat ratio; +- (NSString *)copyNameTableEntryForID:(UInt16)nameID; +@end + +@implementation ZFont +@synthesize cgFont=_cgFont, pointSize=_pointSize, ratio=_ratio; + ++ (ZFont *)fontWithCGFont:(CGFontRef)cgFont size:(CGFloat)fontSize { + return [[[self alloc] initWithCGFont:cgFont size:fontSize] autorelease]; +} + ++ (ZFont *)fontWithUIFont:(UIFont *)uiFont { + NSParameterAssert(uiFont != nil); + CGFontRef cgFont = CGFontCreateWithFontName((CFStringRef)uiFont.fontName); + ZFont *zFont = [[self alloc] initWithCGFont:cgFont size:uiFont.pointSize]; + CGFontRelease(cgFont); + return [zFont autorelease]; +} + +- (id)initWithCGFont:(CGFontRef)cgFont size:(CGFloat)fontSize { + if ((self = [super init])) { + _cgFont = CGFontRetain(cgFont); + _pointSize = fontSize; + _ratio = fontSize/CGFontGetUnitsPerEm(cgFont); + } + return self; +} + +- (id)init { + NSAssert(NO, @"-init is not valid for ZFont"); + return nil; +} + +- (CGFloat)ascender { + return ceilf(self.ratio * CGFontGetAscent(self.cgFont)); +} + +- (CGFloat)descender { + return floorf(self.ratio * CGFontGetDescent(self.cgFont)); +} + +- (CGFloat)leading { + return (self.ascender - self.descender); +} + +- (CGFloat)capHeight { + return ceilf(self.ratio * CGFontGetCapHeight(self.cgFont)); +} + +- (CGFloat)xHeight { + return ceilf(self.ratio * CGFontGetXHeight(self.cgFont)); +} + +- (NSString *)familyName { + if (_familyName == nil) { + _familyName = [self copyNameTableEntryForID:1]; + } + return _familyName; +} + +- (NSString *)fontName { + if (_fontName == nil) { + _fontName = [self copyNameTableEntryForID:4]; + } + return _fontName; +} + +- (NSString *)postScriptName { + if (_postScriptName == nil) { + _postScriptName = [self copyNameTableEntryForID:6]; + } + return _postScriptName; +} + +- (ZFont *)fontWithSize:(CGFloat)fontSize { + if (fontSize == self.pointSize) return self; + NSParameterAssert(fontSize > 0.0); + return [[[ZFont alloc] initWithCGFont:self.cgFont size:fontSize] autorelease]; +} + +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[ZFont class]]) return NO; + ZFont *font = (ZFont *)object; + return (font.cgFont == self.cgFont && font.pointSize == self.pointSize); +} + +- (NSString *)copyNameTableEntryForID:(UInt16)aNameID { + CFDataRef nameTable = CGFontCopyTableForTag(self.cgFont, 'name'); + NSAssert1(nameTable != NULL, @"CGFontCopyTableForTag returned NULL for 'name' tag in font %@", + [(id)CFCopyDescription(self.cgFont) autorelease]); + const UInt8 * const bytes = CFDataGetBytePtr(nameTable); + NSAssert1(OSReadBigInt16(bytes, 0) == 0, @"name table for font %@ has bad version number", + [(id)CFCopyDescription(self.cgFont) autorelease]); + const UInt16 count = OSReadBigInt16(bytes, 2); + const UInt16 stringOffset = OSReadBigInt16(bytes, 4); + const UInt8 * const nameRecords = &bytes[6]; + UInt16 nameLength = 0; + UInt16 nameOffset = 0; + NSStringEncoding encoding = 0; + for (UInt16 idx = 0; idx < count; idx++) { + const uintptr_t recordOffset = 12 * idx; + const UInt16 nameID = OSReadBigInt16(nameRecords, recordOffset + 6); + if (nameID != aNameID) continue; + const UInt16 platformID = OSReadBigInt16(nameRecords, recordOffset + 0); + const UInt16 platformSpecificID = OSReadBigInt16(nameRecords, recordOffset + 2); + encoding = 0; + // for now, we only support a subset of encodings + switch (platformID) { + case 0: // Unicode + encoding = NSUTF16StringEncoding; + break; + case 1: // Macintosh + switch (platformSpecificID) { + case 0: + encoding = NSMacOSRomanStringEncoding; + break; + } + case 3: // Microsoft + switch (platformSpecificID) { + case 1: + encoding = NSUTF16StringEncoding; + break; + } + } + if (encoding == 0) continue; + nameLength = OSReadBigInt16(nameRecords, recordOffset + 8); + nameOffset = OSReadBigInt16(nameRecords, recordOffset + 10); + break; + } + NSString *result = nil; + if (nameOffset > 0) { + const UInt8 *nameBytes = &bytes[stringOffset + nameOffset]; + result = [[NSString alloc] initWithBytes:nameBytes length:nameLength encoding:encoding]; + } + CFRelease(nameTable); + return result; +} + +- (void)dealloc { + CGFontRelease(_cgFont); + [_familyName release]; + [_fontName release]; + [_postScriptName release]; + [super dealloc]; +} +@end -- cgit 1.4.1