diff options
-rw-r--r-- | CHANGELOG.md | 2 | ||||
-rw-r--r-- | platform/darwin/src/local_glyph_rasterizer.mm | 98 |
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; } |