// // FontResolver.h // Tabris // // Created by Jordi Böhme López on 23.07.12. // Copyright (c) 2012 EclipseSource. // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // which accompanies this distribution, and is available at // http://www.eclipse.org/legal/epl-v10.html // #import @interface FontResolver : NSObject +(UIFont*)fontWithDescription:(NSString*)description; @end // // FontResolver.m // Tabris // // Created by Jordi Böhme López on 23.07.12. // Copyright (c) 2012 EclipseSource. // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // which accompanies this distribution, and is available at // http://www.eclipse.org/legal/epl-v10.html // #import "FontResolver.h" #import "FontRegistry.h" @implementation FontResolver NSString *const FONT_FAMILY = @"font-family"; NSString *const FONT_SIZE = @"font-size"; NSString *const FONT_WEIGHT = @"font-weight"; NSString *const FONT_STYLE = @"font-style"; NSString *const FAMILY_SANS_SERIF = @"Helvetica"; NSString *const FAMILY_SERIF = @"Times New Roman"; NSString *const FAMILY_MONOSPACE = @"Courier New"; CGFloat const DEFAULT_FONT_SIZE = 12; #pragma mark - API Methods +(UIFont*)fontWithDescription:(NSString*)description { UIFont *result = nil; CGFloat fontSize = [[self extractSize:description] floatValue]; BOOL isBold = [[self extractWeight:description] boolValue]; BOOL isItalic = [[self extractStyle:description] boolValue]; result = [self computeFont:description forSize:fontSize andBold:isBold andItalic:isItalic]; if( !result ) { result = [self computeFallbackFontForSize:fontSize andBold:isBold andItalic:isItalic]; } return result; } #pragma mark - Internal Methods +(UIFont *)computeFont:(NSString *)description forSize:(CGFloat)size andBold:(BOOL)isBold andItalic:(BOOL)isItalic { UIFont *result = nil; NSString *fontName = [self extractFontName:description forBold:isBold andItalic:isItalic]; if( fontName ) { UIFont *foundFont = [UIFont fontWithName:fontName size:size]; if( foundFont ) { result = foundFont; } } return result; } +(UIFont *)computeFallbackFontForSize:(CGFloat)size andBold:(BOOL)isBold andItalic:(BOOL)isItalic { UIFont *result = nil; if( isBold ) { result = [UIFont boldSystemFontOfSize:size]; } else if( isItalic ) { result = [UIFont italicSystemFontOfSize:size]; } else { result = [UIFont systemFontOfSize:size]; } return result; } +(NSString *)extractFontName:(NSString *)description forBold:(BOOL)isBold andItalic:(BOOL)isItalic { NSString *result = nil; NSString *familyString = [self extractValue:FONT_FAMILY from:description]; NSArray *families = [self splitFamilies:familyString]; for (NSString *family in families) { NSString *foundFamily = [self findFamily:family]; result = [[FontRegistry instance] fontForFamily:foundFamily forBold:isBold andItalic:isItalic]; //replace this with [UIFont fontWithMarkupDescription:] when it's public if( result ) { return result; } } return result; } +(NSArray *)splitFamilies:(NSString *)familiesString { NSMutableArray *result = [NSMutableArray array]; NSArray *families = [familiesString componentsSeparatedByString:@","]; for (NSString *family in families) { [result addObject:[self normalizeFamily:family]]; } return result; } +(NSString *)normalizeFamily:(NSString *)family { NSString *result = trim(family); if( [[result lowercaseString] isEqualToString:@"sans-serif"] ) { result = FAMILY_SANS_SERIF; } else if( [[result lowercaseString] isEqualToString:@"serif"] ) { result = FAMILY_SERIF; } else if( [[result lowercaseString] isEqualToString:@"monospace"] ) { result = FAMILY_MONOSPACE; } return result; } +(NSString *)findFamily:(NSString *)definedFont { NSArray *familyNames = [UIFont familyNames]; for (NSString *familyName in familyNames) { if( [familyName isEqualToString:definedFont] ) { return familyName; } } return nil; } +(NSNumber *)extractSize:(NSString *)description { CGFloat result = DEFAULT_FONT_SIZE; NSString *pixel = [self extractValue:FONT_SIZE from:description]; if( pixel ) { CGFloat px = [pixel floatValue]; result = px; } return [NSNumber numberWithFloat:result]; } +(NSNumber *)extractWeight:(NSString *)description { BOOL result = NO; NSString *foundValue = [self extractValue:FONT_WEIGHT from:description]; if( foundValue && [foundValue isEqualToString:@"bold"] ) { result = YES; } return [NSNumber numberWithBool:result]; } +(NSNumber *)extractStyle:(NSString *)description { BOOL result = NO; NSString *foundValue = [self extractValue:FONT_STYLE from:description]; if( foundValue && [foundValue isEqualToString:@"italic"] ) { result = YES; } return [NSNumber numberWithFloat:result]; } +(NSString *)extractValue:(NSString *)key from:(NSString *)description { NSString *result = nil; NSArray *components = [description componentsSeparatedByString:@";"]; for (NSString *component in components) { NSString *keyValue = trim(component); if( [keyValue hasPrefix:key] ) { result = [keyValue substringFromIndex:[key length]+1]; result = trim(result); } } return result; } NSString * trim(NSString *string) { return [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; } @end