This repository has been archived by the owner on Jun 21, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 122
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ios, macos] Allow specifying multiple fonts or font families for loc…
…al font rendering Removed MGLIdeographicFontFamilyName validation from MGLRendererConfiguration, since mbgl::LocalGlyphRasterizer performs more robust validation. Removed C++ from MGLRendererConfiguration interface, implementation, and tests for simplicity. Pass all the specified font and font family names into mbgl so that mbgl::LocalGlyphRasterizer can form a full font cascade list.
- Loading branch information
Showing
14 changed files
with
287 additions
and
358 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
#import "MGLRendererConfiguration.h" | ||
|
||
#if TARGET_OS_IPHONE | ||
#import <UIKit/UIKit.h> | ||
#else | ||
#import <AppKit/AppKit.h> | ||
#endif | ||
|
||
static NSString * const MGLCollisionBehaviorPre4_0Key = @"MGLCollisionBehaviorPre4_0"; | ||
static NSString * const MGLIdeographicFontFamilyNameKey = @"MGLIdeographicFontFamilyName"; | ||
|
||
@implementation MGLRendererConfiguration | ||
|
||
+ (instancetype)currentConfiguration { | ||
return [[self alloc] init]; | ||
} | ||
|
||
- (const float)scaleFactor { | ||
#if TARGET_OS_IPHONE | ||
return [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale]; | ||
#else | ||
return [NSScreen mainScreen].backingScaleFactor; | ||
#endif | ||
} | ||
|
||
- (nullable NSString *)localFontFamilyName { | ||
id infoDictionaryObject = [NSBundle.mainBundle objectForInfoDictionaryKey:MGLIdeographicFontFamilyNameKey]; | ||
return [self localFontFamilyNameWithInfoDictionaryObject:infoDictionaryObject]; | ||
} | ||
|
||
- (nullable NSString *)localFontFamilyNameWithInfoDictionaryObject:(nullable id)infoDictionaryObject { | ||
if ([infoDictionaryObject isKindOfClass:[NSNumber class]] && ![infoDictionaryObject boolValue]) { | ||
// NO means don’t use local fonts. | ||
return nil; | ||
} else if ([infoDictionaryObject isKindOfClass:[NSString class]]) { | ||
return infoDictionaryObject; | ||
} else if ([infoDictionaryObject isKindOfClass:[NSArray class]]) { | ||
// mbgl::LocalGlyphRasterizer::Impl accepts only a single string, but form a cascade list with one font on each line. | ||
return [infoDictionaryObject componentsJoinedByString:@"\n"]; | ||
} | ||
|
||
#if TARGET_OS_IPHONE | ||
return [UIFont systemFontOfSize:0 weight:UIFontWeightRegular].familyName; | ||
#else | ||
return [NSFont systemFontOfSize:0 weight:NSFontWeightRegular].familyName; | ||
#endif | ||
} | ||
|
||
- (BOOL)perSourceCollisions { | ||
id infoDictionaryObject = [NSBundle.mainBundle objectForInfoDictionaryKey:MGLCollisionBehaviorPre4_0Key]; | ||
return [self perSourceCollisionsWithInfoDictionaryObject:infoDictionaryObject]; | ||
} | ||
|
||
- (BOOL)perSourceCollisionsWithInfoDictionaryObject:(nullable id)infoDictionaryObject { | ||
// Set the collision behaviour. A value set in `NSUserDefaults.standardUserDefaults` | ||
// should override anything in the application's info.plist | ||
if ([NSUserDefaults.standardUserDefaults objectForKey:MGLCollisionBehaviorPre4_0Key]) { | ||
return [NSUserDefaults.standardUserDefaults boolForKey:MGLCollisionBehaviorPre4_0Key]; | ||
} else if ([infoDictionaryObject isKindOfClass:[NSNumber class]] || [infoDictionaryObject isKindOfClass:[NSString class]]) { | ||
// Also support NSString to correspond with the behavior of `-[NSUserDefaults boolForKey:]` | ||
return [infoDictionaryObject boolValue]; | ||
} | ||
return NO; | ||
} | ||
|
||
@end |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
#import <Mapbox/Mapbox.h> | ||
#import <XCTest/XCTest.h> | ||
#import "MGLRendererConfiguration.h" | ||
|
||
static NSString * const MGLRendererConfigurationTests_collisionBehaviorKey = @"MGLCollisionBehaviorPre4_0"; | ||
|
||
@interface MGLRendererConfigurationTests : XCTestCase | ||
@end | ||
|
||
@implementation MGLRendererConfigurationTests | ||
- (void)setUp { | ||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:MGLRendererConfigurationTests_collisionBehaviorKey]; | ||
} | ||
|
||
- (void)tearDown { | ||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:MGLRendererConfigurationTests_collisionBehaviorKey]; | ||
} | ||
|
||
// Emulate what would happen with an Info.plist. | ||
- (void)testSettingMGLCollisionBehaviorPre40 | ||
{ | ||
MGLRendererConfiguration *config = [[MGLRendererConfiguration alloc] init]; | ||
XCTAssertFalse([config perSourceCollisionsWithInfoDictionaryObject:nil]); | ||
XCTAssertFalse([config perSourceCollisionsWithInfoDictionaryObject:@(NO)]); | ||
XCTAssertTrue([config perSourceCollisionsWithInfoDictionaryObject:@(YES)]); | ||
XCTAssertFalse([config perSourceCollisionsWithInfoDictionaryObject:@"NO"]); | ||
XCTAssertTrue([config perSourceCollisionsWithInfoDictionaryObject:@"YES"]); | ||
} | ||
|
||
- (void)testSettingMGLCollisionBehaviorPre40InNSUserDefaults { | ||
{ | ||
XCTAssertNil([[NSUserDefaults standardUserDefaults] objectForKey:MGLRendererConfigurationTests_collisionBehaviorKey]); | ||
MGLRendererConfiguration *config = [MGLRendererConfiguration currentConfiguration]; | ||
XCTAssertFalse(config.perSourceCollisions); | ||
XCTAssertFalse([config perSourceCollisionsWithInfoDictionaryObject:nil]); | ||
} | ||
|
||
[[NSUserDefaults standardUserDefaults] setObject:@(NO) forKey:MGLRendererConfigurationTests_collisionBehaviorKey]; | ||
{ | ||
XCTAssertNotNil([[NSUserDefaults standardUserDefaults] objectForKey:MGLRendererConfigurationTests_collisionBehaviorKey]); | ||
MGLRendererConfiguration *config = [MGLRendererConfiguration currentConfiguration]; | ||
XCTAssertFalse(config.perSourceCollisions); | ||
XCTAssertFalse([config perSourceCollisionsWithInfoDictionaryObject:@(NO)]); | ||
XCTAssertFalse([config perSourceCollisionsWithInfoDictionaryObject:@(YES)]); | ||
} | ||
|
||
[[NSUserDefaults standardUserDefaults] setObject:@(YES) forKey:MGLRendererConfigurationTests_collisionBehaviorKey]; | ||
{ | ||
XCTAssertNotNil([[NSUserDefaults standardUserDefaults] objectForKey:MGLRendererConfigurationTests_collisionBehaviorKey]); | ||
MGLRendererConfiguration *config = [MGLRendererConfiguration currentConfiguration]; | ||
XCTAssert(config.perSourceCollisions); | ||
XCTAssertTrue([config perSourceCollisionsWithInfoDictionaryObject:@(NO)]); | ||
XCTAssertTrue([config perSourceCollisionsWithInfoDictionaryObject:@(YES)]); | ||
} | ||
} | ||
|
||
- (void)testOverridingMGLCollisionBehaviorPre40 { | ||
// Dictionary = NO, NSUserDefaults = YES | ||
{ | ||
[[NSUserDefaults standardUserDefaults] setObject:@(YES) forKey:MGLRendererConfigurationTests_collisionBehaviorKey]; | ||
MGLRendererConfiguration *config = [[MGLRendererConfiguration alloc] init]; | ||
XCTAssert([config perSourceCollisionsWithInfoDictionaryObject:@(NO)]); | ||
} | ||
// Dictionary = YES, NSUserDefaults = NO | ||
{ | ||
[[NSUserDefaults standardUserDefaults] setObject:@(NO) forKey:MGLRendererConfigurationTests_collisionBehaviorKey]; | ||
MGLRendererConfiguration *config = [[MGLRendererConfiguration alloc] init]; | ||
XCTAssertFalse([config perSourceCollisionsWithInfoDictionaryObject:@(YES)]); | ||
} | ||
} | ||
|
||
- (void)testDefaultLocalFontFamilyName { | ||
|
||
MGLRendererConfiguration *config = [[MGLRendererConfiguration alloc] init]; | ||
NSString *localFontFamilyName = config.localFontFamilyName; | ||
|
||
NSString *systemFontFamilyName; | ||
#if TARGET_OS_IPHONE | ||
systemFontFamilyName = [UIFont systemFontOfSize:0 weight:UIFontWeightRegular].familyName; | ||
#else | ||
systemFontFamilyName = [NSFont systemFontOfSize:0 weight:NSFontWeightRegular].familyName; | ||
#endif | ||
|
||
XCTAssertEqualObjects(localFontFamilyName, systemFontFamilyName, @"Default local font family name should match default system font"); | ||
} | ||
|
||
- (void)testSettingMGLIdeographicFontFamilyNameWithPlistValue { | ||
|
||
MGLRendererConfiguration *config = [[MGLRendererConfiguration alloc] init]; | ||
|
||
// `MGLIdeographicFontFamilyName` set to bool value `YES` | ||
{ | ||
NSString *localFontFamilyName = [config localFontFamilyNameWithInfoDictionaryObject:@(YES)]; | ||
|
||
NSString *systemFontFamilyName; | ||
#if TARGET_OS_IPHONE | ||
systemFontFamilyName = [UIFont systemFontOfSize:0 weight:UIFontWeightRegular].familyName; | ||
#else | ||
systemFontFamilyName = [NSFont systemFontOfSize:0 weight:NSFontWeightRegular].familyName; | ||
#endif | ||
XCTAssertEqualObjects(localFontFamilyName, systemFontFamilyName, @"Local font family name should match default system font name when setting `YES`"); | ||
} | ||
|
||
// `MGLIdeographicFontFamilyName` set to bool value `NO` | ||
{ | ||
NSString *localFontFamilyName = [config localFontFamilyNameWithInfoDictionaryObject:@(NO)]; | ||
XCTAssertNil(localFontFamilyName, @"Client rendering font should use remote font when setting `NO`"); | ||
} | ||
|
||
// `MGLIdeographicFontFamilyName` set to a valid font string value | ||
{ | ||
NSString *localFontFamilyName = [config localFontFamilyNameWithInfoDictionaryObject:@"PingFang TC"]; | ||
XCTAssertEqualObjects(localFontFamilyName, @"PingFang TC", @"Local font family name should match a custom valid font name"); | ||
} | ||
|
||
// `MGLIdeographicFontFamilyName` set to an invalid font string value | ||
{ | ||
NSString *localFontFamilyName = [config localFontFamilyNameWithInfoDictionaryObject:@"test font"]; | ||
|
||
NSString *systemFontFamilyName; | ||
#if TARGET_OS_IPHONE | ||
systemFontFamilyName = [UIFont systemFontOfSize:0 weight:UIFontWeightRegular].familyName; | ||
#else | ||
systemFontFamilyName = [NSFont systemFontOfSize:0 weight:NSFontWeightRegular].familyName; | ||
#endif | ||
XCTAssertNotEqualObjects(localFontFamilyName, systemFontFamilyName, @"Local font family name should not be validated by MGLRenderConfiguration"); | ||
} | ||
|
||
// `MGLIdeographicFontFamilyName` set to a valid font family names array value | ||
{ | ||
NSString *localFontFamilyName = [config localFontFamilyNameWithInfoDictionaryObject:@[@"test font 1", @"PingFang TC", @"test font 2"]]; | ||
XCTAssertEqualObjects(localFontFamilyName, @"test font 1\nPingFang TC\ntest font 2"); | ||
} | ||
|
||
// `MGLIdeographicFontFamilyName` set to an invalid font family names array value | ||
{ | ||
NSString *localFontFamilyName = [config localFontFamilyNameWithInfoDictionaryObject:@[@"test font 1", @"test font 2", @"test font 3"]]; | ||
|
||
NSString *systemFontFamilyName; | ||
#if TARGET_OS_IPHONE | ||
systemFontFamilyName = [UIFont systemFontOfSize:0 weight:UIFontWeightRegular].familyName; | ||
#else | ||
systemFontFamilyName = [NSFont systemFontOfSize:0 weight:NSFontWeightRegular].familyName; | ||
#endif | ||
XCTAssertEqualObjects(localFontFamilyName, @"test font 1\ntest font 2\ntest font 3", @"Local font family name should not be validated by MGLRendererConfiguration"); | ||
} | ||
|
||
// `MGLIdeographicFontFamilyName` set to an invalid value type: NSDictionary, NSNumber, NSData, etc. | ||
{ | ||
NSString *localFontFamilyName = [config localFontFamilyNameWithInfoDictionaryObject:[@"test font 1" dataUsingEncoding:NSUTF8StringEncoding]]; | ||
|
||
NSString *systemFontFamilyName; | ||
#if TARGET_OS_IPHONE | ||
systemFontFamilyName = [UIFont systemFontOfSize:0 weight:UIFontWeightRegular].familyName; | ||
#else | ||
systemFontFamilyName = [NSFont systemFontOfSize:0 weight:NSFontWeightRegular].familyName; | ||
#endif | ||
XCTAssertEqualObjects(localFontFamilyName, systemFontFamilyName, @"Local font family name should match default system font name when setting an invalid value type"); | ||
} | ||
} | ||
|
||
@end |
Oops, something went wrong.