Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[ios, macos] Default to local rendering of CJK characters, using syst…
Browse files Browse the repository at this point in the history
…em font (#14862)

* Change default CJK font from "PingFang" to "Helvetica"

* Add CHANGELOG.

* Update CHANGELOG.

* [ios] Enable client-side rendering and use `Helvetica` by default. Set `MGLIdeographicFontFamilyName` to `NULL` for using your custom remote font.

* [ios] Update change log

* [ios] Change default CJK configuration in `iosapp` project

* [ios] Update comment

* [ios] return local font name using default system font.

* [ios] Update changelog

* [ios] update changelogs & comments

* [iOS, macOS]Support mac os

* [iOS, macOS] fix bug

* [iOS, macOS] update change log

* [iOS, macOS] fix nit.

* [iOS, macOS] Ability to specify an array of fonts for fallbacks for `localIdeographicFontFamily`

* [iOS, macOS] Update comments

* [iOS, macOS] Update change log

* [iOS, macOS] update for mac OS font family names

* Fix nit.

* Update platform/ios/CHANGELOG.md

Co-Authored-By: Minh Nguyễn <mxn@1ec5.org>

* [iOS, macOS] Set `MGLIdeographicFontFamilyName` to a Boolean value `NO` for using your custom remote font.

* [iOS, macOS] remove `MGLIdeographicFontFamilyName` from info.plist & update Info.plist Keys.md

* [iOS, macOS] remove `MGLIdeographicFontFamilyName` from macOS demo app project and update info.plist Keys.md

* [iOS, macOS] update macOS changelog

* [iOS, macOS] Change docs

* Update Change log

* [iOS, macOS] Test case

* Update platform/macos/docs/guides/Info.plist Keys.md

Co-Authored-By: Jason Wray <friedbunny@users.noreply.github.com>

* Update platform/macos/docs/guides/Info.plist Keys.md

Co-Authored-By: Jason Wray <friedbunny@users.noreply.github.com>

* Update platform/ios/CHANGELOG.md

Co-Authored-By: Jason Wray <friedbunny@users.noreply.github.com>

* Update platform/darwin/src/MGLRendererConfiguration.mm

Co-Authored-By: Jason Wray <friedbunny@users.noreply.github.com>

* Update platform/darwin/test/MGLRendererConfigurationTests.mm

Co-Authored-By: Jason Wray <friedbunny@users.noreply.github.com>

* Update platform/macos/docs/guides/Info.plist Keys.md

Co-Authored-By: Jason Wray <friedbunny@users.noreply.github.com>

* Update platform/macos/docs/guides/Info.plist Keys.md

Co-Authored-By: Jason Wray <friedbunny@users.noreply.github.com>

* Update platform/macos/docs/guides/Info.plist Keys.md

Co-Authored-By: Jason Wray <friedbunny@users.noreply.github.com>

* [iOS, macOS] update comments

* [iOS, macOS] add plist value test && filter for invalid string

* [iOS, macOS] fix nit

* Update platform/ios/docs/guides/Info.plist Keys.md

Co-Authored-By: Jason Wray <friedbunny@users.noreply.github.com>

* Update platform/ios/docs/guides/Info.plist Keys.md

Co-Authored-By: Jason Wray <friedbunny@users.noreply.github.com>

* Update platform/ios/docs/guides/Info.plist Keys.md

Co-Authored-By: Jason Wray <friedbunny@users.noreply.github.com>

* Update platform/macos/CHANGELOG.md

Co-Authored-By: Jason Wray <friedbunny@users.noreply.github.com>

* Update platform/ios/docs/guides/Info.plist Keys.md

Co-Authored-By: Jason Wray <friedbunny@users.noreply.github.com>

* Update platform/ios/docs/guides/Info.plist Keys.md

Co-Authored-By: Jason Wray <friedbunny@users.noreply.github.com>

* [iOS, macOS] add invalid value type test

* Apply own suggestions from code review
  • Loading branch information
m-stephen authored Jul 10, 2019
1 parent 18f7e4b commit 6b59db8
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 22 deletions.
23 changes: 15 additions & 8 deletions platform/darwin/src/MGLRendererConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,21 @@ MGL_EXPORT
/** The cache dir to use. */
@property (nonatomic, readonly) mbgl::optional<std::string> cacheDir;

/** The name of the font family to use for client-side text rendering.
Currently only used for CJK glyphs. Changing this at run time is not currently
supported. Enable client-side rendering of CJK glyphs by setting
`MGLIdeographicFontFamilyName` in your containing app's Info.plist to a value
which will be available at run time. Default font for local ideograph font family
is "PingFang". */
@property (nonatomic, readonly) std::string localFontFamilyName;
/** The name of the font family to use for client-side text rendering of CJK ideographs.
Set MGLIdeographicFontFamilyName in your containing application's Info.plist to
font family name(s) that will be available at run time, such as “PingFang TC”
or “Marker Felt”. This plist key accepts:
- A string value of a single font family name.
- An array of font family names. Fonts will be used in the defined order,
eventually falling back to default system font if none are available.
- A boolean value NO to disable client-side rendering of CJK glyphs —
remote fonts specified in your style will be used instead.
*/
@property (nonatomic, readonly) mbgl::optional<std::string> localFontFamilyName;

/**
A Boolean value indicating whether symbol layers may enable per-source symbol
Expand Down
51 changes: 48 additions & 3 deletions platform/darwin/src/MGLRendererConfiguration.mm
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#endif

static NSString * const MGLCollisionBehaviorPre4_0Key = @"MGLCollisionBehaviorPre4_0";
static NSString * const MGLIdeographicFontFamilyNameKey = @"MGLIdeographicFontFamilyName";

@interface MGLRendererConfiguration ()
@property (nonatomic, readwrite) BOOL perSourceCollisions;
Expand Down Expand Up @@ -69,10 +70,54 @@ - (const float)scaleFactor {
return mbgl::optional<std::string>();
}

- (std::string)localFontFamilyName {
NSString *fontFamilyName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"MGLIdeographicFontFamilyName"];
- (mbgl::optional<std::string>)localFontFamilyName {
return [self _localFontFamilyNameWithPropertyDictionary:[[NSBundle mainBundle] infoDictionary]];
}

return fontFamilyName ? std::string([fontFamilyName UTF8String]) : std::string("PingFang");
- (mbgl::optional<std::string>)_localFontFamilyNameWithPropertyDictionary:(nonnull NSDictionary *)properties {

std::string systemFontFamilyName;
#if TARGET_OS_IPHONE
systemFontFamilyName = std::string([[UIFont systemFontOfSize:0 weight:UIFontWeightRegular].familyName UTF8String]);
#else
systemFontFamilyName = std::string([[NSFont systemFontOfSize:0 weight:NSFontWeightRegular].familyName UTF8String]);
#endif

id fontFamilyName = properties[MGLIdeographicFontFamilyNameKey];

if([fontFamilyName isKindOfClass:[NSNumber class]] && ![fontFamilyName boolValue])
{
return mbgl::optional<std::string>();
}
else if([fontFamilyName isKindOfClass:[NSString class]])
{
BOOL isValidFont = NO;
#if TARGET_OS_IPHONE
if([[UIFont familyNames] containsObject:fontFamilyName]){
isValidFont = YES;
}
#else
if([[[NSFontManager sharedFontManager] availableFontFamilies] containsObject:fontFamilyName]){
isValidFont = YES;
}
#endif
return (fontFamilyName && isValidFont) ? std::string([fontFamilyName UTF8String]) : systemFontFamilyName;
}
// Ability to specify an array of fonts for fallbacks for `localIdeographicFontFamily`
else if ([fontFamilyName isKindOfClass:[NSArray class]]){
for(NSString *name in fontFamilyName){
#if TARGET_OS_IPHONE
if([[UIFont familyNames] containsObject:name]){
return std::string([name UTF8String]);
}
#else
if([[[NSFontManager sharedFontManager] availableFontFamilies] containsObject:name]){
return std::string([name UTF8String]);
}
#endif
}
}
return systemFontFamilyName;
}

@end
105 changes: 103 additions & 2 deletions platform/darwin/test/MGLRendererConfigurationTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

@interface MGLRendererConfiguration (Tests)
- (instancetype)initWithPropertyDictionary:(nonnull NSDictionary*)bundle;
- (mbgl::optional<std::string>)_localFontFamilyNameWithPropertyDictionary:(nonnull NSDictionary *)properties;
@end


Expand Down Expand Up @@ -77,14 +78,12 @@ - (void)testSettingMGLCollisionBehaviorPre40PListValueUsingString {
}

- (void)testOverridingMGLCollisionBehaviorPre40 {

// Dictionary = NO, NSUserDefaults = YES
{
[[NSUserDefaults standardUserDefaults] setObject:@(YES) forKey:MGLRendererConfigurationTests_collisionBehaviorKey];
MGLRendererConfiguration *config = [[MGLRendererConfiguration alloc] initWithPropertyDictionary:@{MGLRendererConfigurationTests_collisionBehaviorKey:@(NO)}];
XCTAssert(config.perSourceCollisions);
}

// Dictionary = YES, NSUserDefaults = NO
{
[[NSUserDefaults standardUserDefaults] setObject:@(NO) forKey:MGLRendererConfigurationTests_collisionBehaviorKey];
Expand All @@ -93,4 +92,106 @@ - (void)testOverridingMGLCollisionBehaviorPre40 {
}
}

- (void)testDefaultLocalFontFamilyName {

MGLRendererConfiguration *config = [[MGLRendererConfiguration alloc] init];
std::string localFontFamilyName = config.localFontFamilyName.value();

std::string systemFontFamilyName;
#if TARGET_OS_IPHONE
systemFontFamilyName = std::string([[UIFont systemFontOfSize:0 weight:UIFontWeightRegular].familyName UTF8String]);
#else
systemFontFamilyName = std::string([[NSFont systemFontOfSize:0 weight:NSFontWeightRegular].familyName UTF8String]);
#endif

XCTAssertEqual(localFontFamilyName, systemFontFamilyName, @"Default local font family name should match default system font");
}

- (void)testSettingMGLIdeographicFontFamilyNameWithPlistValue {

MGLRendererConfiguration *config = [[MGLRendererConfiguration alloc] init];
NSDictionary *dic;

// `MGLIdeographicFontFamilyName` set to bool value `YES`
{
dic = @{@"MGLIdeographicFontFamilyName": @(YES)};
std::string localFontFamilyName = ([config _localFontFamilyNameWithPropertyDictionary:dic]).value();

std::string systemFontFamilyName;
#if TARGET_OS_IPHONE
systemFontFamilyName = std::string([[UIFont systemFontOfSize:0 weight:UIFontWeightRegular].familyName UTF8String]);
#else
systemFontFamilyName = std::string([[NSFont systemFontOfSize:0 weight:NSFontWeightRegular].familyName UTF8String]);
#endif
XCTAssertEqual(localFontFamilyName, systemFontFamilyName, @"Local font family name should match default system font name when setting `YES`");
}

// `MGLIdeographicFontFamilyName` set to bool value `NO`
{
dic = @{@"MGLIdeographicFontFamilyName": @(NO)};
mbgl::optional<std::string> localFontFamilyName = [config _localFontFamilyNameWithPropertyDictionary:dic];
XCTAssertFalse(localFontFamilyName.has_value(), @"Client rendering font should use remote font when setting `NO`");
}

// `MGLIdeographicFontFamilyName` set to a valid font string value
{
dic = @{@"MGLIdeographicFontFamilyName": @"PingFang TC"};
std::string localFontFamilyName = ([config _localFontFamilyNameWithPropertyDictionary:dic]).value();
std::string targetFontFamilyName = std::string([@"PingFang TC" UTF8String]);
XCTAssertEqual(localFontFamilyName, targetFontFamilyName, @"Local font family name should match a custom valid font name");
}

// `MGLIdeographicFontFamilyName` set to an invalid font string value
{
dic = @{@"MGLIdeographicFontFamilyName": @"test font"};
std::string localFontFamilyName = ([config _localFontFamilyNameWithPropertyDictionary:dic]).value();

std::string systemFontFamilyName;
#if TARGET_OS_IPHONE
systemFontFamilyName = std::string([[UIFont systemFontOfSize:0 weight:UIFontWeightRegular].familyName UTF8String]);
#else
systemFontFamilyName = std::string([[NSFont systemFontOfSize:0 weight:NSFontWeightRegular].familyName UTF8String]);
#endif
XCTAssertEqual(localFontFamilyName, systemFontFamilyName, @"Local font family name should match default system font name when setting an invalid font string");
}

// `MGLIdeographicFontFamilyName` set to a valid font family names array value
{
dic = @{@"MGLIdeographicFontFamilyName": @[@"test font 1", @"PingFang TC", @"test font 2"]};
std::string localFontFamilyName = ([config _localFontFamilyNameWithPropertyDictionary:dic]).value();
std::string targetFontFamilyName = std::string([@"PingFang TC" UTF8String]);
XCTAssertEqual(localFontFamilyName, targetFontFamilyName, @"Local font family name should match a custom valid font name in a font family names array");
}

// `MGLIdeographicFontFamilyName` set to an invalid font family names array value
{
dic = @{@"MGLIdeographicFontFamilyName": @[@"test font 1", @"test font 2", @"test font 3"]};
std::string localFontFamilyName = ([config _localFontFamilyNameWithPropertyDictionary:dic]).value();

std::string systemFontFamilyName;
#if TARGET_OS_IPHONE
systemFontFamilyName = std::string([[UIFont systemFontOfSize:0 weight:UIFontWeightRegular].familyName UTF8String]);
#else
systemFontFamilyName = std::string([[NSFont systemFontOfSize:0 weight:NSFontWeightRegular].familyName UTF8String]);
#endif
XCTAssertEqual(localFontFamilyName, systemFontFamilyName, @"Local font family name should match default system font name when setting an invalid font family names array");
}

// `MGLIdeographicFontFamilyName` set to an invalid value type: NSDictionary, NSNumber, NSData, etc.
{
dic = @{@"MGLIdeographicFontFamilyName": [@"test font 1" dataUsingEncoding:NSUTF8StringEncoding]};
std::string localFontFamilyName = ([config _localFontFamilyNameWithPropertyDictionary:dic]).value();

std::string systemFontFamilyName;
#if TARGET_OS_IPHONE
systemFontFamilyName = std::string([[UIFont systemFontOfSize:0 weight:UIFontWeightRegular].familyName UTF8String]);
#else
systemFontFamilyName = std::string([[NSFont systemFontOfSize:0 weight:NSFontWeightRegular].familyName UTF8String]);
#endif
XCTAssertEqual(localFontFamilyName, systemFontFamilyName, @"Local font family name should match default system font name when setting an invalid value type");
}
}



@end
1 change: 1 addition & 0 deletions platform/ios/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT

## master

* The `MGLIdeographicFontFamilyName` Info.plist key now also accepts an array of font family names, to customize font fallback behavior. It can also be set to a Boolean value of `NO` to force the SDK to typeset CJK characters in a remote font specified by `MGLSymbolStyleLayer.textFontNames`. ([#14862](https://github.com/mapbox/mapbox-gl-native/pull/14862))
* Performance improvements for queryRenderedFeatures API and optimization that allocates containers based on a number of rendered layers. ([#14930](https://github.com/mapbox/mapbox-gl-native/pull/14930))
* Fixed rendering layers after fill-extrusion regression caused by optimization of fill-extrusion rendering. ([#15065](https://github.com/mapbox/mapbox-gl-native/pull/15065))

Expand Down
2 changes: 0 additions & 2 deletions platform/ios/app/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
<string>7877</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>MGLIdeographicFontFamilyName</key>
<string>PingFang TC</string>
<key>NSHumanReadableCopyright</key>
<string>© 2014–2019 Mapbox</string>
<key>NSLocationAlwaysUsageDescription</key>
Expand Down
13 changes: 11 additions & 2 deletions platform/ios/docs/guides/Info.plist Keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,21 @@ If you have implemented custom opt-out of Mapbox Telemetry within the user inter

## MGLIdeographicFontFamilyName

The name of the font family to use for client-side text rendering of CJK ideographs. Set this to the name of a font family which will be available at run time, e.g. `PingFang TC` (iOS 9+), `Heiti TC` (iOS 8+), another appropriate built-in font, or a font provided by your application. Note that if a non-existent font is specified, iOS will fall back to using Helvetica which is likely not to include support for the glyphs needed to render maps in your application.
The name of the font family to use for client-side text rendering of CJK ideographs.

Set `MGLIdeographicFontFamilyName` in your containing application's Info.plist to font family name(s) that will be available at run time, such as “PingFang TC” or “Marker Felt”. This plist key accepts:

- A string value of a single font family name.

- An array of font family names. Fonts will be used in the defined order, eventually falling back to default system font if none are available.

- A boolean value `NO` to disable client-side rendering of CJK glyphs — remote fonts specified in your style will be used instead.

## MGLCollisionBehaviorPre4_0

If this key is set to YES (`true`), collision detection is performed only between symbol style layers based on the same source, as in versions 2.0–3.7 of the Mapbox Maps SDK for iOS. In other words, symbols in an `MGLSymbolStyleLayer` based on one source (for example, an `MGLShapeSource`) may overlap with symbols in another layer that is based on a different source (such as the Mapbox Streets source). This is the case regardless of the `MGLSymbolStyleLayer.iconAllowsOverlap`, `MGLSymbolStyleLayer.iconIgnoresPlacement`, `MGLSymbolStyleLayer.textAllowsOverlap`, and `MGLSymbolStyleLayer.textIgnoresPlacement` properties.

Beginning in version 4.0, the SDK also performs collision detection between style layers based on different sources by default. For the default behavior, omit the `MGLCollisionBehaviorPre4_0` key or set it to NO (`false`).

This property may also be set using `[[NSUserDefaults standardUserDefaults] setObject:@(YES) forKey:@"MGLCollisionBehaviorPre4_0"]`; it will override any value specified in the `Info.plist`.
This property may also be set using `[[NSUserDefaults standardUserDefaults] setObject:@(YES) forKey:@"MGLCollisionBehaviorPre4_0"]`; it will override any value specified in the `Info.plist`.

2 changes: 2 additions & 0 deletions platform/macos/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

* Added an `MGLMapView.prefetchesTiles` property to configure lower-resolution tile prefetching behavior. ([#14816](https://github.com/mapbox/mapbox-gl-native/pull/14816))
* Fixed queryRenderedFeatues bug caused by incorrect sort feature index calculation. ([#14884](https://github.com/mapbox/mapbox-gl-native/pull/14884))
* The `MGLIdeographicFontFamilyName` Info.plist key now also accepts an array of font family names, to customize font fallback behavior. It can also be set to a Boolean value of `NO` to force the SDK to typeset CJK characters in a remote font specified by `MGLSymbolStyleLayer.textFontNames`. ([#14862](https://github.com/mapbox/mapbox-gl-native/pull/14862))
* Performance improvements for queryRenderedFeatures API and optimization that allocates containers based on a number of rendered layers. ([#14930](https://github.com/mapbox/mapbox-gl-native/pull/14930))
* Fixed rendering layers after fill-extrusion regression caused by optimization of fill-extrusion rendering. ([#15065](https://github.com/mapbox/mapbox-gl-native/pull/15065))


### Styles and rendering

* Setting `MGLMapView.contentInset` now moves the map’s focal point to the center of the content frame after insetting. ([#14664](https://github.com/mapbox/mapbox-gl-native/pull/14664))
Expand Down
2 changes: 0 additions & 2 deletions platform/macos/app/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>MGLIdeographicFontFamilyName</key>
<string>PingFang TC</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDocumentTypes</key>
Expand Down
14 changes: 11 additions & 3 deletions platform/macos/docs/guides/Info.plist Keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,20 @@ Use this key if you need to customize the API base URL used throughout the SDK.

The default value is `https://api.mapbox.com`.

## MGLIdeographicFontFamilyName
## MGLIdeographicFontFamilyName

The name of the font family to use for client-side text rendering of CJK ideographs. Set this to the name of a font family which will be available at run time, e.g. `PingFang TC` (iOS 9+), `Heiti TC` (iOS 8+), another appropriate built-in font, or a font provided by your application. Note that if a non-existent font is specified, iOS will fall back to using Helvetica which is likely not to include support for the glyphs needed to render maps in your application.
The name of the font family to use for client-side text rendering of CJK ideographs.

Set `MGLIdeographicFontFamilyName` in your containing application's Info.plist to font family name(s) that will be available at run time, such as “PingFang TC” or “Marker Felt”. This plist key accepts:

- A string value of a single font family name.

- An array of font family names. Fonts will be used in the defined order, eventually falling back to default system font if none are available.

- A boolean value `NO` to disable client-side rendering of CJK glyphs — remote fonts specified in your style will be used instead.

## MGLCollisionBehaviorPre4_0

If this key is set to YES (`true`), collision detection is performed only between symbol style layers based on the same source, as in versions 0.1–0.7 of the Mapbox Maps SDK for iOS. In other words, symbols in an `MGLSymbolStyleLayer` based on one source (for example, an `MGLShapeSource`) may overlap with symbols in another layer that is based on a different source (such as the Mapbox Streets source). This is the case regardless of the `MGLSymbolStyleLayer.iconAllowsOverlap`, `MGLSymbolStyleLayer.iconIgnoresPlacement`, `MGLSymbolStyleLayer.textAllowsOverlap`, and `MGLSymbolStyleLayer.textIgnoresPlacement` properties.

Beginning in version 0.7, the SDK also performs collision detection between style layers based on different sources by default. For the default behavior, omit the `MGLCollisionBehaviorPre4_0` key or set it to NO (`false`). This property is so named because version 0.7 of the Mapbox Maps SDK for macOS corresponds to version 4.0 of the Mapbox Maps SDK for iOS.
Beginning in version 0.7, the SDK also performs collision detection between style layers based on different sources by default. For the default behavior, omit the `MGLCollisionBehaviorPre4_0` key or set it to NO (`false`). This property is so named because version 0.7 of the Mapbox Maps SDK for macOS corresponds to version 4.0 of the Mapbox Maps SDK for iOS.

0 comments on commit 6b59db8

Please sign in to comment.