mirror of https://github.com/axmolengine/axmol.git
171 lines
4.8 KiB
Objective-C
171 lines
4.8 KiB
Objective-C
//
|
|
// 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
|