diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/fonts')
41 files changed, 795 insertions, 490 deletions
diff --git a/chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.cc b/chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.cc index 0b211881222..be4552bc788 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.cc @@ -4,39 +4,15 @@ #include "third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.h" #include "mojo/public/mojom/base/shared_memory.mojom-blink.h" -#include "third_party/blink/public/platform/interface_provider.h" #include "third_party/blink/public/platform/modules/font_unique_name_lookup/font_unique_name_lookup.mojom-blink.h" -#include "third_party/blink/public/platform/platform.h" namespace blink { FontUniqueNameLookupAndroid::~FontUniqueNameLookupAndroid() = default; -bool FontUniqueNameLookupAndroid::EnsureMatchingServiceConnected() { - if (font_table_matcher_) - return true; - - mojom::blink::FontUniqueNameLookupPtr service; - Platform::Current()->GetInterfaceProvider()->GetInterface( - mojo::MakeRequest(&service)); - - base::ReadOnlySharedMemoryRegion region_ptr; - if (!service->GetUniqueNameLookupTable(®ion_ptr)) { - // Tests like StyleEngineTest do not set up a full browser where Blink can - // connect to a browser side service for font lookups. Placing a DCHECK here - // is too strict for such a case. - LOG(ERROR) << "Unable to connect to browser side service for src: local() " - "font lookup."; - return false; - } - - font_table_matcher_ = std::make_unique<FontTableMatcher>(region_ptr.Map()); - return true; -} - sk_sp<SkTypeface> FontUniqueNameLookupAndroid::MatchUniqueName( const String& font_unique_name) { - if (!EnsureMatchingServiceConnected()) + if (!EnsureMatchingServiceConnected<mojom::blink::FontUniqueNameLookupPtr>()) return nullptr; base::Optional<FontTableMatcher::MatchResult> match_result = font_table_matcher_->MatchName(font_unique_name.Utf8().data()); diff --git a/chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.h b/chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.h index 54b1cc7c177..4447709a405 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.h +++ b/chromium/third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.h @@ -19,8 +19,6 @@ class FontUniqueNameLookupAndroid : public FontUniqueNameLookup { sk_sp<SkTypeface> MatchUniqueName(const String& font_unique_name) override; private: - bool EnsureMatchingServiceConnected(); - std::unique_ptr<FontTableMatcher> font_table_matcher_; DISALLOW_COPY_AND_ASSIGN(FontUniqueNameLookupAndroid); }; diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_cache.cc b/chromium/third_party/blink/renderer/platform/fonts/font_cache.cc index b72da9f7015..92d453b5a84 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/font_cache.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/font_cache.cc @@ -46,6 +46,7 @@ #include "third_party/blink/renderer/platform/fonts/font_global_context.h" #include "third_party/blink/renderer/platform/fonts/font_platform_data.h" #include "third_party/blink/renderer/platform/fonts/font_smoothing_mode.h" +#include "third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h" #include "third_party/blink/renderer/platform/fonts/shaping/shape_cache.h" #include "third_party/blink/renderer/platform/fonts/simple_font_data.h" #include "third_party/blink/renderer/platform/fonts/text_rendering_mode.h" @@ -117,7 +118,10 @@ FontPlatformData* FontCache::GetFontPlatformData( float size = font_description.EffectiveFontSize(); unsigned rounded_size = size * FontCacheKey::PrecisionMultiplier(); - FontCacheKey key = font_description.CacheKey(creation_params); + bool is_unique_match = + alternate_font_name == AlternateFontName::kLocalUniqueFace; + FontCacheKey key = + font_description.CacheKey(creation_params, is_unique_match); // Remove the font size from the cache key, and handle the font size // separately in the inner HashMap. So that different size of FontPlatformData @@ -440,4 +444,18 @@ void FontCache::DumpShapeResultCache( WTF::Partitions::kAllocatedObjectPoolName); } +sk_sp<SkTypeface> FontCache::CreateTypefaceFromUniqueName( + const FontFaceCreationParams& creation_params, + CString& name) { + FontUniqueNameLookup* unique_name_lookup = + FontGlobalContext::Get()->GetFontUniqueNameLookup(); + DCHECK(unique_name_lookup); + sk_sp<SkTypeface> uniquely_identified_font = + unique_name_lookup->MatchUniqueName(creation_params.Family()); + if (uniquely_identified_font) { + return uniquely_identified_font; + } + return nullptr; +} + } // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_cache.h b/chromium/third_party/blink/renderer/platform/fonts/font_cache.h index f32563d2997..589e0baf11a 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/font_cache.h +++ b/chromium/third_party/blink/renderer/platform/fonts/font_cache.h @@ -253,6 +253,9 @@ class PLATFORM_EXPORT FontCache { UChar32, const SimpleFontData* font_data_to_substitute, FontFallbackPriority = FontFallbackPriority::kText); + sk_sp<SkTypeface> CreateTypefaceFromUniqueName( + const FontFaceCreationParams& creation_params, + CString& name); friend class FontGlobalContext; FontCache(); diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_cache_key.h b/chromium/third_party/blink/renderer/platform/fonts/font_cache_key.h index a7823cbb3e2..f9d07ff2efa 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/font_cache_key.h +++ b/chromium/third_party/blink/renderer/platform/fonts/font_cache_key.h @@ -53,17 +53,20 @@ struct FontCacheKey { : creation_params_(), font_size_(0), options_(0), - device_scale_factor_(0) {} + device_scale_factor_(0), + is_unique_match_(false) {} FontCacheKey(FontFaceCreationParams creation_params, float font_size, unsigned options, float device_scale_factor, - scoped_refptr<FontVariationSettings> variation_settings) + scoped_refptr<FontVariationSettings> variation_settings, + bool is_unique_match) : creation_params_(creation_params), font_size_(font_size * kFontSizePrecisionMultiplier), options_(options), device_scale_factor_(device_scale_factor), - variation_settings_(std::move(variation_settings)) {} + variation_settings_(std::move(variation_settings)), + is_unique_match_(is_unique_match) {} FontCacheKey(WTF::HashTableDeletedValueType) : font_size_(HashTableDeletedSize()) {} @@ -71,10 +74,13 @@ struct FontCacheKey { unsigned GetHash() const { // Convert from float with 3 digit precision before hashing. unsigned device_scale_factor_hash = device_scale_factor_ * 1000; - unsigned hash_codes[5] = { - creation_params_.GetHash(), font_size_, options_, + unsigned hash_codes[6] = { + creation_params_.GetHash(), + font_size_, + options_, device_scale_factor_hash, - variation_settings_ ? variation_settings_->GetHash() : 0}; + variation_settings_ ? variation_settings_->GetHash() : 0, + is_unique_match_}; return StringHasher::HashMemory<sizeof(hash_codes)>(hash_codes); } @@ -82,7 +88,8 @@ struct FontCacheKey { return creation_params_ == other.creation_params_ && font_size_ == other.font_size_ && options_ == other.options_ && device_scale_factor_ == other.device_scale_factor_ && - variation_settings_ == other.variation_settings_; + variation_settings_ == other.variation_settings_ && + is_unique_match_ == other.is_unique_match_; } bool IsHashTableDeletedValue() const { @@ -105,6 +112,7 @@ struct FontCacheKey { // device_scale_factor_ to be a part of computing the cache key. float device_scale_factor_; scoped_refptr<FontVariationSettings> variation_settings_; + bool is_unique_match_; }; struct FontCacheKeyHash { diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_description.cc b/chromium/third_party/blink/renderer/platform/fonts/font_description.cc index 32d2a97d5a2..63eff2f4e24 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/font_description.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/font_description.cc @@ -214,6 +214,7 @@ float FontDescription::EffectiveFontSize() const { FontCacheKey FontDescription::CacheKey( const FontFaceCreationParams& creation_params, + bool is_unique_match, const FontSelectionRequest& font_selection_request) const { unsigned options = static_cast<unsigned>(fields_.synthetic_italic_) << 6 | // bit 7 @@ -229,7 +230,8 @@ FontCacheKey FontDescription::CacheKey( #endif FontCacheKey cache_key(creation_params, EffectiveFontSize(), options | font_selection_request_.GetHash() << 8, - device_scale_factor_for_key, variation_settings_); + device_scale_factor_for_key, variation_settings_, + is_unique_match); return cache_key; } diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_description.h b/chromium/third_party/blink/renderer/platform/fonts/font_description.h index 925923d8ff1..f97284d0220 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/font_description.h +++ b/chromium/third_party/blink/renderer/platform/fonts/font_description.h @@ -252,6 +252,7 @@ class PLATFORM_EXPORT FontDescription { const; // Returns either the computedSize or the computedPixelSize FontCacheKey CacheKey( const FontFaceCreationParams&, + bool is_unique_match, const FontSelectionRequest& = FontSelectionRequest()) const; void SetFamily(const FontFamily& family) { family_list_ = family; } diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_description_test.cc b/chromium/third_party/blink/renderer/platform/fonts/font_description_test.cc index e573d634fb5..c5935c6bfb4 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/font_description_test.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/font_description_test.cc @@ -25,6 +25,7 @@ #include "third_party/blink/renderer/platform/fonts/font_description.h" +#include "base/stl_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/platform/wtf/vector.h" @@ -48,11 +49,11 @@ TEST(FontDescriptionTest, TestHashCollision) { FontDescription source; WTF::Vector<unsigned> hashes; - for (size_t i = 0; i < arraysize(weights); i++) { + for (size_t i = 0; i < base::size(weights); i++) { source.SetWeight(weights[i]); - for (size_t j = 0; j < arraysize(stretches); j++) { + for (size_t j = 0; j < base::size(stretches); j++) { source.SetStretch(stretches[j]); - for (size_t k = 0; k < arraysize(slopes); k++) { + for (size_t k = 0; k < base::size(slopes); k++) { source.SetStyle(slopes[k]); unsigned hash = source.StyleHashWithoutFamilyList(); ASSERT_FALSE(hashes.Contains(hash)); diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.cc b/chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.cc index 85e8fbc134c..be346f33c16 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.cc @@ -202,7 +202,8 @@ FallbackListCompositeKey FontFallbackList::CompositeKey( platform_data); } if (result) { - key.Add(font_description.CacheKey(params)); + bool is_unique_match = false; + key.Add(font_description.CacheKey(params, is_unique_match)); if (!result->IsSegmented() && !result->IsCustomFont()) FontCache::GetFontCache()->ReleaseFontData(ToSimpleFontData(result)); } diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_metrics.cc b/chromium/third_party/blink/renderer/platform/fonts/font_metrics.cc index abc03f40a1b..b4ed950174e 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/font_metrics.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/font_metrics.cc @@ -34,6 +34,7 @@ #include "third_party/blink/renderer/platform/fonts/vdmx_parser.h" #include <SkFont.h> +#include <SkFontMetrics.h> #include <SkTypeface.h> namespace blink { diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_platform_data.cc b/chromium/third_party/blink/renderer/platform/fonts/font_platform_data.cc index 64dd8218e9a..77b09a33375 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/font_platform_data.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/font_platform_data.cc @@ -51,7 +51,7 @@ FontPlatformData::FontPlatformData(WTF::HashTableDeletedValueType) is_hash_table_deleted_value_(true) #if defined(OS_WIN) , - paint_text_flags_(0) + font_flags_(0) #endif { } @@ -65,7 +65,7 @@ FontPlatformData::FontPlatformData() is_hash_table_deleted_value_(false) #if defined(OS_WIN) , - paint_text_flags_(0) + font_flags_(0) #endif { } @@ -82,7 +82,7 @@ FontPlatformData::FontPlatformData(float size, is_hash_table_deleted_value_(false) #if defined(OS_WIN) , - paint_text_flags_(0) + font_flags_(0) #endif { } @@ -104,7 +104,7 @@ FontPlatformData::FontPlatformData(const FontPlatformData& source) is_hash_table_deleted_value_(false) #if defined(OS_WIN) , - paint_text_flags_(source.paint_text_flags_) + font_flags_(source.font_flags_) #endif { } @@ -140,7 +140,7 @@ FontPlatformData::FontPlatformData(sk_sp<SkTypeface> typeface, is_hash_table_deleted_value_(false) #if defined(OS_WIN) , - paint_text_flags_(0) + font_flags_(0) #endif { #if !defined(OS_WIN) && !defined(OS_MACOSX) @@ -200,7 +200,7 @@ const FontPlatformData& FontPlatformData::operator=( #endif #if defined(OS_WIN) - paint_text_flags_ = 0; + font_flags_ = 0; #endif return *this; @@ -311,20 +311,6 @@ WebFontRenderStyle FontPlatformData::QuerySystemRenderStyle( return result; } -void FontPlatformData::SetupSkPaint(SkPaint* font, - float device_scale_factor, - const Font*) const { - style_.ApplyToSkPaint(*font, device_scale_factor); - - const float ts = text_size_ >= 0 ? text_size_ : 12; - font->setTextSize(SkFloatToScalar(ts)); - font->setTypeface(typeface_); - font->setFakeBoldText(synthetic_bold_); - font->setTextSkewX(synthetic_italic_ ? -SK_Scalar1 / 4 : 0); - - font->setEmbeddedBitmapText(!avoid_embedded_bitmaps_); -} - void FontPlatformData::SetupSkFont(SkFont* font, float device_scale_factor, const Font*) const { diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_platform_data.h b/chromium/third_party/blink/renderer/platform/fonts/font_platform_data.h index 7c6939331e2..e2e018ff469 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/font_platform_data.h +++ b/chromium/third_party/blink/renderer/platform/fonts/font_platform_data.h @@ -31,8 +31,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_PLATFORM_DATA_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_PLATFORM_DATA_H_ -#include "SkPaint.h" -#include "SkTypeface.h" #include "base/memory/scoped_refptr.h" #include "build/build_config.h" #include "third_party/blink/public/platform/web_font_render_style.h" @@ -46,6 +44,7 @@ #include "third_party/blink/renderer/platform/wtf/text/cstring.h" #include "third_party/blink/renderer/platform/wtf/text/string_impl.h" #include "third_party/blink/renderer/platform/wtf/vector.h" +#include "third_party/skia/include/core/SkFont.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkTypeface.h" @@ -154,17 +153,17 @@ class PLATFORM_EXPORT FontPlatformData { const WebFontRenderStyle& GetFontRenderStyle() const { return style_; } #endif - // TODO(reed): SetupSkPaint is deprecated. Remove this once all call sites - // are moved to SetupSkFont. - void SetupSkPaint(SkPaint*, - float device_scale_factor = 1, - const Font* = nullptr) const; void SetupSkFont(SkFont*, float device_scale_factor = 1, const Font* = nullptr) const; #if defined(OS_WIN) - int PaintTextFlags() const { return paint_text_flags_; } + enum Flags { + kAntiAlias = 1 << 0, + kSubpixelsAntiAlias = 1 << 1, + kSubpixelMetrics = 1 << 2, + }; + int FontFlags() const { return font_flags_; } #endif private: @@ -199,8 +198,8 @@ class PLATFORM_EXPORT FontPlatformData { mutable scoped_refptr<HarfBuzzFace> harfbuzz_face_; bool is_hash_table_deleted_value_; #if defined(OS_WIN) - // TODO(https://crbug.com/808221): Replace |paint_text_flags_| with |style_|. - int paint_text_flags_; + // TODO(https://crbug.com/808221): Replace |font_flags_| with |style_|. + int font_flags_; #endif }; diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_selection_types.h b/chromium/third_party/blink/renderer/platform/fonts/font_selection_types.h index 5fb1723e2fe..85d2cb47c23 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/font_selection_types.h +++ b/chromium/third_party/blink/renderer/platform/fonts/font_selection_types.h @@ -185,6 +185,18 @@ static inline const FontSelectionValue& ItalicSlopeValue() { return italicValue; } +static inline const FontSelectionValue& MaxObliqueValue() { + DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValue, maxObliqueValue, + (90)); + return maxObliqueValue; +} + +static inline const FontSelectionValue& MinObliqueValue() { + DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValue, minObliqueValue, + (-90)); + return minObliqueValue; +} + static inline const FontSelectionValue& BoldThreshold() { DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValue, boldThreshold, (600)); diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_unique_name_lookup.cc b/chromium/third_party/blink/renderer/platform/fonts/font_unique_name_lookup.cc index 1a084984c34..ef45e9929b1 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/font_unique_name_lookup.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/font_unique_name_lookup.cc @@ -4,12 +4,17 @@ #include "third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h" #include "base/macros.h" -#include "build/build_config.h" +#include "third_party/blink/public/platform/interface_provider.h" +#include "third_party/blink/public/platform/platform.h" #if defined(OS_ANDROID) +#include "third_party/blink/public/platform/modules/font_unique_name_lookup/font_unique_name_lookup.mojom-blink.h" #include "third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.h" #elif defined(OS_LINUX) #include "third_party/blink/renderer/platform/fonts/linux/font_unique_name_lookup_linux.h" +#elif defined(OS_WIN) +#include "third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom-blink.h" +#include "third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.h" #endif namespace blink { @@ -23,10 +28,45 @@ FontUniqueNameLookup::GetPlatformUniqueNameLookup() { return std::make_unique<FontUniqueNameLookupAndroid>(); #elif defined(OS_LINUX) return std::make_unique<FontUniqueNameLookupLinux>(); +#elif defined(OS_WIN) + return std::make_unique<FontUniqueNameLookupWin>(); #else NOTREACHED(); return nullptr; #endif } +#if defined(OS_WIN) || defined(OS_ANDROID) +template <class ServicePtrType> +bool FontUniqueNameLookup::EnsureMatchingServiceConnected() { + if (font_table_matcher_) + return true; + + ServicePtrType service; + Platform::Current()->GetInterfaceProvider()->GetInterface( + mojo::MakeRequest(&service)); + + base::ReadOnlySharedMemoryRegion region_ptr; + if (!service->GetUniqueNameLookupTable(®ion_ptr)) { + // Tests like StyleEngineTest do not set up a full browser where Blink can + // connect to a browser side service for font lookups. Placing a DCHECK here + // is too strict for such a case. + LOG(ERROR) << "Unable to connect to browser side service for src: local() " + "font lookup."; + return false; + } + + font_table_matcher_ = std::make_unique<FontTableMatcher>(region_ptr.Map()); + return true; +} +#endif + +#if defined(OS_ANDROID) +template bool FontUniqueNameLookup::EnsureMatchingServiceConnected< + mojom::blink::FontUniqueNameLookupPtr>(); +#elif defined(OS_WIN) +template bool FontUniqueNameLookup::EnsureMatchingServiceConnected< + mojom::blink::DWriteFontProxyPtr>(); +#endif + } // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h b/chromium/third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h index 38428c7a9dc..58f5390436b 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h +++ b/chromium/third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h @@ -6,14 +6,21 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_UNIQUE_NAME_LOOKUP_H_ #include "base/macros.h" +#include "build/build_config.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" +#if defined(OS_ANDROID) || defined(OS_WIN) +#include "third_party/blink/public/common/font_unique_name_lookup/font_table_matcher.h" +#endif + #include <SkRefCnt.h> #include <SkTypeface.h> #include <memory> namespace blink { +class FontTableMatcher; + class FontUniqueNameLookup { public: // Factory function to construct a platform specific font unique name lookup @@ -28,6 +35,14 @@ class FontUniqueNameLookup { protected: FontUniqueNameLookup(); + // Windows and Android share the concept of connecting to a Mojo service for + // retrieving a ReadOnlySharedMemoryRegion with the lookup table in it. +#if defined(OS_WIN) || defined(OS_ANDROID) + template <class ServicePtrType> + bool EnsureMatchingServiceConnected(); + std::unique_ptr<FontTableMatcher> font_table_matcher_; +#endif + DISALLOW_COPY_AND_ASSIGN(FontUniqueNameLookup); }; 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 97bebbdb53a..1fcd34ea515 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 @@ -25,6 +25,8 @@ #import <AppKit/NSFont.h> #import <AvailabilityMacros.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" @@ -59,13 +61,13 @@ static CTFontDescriptorRef CascadeToLastResortFontDescriptor() { const void* descriptors[] = {last_resort.Get()}; RetainPtr<CFArrayRef> values_array( kAdoptCF, CFArrayCreate(kCFAllocatorDefault, descriptors, - arraysize(descriptors), &kCFTypeArrayCallBacks)); + base::size(descriptors), &kCFTypeArrayCallBacks)); const void* keys[] = {kCTFontCascadeListAttribute}; const void* values[] = {values_array.Get()}; RetainPtr<CFDictionaryRef> attributes( kAdoptCF, - CFDictionaryCreate(kCFAllocatorDefault, keys, values, arraysize(keys), + CFDictionaryCreate(kCFAllocatorDefault, keys, values, base::size(keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); @@ -112,58 +114,6 @@ static sk_sp<SkTypeface> LoadFromBrowserProcess(NSFont* ns_font, return return_font; } -void FontPlatformData::SetupSkPaint(SkPaint* paint, - float, - const Font* font) const { - bool should_smooth_fonts = true; - bool should_antialias = true; - bool should_subpixel_position = true; - - if (font) { - switch (font->GetFontDescription().FontSmoothing()) { - case kAntialiased: - should_smooth_fonts = false; - break; - case kSubpixelAntialiased: - break; - case kNoSmoothing: - should_antialias = false; - should_smooth_fonts = false; - break; - case kAutoSmoothing: - // For the AutoSmooth case, don't do anything! Keep the default - // settings. - break; - } - } - - if (WebTestSupport::IsRunningWebTest()) { - should_smooth_fonts = false; - should_antialias = - should_antialias && WebTestSupport::IsFontAntialiasingEnabledForTest(); - should_subpixel_position = - WebTestSupport::IsTextSubpixelPositioningAllowedForTest(); - } - - paint->setAntiAlias(should_antialias); - paint->setEmbeddedBitmapText(false); - const float ts = text_size_ >= 0 ? text_size_ : 12; - paint->setTextSize(SkFloatToScalar(ts)); - paint->setTypeface(typeface_); - paint->setFakeBoldText(synthetic_bold_); - paint->setTextSkewX(synthetic_italic_ ? -SK_Scalar1 / 4 : 0); - paint->setLCDRenderText(should_smooth_fonts); - paint->setSubpixelText(should_subpixel_position); - - // When rendering using CoreGraphics, disable hinting when - // webkit-font-smoothing:antialiased or text-rendering:geometricPrecision is - // used. See crbug.com/152304 - if (font && - (font->GetFontDescription().FontSmoothing() == kAntialiased || - font->GetFontDescription().TextRendering() == kGeometricPrecision)) - paint->setHinting(SkFontHinting::kNone); -} - void FontPlatformData::SetupSkFont(SkFont* skfont, float, const Font* font) const { diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.cc b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.cc index 3365749c759..4c18c37138f 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.cc @@ -4,13 +4,43 @@ #include "third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.h" +#include <hb-aat.h> +#include <hb.h> + namespace blink { +namespace { + +bool activationSelectorPresent( + hb_face_t* hb_face, + const hb_aat_layout_feature_type_t feature_type, + const hb_aat_layout_feature_selector_t enabled_selector_expectation) { + Vector<hb_aat_layout_feature_selector_info_t> feature_selectors; + unsigned num_feature_selectors = 0; + unsigned default_index = 0; + num_feature_selectors = hb_aat_layout_feature_type_get_selector_infos( + hb_face, feature_type, 0, nullptr, nullptr, nullptr); + feature_selectors.resize(num_feature_selectors); + if (!hb_aat_layout_feature_type_get_selector_infos( + hb_face, feature_type, 0, &num_feature_selectors, + feature_selectors.data(), &default_index)) { + return false; + } + for (hb_aat_layout_feature_selector_info_t selector_info : + feature_selectors) { + if (selector_info.enable == enabled_selector_expectation) + return true; + } + return false; +} +} // namespace + OpenTypeCapsSupport::OpenTypeCapsSupport() : harfbuzz_face_(nullptr), requested_caps_(FontDescription::kCapsNormal), font_support_(FontSupport::kFull), - caps_synthesis_(CapsSynthesis::kNone) {} + caps_synthesis_(CapsSynthesis::kNone), + font_format_(FontFormat::kUndetermined) {} OpenTypeCapsSupport::OpenTypeCapsSupport( const HarfBuzzFace* harfbuzz_face, @@ -19,7 +49,8 @@ OpenTypeCapsSupport::OpenTypeCapsSupport( : harfbuzz_face_(harfbuzz_face), requested_caps_(requested_caps), font_support_(FontSupport::kFull), - caps_synthesis_(CapsSynthesis::kNone) { + caps_synthesis_(CapsSynthesis::kNone), + font_format_(FontFormat::kUndetermined) { if (requested_caps != FontDescription::kCapsNormal) DetermineFontSupport(script); } @@ -102,24 +133,114 @@ CaseMapIntend OpenTypeCapsSupport::NeedsCaseChange( return case_map_intend; } +OpenTypeCapsSupport::FontFormat OpenTypeCapsSupport::GetFontFormat() const { + if (font_format_ == FontFormat::kUndetermined) { + hb_face_t* hb_face = hb_font_get_face( + harfbuzz_face_->GetScaledFont(nullptr, HarfBuzzFace::NoVerticalLayout)); + + std::unique_ptr<hb_blob_t, decltype(&hb_blob_destroy)> morx_blob( + hb_face_reference_table(hb_face, HB_TAG('m', 'o', 'r', 'x')), + hb_blob_destroy); + std::unique_ptr<hb_blob_t, decltype(&hb_blob_destroy)> mort_blob( + hb_face_reference_table(hb_face, HB_TAG('m', 'o', 'r', 't')), + hb_blob_destroy); + + // TODO(crbug.com/911149): Use hb_aat_layout_has_substitution() for + // has_morx_or_mort and hb_ot_layout_has_substitution() for has_gsub once is + // exposed in HarfBuzz. + bool has_morx_or_mort = hb_blob_get_length(morx_blob.get()) || + hb_blob_get_length(mort_blob.get()); + bool has_gsub = hb_ot_layout_has_substitution(hb_face); + font_format_ = has_morx_or_mort&& !has_gsub + ? font_format_ = FontFormat::kAat + : font_format_ = FontFormat::kOpenType; + } + return font_format_; +} + +bool OpenTypeCapsSupport::SupportsFeature(hb_script_t script, + uint32_t tag) const { + if (GetFontFormat() == FontFormat::kAat) + return SupportsAatFeature(tag); + return SupportsOpenTypeFeature(script, tag); +} + +bool OpenTypeCapsSupport::SupportsAatFeature(uint32_t tag) const { + // We only want to detect small-caps and capitals-to-small-capitals features + // for aat-fonts, any other requests are returned as not supported. + if (tag != HB_TAG('s', 'm', 'c', 'p') && tag != HB_TAG('c', '2', 's', 'c')) { + return false; + } + + hb_face_t* hb_face = hb_font_get_face( + harfbuzz_face_->GetScaledFont(nullptr, HarfBuzzFace::NoVerticalLayout)); + + Vector<hb_aat_layout_feature_type_t> aat_features; + unsigned feature_count = + hb_aat_layout_get_feature_types(hb_face, 0, nullptr, nullptr); + aat_features.resize(feature_count); + if (!hb_aat_layout_get_feature_types(hb_face, 0, &feature_count, + aat_features.data())) + return false; + + if (tag == HB_TAG('s', 'm', 'c', 'p')) { + // Check for presence of new style (feature id 38) or old style (letter + // case, feature id 3) small caps feature presence, then check for the + // specific required activation selectors. + if (!aat_features.Contains(HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE) && + !aat_features.Contains(HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE)) + return false; + + // Check for new style small caps, feature id 38. + if (aat_features.Contains(HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE)) { + if (activationSelectorPresent( + hb_face, HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE, + HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS)) + return true; + } + + // Check for old style small caps enabling selector, feature id 3. + if (aat_features.Contains(HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE)) { + if (activationSelectorPresent(hb_face, + HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE, + HB_AAT_LAYOUT_FEATURE_SELECTOR_SMALL_CAPS)) + return true; + } + + // Neither old or new style small caps present. + return false; + } + + if (tag == HB_TAG('c', '2', 's', 'c')) { + if (!aat_features.Contains(HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE)) + return false; + + return activationSelectorPresent( + hb_face, HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE, + HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_SMALL_CAPS); + } + + return false; +} + void OpenTypeCapsSupport::DetermineFontSupport(hb_script_t script) { switch (requested_caps_) { case FontDescription::kSmallCaps: - if (!SupportsOpenTypeFeature(script, HB_TAG('s', 'm', 'c', 'p'))) { + if (!SupportsFeature(script, HB_TAG('s', 'm', 'c', 'p'))) { font_support_ = FontSupport::kNone; caps_synthesis_ = CapsSynthesis::kLowerToSmallCaps; } break; case FontDescription::kAllSmallCaps: - if (!(SupportsOpenTypeFeature(script, HB_TAG('s', 'm', 'c', 'p')) && - SupportsOpenTypeFeature(script, HB_TAG('c', '2', 's', 'c')))) { + if (!(SupportsFeature(script, HB_TAG('s', 'm', 'c', 'p')) && + SupportsFeature(script, HB_TAG('c', '2', 's', 'c')))) { font_support_ = FontSupport::kNone; caps_synthesis_ = CapsSynthesis::kBothToSmallCaps; } break; case FontDescription::kPetiteCaps: - if (!SupportsOpenTypeFeature(script, HB_TAG('p', 'c', 'a', 'p'))) { - if (SupportsOpenTypeFeature(script, HB_TAG('s', 'm', 'c', 'p'))) { + if (!SupportsFeature(script, HB_TAG('p', 'c', 'a', 'p'))) { + if (SupportsFeature(script, HB_TAG('s', 'm', 'c', 'p'))) { font_support_ = FontSupport::kFallback; } else { font_support_ = FontSupport::kNone; @@ -128,10 +249,10 @@ void OpenTypeCapsSupport::DetermineFontSupport(hb_script_t script) { } break; case FontDescription::kAllPetiteCaps: - if (!(SupportsOpenTypeFeature(script, HB_TAG('p', 'c', 'a', 'p')) && - SupportsOpenTypeFeature(script, HB_TAG('c', '2', 'p', 'c')))) { - if (SupportsOpenTypeFeature(script, HB_TAG('s', 'm', 'c', 'p')) && - SupportsOpenTypeFeature(script, HB_TAG('c', '2', 's', 'c'))) { + if (!(SupportsFeature(script, HB_TAG('p', 'c', 'a', 'p')) && + SupportsFeature(script, HB_TAG('c', '2', 'p', 'c')))) { + if (SupportsFeature(script, HB_TAG('s', 'm', 'c', 'p')) && + SupportsFeature(script, HB_TAG('c', '2', 's', 'c'))) { font_support_ = FontSupport::kFallback; } else { font_support_ = FontSupport::kNone; @@ -140,9 +261,9 @@ void OpenTypeCapsSupport::DetermineFontSupport(hb_script_t script) { } break; case FontDescription::kUnicase: - if (!SupportsOpenTypeFeature(script, HB_TAG('u', 'n', 'i', 'c'))) { + if (!SupportsFeature(script, HB_TAG('u', 'n', 'i', 'c'))) { caps_synthesis_ = CapsSynthesis::kUpperToSmallCaps; - if (SupportsOpenTypeFeature(script, HB_TAG('s', 'm', 'c', 'p'))) { + if (SupportsFeature(script, HB_TAG('s', 'm', 'c', 'p'))) { font_support_ = FontSupport::kFallback; } else { font_support_ = FontSupport::kNone; @@ -150,7 +271,7 @@ void OpenTypeCapsSupport::DetermineFontSupport(hb_script_t script) { } break; case FontDescription::kTitlingCaps: - if (!SupportsOpenTypeFeature(script, HB_TAG('t', 'i', 't', 'l'))) { + if (!SupportsFeature(script, HB_TAG('t', 'i', 't', 'l'))) { font_support_ = FontSupport::kNone; } break; diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.h b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.h index 841e465c8a1..4f53191116f 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.h +++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.h @@ -29,7 +29,13 @@ class PLATFORM_EXPORT OpenTypeCapsSupport { CaseMapIntend NeedsCaseChange(SmallCapsIterator::SmallCapsBehavior run_case); private: + enum class FontFormat { kUndetermined, kOpenType, kAat }; + // Lazily intializes font_format_ when needed and returns the format of the + // underlying HarfBuzzFace/Font. + FontFormat GetFontFormat() const; void DetermineFontSupport(hb_script_t); + bool SupportsFeature(hb_script_t, uint32_t tag) const; + bool SupportsAatFeature(uint32_t tag) const; bool SupportsOpenTypeFeature(hb_script_t, uint32_t tag) const; const HarfBuzzFace* harfbuzz_face_; @@ -50,6 +56,7 @@ class PLATFORM_EXPORT OpenTypeCapsSupport { FontSupport font_support_; CapsSynthesis caps_synthesis_; + mutable FontFormat font_format_; }; }; // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support_test.cc b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support_test.cc new file mode 100644 index 00000000000..f0097556ae1 --- /dev/null +++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support_test.cc @@ -0,0 +1,59 @@ +// Copyright (c) 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.h" + +#include "build/build_config.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/platform/fonts/font_description.h" +#include "third_party/blink/renderer/platform/fonts/font_platform_data.h" + +#include "third_party/skia/include/core/SkRefCnt.h" +#include "third_party/skia/include/core/SkTypeface.h" + +#if defined(OS_MACOSX) +#include "base/mac/mac_util.h" +#endif + +namespace blink { + +void ensureHasNativeSmallCaps(const std::string& font_family_name) { + sk_sp<SkTypeface> test_typeface = + SkTypeface::MakeFromName(font_family_name.c_str(), SkFontStyle()); + FontPlatformData font_platform_data(test_typeface, font_family_name.c_str(), + 16, false, false); + ASSERT_EQ(font_platform_data.FontFamilyName(), font_family_name.c_str()); + + OpenTypeCapsSupport caps_support(font_platform_data.GetHarfBuzzFace(), + FontDescription::FontVariantCaps::kSmallCaps, + HB_SCRIPT_LATIN); + // If caps_support.NeedsRunCaseSplitting() is true, this means that synthetic + // upper-casing / lower-casing is required and the run needs to be segmented + // by upper-case, lower-case properties. If it is false, it means that the + // font feature can be used and no synthetic case-changing is needed. + ASSERT_FALSE(caps_support.NeedsRunCaseSplitting()); +} + +// The AAT fonts for testing are only available on Mac OS X 10.13. +#if defined(OS_MACOSX) +#define MAYBE_SmallCapsForSFNSText SmallCapsForSFNSText +#else +#define MAYBE_SmallCapsForSFNSText DISABLED_SmallCapsForSFNSText +#endif +TEST(OpenTypeCapsSupportTest, MAYBE_SmallCapsForSFNSText) { +#if defined(OS_MACOSX) + if (!base::mac::IsAtLeastOS10_13()) + return; +#endif + std::vector<std::string> test_fonts = { + ".SF NS Text", // has OpenType small-caps + "Apple Chancery", // has old-style (feature id 3,"Letter Case") + // small-caps + "Baskerville"}; // has new-style (feature id 38, "Upper Case") + // small-case. + for (auto& test_font : test_fonts) + ensureHasNativeSmallCaps(test_font); +} + +} // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.cc b/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.cc index 012238f1901..cf3bf20955d 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.cc @@ -168,7 +168,7 @@ ScriptRunIterator::ScriptRunIterator(const UChar* text, ScriptRunIterator::ScriptRunIterator(const UChar* text, wtf_size_t length) : ScriptRunIterator(text, length, ICUScriptData::Instance()) {} -bool ScriptRunIterator::Consume(unsigned& limit, UScriptCode& script) { +bool ScriptRunIterator::Consume(unsigned* limit, UScriptCode* script) { if (current_set_.IsEmpty()) { return false; } @@ -188,16 +188,16 @@ bool ScriptRunIterator::Consume(unsigned& limit, UScriptCode& script) { break; } if (!MergeSets()) { - limit = pos; - script = ResolveCurrentScript(); - FixupStack(script); + *limit = pos; + *script = ResolveCurrentScript(); + FixupStack(*script); current_set_ = *next_set_; return true; } } - limit = length_; - script = ResolveCurrentScript(); + *limit = length_; + *script = ResolveCurrentScript(); current_set_.clear(); return true; } diff --git a/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.h b/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.h index 6f3f16aead4..39d23e3b64f 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.h +++ b/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.h @@ -31,7 +31,7 @@ class PLATFORM_EXPORT ScriptRunIterator { // the process. ScriptRunIterator(const UChar* text, wtf_size_t length, const ScriptData*); - bool Consume(unsigned& limit, UScriptCode&); + bool Consume(unsigned* limit, UScriptCode*); static constexpr int kMaxScriptCount = 20; using UScriptCodeList = Vector<UScriptCode, kMaxScriptCount>; diff --git a/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator_test.cc b/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator_test.cc index a792bdfb5c8..0432f686457 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator_test.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator_test.cc @@ -316,7 +316,7 @@ class ScriptRunIteratorTest : public testing::Test { unsigned limit; UScriptCode code; unsigned long run_count = 0; - while (script_run_iterator->Consume(limit, code)) { + while (script_run_iterator->Consume(&limit, &code)) { ASSERT_LT(run_count, expect.size()); ASSERT_EQ(expect[run_count].limit, limit); ASSERT_EQ(expect[run_count].code, code); @@ -331,7 +331,7 @@ TEST_F(ScriptRunIteratorTest, Empty) { ScriptRunIterator script_run_iterator(empty.Characters16(), empty.length()); unsigned limit = 0; UScriptCode code = USCRIPT_INVALID_CODE; - DCHECK(!script_run_iterator.Consume(limit, code)); + DCHECK(!script_run_iterator.Consume(&limit, &code)); ASSERT_EQ(limit, 0u); ASSERT_EQ(code, USCRIPT_INVALID_CODE); } diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc index 3cef0162ce7..6e239ed1d33 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc @@ -553,7 +553,7 @@ void SplitUntilNextCaseChange( } } -hb_feature_t CreateFeature(hb_tag_t tag, uint32_t value = 0) { +constexpr hb_feature_t CreateFeature(hb_tag_t tag, uint32_t value = 0) { return {tag, value, 0 /* start */, static_cast<unsigned>(-1) /* end */}; } @@ -562,11 +562,11 @@ hb_feature_t CreateFeature(hb_tag_t tag, uint32_t value = 0) { void SetFontFeatures(const Font* font, FeaturesVector* features) { const FontDescription& description = font->GetFontDescription(); - static hb_feature_t no_kern = CreateFeature(HB_TAG('k', 'e', 'r', 'n')); - static hb_feature_t no_vkrn = CreateFeature(HB_TAG('v', 'k', 'r', 'n')); + constexpr hb_feature_t no_kern = CreateFeature(HB_TAG('k', 'e', 'r', 'n')); + constexpr hb_feature_t no_vkrn = CreateFeature(HB_TAG('v', 'k', 'r', 'n')); switch (description.GetKerning()) { case FontDescription::kNormalKerning: - // kern/vkrn are enabled by default + // kern/vkrn are enabled by default in HarfBuzz break; case FontDescription::kNoneKerning: features->push_back(description.IsVerticalAnyUpright() ? no_vkrn @@ -576,51 +576,41 @@ void SetFontFeatures(const Font* font, FeaturesVector* features) { break; } - static hb_feature_t no_clig = CreateFeature(HB_TAG('c', 'l', 'i', 'g')); - static hb_feature_t no_liga = CreateFeature(HB_TAG('l', 'i', 'g', 'a')); - switch (description.CommonLigaturesState()) { - case FontDescription::kDisabledLigaturesState: + { + bool default_is_off = description.TextRendering() == blink::kOptimizeSpeed; + bool letter_spacing = description.LetterSpacing() != 0; + constexpr auto normal = FontDescription::kNormalLigaturesState; + constexpr auto enabled = FontDescription::kEnabledLigaturesState; + constexpr auto disabled = FontDescription::kDisabledLigaturesState; + + // clig and liga are on by default in HarfBuzz + constexpr hb_feature_t no_clig = CreateFeature(HB_TAG('c', 'l', 'i', 'g')); + constexpr hb_feature_t no_liga = CreateFeature(HB_TAG('l', 'i', 'g', 'a')); + auto common = description.CommonLigaturesState(); + if (letter_spacing || + (common == disabled || (common == normal && default_is_off))) { features->push_back(no_liga); features->push_back(no_clig); - break; - case FontDescription::kEnabledLigaturesState: - // liga and clig are on by default - break; - case FontDescription::kNormalLigaturesState: - break; - } - static hb_feature_t dlig = CreateFeature(HB_TAG('d', 'l', 'i', 'g'), 1); - switch (description.DiscretionaryLigaturesState()) { - case FontDescription::kDisabledLigaturesState: - // dlig is off by default - break; - case FontDescription::kEnabledLigaturesState: + } + // dlig is off by default in HarfBuzz + constexpr hb_feature_t dlig = CreateFeature(HB_TAG('d', 'l', 'i', 'g'), 1); + auto discretionary = description.DiscretionaryLigaturesState(); + if (!letter_spacing && discretionary == enabled) { features->push_back(dlig); - break; - case FontDescription::kNormalLigaturesState: - break; - } - static hb_feature_t hlig = CreateFeature(HB_TAG('h', 'l', 'i', 'g'), 1); - switch (description.HistoricalLigaturesState()) { - case FontDescription::kDisabledLigaturesState: - // hlig is off by default - break; - case FontDescription::kEnabledLigaturesState: + } + // hlig is off by default in HarfBuzz + constexpr hb_feature_t hlig = CreateFeature(HB_TAG('h', 'l', 'i', 'g'), 1); + auto historical = description.HistoricalLigaturesState(); + if (!letter_spacing && historical == enabled) { features->push_back(hlig); - break; - case FontDescription::kNormalLigaturesState: - break; - } - static hb_feature_t no_calt = CreateFeature(HB_TAG('c', 'a', 'l', 't')); - switch (description.ContextualLigaturesState()) { - case FontDescription::kDisabledLigaturesState: + } + // calt is on by default in HarfBuzz + constexpr hb_feature_t no_calt = CreateFeature(HB_TAG('c', 'a', 'l', 't')); + auto contextual = description.ContextualLigaturesState(); + if (letter_spacing || + (contextual == disabled || (contextual == normal && default_is_off))) { features->push_back(no_calt); - break; - case FontDescription::kEnabledLigaturesState: - // calt is on by default - break; - case FontDescription::kNormalLigaturesState: - break; + } } static hb_feature_t hwid = CreateFeature(HB_TAG('h', 'w', 'i', 'd'), 1); diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc index 35e0d66e541..8767c55f3cc 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc @@ -114,7 +114,7 @@ class HarfBuzzShaperTest : public testing::Test { class ScopedSubpixelOverride { public: ScopedSubpixelOverride(bool b) { - prev_layout_test_ = WebTestSupport::IsRunningWebTest(); + prev_web_test_ = WebTestSupport::IsRunningWebTest(); prev_subpixel_allowed_ = WebTestSupport::IsTextSubpixelPositioningAllowedForTest(); prev_antialias_ = WebTestSupport::IsFontAntialiasingEnabledForTest(); @@ -147,7 +147,7 @@ class ScopedSubpixelOverride { WebTestSupport::SetFontAntialiasingEnabledForTest(prev_antialias_); WebTestSupport::SetTextSubpixelPositioningAllowedForTest( prev_subpixel_allowed_); - WebTestSupport::SetIsRunningWebTest(prev_layout_test_); + WebTestSupport::SetIsRunningWebTest(prev_web_test_); // Fonts cached with a different subpixel positioning state are not // automatically invalidated and need to be cleared between test @@ -156,7 +156,7 @@ class ScopedSubpixelOverride { } private: - bool prev_layout_test_; + bool prev_web_test_; bool prev_subpixel_allowed_; bool prev_antialias_; bool prev_fd_subpixel_; @@ -1232,13 +1232,13 @@ TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeIntoArabicThaiHanLatin) { composite_result->SnappedStartPositionForOffset(8)); } -TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeAcrossRuns) { +TEST_P(ShapeParameterTest, ShapeResultCopyRangeAcrossRuns) { // Create 3 runs: // [0]: 1 character. // [1]: 5 characters. // [2]: 2 character. String mixed_string(u"\u65E5Hello\u65E5\u65E5"); - TextDirection direction = TextDirection::kLtr; + TextDirection direction = GetParam(); HarfBuzzShaper shaper(mixed_string); scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction); @@ -1251,6 +1251,23 @@ TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeAcrossRuns) { EXPECT_EQ(2u, target->NumCharacters()); } +TEST_P(ShapeParameterTest, ShapeResultCopyRangeContextMultiRuns) { + // Create 2 runs: + // [0]: 5 characters. + // [1]: 4 character. + String mixed_string(u"Hello\u65E5\u65E5\u65E5\u65E5"); + TextDirection direction = GetParam(); + HarfBuzzShaper shaper(mixed_string); + scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction); + + // Copy multiple times using |context| from multiple runs + unsigned context = 0; + scoped_refptr<ShapeResult> sub2to4 = result->SubRange(2, 4, &context); + EXPECT_EQ(2u, sub2to4->NumCharacters()); + scoped_refptr<ShapeResult> sub5to9 = result->SubRange(5, 9, &context); + EXPECT_EQ(4u, sub5to9->NumCharacters()); +} + TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeSegmentGlyphBoundingBox) { String string(u"THello worldL"); TextDirection direction = TextDirection::kLtr; diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.cc index b6c634c08be..910b4ba8516 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.cc @@ -4,6 +4,7 @@ #include "third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h" +#include <algorithm> #include <memory> #include "third_party/blink/renderer/platform/fonts/script_run_iterator.h" @@ -37,38 +38,14 @@ RunSegmenter::RunSegmenter(const UChar* buffer, symbols_iterator_position_(0), at_end_(!buffer_size_) {} -void RunSegmenter::ConsumeScriptIteratorPastLastSplit() { - DCHECK(script_run_iterator_); - if (script_run_iterator_position_ <= last_split_ && - script_run_iterator_position_ < buffer_size_) { - while (script_run_iterator_->Consume(script_run_iterator_position_, - candidate_range_.script)) { - if (script_run_iterator_position_ > last_split_) - return; - } - } -} - -void RunSegmenter::ConsumeOrientationIteratorPastLastSplit() { - if (orientation_iterator_ && orientation_iterator_position_ <= last_split_ && - orientation_iterator_position_ < buffer_size_) { - while ( - orientation_iterator_->Consume(&orientation_iterator_position_, - &candidate_range_.render_orientation)) { - if (orientation_iterator_position_ > last_split_) - return; - } - } -} - -void RunSegmenter::ConsumeSymbolsIteratorPastLastSplit() { - DCHECK(symbols_iterator_); - if (symbols_iterator_position_ <= last_split_ && - symbols_iterator_position_ < buffer_size_) { - while ( - symbols_iterator_->Consume(&symbols_iterator_position_, - &candidate_range_.font_fallback_priority)) { - if (symbols_iterator_position_ > last_split_) +template <class Iterator, typename SegmentationCategory> +void RunSegmenter::ConsumeIteratorPastLastSplit( + std::unique_ptr<Iterator>& iterator, + unsigned* iterator_position, + SegmentationCategory* segmentation_category) { + if (*iterator_position <= last_split_ && *iterator_position < buffer_size_) { + while (iterator->Consume(iterator_position, segmentation_category)) { + if (*iterator_position > last_split_) return; } } @@ -80,24 +57,20 @@ bool RunSegmenter::Consume(RunSegmenterRange* next_range) { if (at_end_) return false; - ConsumeScriptIteratorPastLastSplit(); - ConsumeOrientationIteratorPastLastSplit(); - ConsumeSymbolsIteratorPastLastSplit(); + ConsumeIteratorPastLastSplit(script_run_iterator_, + &script_run_iterator_position_, + &candidate_range_.script); + ConsumeIteratorPastLastSplit(orientation_iterator_, + &orientation_iterator_position_, + &candidate_range_.render_orientation); + ConsumeIteratorPastLastSplit(symbols_iterator_, &symbols_iterator_position_, + &candidate_range_.font_fallback_priority); - if (script_run_iterator_position_ <= orientation_iterator_position_ && - script_run_iterator_position_ <= symbols_iterator_position_) { - last_split_ = script_run_iterator_position_; - } + unsigned positions[] = {script_run_iterator_position_, + orientation_iterator_position_, + symbols_iterator_position_}; - if (orientation_iterator_position_ <= script_run_iterator_position_ && - orientation_iterator_position_ <= symbols_iterator_position_) { - last_split_ = orientation_iterator_position_; - } - - if (symbols_iterator_position_ <= script_run_iterator_position_ && - symbols_iterator_position_ <= orientation_iterator_position_) { - last_split_ = symbols_iterator_position_; - } + last_split_ = *std::min_element(std::begin(positions), std::end(positions)); candidate_range_.start = candidate_range_.end; candidate_range_.end = last_split_; diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h index 86bfc774f28..84647cae75b 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h +++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h @@ -47,9 +47,11 @@ class PLATFORM_EXPORT RunSegmenter { } private: - void ConsumeOrientationIteratorPastLastSplit(); - void ConsumeScriptIteratorPastLastSplit(); - void ConsumeSymbolsIteratorPastLastSplit(); + template <class Iterator, typename SegmentationCategory> + void ConsumeIteratorPastLastSplit( + std::unique_ptr<Iterator>& iterator, + unsigned* iterator_position, + SegmentationCategory* segmentation_category); unsigned buffer_size_; RunSegmenterRange candidate_range_; diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_cache.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_cache.cc index 664b1fcf3fa..ccf3942cc92 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_cache.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_cache.cc @@ -39,7 +39,8 @@ namespace blink { void ShapeCache::SmallStringKey::HashString() { // TODO(cavalcanti): next add xxhash. #if defined(USE_FUNCTION_CITYHASH) - hash_ = CityHash64((const char*)characters_, length_ * sizeof(UChar)); + hash_ = static_cast<unsigned>( + CityHash64((const char*)characters_, length_ * sizeof(UChar))); #endif } diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc index 11ca1595552..42a823029a7 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc @@ -122,13 +122,14 @@ unsigned ShapeResult::RunInfo::NumGraphemes(unsigned start, unsigned end) const { if (graphemes_.size() == 0 || start >= num_characters_) return 0; - DCHECK_LT(start, end); - DCHECK_LE(end, num_characters_); + CHECK_LT(start, end); + CHECK_LE(end, num_characters_); + CHECK_EQ(num_characters_, graphemes_.size()); return graphemes_[end - 1] - graphemes_[start] + 1; } void ShapeResult::EnsureGraphemes(const StringView& text) const { - DCHECK_EQ(NumCharacters(), text.length()); + CHECK_EQ(NumCharacters(), text.length()); // Hit-testing, canvas, etc. may still call this function for 0-length text, // or glyphs may be missing at all. @@ -144,7 +145,7 @@ void ShapeResult::EnsureGraphemes(const StringView& text) const { return; unsigned result_start_index = StartIndex(); - for (const auto& run : runs_) { + for (const scoped_refptr<RunInfo>& run : runs_) { if (!run) continue; DCHECK_GE(run->start_index_, result_start_index); @@ -289,7 +290,6 @@ void ShapeResult::RunInfo::CharacterIndexForXPosition( BreakGlyphsOption break_glyphs_option, GlyphIndexResult* result) const { DCHECK(target_x >= 0 && target_x <= width_); - const unsigned num_glyphs = glyph_data_.size(); result->origin_x = 0; unsigned glyph_sequence_start = 0; @@ -301,12 +301,12 @@ void ShapeResult::RunInfo::CharacterIndexForXPosition( glyph_sequence_start = glyph_sequence_end = num_characters_; } - for (unsigned i = 0; i < num_glyphs; ++i) { - unsigned current_glyph_char_index = glyph_data_[i].character_index; + for (const HarfBuzzRunGlyphData& glyph_data : glyph_data_) { + unsigned current_glyph_char_index = glyph_data.character_index; // If the glyph is part of the same sequence, we just accumulate the // advance. if (glyph_sequence_start == current_glyph_char_index) { - result->advance += glyph_data_[i].advance; + result->advance += glyph_data.advance; continue; } @@ -328,7 +328,7 @@ void ShapeResult::RunInfo::CharacterIndexForXPosition( } glyph_sequence_start = current_glyph_char_index; result->origin_x += result->advance; - result->advance = glyph_data_[i].advance; + result->advance = glyph_data.advance; } // At this point, we have [glyph_sequence_start, glyph_sequence_end) @@ -512,19 +512,18 @@ void ShapeResult::OffsetForPosition(float target_x, unsigned characters_so_far = Rtl() ? NumCharacters() : 0; float current_x = 0; - for (unsigned i = 0; i < runs_.size(); ++i) { - const RunInfo* run = runs_[i].get(); + for (const scoped_refptr<RunInfo>& run_ptr : runs_) { + const RunInfo* run = run_ptr.get(); if (!run) continue; if (Rtl()) - characters_so_far -= runs_[i]->num_characters_; + characters_so_far -= run->num_characters_; float next_x = current_x + run->width_; float offset_for_run = target_x - current_x; if (offset_for_run >= 0 && offset_for_run < run->width_) { // The x value in question is within this script run. run->CharacterIndexForXPosition(offset_for_run, break_glyphs_option, result); - result->run_index = i; result->characters_on_left_runs = characters_so_far; if (Rtl()) { result->left_character_index = @@ -555,7 +554,6 @@ void ShapeResult::OffsetForPosition(float target_x, result->right_character_index += characters_so_far; } - result->run_index = runs_.size() - 1; result->characters_on_left_runs = characters_so_far; DCHECK_LE(result->left_character_index, NumCharacters()); @@ -971,38 +969,67 @@ unsigned ShapeResult::RunInfo::LimitNumGlyphs( const bool is_ltr, const hb_glyph_info_t* glyph_infos) { unsigned num_glyphs = *num_glyphs_in_out; + CHECK_GT(num_glyphs, 0u); // If there were larger character indexes than kMaxCharacterIndex, reduce // num_glyphs so that all character indexes can fit to kMaxCharacterIndex. // Because code points and glyphs are not always 1:1, we need to check the // first and the last cluster. + const hb_glyph_info_t* left_glyph_info = &glyph_infos[start_glyph]; + const hb_glyph_info_t* right_glyph_info = &left_glyph_info[num_glyphs - 1]; unsigned start_cluster; if (is_ltr) { - start_cluster = glyph_infos[start_glyph].cluster; - unsigned last_cluster = glyph_infos[start_glyph + num_glyphs - 1].cluster; - unsigned last_character_index = last_cluster - start_cluster; - if (UNLIKELY(last_character_index > - HarfBuzzRunGlyphData::kMaxCharacterIndex)) { - // Make sure the end is a cluster boundary. - do { - num_glyphs--; - num_characters_ = last_character_index; - last_cluster = glyph_infos[start_glyph + num_glyphs - 1].cluster; - last_character_index = last_cluster - start_cluster; - } while (last_character_index > HarfBuzzRunGlyphData::kMaxCharacterIndex); + start_cluster = left_glyph_info->cluster; + unsigned last_cluster = right_glyph_info->cluster; + unsigned max_cluster = + start_cluster + HarfBuzzRunGlyphData::kMaxCharacterIndex; + if (UNLIKELY(last_cluster > max_cluster)) { + // Limit at |max_cluster| in LTR. If |max_cluster| is 100: + // 0 1 2 ... 98 99 99 101 101 103 ... + // ^ limit here. + // Find |glyph_info| where |cluster| <= |max_cluster|. + const hb_glyph_info_t* limit_glyph_info = std::upper_bound( + left_glyph_info, right_glyph_info + 1, max_cluster, + [](unsigned cluster, const hb_glyph_info_t& glyph_info) { + return cluster < glyph_info.cluster; + }); + --limit_glyph_info; + CHECK_GT(limit_glyph_info, left_glyph_info); + CHECK_LT(limit_glyph_info, right_glyph_info); + DCHECK_LE(limit_glyph_info->cluster, max_cluster); + // Adjust |right_glyph_info| and recompute dependent variables. + right_glyph_info = limit_glyph_info; + num_glyphs = right_glyph_info - left_glyph_info + 1; + num_characters_ = right_glyph_info[1].cluster - start_cluster; } } else { - start_cluster = glyph_infos[start_glyph + num_glyphs - 1].cluster; - const unsigned last_cluster = glyph_infos[start_glyph].cluster; - unsigned last_character_index = last_cluster - start_cluster; - if (UNLIKELY(last_character_index > - HarfBuzzRunGlyphData::kMaxCharacterIndex)) { - do { - num_glyphs--; - num_characters_ = last_character_index; - start_cluster = glyph_infos[start_glyph + num_glyphs - 1].cluster; - last_character_index = last_cluster - start_cluster; - } while (last_character_index > HarfBuzzRunGlyphData::kMaxCharacterIndex); + start_cluster = right_glyph_info->cluster; + unsigned last_cluster = left_glyph_info->cluster; + unsigned max_cluster = + start_cluster + HarfBuzzRunGlyphData::kMaxCharacterIndex; + if (UNLIKELY(last_cluster > max_cluster)) { + // Limit the right edge, which is in the reverse order in RTL. + // If |min_cluster| is 3: + // 103 102 ... 4 4 2 2 ... + // ^ limit here. + // Find |glyph_info| where |cluster| >= |min_cluster|. + unsigned min_cluster = + last_cluster - HarfBuzzRunGlyphData::kMaxCharacterIndex; + DCHECK_LT(start_cluster, min_cluster); + const hb_glyph_info_t* limit_glyph_info = std::upper_bound( + left_glyph_info, right_glyph_info + 1, min_cluster, + [](unsigned cluster, const hb_glyph_info_t& glyph_info) { + return cluster > glyph_info.cluster; + }); + --limit_glyph_info; + CHECK_GT(limit_glyph_info, left_glyph_info); + CHECK_LT(limit_glyph_info, right_glyph_info); + DCHECK_GE(limit_glyph_info->cluster, min_cluster); + // Adjust |right_glyph_info| and recompute dependent variables. + right_glyph_info = limit_glyph_info; + start_cluster = right_glyph_info->cluster; + num_glyphs = right_glyph_info - left_glyph_info + 1; + num_characters_ = last_cluster - right_glyph_info[1].cluster; } } @@ -1331,7 +1358,9 @@ void ShapeResult::CopyRange(unsigned start_offset, // No need to process runs after the end of the range. if ((!Rtl() && end_offset <= run_end) || (Rtl() && start_offset > run_start)) { - if (start_run_index) + // RTL cannot use |start_run_index| because runs are in the descending + // order. + if (!Rtl() && start_run_index) *start_run_index = run_index; break; } diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.h index 72e7d4ee9f9..05ff17be9dc 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.h +++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.h @@ -342,7 +342,6 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> { STACK_ALLOCATED(); public: - unsigned run_index = 0; // The total number of characters of runs_[0..run_index - 1]. unsigned characters_on_left_runs = 0; diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc index 22198066fef..d6864da1866 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc @@ -4,35 +4,24 @@ #include "third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.h" -#include "third_party/blink/renderer/platform/fonts/font.h" -#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h" #include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h" -#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h" #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h" #include "third_party/blink/renderer/platform/text/text_break_iterator.h" namespace blink { ShapingLineBreaker::ShapingLineBreaker( - const HarfBuzzShaper* shaper, - const Font* font, scoped_refptr<const ShapeResult> result, const LazyLineBreakIterator* break_iterator, - const RunSegmenter::RunSegmenterRange* pre_segmented, - ShapeResultSpacing<String>* spacing, - const Hyphenation* hyphenation) - : shaper_(shaper), - font_(font), + const Hyphenation* hyphenation, + ShapeCallback shape_callback, + void* shape_callback_context) + : shape_callback_(shape_callback), + shape_callback_context_(shape_callback_context), result_(result), - pre_segmented_(pre_segmented), break_iterator_(break_iterator), - spacing_(spacing), hyphenation_(hyphenation), is_soft_hyphen_enabled_(true) { - // ShapeResultSpacing is stateful when it has expansions. We may use it in - // arbitrary order that it cannot have expansions. - DCHECK(!spacing_ || !spacing_->HasExpansion()); - // Line breaking performance relies on high-performance x-position to // character offset lookup. Ensure that the desired cache has been computed. DCHECK(result_); @@ -175,18 +164,6 @@ ShapingLineBreaker::BreakOpportunity ShapingLineBreaker::NextBreakOpportunity( return {break_iterator_->NextBreakOpportunity(offset, len), false}; } -inline scoped_refptr<ShapeResult> ShapingLineBreaker::Shape(TextDirection direction, - unsigned start, - unsigned end) { - if (!spacing_ || !spacing_->HasSpacing()) - return shaper_->Shape(font_, direction, start, end, pre_segmented_); - - scoped_refptr<ShapeResult> result = - shaper_->Shape(font_, direction, start, end, pre_segmented_); - result->ApplySpacing(*spacing_); - return result; -} - // Shapes a line of text by finding a valid and appropriate break opportunity // based on the shaping results for the entire paragraph. Re-shapes the start // and end of the line as needed. @@ -289,14 +266,14 @@ scoped_refptr<const ShapeResultView> ShapingLineBreaker::ShapeLine( // There is no safe-to-break, reshape the whole range. result_out->break_offset = break_opportunity.offset; return ShapeResultView::Create( - Shape(direction, start, break_opportunity.offset).get()); + Shape(start, break_opportunity.offset).get()); } LayoutUnit original_width = FlipRtl( SnapEnd(result_->CachedPositionForOffset(first_safe - range_start), direction) - start_position, direction); - line_start_result = Shape(direction, start, first_safe); + line_start_result = Shape(start, first_safe); available_space += line_start_result->SnappedWidth() - original_width; } DCHECK_GE(first_safe, start); @@ -320,12 +297,12 @@ scoped_refptr<const ShapeResultView> ShapingLineBreaker::ShapeLine( break; DCHECK_LE(break_opportunity.offset, range_end); if (is_overflow) { - line_end_result = Shape(direction, last_safe, break_opportunity.offset); + line_end_result = Shape(last_safe, break_opportunity.offset); break; } LayoutUnit safe_position = SnapStart( result_->CachedPositionForOffset(last_safe - range_start), direction); - line_end_result = Shape(direction, last_safe, break_opportunity.offset); + line_end_result = Shape(last_safe, break_opportunity.offset); if (line_end_result->SnappedWidth() <= FlipRtl(end_position - safe_position, direction)) break; @@ -402,14 +379,13 @@ scoped_refptr<const ShapeResultView> ShapingLineBreaker::ShapeToEnd( return ShapeResultView::Create(result_.get(), start, range_end); // If no safe-to-break offset is found in range, reshape the entire range. - TextDirection direction = result_->Direction(); if (first_safe >= range_end) { - scoped_refptr<ShapeResult> line_result = Shape(direction, start, range_end); + scoped_refptr<ShapeResult> line_result = Shape(start, range_end); return ShapeResultView::Create(line_result.get()); } // Otherwise reshape to |first_safe|, then copy the rest. - scoped_refptr<ShapeResult> line_start = Shape(direction, start, first_safe); + scoped_refptr<ShapeResult> line_start = Shape(start, first_safe); ShapeResultView::Segment segments[2] = { {line_start.get(), 0, std::numeric_limits<unsigned>::max()}, {result_.get(), first_safe, range_end}}; diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.h index 159cd3e4068..14ed982839e 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.h +++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.h @@ -13,15 +13,11 @@ namespace blink { -class Font; class ShapeResult; class ShapeResultView; -class HarfBuzzShaper; class Hyphenation; class LazyLineBreakIterator; enum class LineBreakType; -template <typename TextContainerType> -class ShapeResultSpacing; // Shapes a line of text by finding the ideal break position as indicated by the // available space and the shape results for the entire paragraph. Once an ideal @@ -37,18 +33,20 @@ class PLATFORM_EXPORT ShapingLineBreaker final { STACK_ALLOCATED(); public: - // Construct a ShapingLineBreaker. + // Callback function to reshape line edges. // - // When the ShapeResult is from a RunSegmenterRange, giving it can skip - // running RunSegmenter for much better performance. - ShapingLineBreaker(const HarfBuzzShaper*, - const Font*, - scoped_refptr<const ShapeResult>, - const LazyLineBreakIterator*, - const RunSegmenter::RunSegmenterRange* = nullptr, - ShapeResultSpacing<String>* = nullptr, - const Hyphenation* = nullptr); - ~ShapingLineBreaker() = default; + // std::function is forbidden in Chromium and base::Callback is way too + // expensive so we resort to a good old function pointer instead. + using ShapeCallback = scoped_refptr<ShapeResult> (*)(void* context, + unsigned start, + unsigned end); + + // Construct a ShapingLineBreaker. + ShapingLineBreaker(scoped_refptr<const ShapeResult> result, + const LazyLineBreakIterator* break_iterator, + const Hyphenation* hyphenation, + ShapeCallback shape_callback, + void* shape_callback_context); // Represents details of the result of |ShapeLine()|. struct Result { @@ -116,20 +114,18 @@ class PLATFORM_EXPORT ShapingLineBreaker final { unsigned word_end, bool backwards) const; - scoped_refptr<ShapeResult> Shape(TextDirection, unsigned start, unsigned end); + scoped_refptr<ShapeResult> Shape(unsigned start, unsigned end) { + return (*shape_callback_)(shape_callback_context_, start, end); + } scoped_refptr<const ShapeResultView> ShapeToEnd(unsigned start, unsigned first_safe, unsigned range_start, unsigned range_end); - const HarfBuzzShaper* shaper_; - const Font* font_; + const ShapeCallback shape_callback_; + void* shape_callback_context_; scoped_refptr<const ShapeResult> result_; - const RunSegmenter::RunSegmenterRange* pre_segmented_; const LazyLineBreakIterator* break_iterator_; - // TODO(kojii): ShapeResultSpacing is not const because it's stateful when it - // has expansions. Split spacing and expansions to make this const. - ShapeResultSpacing<String>* spacing_; const Hyphenation* hyphenation_; bool is_soft_hyphen_enabled_; diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker_test.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker_test.cc index 25ba3d14546..2e05f3302cc 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker_test.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker_test.cc @@ -20,6 +20,20 @@ namespace blink { namespace { +struct HarfBuzzShaperCallbackContext { + const HarfBuzzShaper* shaper; + const Font* font; + TextDirection direction; +}; + +scoped_refptr<ShapeResult> HarfBuzzShaperCallback(void* untyped_context, + unsigned start, + unsigned end) { + HarfBuzzShaperCallbackContext* context = + static_cast<HarfBuzzShaperCallbackContext*>(untyped_context); + return context->shaper->Shape(context->font, context->direction, start, end); +} + scoped_refptr<const ShapeResultView> ShapeLine(ShapingLineBreaker* breaker, unsigned start_offset, LayoutUnit available_space, @@ -109,7 +123,9 @@ TEST_F(ShapingLineBreakerTest, ShapeLineLatin) { shaper.Shape(&font, direction, 0, 4); ASSERT_LT(first1->SnappedWidth(), first2->SnappedWidth()); - ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator); + HarfBuzzShaperCallbackContext context{&shaper, &font, result->Direction()}; + ShapingLineBreaker breaker(result, &break_iterator, nullptr, + HarfBuzzShaperCallback, &context); scoped_refptr<const ShapeResultView> line; unsigned break_offset = 0; @@ -168,7 +184,9 @@ TEST_F(ShapingLineBreakerTest, ShapeLineLatinMultiLine) { scoped_refptr<const ShapeResult> mid_third = shaper.Shape(&font, direction, 0, 16); - ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator); + HarfBuzzShaperCallbackContext context{&shaper, &font, result->Direction()}; + ShapingLineBreaker breaker(result, &break_iterator, nullptr, + HarfBuzzShaperCallback, &context); unsigned break_offset = 0; ShapeLine(&breaker, 0, result->SnappedWidth() - 1, &break_offset); @@ -195,7 +213,9 @@ TEST_F(ShapingLineBreakerTest, ShapeLineLatinBreakAll) { scoped_refptr<const ShapeResult> midpoint = shaper.Shape(&font, direction, 0, 16); - ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator); + HarfBuzzShaperCallbackContext context{&shaper, &font, result->Direction()}; + ShapingLineBreaker breaker(result, &break_iterator, nullptr, + HarfBuzzShaperCallback, &context); scoped_refptr<const ShapeResultView> line; unsigned break_offset = 0; @@ -216,7 +236,9 @@ TEST_F(ShapingLineBreakerTest, ShapeLineZeroAvailableWidth) { HarfBuzzShaper shaper(string); scoped_refptr<const ShapeResult> result = shaper.Shape(&font, direction); - ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator); + HarfBuzzShaperCallbackContext context{&shaper, &font, result->Direction()}; + ShapingLineBreaker breaker(result, &break_iterator, nullptr, + HarfBuzzShaperCallback, &context); scoped_refptr<const ShapeResultView> line; unsigned break_offset = 0; LayoutUnit zero(0); @@ -259,7 +281,9 @@ TEST_F(ShapingLineBreakerTest, DISABLED_ShapeLineArabicThaiHanLatin) { }); LayoutUnit longest_word_width = (*longest_word)->SnappedWidth(); - ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator); + HarfBuzzShaperCallbackContext context{&shaper, &font, result->Direction()}; + ShapingLineBreaker breaker(result, &break_iterator, nullptr, + HarfBuzzShaperCallback, &context); scoped_refptr<const ShapeResult> line; unsigned break_offset = 0; @@ -288,7 +312,9 @@ TEST_F(ShapingLineBreakerTest, ShapeLineRangeEndMidWord) { scoped_refptr<const ShapeResult> result = shaper.Shape(&font, direction, 0, 2); - ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator); + HarfBuzzShaperCallbackContext context{&shaper, &font, result->Direction()}; + ShapingLineBreaker breaker(result, &break_iterator, nullptr, + HarfBuzzShaperCallback, &context); scoped_refptr<const ShapeResultView> line; unsigned break_offset = 0; @@ -325,7 +351,9 @@ TEST_P(BreakOpportunityTest, Next) { scoped_refptr<const ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr); - ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator); + HarfBuzzShaperCallbackContext context{&shaper, &font, result->Direction()}; + ShapingLineBreaker breaker(result, &break_iterator, nullptr, + HarfBuzzShaperCallback, &context); EXPECT_THAT(BreakPositionsByNext(breaker, string), testing::ElementsAreArray(data.break_positions)); @@ -345,7 +373,9 @@ TEST_P(BreakOpportunityTest, Previous) { scoped_refptr<const ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr); - ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator); + HarfBuzzShaperCallbackContext context{&shaper, &font, result->Direction()}; + ShapingLineBreaker breaker(result, &break_iterator, nullptr, + HarfBuzzShaperCallback, &context); EXPECT_THAT(BreakPositionsByPrevious(breaker, string), testing::ElementsAreArray(data.break_positions)); diff --git a/chromium/third_party/blink/renderer/platform/fonts/simple_font_data.cc b/chromium/third_party/blink/renderer/platform/fonts/simple_font_data.cc index d742599579d..144c2272df3 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/simple_font_data.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/simple_font_data.cc @@ -35,6 +35,7 @@ #include <memory> #include <utility> +#include "SkFontMetrics.h" #include "SkPath.h" #include "SkTypeface.h" #include "SkTypes.h" diff --git a/chromium/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc b/chromium/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc index 90898dbc4a8..3eb56e5f013 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc @@ -43,7 +43,6 @@ #include "third_party/blink/renderer/platform/fonts/font_description.h" #include "third_party/blink/renderer/platform/fonts/font_face_creation_params.h" #include "third_party/blink/renderer/platform/fonts/font_global_context.h" -#include "third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h" #include "third_party/blink/renderer/platform/fonts/simple_font_data.h" #include "third_party/blink/renderer/platform/fonts/skia/sktypeface_factory.h" #include "third_party/blink/renderer/platform/language.h" @@ -57,25 +56,6 @@ namespace blink { -#if defined(OS_ANDROID) || defined(OS_LINUX) -namespace { - -static sk_sp<SkTypeface> CreateTypefaceFromUniqueName( - const FontFaceCreationParams& creation_params, - CString& name) { - FontUniqueNameLookup* unique_name_lookup = - FontGlobalContext::Get()->GetFontUniqueNameLookup(); - DCHECK(unique_name_lookup); - sk_sp<SkTypeface> uniquely_identified_font = - unique_name_lookup->MatchUniqueName(creation_params.Family()); - if (uniquely_identified_font) { - return uniquely_identified_font; - } - return nullptr; -} -} // namespace -#endif - AtomicString ToAtomicString(const SkString& str) { return AtomicString::FromUTF8(str.c_str(), str.size()); } diff --git a/chromium/third_party/blink/renderer/platform/fonts/web_font_decoder.cc b/chromium/third_party/blink/renderer/platform/fonts/web_font_decoder.cc index bc300449603..dad31d2a64d 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/web_font_decoder.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/web_font_decoder.cc @@ -37,6 +37,7 @@ #include "third_party/blink/renderer/platform/histogram.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" #include "third_party/blink/renderer/platform/shared_buffer.h" +#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" #include "third_party/blink/renderer/platform/wtf/time.h" #include "third_party/ots/include/ots-memory-stream.h" #include "third_party/skia/include/core/SkStream.h" @@ -209,7 +210,7 @@ sk_sp<SkTypeface> WebFontDecoder::Decode(SharedBuffer* buffer) { return nullptr; } - const size_t decoded_length = output.Tell(); + const size_t decoded_length = SafeCast<size_t>(output.Tell()); RecordDecodeSpeedHistogram(data, buffer->size(), CurrentTime() - start, decoded_length); diff --git a/chromium/third_party/blink/renderer/platform/fonts/web_font_render_style.cc b/chromium/third_party/blink/renderer/platform/fonts/web_font_render_style.cc index b63f8a2051d..e78ea8c04c4 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/web_font_render_style.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/web_font_render_style.cc @@ -97,25 +97,6 @@ void WebFontRenderStyle::OverrideWith(const WebFontRenderStyle& other) { use_subpixel_positioning = other.use_subpixel_positioning; } -void WebFontRenderStyle::ApplyToSkPaint(SkPaint& font, - float device_scale_factor) const { - auto sk_hint_style = static_cast<SkFontHinting>(hint_style); - font.setAntiAlias(use_anti_alias); - font.setHinting(sk_hint_style); - font.setEmbeddedBitmapText(use_bitmaps); - font.setAutohinted(use_auto_hint); - if (use_anti_alias) - font.setLCDRenderText(use_subpixel_rendering); - - // Force-enable subpixel positioning, except when full hinting is requested on - // low-dpi screen or when running web tests. - bool force_subpixel_positioning = - !WebTestSupport::IsRunningWebTest() && - (sk_hint_style != SkFontHinting::kFull || device_scale_factor > 1.0f); - - font.setSubpixelText(force_subpixel_positioning || use_subpixel_positioning); -} - void WebFontRenderStyle::ApplyToSkFont(SkFont* font, float device_scale_factor) const { auto sk_hint_style = static_cast<SkFontHinting>(hint_style); diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/font_cache_skia_win.cc b/chromium/third_party/blink/renderer/platform/fonts/win/font_cache_skia_win.cc index b3e09a38bc1..99641e3d337 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/win/font_cache_skia_win.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/win/font_cache_skia_win.cc @@ -35,6 +35,7 @@ #include <utility> #include "base/debug/alias.h" +#include "base/stl_util.h" #include "third_party/blink/renderer/platform/fonts/bitmap_glyphs_blacklist.h" #include "third_party/blink/renderer/platform/fonts/font_description.h" #include "third_party/blink/renderer/platform/fonts/font_face_creation_params.h" @@ -42,9 +43,14 @@ #include "third_party/blink/renderer/platform/fonts/simple_font_data.h" #include "third_party/blink/renderer/platform/fonts/win/font_fallback_win.h" #include "third_party/blink/renderer/platform/language.h" +#include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/skia/include/core/SkFontMgr.h" +#include "third_party/skia/include/core/SkStream.h" #include "third_party/skia/include/ports/SkTypeface_win.h" +#include <ft2build.h> +#include <freetype/freetype.h> + namespace blink { HashMap<String, sk_sp<SkTypeface>, CaseFoldingHash>* @@ -67,6 +73,44 @@ int32_t EnsureMinimumFontHeightIfNeeded(int32_t font_height) { return (font_height < 12.0f) && (GetACP() == 936) ? 12.0f : font_height; } +// Test-only code for matching sideloaded fonts by postscript name. This +// implementation is incomplete, as it does not match the full font name and +// only uses FT_Get_Postscript_Name, which returns an ASCII font name. This is +// intended to pass tests on Windows, where for example src: local(Ahem) is used +// in @font-face CSS declarations. Skia does not expose getAdvancedMetrics, so +// we use FreeType here to parse the font's postscript name. +sk_sp<SkTypeface> FindUniqueFontNameFromSideloadedFonts( + const String& font_name, + HashMap<String, sk_sp<SkTypeface>, CaseFoldingHash>* sideloaded_fonts) { + CHECK(sideloaded_fonts); + FT_Library library; + FT_Init_FreeType(&library); + + sk_sp<SkTypeface> return_typeface(nullptr); + for (auto& sideloaded_font : sideloaded_fonts->Values()) { + // Open ttc index zero as we can assume that we do not sideload TrueType + // collections. + SkStreamAsset* typeface_stream = sideloaded_font->openStream(0); + CHECK(typeface_stream->getMemoryBase()); + std::string font_family_name; + FT_Face font_face; + FT_Open_Args open_args = { + FT_OPEN_MEMORY, + reinterpret_cast<const FT_Byte*>(typeface_stream->getMemoryBase()), + typeface_stream->getLength()}; + CHECK_EQ(FT_Err_Ok, FT_Open_Face(library, &open_args, 0, &font_face)); + font_family_name = FT_Get_Postscript_Name(font_face); + FT_Done_Face(font_face); + + if (font_name.FoldCase() == String(font_family_name.c_str()).FoldCase()) { + return_typeface = sideloaded_font; + break; + } + } + FT_Done_FreeType(library); + return return_typeface; +} + } // namespace // static @@ -215,10 +259,10 @@ scoped_refptr<SimpleFontData> FontCache::PlatformFallbackFontForCharacter( int num_fonts = 0; if (script == USCRIPT_HAN) { pan_uni_fonts = kCjkFonts; - num_fonts = arraysize(kCjkFonts); + num_fonts = base::size(kCjkFonts); } else { pan_uni_fonts = kCommonFonts; - num_fonts = arraysize(kCommonFonts); + num_fonts = base::size(kCommonFonts); } // Font returned from getFallbackFamily may not cover |character| // because it's based on script to font mapping. This problem is @@ -294,7 +338,7 @@ static bool TypefacesHasWeightSuffix(const AtomicString& family, {L" ultrabold", 10, FontSelectionValue(800)}, {L" black", 6, FontSelectionValue(900)}, {L" heavy", 6, FontSelectionValue(900)}}; - size_t num_variants = arraysize(kVariantForSuffix); + size_t num_variants = base::size(kVariantForSuffix); for (size_t i = 0; i < num_variants; i++) { const FamilyWeightSuffix& entry = kVariantForSuffix[i]; if (family.EndsWith(entry.suffix, kTextCaseUnicodeInsensitive)) { @@ -331,7 +375,7 @@ static bool TypefacesHasStretchSuffix(const AtomicString& family, {L" expanded", 9, ExpandedWidthValue()}, {L" extraexpanded", 14, ExtraExpandedWidthValue()}, {L" ultraexpanded", 14, UltraExpandedWidthValue()}}; - size_t num_variants = arraysize(kVariantForSuffix); + size_t num_variants = base::size(kVariantForSuffix); for (size_t i = 0; i < num_variants; i++) { const FamilyStretchSuffix& entry = kVariantForSuffix[i]; if (family.EndsWith(entry.suffix, kTextCaseUnicodeInsensitive)) { @@ -352,59 +396,79 @@ std::unique_ptr<FontPlatformData> FontCache::CreateFontPlatformData( float font_size, AlternateFontName alternate_font_name) { DCHECK_EQ(creation_params.CreationType(), kCreateFontByFamily); + sk_sp<SkTypeface> typeface; CString name; - sk_sp<SkTypeface> typeface = - CreateTypeface(font_description, creation_params, name); - // Windows will always give us a valid pointer here, even if the face name - // is non-existent. We have to double-check and see if the family name was - // really used. - if (!typeface || - !TypefacesMatchesFamily(typeface.get(), creation_params.Family())) { - AtomicString adjusted_name; - FontSelectionValue variant_weight; - FontSelectionValue variant_stretch; - - // TODO: crbug.com/627143 LocalFontFaceSource.cpp, which implements - // retrieving src: local() font data uses getFontData, which in turn comes - // here, to retrieve fonts from the cache and specifies the argument to - // local() as family name. So we do not match by full font name or - // postscript name as the spec says: - // https://drafts.csswg.org/css-fonts-3/#src-desc - - // Prevent one side effect of the suffix translation below where when - // matching local("Roboto Regular") it tries to find the closest match even - // though that can be a bold font in case of Roboto Bold. - if (alternate_font_name == AlternateFontName::kLocalUniqueFace) { - return nullptr; + + if (alternate_font_name == AlternateFontName::kLocalUniqueFace && + RuntimeEnabledFeatures::FontSrcLocalMatchingEnabled()) { + typeface = CreateTypefaceFromUniqueName(creation_params, name); + + if (!typeface && sideloaded_fonts_) { + typeface = FindUniqueFontNameFromSideloadedFonts(creation_params.Family(), + sideloaded_fonts_); } - if (alternate_font_name == AlternateFontName::kLastResort) { - if (!typeface) - return nullptr; - } else if (TypefacesHasWeightSuffix(creation_params.Family(), adjusted_name, - variant_weight)) { - FontFaceCreationParams adjusted_params(adjusted_name); - FontDescription adjusted_font_description = font_description; - adjusted_font_description.SetWeight(variant_weight); - typeface = - CreateTypeface(adjusted_font_description, adjusted_params, name); - if (!typeface || !TypefacesMatchesFamily(typeface.get(), adjusted_name)) { + // We do not need to try any heuristic around the font name, as below, for + // family matching. + if (!typeface) + return nullptr; + + } else { + typeface = CreateTypeface(font_description, creation_params, name); + + // For a family match, Windows will always give us a valid pointer here, + // even if the face name is non-existent. We have to double-check and see if + // the family name was really used. + if (!typeface || + !TypefacesMatchesFamily(typeface.get(), creation_params.Family())) { + AtomicString adjusted_name; + FontSelectionValue variant_weight; + FontSelectionValue variant_stretch; + + // TODO: crbug.com/627143 LocalFontFaceSource.cpp, which implements + // retrieving src: local() font data uses getFontData, which in turn comes + // here, to retrieve fonts from the cache and specifies the argument to + // local() as family name. So we do not match by full font name or + // postscript name as the spec says: + // https://drafts.csswg.org/css-fonts-3/#src-desc + + // Prevent one side effect of the suffix translation below where when + // matching local("Roboto Regular") it tries to find the closest match + // even though that can be a bold font in case of Roboto Bold. + if (alternate_font_name == AlternateFontName::kLocalUniqueFace) { return nullptr; } - } else if (TypefacesHasStretchSuffix(creation_params.Family(), - adjusted_name, variant_stretch)) { - FontFaceCreationParams adjusted_params(adjusted_name); - FontDescription adjusted_font_description = font_description; - adjusted_font_description.SetStretch(variant_stretch); - typeface = - CreateTypeface(adjusted_font_description, adjusted_params, name); - if (!typeface || !TypefacesMatchesFamily(typeface.get(), adjusted_name)) { + if (alternate_font_name == AlternateFontName::kLastResort) { + if (!typeface) + return nullptr; + } else if (TypefacesHasWeightSuffix(creation_params.Family(), + adjusted_name, variant_weight)) { + FontFaceCreationParams adjusted_params(adjusted_name); + FontDescription adjusted_font_description = font_description; + adjusted_font_description.SetWeight(variant_weight); + typeface = + CreateTypeface(adjusted_font_description, adjusted_params, name); + if (!typeface || + !TypefacesMatchesFamily(typeface.get(), adjusted_name)) { + return nullptr; + } + + } else if (TypefacesHasStretchSuffix(creation_params.Family(), + adjusted_name, variant_stretch)) { + FontFaceCreationParams adjusted_params(adjusted_name); + FontDescription adjusted_font_description = font_description; + adjusted_font_description.SetStretch(variant_stretch); + typeface = + CreateTypeface(adjusted_font_description, adjusted_params, name); + if (!typeface || + !TypefacesMatchesFamily(typeface.get(), adjusted_name)) { + return nullptr; + } + } else { return nullptr; } - } else { - return nullptr; } } diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc b/chromium/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc index ecb970bdd70..1c4ad7ccb81 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc @@ -34,6 +34,7 @@ #include <unicode/uchar.h> #include <limits> +#include "base/stl_util.h" #include "third_party/blink/renderer/platform/fonts/font_cache.h" #include "third_party/blink/renderer/platform/text/icu_error.h" #include "third_party/blink/renderer/platform/wtf/hash_map.h" @@ -376,13 +377,13 @@ const UChar* GetFontBasedOnUnicodeBlock(UBlockCode block_code, static const UChar* math_font = 0; static bool initialized = false; if (!initialized) { - for (size_t i = 0; i < arraysize(kEmojiFonts); i++) { + for (size_t i = 0; i < base::size(kEmojiFonts); i++) { if (IsFontPresent(kEmojiFonts[i], font_manager)) { emoji_font = kEmojiFonts[i]; break; } } - for (size_t i = 0; i < arraysize(kMathFonts); i++) { + for (size_t i = 0; i < base::size(kMathFonts); i++) { if (IsFontPresent(kMathFonts[i], font_manager)) { math_font = kMathFonts[i]; break; diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/font_platform_data_win.cc b/chromium/third_party/blink/renderer/platform/fonts/win/font_platform_data_win.cc index 4fc4b20ddfa..e5cc3293961 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/win/font_platform_data_win.cc +++ b/chromium/third_party/blink/renderer/platform/fonts/win/font_platform_data_win.cc @@ -39,55 +39,21 @@ namespace blink { -void FontPlatformData::SetupSkPaint(SkPaint* font, float, const Font*) const { - font->setTextSize(SkFloatToScalar(text_size_)); - font->setTypeface(typeface_); - font->setFakeBoldText(synthetic_bold_); - font->setTextSkewX(synthetic_italic_ ? -SK_Scalar1 / 4 : 0); - - uint32_t text_flags = PaintTextFlags(); - uint32_t flags = font->getFlags(); - static const uint32_t kTextFlagsMask = - SkPaint::kAntiAlias_Flag | SkPaint::kLCDRenderText_Flag | - SkPaint::kEmbeddedBitmapText_Flag | SkPaint::kSubpixelText_Flag; - flags &= ~kTextFlagsMask; - - // Only use sub-pixel positioning if anti aliasing is enabled. Otherwise, - // without font smoothing, subpixel text positioning leads to uneven spacing - // since subpixel test placement coordinates would be passed to Skia, which - // only has non-antialiased glyphs to draw, so they necessarily get clamped at - // pixel positions, which leads to uneven spacing, either too close or too far - // away from adjacent glyphs. We avoid this by linking the two flags. - if (text_flags & SkPaint::kAntiAlias_Flag) - flags |= SkPaint::kSubpixelText_Flag; - - if (WebTestSupport::IsRunningWebTest() && - !WebTestSupport::IsTextSubpixelPositioningAllowedForTest()) - flags &= ~SkPaint::kSubpixelText_Flag; - - SkASSERT(!(text_flags & ~kTextFlagsMask)); - flags |= text_flags; - - font->setFlags(flags); - - font->setEmbeddedBitmapText(!avoid_embedded_bitmaps_); -} - void FontPlatformData::SetupSkFont(SkFont* font, float, const Font*) const { font->setSize(SkFloatToScalar(text_size_)); font->setTypeface(typeface_); font->setEmbolden(synthetic_bold_); font->setSkewX(synthetic_italic_ ? -SK_Scalar1 / 4 : 0); - uint32_t text_flags = PaintTextFlags(); - if (text_flags & SkPaint::kLCDRenderText_Flag) { + uint32_t font_flags = FontFlags(); + if (font_flags & kSubpixelsAntiAlias) { font->setEdging(SkFont::Edging::kSubpixelAntiAlias); - } else if (text_flags & SkPaint::kAntiAlias_Flag) { + } else if (font_flags & kAntiAlias) { font->setEdging(SkFont::Edging::kAntiAlias); } else { font->setEdging(SkFont::Edging::kAlias); } - font->setSubpixel(SkToBool(text_flags & SkPaint::kSubpixelText_Flag)); + font->setSubpixel(SkToBool(font_flags & kSubpixelMetrics)); // Only use sub-pixel positioning if anti aliasing is enabled. Otherwise, // without font smoothing, subpixel text positioning leads to uneven spacing @@ -95,7 +61,7 @@ void FontPlatformData::SetupSkFont(SkFont* font, float, const Font*) const { // only has non-antialiased glyphs to draw, so they necessarily get clamped at // pixel positions, which leads to uneven spacing, either too close or too far // away from adjacent glyphs. We avoid this by linking the two flags. - if (text_flags & SkPaint::kAntiAlias_Flag) + if (font_flags & kAntiAlias) font->setSubpixel(true); if (WebTestSupport::IsRunningWebTest() && @@ -113,18 +79,18 @@ static bool IsWebFont(const String& family_name) { '=' == family_name[23]; } -static int ComputePaintTextFlags(String font_family_name) { +static int ComputeFontFlags(String font_family_name) { if (WebTestSupport::IsRunningWebTest()) return WebTestSupport::IsFontAntialiasingEnabledForTest() - ? SkPaint::kAntiAlias_Flag + ? FontPlatformData::kAntiAlias : 0; - int text_flags = 0; + int font_flags = 0; if (FontCache::GetFontCache()->AntialiasedTextEnabled()) { int lcd_flag = FontCache::GetFontCache()->LcdTextEnabled() - ? SkPaint::kLCDRenderText_Flag + ? FontPlatformData::kSubpixelsAntiAlias : 0; - text_flags = SkPaint::kAntiAlias_Flag | lcd_flag; + font_flags = FontPlatformData::kAntiAlias | lcd_flag; } // Many web-fonts are so poorly hinted that they are terrible to read when @@ -132,13 +98,13 @@ static int ComputePaintTextFlags(String font_family_name) { // drawn with at least grayscale AA, even when the System (getSystemTextFlags) // tells us to draw only in BW. if (IsWebFont(font_family_name)) - text_flags |= SkPaint::kAntiAlias_Flag; + font_flags |= FontPlatformData::kAntiAlias; - return text_flags; + return font_flags; } void FontPlatformData::QuerySystemForRenderStyle() { - paint_text_flags_ = ComputePaintTextFlags(FontFamilyName()); + font_flags_ = ComputeFontFlags(FontFamilyName()); } } // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.cc b/chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.cc new file mode 100644 index 00000000000..715ce8996a0 --- /dev/null +++ b/chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.cc @@ -0,0 +1,75 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.h" + +#include "base/files/file_path.h" +#include "mojo/public/mojom/base/shared_memory.mojom-blink.h" +#include "third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom-blink.h" +#include "third_party/blink/renderer/platform/histogram.h" +#include "third_party/skia/include/ports/SkTypeface_win.h" + +namespace { + +// These enum values correspond to the +// "Blink.Fonts.WindowsUniqueLocalFontInstantiationResult" histogram, new values +// can be added, but old values should never be reused. +enum WindowsUniqueLocalFontInstantiationResult { + kSuccess = 0, + kErrorOutsideWindowsFontsDirectory = 1, + kErrorOther = 2, + kMaxWindowsUniqueLocalFontInstantiationResult = 3 +}; + +} // namespace + +namespace blink { + +FontUniqueNameLookupWin::FontUniqueNameLookupWin() = default; + +FontUniqueNameLookupWin::~FontUniqueNameLookupWin() = default; + +sk_sp<SkTypeface> FontUniqueNameLookupWin::MatchUniqueName( + const String& font_unique_name) { + if (!EnsureMatchingServiceConnected<mojom::blink::DWriteFontProxyPtr>()) + return nullptr; + + base::Optional<FontTableMatcher::MatchResult> match_result = + font_table_matcher_->MatchName(font_unique_name.Utf8().data()); + if (!match_result) + return nullptr; + // Record here when a locally uniquely matched font could not be + // instantiated. One reason could be that the font was outside the + // C:\Windows\Fonts directory and thus not accessible due to sandbox + // restrictions. + sk_sp<SkTypeface> local_typeface = SkTypeface::MakeFromFile( + match_result->font_path.c_str(), match_result->ttc_index); + + WindowsUniqueLocalFontInstantiationResult result = kSuccess; + + // There is a chance that some systems have managed to register fonts into the + // Windows system font collection outside the C:\Windows\Fonts directory. For + // sandboxing reasons, we are unable to access them here. This histogram + // serves to quantify how often this case occurs and whether we need and + // additional sandbox helper to open the file handle on the browser process + // side. + if (!local_typeface) { + base::FilePath windows_fonts_path(L"C:\\WINDOWS\\FONTS"); + if (!windows_fonts_path.IsParent( + base::FilePath::FromUTF8Unsafe(match_result->font_path.c_str()))) + result = kErrorOutsideWindowsFontsDirectory; + else + result = kErrorOther; + } + + DEFINE_THREAD_SAFE_STATIC_LOCAL( + EnumerationHistogram, windows_unique_local_font_instantiation_histogram, + ("Blink.Fonts.WindowsUniqueLocalFontInstantiationResult", + kMaxWindowsUniqueLocalFontInstantiationResult)); + windows_unique_local_font_instantiation_histogram.Count(result); + + return local_typeface; +} + +} // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.h b/chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.h new file mode 100644 index 00000000000..4593b9c5fee --- /dev/null +++ b/chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.h @@ -0,0 +1,25 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_WIN_FONT_UNIQUE_NAME_LOOKUP_WIN_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_WIN_FONT_UNIQUE_NAME_LOOKUP_WIN_H_ + +#include "third_party/blink/public/common/font_unique_name_lookup/font_table_matcher.h" +#include "third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h" + +namespace blink { + +class FontUniqueNameLookupWin : public FontUniqueNameLookup { + public: + FontUniqueNameLookupWin(); + ~FontUniqueNameLookupWin() override; + sk_sp<SkTypeface> MatchUniqueName(const String& font_unique_name) override; + + private: + DISALLOW_COPY_AND_ASSIGN(FontUniqueNameLookupWin); +}; + +} // namespace blink + +#endif |