summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2020-03-19 17:43:11 -0700
committerMinh Nguyễn <mxn@1ec5.org>2020-04-24 13:46:40 -0700
commitc4c35449cbd0ef8b41ce334a53325101b8f1164e (patch)
treeae929ef64f6dd6fdd043512ec2221fcada253635
parent76ddb15dbcee8d75a02c1202ded8ea8a282f9f8c (diff)
downloadqtlocation-mapboxgl-c4c35449cbd0ef8b41ce334a53325101b8f1164e.tar.gz
[ios, macos] Choose fonts from font stack that match local fonts
Prefer local fonts that match the names specified in the font stack (from the text-font layout property), except for the last resort fonts that mbgl hard-codes. Fall back to the list of fallback CJK fonts in user defaults, then the fonts passed in through the platform-agnostic interface (that come from Info.plist). Explicitly use the first font descriptor in the cascade list instead of the system default of Helvetica. Since the font stack can vary from one rasterization operation to the next, avoid caching the resolved font for now. Removed null checks that are unrealistic given the Core Text API contract.
-rw-r--r--CHANGELOG.md2
-rw-r--r--platform/darwin/src/local_glyph_rasterizer.mm98
2 files changed, 52 insertions, 48 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 36c8126851..8c54342ce7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -28,7 +28,7 @@
- [ios, macos] Allow specifying multiple fonts or font families for local font rendering ([#16253](https://github.com/mapbox/mapbox-gl-native/pull/16253))
- The `localFontFamily` parameter of `mbgl::Renderer::Renderer()` and `mbgl::MapSnapshotter::MapSnapshotter()` can now contain a list of font family names, font display names, and font PostScript names, each name separated by a newline.
+ By default, CJK characters are now set in the font specified by the `text-font` layout property. If the named font is not installed on the device or bundled with the application, the characters are set in one of the fallback fonts passed into the `localFontFamily` parameter of `mbgl::Renderer::Renderer()` and `mbgl::MapSnapshotter::MapSnapshotter()`. This parameter can now contain a list of font family names, font display names, and font PostScript names, each name separated by a newline.
### 🐞 Bug fixes
diff --git a/platform/darwin/src/local_glyph_rasterizer.mm b/platform/darwin/src/local_glyph_rasterizer.mm
index bbbb482969..a6a9d9cca8 100644
--- a/platform/darwin/src/local_glyph_rasterizer.mm
+++ b/platform/darwin/src/local_glyph_rasterizer.mm
@@ -1,6 +1,7 @@
#include <mbgl/text/local_glyph_rasterizer.hpp>
#include <mbgl/util/i18n.hpp>
#include <mbgl/util/platform.hpp>
+#include <mbgl/util/constants.hpp>
#include <unordered_map>
@@ -54,60 +55,63 @@ using CTLineRefHandle = CFHandle<CTLineRef, CFTypeRef, CFRelease>;
class LocalGlyphRasterizer::Impl {
public:
Impl(const optional<std::string> fontFamily_)
- : fontFamily(fontFamily_)
- , fontHandle(NULL)
- {}
+ {
+ fallbackFontNames = [[NSUserDefaults standardUserDefaults] stringArrayForKey:@"MGLIdeographicFontFamilyName"];
+ if (fontFamily_) {
+ fallbackFontNames = [fallbackFontNames ?: @[] arrayByAddingObjectsFromArray:[@(fontFamily_->c_str()) componentsSeparatedByString:@"\n"]];
+ }
+ }
~Impl() {
- if (fontHandle) {
- CFRelease(fontHandle);
- }
}
-
- CTFontRef getFont() {
- if (!fontHandle) {
- NSArray<NSString *> *fontFamilyNames = [[NSUserDefaults standardUserDefaults] stringArrayForKey:@"MGLIdeographicFontFamilyName"] ?: @[];
- if (fontFamily) {
- fontFamilyNames = [fontFamilyNames arrayByAddingObjectsFromArray:[@(fontFamily->c_str()) componentsSeparatedByString:@"\n"]];
- }
- if (!fontFamilyNames.count) {
- return NULL;
+
+ bool isEnabled() { return fallbackFontNames; }
+
+ CTFontDescriptorRef createFontDescriptor(const FontStack& fontStack) {
+ NSMutableArray *fontNames = [NSMutableArray arrayWithCapacity:fontStack.size() + fallbackFontNames.count];
+ for (auto& fontName : fontStack) {
+ if (fontName != util::LAST_RESORT_ALPHABETIC_FONT && fontName != util::LAST_RESORT_PAN_UNICODE_FONT) {
+ [fontNames addObject:@(fontName.c_str())];
}
+ }
+ [fontNames addObjectsFromArray:fallbackFontNames];
+
+ CFMutableArrayRefHandle fontDescriptors(CFArrayCreateMutable(kCFAllocatorDefault, fontNames.count, &kCFTypeArrayCallBacks));
+ for (NSString *name in fontNames) {
+ NSDictionary *fontAttributes = @{
+ (NSString *)kCTFontSizeAttribute: @(util::ONE_EM),
+ (NSString *)kCTFontNameAttribute: name,
+ (NSString *)kCTFontDisplayNameAttribute: name,
+ (NSString *)kCTFontFamilyNameAttribute: name,
+ };
- CFMutableArrayRefHandle fontDescriptors(CFArrayCreateMutable(kCFAllocatorDefault, fontFamilyNames.count, &kCFTypeArrayCallBacks));
- for (NSString *name in fontFamilyNames) {
- NSDictionary *fontAttributes = @{
- (NSString *)kCTFontSizeAttribute: @(24.0),
- (NSString *)kCTFontNameAttribute: name,
- (NSString *)kCTFontDisplayNameAttribute: name,
- (NSString *)kCTFontFamilyNameAttribute: name,
- };
-
- CTFontDescriptorRefHandle descriptor(CTFontDescriptorCreateWithAttributes((CFDictionaryRef)fontAttributes));
- CFArrayAppendValue(*fontDescriptors, *descriptor);
- }
-
- CFStringRef keys[] = { kCTFontSizeAttribute, kCTFontCascadeListAttribute };
- CFTypeRef values[] = { (__bridge CFNumberRef)@(24.0), *fontDescriptors };
+ CTFontDescriptorRefHandle descriptor(CTFontDescriptorCreateWithAttributes((CFDictionaryRef)fontAttributes));
+ CFArrayAppendValue(*fontDescriptors, *descriptor);
+ }
- CFDictionaryRefHandle attributes(
- CFDictionaryCreate(kCFAllocatorDefault, (const void**)&keys,
- (const void**)&values, sizeof(keys) / sizeof(keys[0]),
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
-
- CTFontDescriptorRefHandle descriptor(CTFontDescriptorCreateWithAttributes(*attributes));
- fontHandle = CTFontCreateWithFontDescriptor(*descriptor, 0.0, NULL);
- if (!fontHandle) {
- throw std::runtime_error("CTFontCreateWithFontDescriptor failed");
- }
+ CFStringRef keys[] = { kCTFontSizeAttribute, kCTFontCascadeListAttribute };
+ CFTypeRef values[] = { (__bridge CFNumberRef)@(util::ONE_EM), *fontDescriptors };
+
+ CFDictionaryRefHandle attributes(
+ CFDictionaryCreate(kCFAllocatorDefault, (const void**)&keys,
+ (const void**)&values, sizeof(keys) / sizeof(keys[0]),
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+ if (CFArrayGetCount(*fontDescriptors)) {
+ CTFontDescriptorRef firstDescriptor = (CTFontDescriptorRef)CFArrayGetValueAtIndex(*fontDescriptors, 0);
+ return CTFontDescriptorCreateCopyWithAttributes(firstDescriptor, *attributes);
+ } else {
+ return CTFontDescriptorCreateWithAttributes(*attributes);
}
- return fontHandle;
+ }
+
+ CTFontRef createFont(const FontStack& fontStack) {
+ CTFontDescriptorRefHandle descriptor(createFontDescriptor(fontStack));
+ return CTFontCreateWithFontDescriptor(*descriptor, 0.0, NULL);
}
private:
- optional<std::string> fontFamily;
- CTFontRef fontHandle;
+ NSArray<NSString *> *fallbackFontNames;
};
LocalGlyphRasterizer::LocalGlyphRasterizer(const optional<std::string>& fontFamily)
@@ -118,7 +122,7 @@ LocalGlyphRasterizer::~LocalGlyphRasterizer()
{}
bool LocalGlyphRasterizer::canRasterizeGlyph(const FontStack&, GlyphID glyphID) {
- return util::i18n::allowsFixedWidthGlyphGeneration(glyphID) && impl->getFont();
+ return util::i18n::allowsFixedWidthGlyphGeneration(glyphID) && impl->isEnabled();
}
PremultipliedImage drawGlyphBitmap(GlyphID glyphID, CTFontRef font, Size size) {
@@ -166,9 +170,9 @@ PremultipliedImage drawGlyphBitmap(GlyphID glyphID, CTFontRef font, Size size) {
return rgbaBitmap;
}
-Glyph LocalGlyphRasterizer::rasterizeGlyph(const FontStack&, GlyphID glyphID) {
+Glyph LocalGlyphRasterizer::rasterizeGlyph(const FontStack& fontStack, GlyphID glyphID) {
Glyph fixedMetrics;
- CTFontRef font = impl->getFont();
+ CTFontRef font = impl->createFont(fontStack);
if (!font) {
return fixedMetrics;
}