diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/fonts/mac')
5 files changed, 158 insertions, 42 deletions
diff --git a/chromium/third_party/blink/renderer/platform/fonts/mac/core_text_font_format_support.h b/chromium/third_party/blink/renderer/platform/fonts/mac/core_text_font_format_support.h index 1816f6f49d7..b5f3ffe9738 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/mac/core_text_font_format_support.h +++ b/chromium/third_party/blink/renderer/platform/fonts/mac/core_text_font_format_support.h @@ -9,6 +9,7 @@ namespace blink { bool CoreTextVersionSupportsVariations(); bool CoreTextVersionSupportsColrCpal(); + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_MAC_CORE_TEXT_FONT_FORMAT_SUPPORT_H_ diff --git a/chromium/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm b/chromium/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm index f50fc36281d..fedd1b91424 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm +++ b/chromium/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm @@ -29,8 +29,11 @@ #import "third_party/blink/renderer/platform/fonts/font_cache.h" -#import <AppKit/AppKit.h> #include <memory> + +#import <AppKit/AppKit.h> +#import <CoreText/CoreText.h> + #include "base/location.h" #include "base/mac/foundation_util.h" #include "third_party/blink/public/platform/platform.h" @@ -59,6 +62,22 @@ inLanguage:(id)useNil; @end +namespace { + +NSString* GetLocalizedString(CTFontDescriptorRef fd, CFStringRef attribute) { + base::ScopedCFTypeRef<CFStringRef> cf_str(base::mac::CFCast<CFStringRef>( + CTFontDescriptorCopyLocalizedAttribute(fd, attribute, nullptr))); + return [base::mac::CFToNSCast(cf_str.release()) autorelease]; +} + +NSString* GetString(CTFontDescriptorRef fd, CFStringRef attribute) { + base::ScopedCFTypeRef<CFStringRef> cf_str(base::mac::CFCast<CFStringRef>( + CTFontDescriptorCopyAttribute(fd, attribute))); + return [base::mac::CFToNSCast(cf_str.release()) autorelease]; +} + +} // namespace + namespace blink { const char kColorEmojiFontMac[] = "Apple Color Emoji"; @@ -221,9 +240,12 @@ scoped_refptr<SimpleFontData> FontCache::PlatformFallbackFontForCharacter( substitute_font, platform_data.size(), synthetic_bold, (traits & NSFontItalicTrait) && !(substitute_font_traits & NSFontItalicTrait), - platform_data.Orientation(), + platform_data.Orientation(), font_description.FontOpticalSizing(), nullptr); // No variation paramaters in fallback. + if (!alternate_font) + return nullptr; + return FontDataFromFontPlatformData(alternate_font.get(), kDoNotRetain); } @@ -295,11 +317,43 @@ std::unique_ptr<FontPlatformData> FontCache::CreateFontPlatformData( // the returned FontPlatformData since it will not have a valid SkTypeface. std::unique_ptr<FontPlatformData> platform_data = FontPlatformDataFromNSFont( platform_font, size, synthetic_bold, synthetic_italic, - font_description.Orientation(), font_description.VariationSettings()); - if (!platform_data->Typeface()) { + font_description.Orientation(), font_description.FontOpticalSizing(), + font_description.VariationSettings()); + if (!platform_data || !platform_data->Typeface()) { return nullptr; } return platform_data; } +std::vector<FontEnumerationEntry> FontCache::EnumeratePlatformAvailableFonts() { + DCHECK(RuntimeEnabledFeatures::FontAccessEnabled()); + @autoreleasepool { + std::vector<FontEnumerationEntry> output; + + CFTypeRef values[1] = {kCFBooleanTrue}; + base::ScopedCFTypeRef<CFDictionaryRef> options(CFDictionaryCreate( + kCFAllocatorDefault, + (const void**)kCTFontCollectionRemoveDuplicatesOption, + (const void**)&values, + /*numValues=*/1, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); + base::ScopedCFTypeRef<CTFontCollectionRef> collection( + CTFontCollectionCreateFromAvailableFonts(options)); + + base::ScopedCFTypeRef<CFArrayRef> font_descs( + CTFontCollectionCreateMatchingFontDescriptors(collection)); + + for (CFIndex i = 0; i < CFArrayGetCount(font_descs); ++i) { + CTFontDescriptorRef fd = base::mac::CFCast<CTFontDescriptorRef>( + CFArrayGetValueAtIndex(font_descs, i)); + NSString* postscript_name = GetString(fd, kCTFontNameAttribute); + NSString* full_name = GetLocalizedString(fd, kCTFontDisplayNameAttribute); + NSString* family = GetLocalizedString(fd, kCTFontFamilyNameAttribute); + output.push_back(FontEnumerationEntry{String(postscript_name), + String(full_name), String(family)}); + } + return output; + } +} + } // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm b/chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm index 8d01704041c..cf25ba022f2 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm +++ b/chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm @@ -46,7 +46,7 @@ namespace { -static CGFloat toYosemiteFontWeight(blink::FontSelectionValue font_weight) { +static CGFloat toFontWeight(blink::FontSelectionValue font_weight) { static uint64_t ns_font_weights[] = { 0xbfe99999a0000000, // NSFontWeightUltraLight 0xbfe3333340000000, // NSFontWeightThin @@ -181,8 +181,7 @@ NSFont* MatchNSFontFamily(const AtomicString& desired_family_string, // On OSX 10.10+, the default system font has more weights. #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunguarded-availability" - font = [NSFont systemFontOfSize:size - weight:toYosemiteFontWeight(desired_weight)]; + font = [NSFont systemFontOfSize:size weight:toFontWeight(desired_weight)]; #pragma clang diagnostic pop if (desired_traits & IMPORTANT_FONT_TRAITS) diff --git a/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h b/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h index b1224beff2c..cd0e338cdb5 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h +++ b/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h @@ -31,6 +31,8 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_MAC_FONT_PLATFORM_DATA_MAC_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_MAC_FONT_PLATFORM_DATA_MAC_H_ +#include "third_party/blink/renderer/platform/fonts/font_optical_sizing.h" + #include <memory> @class NSFont; @@ -47,6 +49,7 @@ std::unique_ptr<FontPlatformData> FontPlatformDataFromNSFont( bool synthetic_bold, bool synthetic_italic, FontOrientation, + OpticalSizing, FontVariationSettings*); } // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm b/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm index 16bcce4ba40..9bc59e46e5e 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm +++ b/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm @@ -27,21 +27,26 @@ #import <AvailabilityMacros.h> #include "base/mac/foundation_util.h" -#include "base/mac/scoped_cftyperef.h" #include "base/mac/scoped_nsobject.h" #include "base/stl_util.h" #import "third_party/blink/public/platform/mac/web_sandbox_support.h" #import "third_party/blink/public/platform/platform.h" #import "third_party/blink/renderer/platform/fonts/font.h" #import "third_party/blink/renderer/platform/fonts/font_platform_data.h" +#import "third_party/blink/renderer/platform/fonts/mac/core_text_font_format_support.h" #import "third_party/blink/renderer/platform/fonts/opentype/font_settings.h" #import "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h" #import "third_party/blink/renderer/platform/web_test_support.h" #import "third_party/blink/renderer/platform/wtf/text/wtf_string.h" #import "third_party/skia/include/core/SkFont.h" #import "third_party/skia/include/core/SkStream.h" +#import "third_party/skia/include/core/SkTypes.h" #import "third_party/skia/include/ports/SkTypeface_mac.h" +namespace { +constexpr SkFourByteTag kOpszTag = SkSetFourByteTag('o', 'p', 's', 'z'); +} + namespace blink { static bool CanLoadInProcess(NSFont* ns_font) { @@ -53,10 +58,10 @@ static bool CanLoadInProcess(NSFont* ns_font) { return ![font_name isEqualToString:@"LastResort"]; } -static CTFontDescriptorRef CascadeToLastResortFontDescriptor() { - static CTFontDescriptorRef descriptor; - if (descriptor) - return descriptor; +static CFDictionaryRef CascadeToLastResortFontAttributes() { + static CFDictionaryRef attributes; + if (attributes) + return attributes; base::ScopedCFTypeRef<CTFontDescriptorRef> last_resort( CTFontDescriptorCreateWithNameAndSize(CFSTR("LastResort"), 0)); @@ -67,13 +72,10 @@ static CTFontDescriptorRef CascadeToLastResortFontDescriptor() { const void* keys[] = {kCTFontCascadeListAttribute}; const void* values[] = {values_array}; - base::ScopedCFTypeRef<CFDictionaryRef> attributes(CFDictionaryCreate( + attributes = CFDictionaryCreate( kCFAllocatorDefault, keys, values, base::size(keys), - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); - - descriptor = CTFontDescriptorCreateWithAttributes(attributes); - - return descriptor; + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + return attributes; } static sk_sp<SkTypeface> LoadFromBrowserProcess(NSFont* ns_font, @@ -88,20 +90,23 @@ static sk_sp<SkTypeface> LoadFromBrowserProcess(NSFont* ns_font, return nullptr; } - CGFontRef loaded_cg_font; + base::ScopedCFTypeRef<CTFontDescriptorRef> loaded_data_descriptor; uint32_t font_id; if (!sandbox_support->LoadFont(base::mac::NSToCFCast(ns_font), - &loaded_cg_font, &font_id)) { + &loaded_data_descriptor, &font_id)) { // TODO crbug.com/461279: Make this appear in the inspector console? DLOG(ERROR) << "Loading user font \"" << [[ns_font familyName] UTF8String] << "\" from non system location failed. Corrupt or missing font file?"; return nullptr; } - base::ScopedCFTypeRef<CGFontRef> cg_font(loaded_cg_font); - base::ScopedCFTypeRef<CTFontRef> ct_font(CTFontCreateWithGraphicsFont( - cg_font, text_size, 0, CascadeToLastResortFontDescriptor())); - sk_sp<SkTypeface> return_font(SkCreateTypefaceFromCTFont(ct_font, cg_font)); + + base::ScopedCFTypeRef<CTFontDescriptorRef> data_descriptor_with_cascade( + CTFontDescriptorCreateCopyWithAttributes( + loaded_data_descriptor, CascadeToLastResortFontAttributes())); + base::ScopedCFTypeRef<CTFontRef> ct_font(CTFontCreateWithFontDescriptor( + data_descriptor_with_cascade.get(), text_size, 0)); + sk_sp<SkTypeface> return_font = SkMakeTypefaceFromCTFont(ct_font); if (!return_font.get()) // TODO crbug.com/461279: Make this appear in the inspector console? @@ -117,11 +122,12 @@ std::unique_ptr<FontPlatformData> FontPlatformDataFromNSFont( bool synthetic_bold, bool synthetic_italic, FontOrientation orientation, + OpticalSizing optical_sizing, FontVariationSettings* variation_settings) { DCHECK(ns_font); sk_sp<SkTypeface> typeface; if (CanLoadInProcess(ns_font)) { - typeface.reset(SkCreateTypefaceFromCTFont(base::mac::NSToCFCast(ns_font))); + typeface = SkMakeTypefaceFromCTFont(base::mac::NSToCFCast(ns_font)); } else { // In process loading fails for cases where third party font manager // software registers fonts in non system locations such as /Library/Fonts @@ -129,26 +135,79 @@ std::unique_ptr<FontPlatformData> FontPlatformDataFromNSFont( typeface = LoadFromBrowserProcess(ns_font, size); } - if (variation_settings && variation_settings->size() < UINT16_MAX) { - SkFontArguments::Axis axes[variation_settings->size()]; - for (size_t i = 0; i < variation_settings->size(); ++i) { - AtomicString feature_tag = variation_settings->at(i).Tag(); - axes[i] = {AtomicStringToFourByteTag(feature_tag), - SkFloatToScalar(variation_settings->at(i).Value())}; + auto make_typeface_fontplatformdata = [&typeface, &size, &synthetic_bold, + &synthetic_italic, &orientation]() { + return std::make_unique<FontPlatformData>( + std::move(typeface), std::string(), size, synthetic_bold, + synthetic_italic, orientation); + }; + + wtf_size_t valid_configured_axes = + variation_settings && variation_settings->size() < UINT16_MAX + ? variation_settings->size() + : 0; + + // No variable font requested, return static font. + if (!valid_configured_axes && optical_sizing == kNoneOpticalSizing) + return make_typeface_fontplatformdata(); + + if (!typeface) + return nullptr; + + int existing_axes = typeface->getVariationDesignPosition(nullptr, 0); + // Don't apply variation parameters if the font does not have axes or we + // fail to retrieve the existing ones. + if (existing_axes <= 0) + return make_typeface_fontplatformdata(); + + Vector<SkFontArguments::VariationPosition::Coordinate> coordinates_to_set; + coordinates_to_set.resize(existing_axes); + + if (typeface->getVariationDesignPosition(coordinates_to_set.data(), + existing_axes) != existing_axes) { + return make_typeface_fontplatformdata(); + } + + // Iterate over the font's axes and find a missing tag from variation + // settings, special case opsz, track the number of axes reconfigured. + bool axes_reconfigured = false; + for (auto& coordinate : coordinates_to_set) { + // Set opsz to font size but allow having it overriden by + // font-variation-settings in case it has 'opsz'. + if (coordinate.axis == kOpszTag && optical_sizing == kAutoOpticalSizing) { + if (coordinate.value != SkFloatToScalar(size)) { + coordinate.value = SkFloatToScalar(size); + axes_reconfigured = true; + } + } + FontVariationAxis found_variation_setting(AtomicString(), 0); + if (variation_settings && + variation_settings->FindPair(FourByteTagToAtomicString(coordinate.axis), + &found_variation_setting)) { + if (coordinate.value != found_variation_setting.Value()) { + coordinate.value = found_variation_setting.Value(); + axes_reconfigured = true; + } } - sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault()); - // TODO crbug.com/670246: Refactor this to a future Skia API that acccepts - // axis parameters on system fonts directly. - typeface = fm->makeFromStream( - typeface->openStream(nullptr)->duplicate(), - SkFontArguments().setAxes(axes, variation_settings->size())); } - return std::make_unique<FontPlatformData>( - std::move(typeface), - std::string(), // family_ doesn't exist on Mac, this avoids conversion - // from NSString which requires including a //base header - size, synthetic_bold, synthetic_italic, orientation); + if (!axes_reconfigured) { + // No variable axes touched, return the previous typeface. + return make_typeface_fontplatformdata(); + } + + SkFontArguments::VariationPosition variation_design_position{ + coordinates_to_set.data(), coordinates_to_set.size()}; + + sk_sp<SkTypeface> cloned_typeface(typeface->makeClone( + SkFontArguments().setVariationDesignPosition(variation_design_position))); + + if (!cloned_typeface) { + // Applying varition parameters failed, return original typeface. + return make_typeface_fontplatformdata(); + } + typeface = cloned_typeface; + return make_typeface_fontplatformdata(); } void FontPlatformData::SetupSkFont(SkFont* skfont, |