Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit 5b239aa

Browse files
Lloyd Shengjmkiley
andauthored
[ios] Add glyphs rasterization options (#517)
* add glyphs rasterization options * fix issues * fix issue * fix issue * Address some feedback * Switch to closed enum, remove default * Update tests Co-authored-by: jmkiley <jordan.kiley@mapbox.com>
1 parent 2886995 commit 5b239aa

8 files changed

Lines changed: 269 additions & 84 deletions

platform/darwin/src/MGLMapSnapshotter.mm

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#import "MGLStyle_Private.h"
1515
#import "MGLAttributionInfo_Private.h"
1616
#import "MGLLoggingConfiguration_Private.h"
17-
#import "MGLRendererConfiguration.h"
17+
#import "MGLRendererConfiguration_Private.h"
1818
#import "MGLMapSnapshotter_Private.h"
1919

2020
#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
@@ -725,10 +725,9 @@ - (void)configureWithOptions:(MGLMapSnapshotOptions *)options {
725725
.withAssetPath(NSBundle.mainBundle.resourceURL.path.UTF8String);
726726

727727
// Create the snapshotter
728-
mbgl::optional<std::string> localFontFamilyName = config.localFontFamilyName ? mbgl::optional<std::string>(std::string(config.localFontFamilyName.UTF8String)) : mbgl::nullopt;
729728
_delegateHost = std::make_unique<MGLMapSnapshotterDelegateHost>(self);
730729
_mbglMapSnapshotter = std::make_unique<mbgl::MapSnapshotter>(
731-
size, pixelRatio, resourceOptions, *_delegateHost, localFontFamilyName);
730+
size, pixelRatio, resourceOptions, *_delegateHost, config.glyphsRasterizationOptions);
732731

733732
_mbglMapSnapshotter->setStyleURL(std::string(options.styleURL.absoluteString.UTF8String));
734733

platform/darwin/src/MGLRendererConfiguration.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@
33

44
NS_ASSUME_NONNULL_BEGIN
55

6+
/// Indicates how the map view load glyphs.
7+
typedef NS_CLOSED_ENUM(NSUInteger, MGLGlyphsRasterizationMode) {
8+
/// The MGLGlyphsRasterizationMode was unset.
9+
MGLGlyphsRasterizationModeNone,
10+
/// Ideographs are rasterized locally, and they are not loaded from the server.
11+
MGLGlyphsRasterizationModeIdeographsRasterizedLocally,
12+
/// No glyphs are rasterized locally. All glyphs are loaded from the server.
13+
MGLGlyphsRasterizationModeNoGlyphsRasterizedLocally,
14+
/// All glyphs are rasterized locally. No glyphs are loaded from the server.
15+
MGLGlyphsRasterizationModeAllGlyphsRasterizedLocally
16+
};
17+
618
/**
719
The MGLRendererConfiguration object represents configuration values for the
820
renderer.
@@ -51,6 +63,15 @@ MGL_EXPORT
5163

5264
- (BOOL)perSourceCollisionsWithInfoDictionaryObject:(nullable id)infoDictionaryObject;
5365

66+
/**
67+
Indicates how the map view load glyphs.
68+
69+
Set `MGLGlyphsRasterizationOptions` in your containing app's Info.plist.
70+
*/
71+
@property (nonatomic, readonly) MGLGlyphsRasterizationMode glyphsRasterizationMode;
72+
73+
- (MGLGlyphsRasterizationMode)glyphsRasterizationModeWithInfoDictionaryObject:(nullable id)infoDictionaryObject;
74+
5475
@end
5576

5677
NS_ASSUME_NONNULL_END

platform/darwin/src/MGLRendererConfiguration.m

Lines changed: 0 additions & 66 deletions
This file was deleted.
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#import "MGLRendererConfiguration_Private.h"
2+
#import "MGLLoggingConfiguration_Private.h"
3+
4+
#if TARGET_OS_IPHONE
5+
#import <UIKit/UIKit.h>
6+
#else
7+
#import <AppKit/AppKit.h>
8+
#endif
9+
10+
static NSString * const MGLCollisionBehaviorPre4_0Key = @"MGLCollisionBehaviorPre4_0";
11+
static NSString * const MGLIdeographicFontFamilyNameKey = @"MGLIdeographicFontFamilyName";
12+
static NSString * const MGLGlyphsRasterizationModeKey = @"MGLGlyphsRasterizationMode";
13+
14+
@implementation MGLRendererConfiguration
15+
16+
+ (instancetype)currentConfiguration {
17+
return [[self alloc] init];
18+
}
19+
20+
- (const float)scaleFactor {
21+
#if TARGET_OS_IPHONE
22+
return [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale];
23+
#else
24+
return [NSScreen mainScreen].backingScaleFactor;
25+
#endif
26+
}
27+
28+
- (nullable NSString *)localFontFamilyName {
29+
id infoDictionaryObject = [NSBundle.mainBundle objectForInfoDictionaryKey:MGLIdeographicFontFamilyNameKey];
30+
return [self localFontFamilyNameWithInfoDictionaryObject:infoDictionaryObject];
31+
}
32+
33+
- (nullable NSString *)localFontFamilyNameWithInfoDictionaryObject:(nullable id)infoDictionaryObject {
34+
if ([infoDictionaryObject isKindOfClass:[NSNumber class]] && ![infoDictionaryObject boolValue]) {
35+
// NO means don’t use local fonts.
36+
return nil;
37+
} else if ([infoDictionaryObject isKindOfClass:[NSString class]]) {
38+
return infoDictionaryObject;
39+
} else if ([infoDictionaryObject isKindOfClass:[NSArray class]]) {
40+
// mbgl::LocalGlyphRasterizer::Impl accepts only a single string, but form a cascade list with one font on each line.
41+
return [infoDictionaryObject componentsJoinedByString:@"\n"];
42+
}
43+
44+
#if TARGET_OS_IPHONE
45+
return [UIFont systemFontOfSize:0 weight:UIFontWeightRegular].familyName;
46+
#else
47+
return [NSFont systemFontOfSize:0 weight:NSFontWeightRegular].familyName;
48+
#endif
49+
}
50+
51+
- (BOOL)perSourceCollisions {
52+
id infoDictionaryObject = [NSBundle.mainBundle objectForInfoDictionaryKey:MGLCollisionBehaviorPre4_0Key];
53+
return [self perSourceCollisionsWithInfoDictionaryObject:infoDictionaryObject];
54+
}
55+
56+
- (BOOL)perSourceCollisionsWithInfoDictionaryObject:(nullable id)infoDictionaryObject {
57+
// Set the collision behaviour. A value set in `NSUserDefaults.standardUserDefaults`
58+
// should override anything in the application's info.plist
59+
if ([NSUserDefaults.standardUserDefaults objectForKey:MGLCollisionBehaviorPre4_0Key]) {
60+
return [NSUserDefaults.standardUserDefaults boolForKey:MGLCollisionBehaviorPre4_0Key];
61+
} else if ([infoDictionaryObject isKindOfClass:[NSNumber class]] || [infoDictionaryObject isKindOfClass:[NSString class]]) {
62+
// Also support NSString to correspond with the behavior of `-[NSUserDefaults boolForKey:]`
63+
return [infoDictionaryObject boolValue];
64+
}
65+
return NO;
66+
}
67+
68+
- (MGLGlyphsRasterizationMode)glyphsRasterizationMode {
69+
id infoDictionaryObject = [NSBundle.mainBundle objectForInfoDictionaryKey:MGLGlyphsRasterizationModeKey];
70+
return [self glyphsRasterizationModeWithInfoDictionaryObject:infoDictionaryObject];
71+
}
72+
73+
- (MGLGlyphsRasterizationMode)glyphsRasterizationModeWithInfoDictionaryObject:(id)infoDictionaryObject {
74+
if (!infoDictionaryObject || ![infoDictionaryObject isKindOfClass:[NSString class]]) {
75+
return MGLGlyphsRasterizationModeNone;
76+
}
77+
NSDictionary *nameOptionMap = @{@"MGLNoGlyphsRasterizedLocally":@(MGLGlyphsRasterizationModeNoGlyphsRasterizedLocally),
78+
@"MGLIdeographsRasterizedLocally":@(MGLGlyphsRasterizationModeIdeographsRasterizedLocally),
79+
@"MGLAllGlyphsRasterizedLocally":@(MGLGlyphsRasterizationModeAllGlyphsRasterizedLocally)};
80+
81+
return (MGLGlyphsRasterizationMode)[nameOptionMap[infoDictionaryObject] integerValue];
82+
}
83+
84+
- (mbgl::GlyphsRasterizationOptions)glyphsRasterizationOptions {
85+
return [self glyphsRasterizationOptionsWithLocalFontFamilyName:self.localFontFamilyName rasterizationMode:self.glyphsRasterizationMode];
86+
}
87+
88+
- (mbgl::GlyphsRasterizationOptions)glyphsRasterizationOptionsWithLocalFontFamilyName:(nullable NSString *)fontFamilyName
89+
rasterizationMode:(MGLGlyphsRasterizationMode)rasterizationMode {
90+
mbgl::GlyphsRasterizationOptions options;
91+
if (fontFamilyName == nil) {
92+
if (rasterizationMode != MGLGlyphsRasterizationModeNoGlyphsRasterizedLocally && rasterizationMode != MGLGlyphsRasterizationModeNone) {
93+
MGLLogWarning(@"The `MGLIdeographicFontFamilyName` is set to `NO`, this will make `MGLGlyphsRasterizationMode` always be `MGLNoGlyphsRasterizedLocally`.");
94+
}
95+
options.rasterizationMode = mbgl::GlyphsRasterizationMode::NoGlyphsRasterizedLocally;
96+
return options;
97+
}
98+
99+
options.fontFamily = std::string(fontFamilyName.UTF8String);
100+
switch (rasterizationMode) {
101+
case MGLGlyphsRasterizationModeIdeographsRasterizedLocally:
102+
options.rasterizationMode = mbgl::GlyphsRasterizationMode::IdeographsRasterizedLocally;
103+
break;
104+
case MGLGlyphsRasterizationModeNoGlyphsRasterizedLocally:
105+
options.rasterizationMode = mbgl::GlyphsRasterizationMode::NoGlyphsRasterizedLocally;
106+
break;
107+
case MGLGlyphsRasterizationModeAllGlyphsRasterizedLocally:
108+
options.rasterizationMode = mbgl::GlyphsRasterizationMode::AllGlyphsRasterizedLocally;
109+
break;
110+
case MGLGlyphsRasterizationModeNone:
111+
MGLLogWarning(@"Falling back to MGLIdeographsRasterizedLocally because MGLIdeographicFontFamilies are specified.")
112+
options.rasterizationMode = mbgl::GlyphsRasterizationMode::NoGlyphsRasterizedLocally;
113+
break;
114+
}
115+
116+
return options;
117+
}
118+
119+
120+
@end
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#import "MGLRendererConfiguration.h"
2+
#include <mbgl/map/glyphs_rasterization_options.hpp>
3+
4+
5+
NS_ASSUME_NONNULL_BEGIN
6+
7+
@interface MGLRendererConfiguration (Private)
8+
9+
- (mbgl::GlyphsRasterizationOptions)glyphsRasterizationOptions;
10+
11+
- (mbgl::GlyphsRasterizationOptions)glyphsRasterizationOptionsWithLocalFontFamilyName:(nullable NSString *)fontFamilyName
12+
rasterizationMode:(MGLGlyphsRasterizationMode)rasterizationMode;
13+
14+
@end
15+
16+
NS_ASSUME_NONNULL_END

platform/darwin/test/MGLRendererConfigurationTests.m renamed to platform/darwin/test/MGLRendererConfigurationTests.mm

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#import <Mapbox/Mapbox.h>
22
#import <XCTest/XCTest.h>
3-
#import "MGLRendererConfiguration.h"
3+
#import "MGLRendererConfiguration_Private.h"
44

55
static NSString * const MGLRendererConfigurationTests_collisionBehaviorKey = @"MGLCollisionBehaviorPre4_0";
66

@@ -159,4 +159,95 @@ - (void)testSettingMGLIdeographicFontFamilyNameWithPlistValue {
159159
}
160160
}
161161

162+
- (void)testMGLGlyphsRasterizationModeWithPlistValue {
163+
MGLRendererConfiguration *config = [[MGLRendererConfiguration alloc] init];
164+
165+
// `MGLGlyphsRasterizationMode` set to nil or not set.
166+
{
167+
MGLGlyphsRasterizationMode mode = [config glyphsRasterizationModeWithInfoDictionaryObject:nil];
168+
169+
XCTAssertEqual(mode, MGLGlyphsRasterizationModeNone, @"Glyphs rasterization mode should be `MGLGlyphsRasterizationModeNone` when it setting to nil or not set");
170+
}
171+
172+
// `MGLGlyphsRasterizationMode` set to invalid value.
173+
{
174+
MGLGlyphsRasterizationMode mode = [config glyphsRasterizationModeWithInfoDictionaryObject:@"invalide option value"];
175+
176+
XCTAssertEqual(mode, MGLGlyphsRasterizationModeNone, @"Glyphs rasterization mode should be `MGLGlyphsRasterizationModeNone` when it setting to invalid value.");
177+
}
178+
179+
// `MGLGlyphsRasterizationMode` set to "MGLNoGlyphsRasterizedLocally".
180+
{
181+
MGLGlyphsRasterizationMode mode = [config glyphsRasterizationModeWithInfoDictionaryObject:@"MGLNoGlyphsRasterizedLocally"];
182+
183+
XCTAssertEqual(mode, MGLGlyphsRasterizationModeNoGlyphsRasterizedLocally, @"Glyphs rasterization mode should be `MGLGlyphsRasterizationModeNoGlyphsRasterizedLocally`.");
184+
}
185+
186+
// `MGLGlyphsRasterizationMode` set to "MGLGlyphsRasterizationModeIdeographsRasterizedLocally".
187+
{
188+
MGLGlyphsRasterizationMode mode = [config glyphsRasterizationModeWithInfoDictionaryObject:@"MGLIdeographsRasterizedLocally"];
189+
190+
XCTAssertEqual(mode, MGLGlyphsRasterizationModeIdeographsRasterizedLocally, @"Glyphs rasterization mode should be `MGLGlyphsRasterizationModeIdeographsRasterizedLocally`.");
191+
}
192+
193+
// `MGLGlyphsRasterizationMode` set to "MGLAllGlyphsRasterizedLocally".
194+
{
195+
MGLGlyphsRasterizationMode mode = [config glyphsRasterizationModeWithInfoDictionaryObject:@"MGLAllGlyphsRasterizedLocally"];
196+
197+
XCTAssertEqual(mode, MGLGlyphsRasterizationModeAllGlyphsRasterizedLocally, @"Glyphs rasterization mode should be `MGLAllGlyphsRasterizedLocally`.");
198+
}
199+
}
200+
201+
- (void)testGlyphsRasterizationOptions {
202+
MGLRendererConfiguration *config = [[MGLRendererConfiguration alloc] init];
203+
204+
// `MGLIdeographicFontFamilyName` unset, MGLGlyphsRasterizationMode set to AllGlyphsRasterizedLocally.
205+
{
206+
mbgl::GlyphsRasterizationOptions options = [config glyphsRasterizationOptionsWithLocalFontFamilyName:nil rasterizationMode:MGLGlyphsRasterizationModeAllGlyphsRasterizedLocally];
207+
208+
XCTAssertEqual(options.fontFamily, mbgl::nullopt, @"Font family name should be `nullptr`");
209+
XCTAssertEqual(options.rasterizationMode, mbgl::GlyphsRasterizationMode::NoGlyphsRasterizedLocally, @"Glyphs rasterization mode should be `NoGlyphsRasterizedLocally`");
210+
}
211+
212+
// `MGLIdeographicFontFamilyName` unset, MGLGlyphsRasterizationMode set to NoGlyphsRasterizedLocally.
213+
{
214+
mbgl::GlyphsRasterizationOptions options = [config glyphsRasterizationOptionsWithLocalFontFamilyName:nil rasterizationMode:MGLGlyphsRasterizationModeNoGlyphsRasterizedLocally];
215+
216+
XCTAssertEqual(options.fontFamily, mbgl::nullopt, @"Font family name should be `nullptr`");
217+
XCTAssertEqual(options.rasterizationMode, mbgl::GlyphsRasterizationMode::NoGlyphsRasterizedLocally, @"Glyphs rasterization mode should be `NoGlyphsRasterizedLocally`");
218+
}
219+
220+
// `MGLIdeographicFontFamilyName` set to "Ping Fang", MGLGlyphsRasterizationMode set to IdeographsRasterizedLocally.
221+
{
222+
mbgl::GlyphsRasterizationOptions options = [config glyphsRasterizationOptionsWithLocalFontFamilyName:@"Ping Fang" rasterizationMode:MGLGlyphsRasterizationModeIdeographsRasterizedLocally];
223+
224+
XCTAssertEqual(options.fontFamily, std::string(@"Ping Fang".UTF8String), @"Font family name should be `Ping Fang`");
225+
XCTAssertEqual(options.rasterizationMode, mbgl::GlyphsRasterizationMode::IdeographsRasterizedLocally, @"Glyphs rasterization mode should be `IdeographsRasterizedLocally`");
226+
}
227+
228+
// `MGLIdeographicFontFamilyName` set to "Ping Fang", MGLGlyphsRasterizationMode set to NoGlyphsRasterizedLocally.
229+
{
230+
mbgl::GlyphsRasterizationOptions options = [config glyphsRasterizationOptionsWithLocalFontFamilyName:@"Ping Fang" rasterizationMode:MGLGlyphsRasterizationModeNoGlyphsRasterizedLocally];
231+
232+
XCTAssertEqual(options.fontFamily, std::string(@"Ping Fang".UTF8String), @"Font family name should be `Ping Fang`");
233+
XCTAssertEqual(options.rasterizationMode, mbgl::GlyphsRasterizationMode::NoGlyphsRasterizedLocally, @"Glyphs rasterization mode should be `NoGlyphsRasterizedLocally`");
234+
}
235+
236+
// `MGLIdeographicFontFamilyName` set to "Ping Fang", MGLGlyphsRasterizationMode set to AllGlyphsRasterizedLocally.
237+
{
238+
mbgl::GlyphsRasterizationOptions options = [config glyphsRasterizationOptionsWithLocalFontFamilyName:@"Ping Fang" rasterizationMode:MGLGlyphsRasterizationModeAllGlyphsRasterizedLocally];
239+
240+
XCTAssertEqual(options.fontFamily, std::string(@"Ping Fang".UTF8String), @"Font family name should be `Ping Fang`");
241+
XCTAssertEqual(options.rasterizationMode, mbgl::GlyphsRasterizationMode::AllGlyphsRasterizedLocally, @"Glyphs rasterization mode should be `AllGlyphsRasterizedLocally`");
242+
}
243+
244+
// `MGLIdeographicFontFamilyName` set to "Ping Fang", MGLGlyphsRasterizationMode unset.
245+
{
246+
mbgl::GlyphsRasterizationOptions options = [config glyphsRasterizationOptionsWithLocalFontFamilyName:@"Ping Fang" rasterizationMode:MGLGlyphsRasterizationModeNone];
247+
248+
XCTAssertEqual(options.fontFamily, std::string(@"Ping Fang".UTF8String), @"Font family name should be `Ping Fang`");
249+
XCTAssertEqual(options.rasterizationMode, mbgl::GlyphsRasterizationMode::NoGlyphsRasterizedLocally, @"Glyphs rasterization mode should be `NoGlyphsRasterizedLocally`");
250+
}
251+
}
252+
162253
@end

0 commit comments

Comments
 (0)