summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/fonts
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-13 15:05:36 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-14 10:33:47 +0000
commite684a3455bcc29a6e3e66a004e352dea4e1141e7 (patch)
treed55b4003bde34d7d05f558f02cfd82b2a66a7aac /chromium/third_party/blink/renderer/platform/fonts
parent2b94bfe47ccb6c08047959d1c26e392919550e86 (diff)
downloadqtwebengine-chromium-e684a3455bcc29a6e3e66a004e352dea4e1141e7.tar.gz
BASELINE: Update Chromium to 72.0.3626.110 and Ninja to 1.9.0
Change-Id: Ic57220b00ecc929a893c91f5cc552f5d3e99e922 Reviewed-by: Michael Brüning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/fonts')
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/DEPS3
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/alternate_font_family.h48
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_cache.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_description.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_fallback_list.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_family_names.json52
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_metrics.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_metrics.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_platform_data.cc51
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_platform_data.h13
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_selector.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm16
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac_test.mm2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm92
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/ng_text_fragment_paint_info.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support_mpl.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_types.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.cc128
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/paint_font.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/paint_text_blob.h16
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/script_run_iterator_test.cc44
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/glyph_bounds_accumulator.h102
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc121
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc203
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_cache.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc254
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.h59
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc165
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h47
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc472
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h167
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view_test.cc366
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc47
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.h25
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/simple_font_data.cc20
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/simple_font_data.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc18
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.cc95
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.h45
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/utf16_text_iterator.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/web_font_render_style.cc59
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/font_platform_data_win.cc69
55 files changed, 2150 insertions, 875 deletions
diff --git a/chromium/third_party/blink/renderer/platform/fonts/DEPS b/chromium/third_party/blink/renderer/platform/fonts/DEPS
index 971791ef45b..d859ec63d6e 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/DEPS
+++ b/chromium/third_party/blink/renderer/platform/fonts/DEPS
@@ -13,8 +13,6 @@ include_rules = [
"+third_party/blink/renderer/platform/histogram.h",
"+third_party/blink/renderer/platform/instrumentation",
"+third_party/blink/renderer/platform/language.h",
- "+third_party/blink/renderer/platform/layout_test_support.h",
- "+third_party/blink/renderer/platform/layout_unit.h",
"+third_party/blink/renderer/platform/mac/version_util_mac.h",
"+third_party/blink/renderer/platform/platform_export.h",
"+third_party/blink/renderer/platform/resolution_units.h",
@@ -23,5 +21,6 @@ include_rules = [
"+third_party/blink/renderer/platform/shared_buffer.h",
"+third_party/blink/renderer/platform/testing",
"+third_party/blink/renderer/platform/text",
+ "+third_party/blink/renderer/platform/web_test_support.h",
"+third_party/blink/renderer/platform/wtf",
]
diff --git a/chromium/third_party/blink/renderer/platform/fonts/alternate_font_family.h b/chromium/third_party/blink/renderer/platform/fonts/alternate_font_family.h
index 62ae63d6b66..2382615a524 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/alternate_font_family.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/alternate_font_family.h
@@ -48,20 +48,20 @@ inline const AtomicString& AdjustFamilyNameToAvoidUnsupportedFonts(
// 'Courier' is a bitmap font. On Mac on the other hand 'Courier' is
// a truetype font. Thus pages asking for Courier are better of
// using 'Courier New' on windows.
- if (EqualIgnoringASCIICase(family_name, FontFamilyNames::Courier))
- return FontFamilyNames::Courier_New;
+ if (EqualIgnoringASCIICase(family_name, font_family_names::kCourier))
+ return font_family_names::kCourierNew;
// Alias 'MS Sans Serif' (bitmap font) -> 'Microsoft Sans Serif'
// (truetype font).
- if (EqualIgnoringASCIICase(family_name, FontFamilyNames::MS_Sans_Serif))
- return FontFamilyNames::Microsoft_Sans_Serif;
+ if (EqualIgnoringASCIICase(family_name, font_family_names::kMSSansSerif))
+ return font_family_names::kMicrosoftSansSerif;
// Alias 'MS Serif' (bitmap) -> 'Times New Roman' (truetype font).
// Alias 'Times' -> 'Times New Roman' (truetype font).
// There's no 'Microsoft Sans Serif-equivalent' for Serif.
- if (EqualIgnoringASCIICase(family_name, FontFamilyNames::MS_Serif) ||
- EqualIgnoringASCIICase(family_name, FontFamilyNames::Times))
- return FontFamilyNames::Times_New_Roman;
+ if (EqualIgnoringASCIICase(family_name, font_family_names::kMSSerif) ||
+ EqualIgnoringASCIICase(family_name, font_family_names::kTimes))
+ return font_family_names::kTimesNewRoman;
#endif
return family_name;
@@ -70,27 +70,27 @@ inline const AtomicString& AdjustFamilyNameToAvoidUnsupportedFonts(
inline const AtomicString& AlternateFamilyName(
const AtomicString& family_name) {
// Alias Courier <-> Courier New
- if (EqualIgnoringASCIICase(family_name, FontFamilyNames::Courier))
- return FontFamilyNames::Courier_New;
+ if (EqualIgnoringASCIICase(family_name, font_family_names::kCourier))
+ return font_family_names::kCourierNew;
#if !defined(OS_WIN)
// On Windows, Courier New (truetype font) is always present and
// Courier is a bitmap font. So, we don't want to map Courier New to
// Courier.
- if (EqualIgnoringASCIICase(family_name, FontFamilyNames::Courier_New))
- return FontFamilyNames::Courier;
+ if (EqualIgnoringASCIICase(family_name, font_family_names::kCourierNew))
+ return font_family_names::kCourier;
#endif
// Alias Times and Times New Roman.
- if (EqualIgnoringASCIICase(family_name, FontFamilyNames::Times))
- return FontFamilyNames::Times_New_Roman;
- if (EqualIgnoringASCIICase(family_name, FontFamilyNames::Times_New_Roman))
- return FontFamilyNames::Times;
+ if (EqualIgnoringASCIICase(family_name, font_family_names::kTimes))
+ return font_family_names::kTimesNewRoman;
+ if (EqualIgnoringASCIICase(family_name, font_family_names::kTimesNewRoman))
+ return font_family_names::kTimes;
// Alias Arial and Helvetica
- if (EqualIgnoringASCIICase(family_name, FontFamilyNames::Arial))
- return FontFamilyNames::Helvetica;
- if (EqualIgnoringASCIICase(family_name, FontFamilyNames::Helvetica))
- return FontFamilyNames::Arial;
+ if (EqualIgnoringASCIICase(family_name, font_family_names::kArial))
+ return font_family_names::kHelvetica;
+ if (EqualIgnoringASCIICase(family_name, font_family_names::kHelvetica))
+ return font_family_names::kArial;
return g_empty_atom;
}
@@ -99,15 +99,15 @@ inline const AtomicString& GetFallbackFontFamily(
const FontDescription& description) {
switch (description.GenericFamily()) {
case FontDescription::kSansSerifFamily:
- return FontFamilyNames::sans_serif;
+ return font_family_names::kSansSerif;
case FontDescription::kSerifFamily:
- return FontFamilyNames::serif;
+ return font_family_names::kSerif;
case FontDescription::kMonospaceFamily:
- return FontFamilyNames::monospace;
+ return font_family_names::kMonospace;
case FontDescription::kCursiveFamily:
- return FontFamilyNames::cursive;
+ return font_family_names::kCursive;
case FontDescription::kFantasyFamily:
- return FontFamilyNames::fantasy;
+ return font_family_names::kFantasy;
default:
// Let the caller use the system default font.
return g_empty_atom;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android.cc b/chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android.cc
index 6c8efc827f5..99aec1d670c 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android.cc
@@ -56,7 +56,7 @@ static AtomicString DefaultFontFamily(sk_sp<SkFontMgr> font_manager) {
// do here, use "Arial", the value LayoutTheme uses for CSS system font
// keywords such as "menu".
NOTREACHED();
- return FontFamilyNames::Arial;
+ return font_family_names::kArial;
}
static AtomicString DefaultFontFamily() {
@@ -99,7 +99,7 @@ AtomicString FontCache::GetGenericFamilyNameForScript(
// i18n fonts are likely not monospace. Monospace is mostly used
// for code, but when i18n characters appear in monospace, system
// fallback can still render the characters.
- if (family_name == FontFamilyNames::webkit_monospace)
+ if (family_name == font_family_names::kWebkitMonospace)
return family_name;
// The CJK hack below should be removed, at latest when we have
diff --git a/chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android_test.cc b/chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android_test.cc
index efe8ddc64ef..5f03b588f82 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android_test.cc
@@ -39,26 +39,25 @@ TEST(FontCacheAndroid, genericFamilyNameForScript) {
FontDescription chinese;
chinese.SetLocale(LayoutLocale::Get("zh"));
- if (FontFamilyNames::webkit_standard.IsEmpty())
- FontFamilyNames::init();
+ font_family_names::Init();
// For non-CJK, getGenericFamilyNameForScript should return the given
// familyName.
- EXPECT_EQ(FontFamilyNames::webkit_standard,
+ EXPECT_EQ(font_family_names::kWebkitStandard,
FontCache::GetGenericFamilyNameForScript(
- FontFamilyNames::webkit_standard, english));
- EXPECT_EQ(FontFamilyNames::webkit_monospace,
+ font_family_names::kWebkitStandard, english));
+ EXPECT_EQ(font_family_names::kWebkitMonospace,
FontCache::GetGenericFamilyNameForScript(
- FontFamilyNames::webkit_monospace, english));
+ font_family_names::kWebkitMonospace, english));
// For CJK, getGenericFamilyNameForScript should return CJK fonts except
// monospace.
- EXPECT_NE(FontFamilyNames::webkit_standard,
+ EXPECT_NE(font_family_names::kWebkitStandard,
FontCache::GetGenericFamilyNameForScript(
- FontFamilyNames::webkit_standard, chinese));
- EXPECT_EQ(FontFamilyNames::webkit_monospace,
+ font_family_names::kWebkitStandard, chinese));
+ EXPECT_EQ(font_family_names::kWebkitMonospace,
FontCache::GetGenericFamilyNameForScript(
- FontFamilyNames::webkit_monospace, chinese));
+ font_family_names::kWebkitMonospace, chinese));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font.cc b/chromium/third_party/blink/renderer/platform/fonts/font.cc
index def231a9a7a..ef63a49a1f5 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font.cc
@@ -31,13 +31,12 @@
#include "third_party/blink/renderer/platform/fonts/font_fallback_iterator.h"
#include "third_party/blink/renderer/platform/fonts/font_fallback_list.h"
#include "third_party/blink/renderer/platform/fonts/ng_text_fragment_paint_info.h"
-#include "third_party/blink/renderer/platform/fonts/paint_text_blob.h"
#include "third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h"
#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
#include "third_party/blink/renderer/platform/fonts/text_run_paint_info.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
-#include "third_party/blink/renderer/platform/layout_unit.h"
+#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
#include "third_party/blink/renderer/platform/text/bidi_resolver.h"
#include "third_party/blink/renderer/platform/text/character.h"
#include "third_party/blink/renderer/platform/text/text_run.h"
@@ -291,9 +290,8 @@ unsigned InterceptsFromBlobs(const ShapeResultBloberizer::BlobBuffer& blobs,
SkScalar* offset_intercepts_buffer = nullptr;
if (intercepts_buffer)
offset_intercepts_buffer = &intercepts_buffer[num_intervals];
- num_intervals +=
- paint.getTextBlobIntercepts(blob_info.blob->ToSkTextBlob().get(),
- bounds_array, offset_intercepts_buffer);
+ num_intervals += paint.getTextBlobIntercepts(
+ blob_info.blob.get(), bounds_array, offset_intercepts_buffer);
}
return num_intervals;
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font.h b/chromium/third_party/blink/renderer/platform/fonts/font.h
index 559bd97f1d3..313afb7a155 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font.h
@@ -29,7 +29,7 @@
#include "third_party/blink/renderer/platform/fonts/font_fallback_list.h"
#include "third_party/blink/renderer/platform/fonts/font_fallback_priority.h"
#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
-#include "third_party/blink/renderer/platform/layout_unit.h"
+#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/text/tab_size.h"
#include "third_party/blink/renderer/platform/text/text_direction.h"
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 ac44cca505d..b72da9f7015 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_cache.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_cache.cc
@@ -89,10 +89,10 @@ FontPlatformData* FontCache::SystemFontPlatformData(
const FontDescription& font_description) {
const AtomicString& family = FontCache::SystemFontFamily();
#if defined(OS_LINUX)
- if (family.IsEmpty() || family == FontFamilyNames::system_ui)
+ if (family.IsEmpty() || family == font_family_names::kSystemUi)
return nullptr;
#else
- DCHECK(!family.IsEmpty() && family != FontFamilyNames::system_ui);
+ DCHECK(!family.IsEmpty() && family != font_family_names::kSystemUi);
#endif
return GetFontPlatformData(font_description, FontFaceCreationParams(family),
AlternateFontName::kNoAlternate);
@@ -110,7 +110,7 @@ FontPlatformData* FontCache::GetFontPlatformData(
#if !defined(OS_MACOSX)
if (creation_params.CreationType() == kCreateFontByFamily &&
- creation_params.Family() == FontFamilyNames::system_ui) {
+ creation_params.Family() == font_family_names::kSystemUi) {
return SystemFontPlatformData(font_description);
}
#endif
@@ -355,7 +355,8 @@ void FontCache::Purge(PurgeSeverity purge_severity) {
void FontCache::AddClient(FontCacheClient* client) {
CHECK(client);
if (!font_cache_clients_) {
- font_cache_clients_ = new HeapHashSet<WeakMember<FontCacheClient>>();
+ font_cache_clients_ =
+ MakeGarbageCollected<HeapHashSet<WeakMember<FontCacheClient>>>();
font_cache_clients_.RegisterAsStaticReference();
}
DCHECK(!font_cache_clients_->Contains(client));
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 15a999cb190..925923d8ff1 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_description.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_description.h
@@ -179,7 +179,7 @@ class PLATFORM_EXPORT FontDescription {
// family is "monospace"
bool IsMonospace() const {
return GenericFamily() == kMonospaceFamily && !Family().Next() &&
- Family().Family() == FontFamilyNames::webkit_monospace;
+ Family().Family() == font_family_names::kWebkitMonospace;
}
Kerning GetKerning() const { return static_cast<Kerning>(fields_.kerning_); }
FontVariantEastAsian VariantEastAsian() const {
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 a29433a64c5..85e8fbc134c 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
@@ -174,7 +174,7 @@ scoped_refptr<FontData> FontFallbackList::GetFontData(
if (font_selector_) {
// Try the user's preferred standard font.
if (scoped_refptr<FontData> data = font_selector_->GetFontData(
- font_description, FontFamilyNames::webkit_standard))
+ font_description, font_family_names::kWebkitStandard))
return data;
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_family_names.json5 b/chromium/third_party/blink/renderer/platform/fonts/font_family_names.json5
index 638bf7995fe..ac7a142f9bf 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_family_names.json5
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_family_names.json5
@@ -1,6 +1,6 @@
{
metadata: {
- namespace: "FontFamily",
+ namespace: "font_family_names",
export: "PLATFORM_EXPORT",
},
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 0d431a2eb65..abc03f40a1b 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_metrics.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_metrics.cc
@@ -33,7 +33,7 @@
#include "third_party/blink/renderer/platform/fonts/font_platform_data.h"
#include "third_party/blink/renderer/platform/fonts/vdmx_parser.h"
-#include <SkPaint.h>
+#include <SkFont.h>
#include <SkTypeface.h>
namespace blink {
@@ -49,13 +49,13 @@ void FontMetrics::AscentDescentWithHacks(
unsigned& visual_overflow_inflation_for_ascent,
unsigned& visual_overflow_inflation_for_descent,
const FontPlatformData& platform_data,
- const SkPaint& paint,
+ const SkFont& font,
bool subpixel_ascent_descent) {
- SkTypeface* face = paint.getTypeface();
+ SkTypeface* face = font.getTypeface();
DCHECK(face);
- SkPaint::FontMetrics metrics;
- paint.getFontMetrics(&metrics);
+ SkFontMetrics metrics;
+ font.getMetrics(&metrics);
int vdmx_ascent = 0, vdmx_descent = 0;
bool is_vdmx_valid = false;
@@ -66,9 +66,9 @@ void FontMetrics::AscentDescentWithHacks(
// done. This code should be pushed into FreeType (hinted font metrics).
static const uint32_t kVdmxTag = SkSetFourByteTag('V', 'D', 'M', 'X');
int pixel_size = platform_data.size() + 0.5;
- if (!paint.isAutohinted() &&
- (paint.getHinting() == SkPaint::kFull_Hinting ||
- paint.getHinting() == SkPaint::kNormal_Hinting)) {
+ if (!font.isForceAutoHinting() &&
+ (font.getHinting() == SkFontHinting::kFull ||
+ font.getHinting() == SkFontHinting::kNormal)) {
size_t vdmx_size = face->getTableSize(kVdmxTag);
if (vdmx_size && vdmx_size < kMaxVDMXTableSize) {
uint8_t* vdmx_table = (uint8_t*)WTF::Partitions::FastMalloc(
@@ -132,9 +132,9 @@ void FontMetrics::AscentDescentWithHacks(
// incorrectly added to line spacing, so we use a 15% adjustment instead
// and add it to the ascent.
String family_name = platform_data.FontFamilyName();
- if (family_name == FontFamilyNames::Times ||
- family_name == FontFamilyNames::Helvetica ||
- family_name == FontFamilyNames::Courier)
+ if (family_name == font_family_names::kTimes ||
+ family_name == font_family_names::kHelvetica ||
+ family_name == font_family_names::kCourier)
ascent += floorf(((ascent + descent) * 0.15f) + 0.5f);
#endif
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_metrics.h b/chromium/third_party/blink/renderer/platform/fonts/font_metrics.h
index fbacc8cfee4..e440a79c627 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_metrics.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_metrics.h
@@ -21,11 +21,11 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_METRICS_H_
#include "third_party/blink/renderer/platform/fonts/font_baseline.h"
-#include "third_party/blink/renderer/platform/layout_unit.h"
+#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
-#include <SkPaint.h>
+class SkFont;
namespace blink {
@@ -168,7 +168,7 @@ class FontMetrics {
unsigned& visual_overflow_inflation_for_ascent,
unsigned& visual_overflow_inflation_for_descent,
const FontPlatformData&,
- const SkPaint&,
+ const SkFont&,
bool subpixel_ascent_descent = false);
private:
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 426c7db61e5..64dd8218e9a 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
@@ -20,6 +20,7 @@
#include "third_party/blink/renderer/platform/fonts/font_platform_data.h"
+#include "SkFont.h"
#include "SkTypeface.h"
#include "build/build_config.h"
#include "hb-ot.h"
@@ -28,8 +29,8 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h"
-#include "third_party/blink/renderer/platform/layout_test_support.h"
#include "third_party/blink/renderer/platform/text/character.h"
+#include "third_party/blink/renderer/platform/web_test_support.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
@@ -147,11 +148,11 @@ FontPlatformData::FontPlatformData(sk_sp<SkTypeface> typeface,
auto system_style =
QuerySystemRenderStyle(family_, text_size_, typeface_->fontStyle());
- // In layout tests, ignore system preference for subpixel positioning,
+ // In web tests, ignore system preference for subpixel positioning,
// or explicitly disable if requested.
- if (LayoutTestSupport::IsRunningLayoutTest()) {
+ if (WebTestSupport::IsRunningWebTest()) {
system_style.use_subpixel_positioning =
- LayoutTestSupport::IsTextSubpixelPositioningAllowedForTest()
+ WebTestSupport::IsTextSubpixelPositioningAllowedForTest()
? WebFontRenderStyle::kNoPreference
: 0;
}
@@ -281,13 +282,9 @@ unsigned FontPlatformData::GetHash() const {
#if !defined(OS_MACOSX)
bool FontPlatformData::FontContainsCharacter(UChar32 character) {
- PaintFont font;
- SetupPaintFont(&font);
- font.SetTextEncoding(SkPaint::kUTF32_TextEncoding);
-
- uint16_t glyph;
- font.ToSkPaint().textToGlyphs(&character, sizeof(character), &glyph);
- return glyph;
+ SkFont font;
+ SetupSkFont(&font);
+ return font.unicharToGlyph(character);
}
#endif
@@ -314,18 +311,32 @@ WebFontRenderStyle FontPlatformData::QuerySystemRenderStyle(
return result;
}
-void FontPlatformData::SetupPaintFont(PaintFont* font,
- float device_scale_factor,
- const Font*) const {
- style_.ApplyToPaintFont(*font, device_scale_factor);
+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 {
+ style_.ApplyToSkFont(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->setSize(SkFloatToScalar(ts));
+ font->setTypeface(typeface_);
+ font->setEmbolden(synthetic_bold_);
+ font->setSkewX(synthetic_italic_ ? -SK_Scalar1 / 4 : 0);
- font->SetEmbeddedBitmapText(!avoid_embedded_bitmaps_);
+ font->setEmbeddedBitmaps(!avoid_embedded_bitmaps_);
}
#endif
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 ea701d0480a..7c6939331e2 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
@@ -38,7 +38,6 @@
#include "third_party/blink/public/platform/web_font_render_style.h"
#include "third_party/blink/renderer/platform/fonts/font_description.h"
#include "third_party/blink/renderer/platform/fonts/font_orientation.h"
-#include "third_party/blink/renderer/platform/fonts/paint_font.h"
#include "third_party/blink/renderer/platform/fonts/small_caps_iterator.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
@@ -66,6 +65,7 @@ inline NSFont* toNSFont(CTFontRef ctFontRef) {
}
#endif // defined(OS_MACOSX)
+class SkFont;
class SkTypeface;
typedef uint32_t SkFontID;
@@ -154,9 +154,14 @@ class PLATFORM_EXPORT FontPlatformData {
const WebFontRenderStyle& GetFontRenderStyle() const { return style_; }
#endif
- void SetupPaintFont(PaintFont*,
- float device_scale_factor = 1,
- const Font* = nullptr) const;
+ // 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_; }
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_selector.cc b/chromium/third_party/blink/renderer/platform/fonts/font_selector.cc
index 90bb107acbc..4e484041c51 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_selector.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_selector.cc
@@ -18,7 +18,7 @@ AtomicString FontSelector::FamilyNameFromSettings(
#if defined(OS_ANDROID)
if (font_description.GenericFamily() == FontDescription::kStandardFamily) {
return FontCache::GetGenericFamilyNameForScript(
- FontFamilyNames::webkit_standard, font_description);
+ font_family_names::kWebkitStandard, font_description);
}
if (generic_family_name.StartsWith("-webkit-")) {
@@ -29,19 +29,19 @@ AtomicString FontSelector::FamilyNameFromSettings(
UScriptCode script = font_description.GetScript();
if (font_description.GenericFamily() == FontDescription::kStandardFamily)
return settings.Standard(script);
- if (generic_family_name == FontFamilyNames::webkit_serif)
+ if (generic_family_name == font_family_names::kWebkitSerif)
return settings.Serif(script);
- if (generic_family_name == FontFamilyNames::webkit_sans_serif)
+ if (generic_family_name == font_family_names::kWebkitSansSerif)
return settings.SansSerif(script);
- if (generic_family_name == FontFamilyNames::webkit_cursive)
+ if (generic_family_name == font_family_names::kWebkitCursive)
return settings.Cursive(script);
- if (generic_family_name == FontFamilyNames::webkit_fantasy)
+ if (generic_family_name == font_family_names::kWebkitFantasy)
return settings.Fantasy(script);
- if (generic_family_name == FontFamilyNames::webkit_monospace)
+ if (generic_family_name == font_family_names::kWebkitMonospace)
return settings.Fixed(script);
- if (generic_family_name == FontFamilyNames::webkit_pictograph)
+ if (generic_family_name == font_family_names::kWebkitPictograph)
return settings.Pictograph(script);
- if (generic_family_name == FontFamilyNames::webkit_standard)
+ if (generic_family_name == font_family_names::kWebkitStandard)
return settings.Standard(script);
#endif
return g_empty_atom;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm b/chromium/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm
index 8b605043d91..829170dec12 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm
+++ b/chromium/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm
@@ -39,9 +39,9 @@
#include "third_party/blink/renderer/platform/fonts/font_platform_data.h"
#include "third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.h"
#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
-#include "third_party/blink/renderer/platform/layout_test_support.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
+#include "third_party/blink/renderer/platform/web_test_support.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
@@ -63,12 +63,12 @@ const char kColorEmojiFontMac[] = "Apple Color Emoji";
// static
const AtomicString& FontCache::LegacySystemFontFamily() {
- return FontFamilyNames::BlinkMacSystemFont;
+ return font_family_names::kBlinkMacSystemFont;
}
static void InvalidateFontCache() {
if (!IsMainThread()) {
- Platform::Current()->MainThread()->GetTaskRunner()->PostTask(
+ Thread::MainThread()->GetTaskRunner()->PostTask(
FROM_HERE, WTF::Bind(&InvalidateFontCache));
return;
}
@@ -87,9 +87,9 @@ static void FontCacheRegisteredFontsChangedNotificationCallback(
}
static bool UseHinting() {
- // Enable hinting only when antialiasing is disabled in layout tests.
- return (LayoutTestSupport::IsRunningLayoutTest() &&
- !LayoutTestSupport::IsFontAntialiasingEnabledForTest());
+ // Enable hinting only when antialiasing is disabled in web tests.
+ return (WebTestSupport::IsRunningWebTest() &&
+ !WebTestSupport::IsFontAntialiasingEnabledForTest());
}
void FontCache::PlatformInit() {
@@ -232,7 +232,7 @@ scoped_refptr<SimpleFontData> FontCache::GetLastResortFallbackFont(
// For now we'll pick the default that the user would get without changing
// any prefs.
scoped_refptr<SimpleFontData> simple_font_data =
- GetFontData(font_description, FontFamilyNames::Times,
+ GetFontData(font_description, font_family_names::kTimes,
AlternateFontName::kAllowAlternate, should_retain);
if (simple_font_data)
return simple_font_data;
@@ -241,7 +241,7 @@ scoped_refptr<SimpleFontData> FontCache::GetLastResortFallbackFont(
// where the user doesn't have it, we fall back on Lucida Grande because
// that's guaranteed to be there, according to Nathan Taylor. This is good
// enough to avoid a crash at least.
- return GetFontData(font_description, FontFamilyNames::Lucida_Grande,
+ return GetFontData(font_description, font_family_names::kLucidaGrande,
AlternateFontName::kAllowAlternate, should_retain);
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm b/chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm
index c6bced3e598..8d71fc2f18a 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm
+++ b/chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm
@@ -174,7 +174,7 @@ NSFont* MatchNSFontFamily(const AtomicString& desired_family_string,
float size) {
DCHECK_NE(desired_family_string, FontCache::LegacySystemFontFamily());
- if (desired_family_string == FontFamilyNames::system_ui) {
+ if (desired_family_string == font_family_names::kSystemUi) {
NSFont* font = nil;
// Normally we'd use an availability macro here, but
// systemFontOfSize:weight: is available but not visible on macOS 10.10,
diff --git a/chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac_test.mm b/chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac_test.mm
index 67476f5a82b..c1d9ad62145 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac_test.mm
+++ b/chromium/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac_test.mm
@@ -19,7 +19,7 @@ namespace blink {
void TestSystemFontContainsString(FontSelectionValue desired_weight,
NSString* substring) {
NSFont* font =
- MatchNSFontFamily(FontFamilyNames::system_ui, 0, desired_weight, 11);
+ MatchNSFontFamily(font_family_names::kSystemUi, 0, desired_weight, 11);
EXPECT_TRUE([font.description containsString:substring]);
}
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 33b228f6b8a..97bebbdb53a 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
@@ -30,9 +30,10 @@
#import "third_party/blink/renderer/platform/fonts/font.h"
#import "third_party/blink/renderer/platform/fonts/opentype/font_settings.h"
#import "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h"
-#import "third_party/blink/renderer/platform/layout_test_support.h"
+#import "third_party/blink/renderer/platform/web_test_support.h"
#import "third_party/blink/renderer/platform/wtf/retain_ptr.h"
#import "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#import "third_party/skia/include/core/SkFont.h"
#import "third_party/skia/include/core/SkStream.h"
#import "third_party/skia/include/ports/SkTypeface_mac.h"
@@ -111,9 +112,9 @@ static sk_sp<SkTypeface> LoadFromBrowserProcess(NSFont* ns_font,
return return_font;
}
-void FontPlatformData::SetupPaintFont(PaintFont* paint_font,
- float,
- const Font* font) const {
+void FontPlatformData::SetupSkPaint(SkPaint* paint,
+ float,
+ const Font* font) const {
bool should_smooth_fonts = true;
bool should_antialias = true;
bool should_subpixel_position = true;
@@ -136,23 +137,23 @@ void FontPlatformData::SetupPaintFont(PaintFont* paint_font,
}
}
- if (LayoutTestSupport::IsRunningLayoutTest()) {
+ if (WebTestSupport::IsRunningWebTest()) {
should_smooth_fonts = false;
- should_antialias = should_antialias &&
- LayoutTestSupport::IsFontAntialiasingEnabledForTest();
+ should_antialias =
+ should_antialias && WebTestSupport::IsFontAntialiasingEnabledForTest();
should_subpixel_position =
- LayoutTestSupport::IsTextSubpixelPositioningAllowedForTest();
+ WebTestSupport::IsTextSubpixelPositioningAllowedForTest();
}
- paint_font->SetAntiAlias(should_antialias);
- paint_font->SetEmbeddedBitmapText(false);
+ paint->setAntiAlias(should_antialias);
+ paint->setEmbeddedBitmapText(false);
const float ts = text_size_ >= 0 ? text_size_ : 12;
- paint_font->SetTextSize(SkFloatToScalar(ts));
- paint_font->SetTypeface(typeface_);
- paint_font->SetFakeBoldText(synthetic_bold_);
- paint_font->SetTextSkewX(synthetic_italic_ ? -SK_Scalar1 / 4 : 0);
- paint_font->SetLcdRenderText(should_smooth_fonts);
- paint_font->SetSubpixelText(should_subpixel_position);
+ 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
@@ -160,7 +161,64 @@ void FontPlatformData::SetupPaintFont(PaintFont* paint_font,
if (font &&
(font->GetFontDescription().FontSmoothing() == kAntialiased ||
font->GetFontDescription().TextRendering() == kGeometricPrecision))
- paint_font->SetHinting(SkPaint::kNo_Hinting);
+ paint->setHinting(SkFontHinting::kNone);
+}
+
+void FontPlatformData::SetupSkFont(SkFont* skfont,
+ 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();
+ }
+
+ if (should_antialias && should_smooth_fonts) {
+ skfont->setEdging(SkFont::Edging::kSubpixelAntiAlias);
+ } else if (should_antialias) {
+ skfont->setEdging(SkFont::Edging::kAntiAlias);
+ } else {
+ skfont->setEdging(SkFont::Edging::kAlias);
+ }
+ skfont->setEmbeddedBitmaps(false);
+ const float ts = text_size_ >= 0 ? text_size_ : 12;
+ skfont->setSize(SkFloatToScalar(ts));
+ skfont->setTypeface(typeface_);
+ skfont->setEmbolden(synthetic_bold_);
+ skfont->setSkewX(synthetic_italic_ ? -SK_Scalar1 / 4 : 0);
+ skfont->setSubpixel(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))
+ skfont->setHinting(SkFontHinting::kNone);
}
FontPlatformData::FontPlatformData(NSFont* ns_font,
diff --git a/chromium/third_party/blink/renderer/platform/fonts/ng_text_fragment_paint_info.h b/chromium/third_party/blink/renderer/platform/fonts/ng_text_fragment_paint_info.h
index e4b58a8a90b..d42fc22c15f 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/ng_text_fragment_paint_info.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/ng_text_fragment_paint_info.h
@@ -10,7 +10,7 @@
namespace blink {
-class ShapeResult;
+class ShapeResultView;
// Bridge struct for painting text. Encapsulates info needed by the paint code.
struct PLATFORM_EXPORT NGTextFragmentPaintInfo {
@@ -23,7 +23,7 @@ struct PLATFORM_EXPORT NGTextFragmentPaintInfo {
// The |shape_result| may not contain all characters of the |text|, but is
// guaranteed to contain |from| to |to|.
- const ShapeResult* shape_result;
+ const ShapeResultView* shape_result;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support_mpl.cc b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support_mpl.cc
index 0e0a808ac1c..f04b91d087b 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support_mpl.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support_mpl.cc
@@ -6,6 +6,7 @@
*
* ***** END LICENSE BLOCK ***** */
+#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.h"
#include <hb-ot.h>
@@ -29,17 +30,18 @@ bool OpenTypeCapsSupport::SupportsOpenTypeFeature(hb_script_t script,
return false;
// Get the OpenType tag(s) that match this script code
- hb_tag_t script_tags[] = {
- HB_TAG_NONE, HB_TAG_NONE, HB_TAG_NONE,
- };
- hb_ot_tags_from_script(static_cast<hb_script_t>(script), &script_tags[0],
- &script_tags[1]);
+ DCHECK_EQ(HB_TAG_NONE, 0u);
+ hb_tag_t script_tags[2] = {};
+ unsigned num_returned_script_tags = base::size(script_tags);
+ hb_ot_tags_from_script_and_language(
+ static_cast<hb_script_t>(script), HB_LANGUAGE_INVALID,
+ &num_returned_script_tags, script_tags, nullptr, nullptr);
const hb_tag_t kGSUB = HB_TAG('G', 'S', 'U', 'B');
unsigned script_index = 0;
// Identify for which script a GSUB table is available.
- hb_ot_layout_table_choose_script(face, kGSUB, script_tags, &script_index,
- nullptr);
+ hb_ot_layout_table_select_script(face, kGSUB, num_returned_script_tags,
+ script_tags, &script_index, nullptr);
if (hb_ot_layout_language_find_feature(face, kGSUB, script_index,
HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_types.h b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_types.h
index d605c176897..12c90c9b174 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_types.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_types.h
@@ -29,7 +29,7 @@
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
-namespace OpenType {
+namespace open_type {
struct Int16 {
DISALLOW_NEW();
@@ -101,6 +101,6 @@ struct TableBase {
}
};
-} // namespace OpenType
+} // namespace open_type
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_OPENTYPE_OPEN_TYPE_TYPES_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.cc b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.cc
index 32362740417..39676595708 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.cc
@@ -33,7 +33,7 @@
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
namespace blink {
-namespace OpenType {
+namespace open_type {
// The input characters are big-endian (first is most significant).
#define OT_MAKE_TAG(ch1, ch2, ch3, ch4) \
@@ -50,46 +50,46 @@ const SkFontTableTag kVORGTag = OT_MAKE_TAG('V', 'O', 'R', 'G');
struct HheaTable {
DISALLOW_NEW();
- OpenType::Fixed version;
- OpenType::Int16 ascender;
- OpenType::Int16 descender;
- OpenType::Int16 line_gap;
- OpenType::Int16 advance_width_max;
- OpenType::Int16 min_left_side_bearing;
- OpenType::Int16 min_right_side_bearing;
- OpenType::Int16 x_max_extent;
- OpenType::Int16 caret_slope_rise;
- OpenType::Int16 caret_slope_run;
- OpenType::Int16 caret_offset;
- OpenType::Int16 reserved[4];
- OpenType::Int16 metric_data_format;
- OpenType::UInt16 number_of_h_metrics;
+ open_type::Fixed version;
+ open_type::Int16 ascender;
+ open_type::Int16 descender;
+ open_type::Int16 line_gap;
+ open_type::Int16 advance_width_max;
+ open_type::Int16 min_left_side_bearing;
+ open_type::Int16 min_right_side_bearing;
+ open_type::Int16 x_max_extent;
+ open_type::Int16 caret_slope_rise;
+ open_type::Int16 caret_slope_run;
+ open_type::Int16 caret_offset;
+ open_type::Int16 reserved[4];
+ open_type::Int16 metric_data_format;
+ open_type::UInt16 number_of_h_metrics;
};
struct VheaTable {
DISALLOW_NEW();
- OpenType::Fixed version;
- OpenType::Int16 ascent;
- OpenType::Int16 descent;
- OpenType::Int16 line_gap;
- OpenType::Int16 advance_height_max;
- OpenType::Int16 min_top_side_bearing;
- OpenType::Int16 min_bottom_side_bearing;
- OpenType::Int16 y_max_extent;
- OpenType::Int16 caret_slope_rise;
- OpenType::Int16 caret_slope_run;
- OpenType::Int16 caret_offset;
- OpenType::Int16 reserved[4];
- OpenType::Int16 metric_data_format;
- OpenType::UInt16 num_of_long_ver_metrics;
+ open_type::Fixed version;
+ open_type::Int16 ascent;
+ open_type::Int16 descent;
+ open_type::Int16 line_gap;
+ open_type::Int16 advance_height_max;
+ open_type::Int16 min_top_side_bearing;
+ open_type::Int16 min_bottom_side_bearing;
+ open_type::Int16 y_max_extent;
+ open_type::Int16 caret_slope_rise;
+ open_type::Int16 caret_slope_run;
+ open_type::Int16 caret_offset;
+ open_type::Int16 reserved[4];
+ open_type::Int16 metric_data_format;
+ open_type::UInt16 num_of_long_ver_metrics;
};
struct HmtxTable {
DISALLOW_NEW();
struct Entry {
DISALLOW_NEW();
- OpenType::UInt16 advance_width;
- OpenType::Int16 lsb;
+ open_type::UInt16 advance_width;
+ open_type::Int16 lsb;
} entries[1];
};
@@ -97,21 +97,21 @@ struct VmtxTable {
DISALLOW_NEW();
struct Entry {
DISALLOW_NEW();
- OpenType::UInt16 advance_height;
- OpenType::Int16 top_side_bearing;
+ open_type::UInt16 advance_height;
+ open_type::Int16 top_side_bearing;
} entries[1];
};
struct VORGTable {
DISALLOW_NEW();
- OpenType::UInt16 major_version;
- OpenType::UInt16 minor_version;
- OpenType::Int16 default_vert_origin_y;
- OpenType::UInt16 num_vert_origin_y_metrics;
+ open_type::UInt16 major_version;
+ open_type::UInt16 minor_version;
+ open_type::Int16 default_vert_origin_y;
+ open_type::UInt16 num_vert_origin_y_metrics;
struct VertOriginYMetrics {
DISALLOW_NEW();
- OpenType::UInt16 glyph_index;
- OpenType::Int16 vert_origin_y;
+ open_type::UInt16 glyph_index;
+ open_type::Int16 vert_origin_y;
} vert_origin_y_metrics[1];
size_t RequiredSize() const {
@@ -122,7 +122,7 @@ struct VORGTable {
#pragma pack()
-} // namespace OpenType
+} // namespace open_type
OpenTypeVerticalData::OpenTypeVerticalData(sk_sp<SkTypeface> typeface)
: default_vert_origin_y_(0),
@@ -146,9 +146,9 @@ void OpenTypeVerticalData::LoadMetrics(sk_sp<SkTypeface> typeface) {
// Load hhea and hmtx to get x-component of vertical origins.
// If these tables are missing, it's not an OpenType font.
Vector<char> buffer;
- CopyOpenTypeTable(typeface, OpenType::kHheaTag, buffer);
- const OpenType::HheaTable* hhea =
- OpenType::ValidateTable<OpenType::HheaTable>(buffer);
+ CopyOpenTypeTable(typeface, open_type::kHheaTag, buffer);
+ const open_type::HheaTable* hhea =
+ open_type::ValidateTable<open_type::HheaTable>(buffer);
if (!hhea)
return;
uint16_t count_hmtx_entries = hhea->number_of_h_metrics;
@@ -157,9 +157,10 @@ void OpenTypeVerticalData::LoadMetrics(sk_sp<SkTypeface> typeface) {
return;
}
- CopyOpenTypeTable(typeface, OpenType::kHmtxTag, buffer);
- const OpenType::HmtxTable* hmtx =
- OpenType::ValidateTable<OpenType::HmtxTable>(buffer, count_hmtx_entries);
+ CopyOpenTypeTable(typeface, open_type::kHmtxTag, buffer);
+ const open_type::HmtxTable* hmtx =
+ open_type::ValidateTable<open_type::HmtxTable>(buffer,
+ count_hmtx_entries);
if (!hmtx) {
DLOG(ERROR) << "hhea exists but hmtx does not (or broken)";
return;
@@ -170,9 +171,9 @@ void OpenTypeVerticalData::LoadMetrics(sk_sp<SkTypeface> typeface) {
// Load vhea first. This table is required for fonts that support vertical
// flow.
- CopyOpenTypeTable(typeface, OpenType::kVheaTag, buffer);
- const OpenType::VheaTable* vhea =
- OpenType::ValidateTable<OpenType::VheaTable>(buffer);
+ CopyOpenTypeTable(typeface, open_type::kVheaTag, buffer);
+ const open_type::VheaTable* vhea =
+ open_type::ValidateTable<open_type::VheaTable>(buffer);
if (!vhea)
return;
uint16_t count_vmtx_entries = vhea->num_of_long_ver_metrics;
@@ -182,9 +183,9 @@ void OpenTypeVerticalData::LoadMetrics(sk_sp<SkTypeface> typeface) {
}
// Load VORG. This table is optional.
- CopyOpenTypeTable(typeface, OpenType::kVORGTag, buffer);
- const OpenType::VORGTable* vorg =
- OpenType::ValidateTable<OpenType::VORGTable>(buffer);
+ CopyOpenTypeTable(typeface, open_type::kVORGTag, buffer);
+ const open_type::VORGTable* vorg =
+ open_type::ValidateTable<open_type::VORGTable>(buffer);
if (vorg && buffer.size() >= vorg->RequiredSize()) {
default_vert_origin_y_ = vorg->default_vert_origin_y;
uint16_t count_vert_origin_y_metrics = vorg->num_vert_origin_y_metrics;
@@ -193,7 +194,7 @@ void OpenTypeVerticalData::LoadMetrics(sk_sp<SkTypeface> typeface) {
vert_origin_y_.Set(0, default_vert_origin_y_);
} else {
for (uint16_t i = 0; i < count_vert_origin_y_metrics; ++i) {
- const OpenType::VORGTable::VertOriginYMetrics& metrics =
+ const open_type::VORGTable::VertOriginYMetrics& metrics =
vorg->vert_origin_y_metrics[i];
vert_origin_y_.Set(metrics.glyph_index, metrics.vert_origin_y);
}
@@ -202,9 +203,10 @@ void OpenTypeVerticalData::LoadMetrics(sk_sp<SkTypeface> typeface) {
// Load vmtx then. This table is required for fonts that support vertical
// flow.
- CopyOpenTypeTable(typeface, OpenType::kVmtxTag, buffer);
- const OpenType::VmtxTable* vmtx =
- OpenType::ValidateTable<OpenType::VmtxTable>(buffer, count_vmtx_entries);
+ CopyOpenTypeTable(typeface, open_type::kVmtxTag, buffer);
+ const open_type::VmtxTable* vmtx =
+ open_type::ValidateTable<open_type::VmtxTable>(buffer,
+ count_vmtx_entries);
if (!vmtx) {
DLOG(ERROR) << "vhea exists but vmtx does not (or broken)";
return;
@@ -219,20 +221,20 @@ void OpenTypeVerticalData::LoadMetrics(sk_sp<SkTypeface> typeface) {
return;
wtf_size_t size_extra =
- buffer.size() - sizeof(OpenType::VmtxTable::Entry) * count_vmtx_entries;
- if (size_extra % sizeof(OpenType::Int16)) {
+ buffer.size() - sizeof(open_type::VmtxTable::Entry) * count_vmtx_entries;
+ if (size_extra % sizeof(open_type::Int16)) {
DLOG(ERROR) << "vmtx has incorrect tsb count";
return;
}
wtf_size_t count_top_side_bearings =
- count_vmtx_entries + size_extra / sizeof(OpenType::Int16);
+ count_vmtx_entries + size_extra / sizeof(open_type::Int16);
top_side_bearings_.resize(count_top_side_bearings);
wtf_size_t i;
for (i = 0; i < count_vmtx_entries; ++i)
top_side_bearings_[i] = vmtx->entries[i].top_side_bearing;
if (i < count_top_side_bearings) {
- const OpenType::Int16* p_top_side_bearings_extra =
- reinterpret_cast<const OpenType::Int16*>(
+ const open_type::Int16* p_top_side_bearings_extra =
+ reinterpret_cast<const open_type::Int16*>(
&vmtx->entries[count_vmtx_entries]);
for (; i < count_top_side_bearings; ++i, ++p_top_side_bearings_extra)
top_side_bearings_[i] = *p_top_side_bearings_extra;
@@ -261,7 +263,7 @@ float OpenTypeVerticalData::AdvanceHeight(Glyph glyph) const {
}
void OpenTypeVerticalData::GetVerticalTranslationsForGlyphs(
- const SkPaint& paint,
+ const SkFont& font,
const Glyph* glyphs,
size_t count,
float* out_xy_array) const {
@@ -302,7 +304,7 @@ void OpenTypeVerticalData::GetVerticalTranslationsForGlyphs(
float top_side_bearing = top_side_bearing_f_unit * size_per_unit_;
SkRect skiaBounds;
- SkiaTextMetrics(&paint).GetSkiaBoundsForGlyph(glyph, &skiaBounds);
+ SkFontGetBoundsForGlyph(font, glyph, &skiaBounds);
FloatRect bounds(skiaBounds);
out_xy_array[1] = bounds.Y() - top_side_bearing;
continue;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.h b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.h
index 109609279df..d6aa27105a2 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.h
@@ -33,10 +33,11 @@
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
-#include <SkPaint.h>
#include <SkRefCnt.h>
#include <SkTypeface.h>
+class SkFont;
+
namespace blink {
class PLATFORM_EXPORT OpenTypeVerticalData
@@ -55,7 +56,7 @@ class PLATFORM_EXPORT OpenTypeVerticalData
bool HasVerticalMetrics() const { return !advance_heights_.IsEmpty(); }
float AdvanceHeight(Glyph) const;
- void GetVerticalTranslationsForGlyphs(const SkPaint&,
+ void GetVerticalTranslationsForGlyphs(const SkFont&,
const Glyph*,
size_t,
float* out_xy_array) const;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data_test.cc b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data_test.cc
index cd03dc5d349..bdb7d7bc845 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data_test.cc
@@ -28,9 +28,9 @@
namespace blink {
-struct TestTable : OpenType::TableBase {
- OpenType::Fixed version;
- OpenType::Int16 ascender;
+struct TestTable : open_type::TableBase {
+ open_type::Fixed version;
+ open_type::Int16 ascender;
template <typename T>
const T* ValidateOffset(const Vector<char>& buffer, uint16_t offset) const {
@@ -40,21 +40,21 @@ struct TestTable : OpenType::TableBase {
TEST(OpenTypeVerticalDataTest, ValidateTableTest) {
Vector<char> buffer(sizeof(TestTable));
- const TestTable* table = OpenType::ValidateTable<TestTable>(buffer);
+ const TestTable* table = open_type::ValidateTable<TestTable>(buffer);
EXPECT_TRUE(table);
buffer = Vector<char>(sizeof(TestTable) - 1);
- table = OpenType::ValidateTable<TestTable>(buffer);
+ table = open_type::ValidateTable<TestTable>(buffer);
EXPECT_FALSE(table);
buffer = Vector<char>(sizeof(TestTable) + 1);
- table = OpenType::ValidateTable<TestTable>(buffer);
+ table = open_type::ValidateTable<TestTable>(buffer);
EXPECT_TRUE(table);
}
TEST(OpenTypeVerticalDataTest, ValidateOffsetTest) {
Vector<char> buffer(sizeof(TestTable));
- const TestTable* table = OpenType::ValidateTable<TestTable>(buffer);
+ const TestTable* table = open_type::ValidateTable<TestTable>(buffer);
ASSERT_TRUE(table);
// Test overflow
diff --git a/chromium/third_party/blink/renderer/platform/fonts/paint_font.h b/chromium/third_party/blink/renderer/platform/fonts/paint_font.h
deleted file mode 100644
index 1902b8ba259..00000000000
--- a/chromium/third_party/blink/renderer/platform/fonts/paint_font.h
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2017 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_PAINT_FONT_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_PAINT_FONT_H_
-
-#include "cc/paint/paint_font.h"
-
-namespace blink {
-using cc::PaintFont;
-}
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_PAINT_FONT_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/paint_text_blob.h b/chromium/third_party/blink/renderer/platform/fonts/paint_text_blob.h
deleted file mode 100644
index 978dc6392ca..00000000000
--- a/chromium/third_party/blink/renderer/platform/fonts/paint_text_blob.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2017 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_PAINT_TEXT_BLOB_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_PAINT_TEXT_BLOB_H_
-
-#include "cc/paint/paint_text_blob.h"
-#include "cc/paint/paint_text_blob_builder.h"
-
-namespace blink {
-using cc::PaintTextBlob;
-using cc::PaintTextBlobBuilder;
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_PAINT_TEXT_BLOB_H_
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 86da0df514e..012238f1901 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
@@ -10,6 +10,26 @@
namespace blink {
+namespace {
+
+// UScriptCode and OpenType script are not 1:1; specifically, both Hiragana and
+// Katakana map to 'kana' in OpenType. They will be mapped correctly in
+// HarfBuzz, but normalizing earlier helps to reduce splitting runs between
+// these scripts.
+// https://docs.microsoft.com/en-us/typography/opentype/spec/scripttags
+inline UScriptCode getScriptForOpenType(UChar32 ch, UErrorCode* status) {
+ UScriptCode script = uscript_getScript(ch, status);
+ if (UNLIKELY(U_FAILURE(*status)))
+ return script;
+ if (UNLIKELY(script == USCRIPT_KATAKANA ||
+ script == USCRIPT_KATAKANA_OR_HIRAGANA)) {
+ return USCRIPT_HIRAGANA;
+ }
+ return script;
+}
+
+} // namespace
+
typedef ScriptData::PairedBracketType PairedBracketType;
constexpr int ScriptRunIterator::kMaxScriptCount;
@@ -27,6 +47,10 @@ void ICUScriptData::GetScripts(UChar32 ch, UScriptCodeList& dst) const {
// regardless of the capacity passed to the call. So count can be greater
// than dst->size(), if a later version of the unicode data has more
// than kMaxScriptCount items.
+
+ // |uscript_getScriptExtensions| do not need to be collated to
+ // USCRIPT_HIRAGANA because when ScriptExtensions contains Kana, it contains
+ // Hira as well, and Hira is always before Kana.
int count = uscript_getScriptExtensions(ch, &dst[0], dst.size(), &status);
if (status == U_BUFFER_OVERFLOW_ERROR) {
// Allow this, we'll just use what we have.
@@ -35,7 +59,7 @@ void ICUScriptData::GetScripts(UChar32 ch, UScriptCodeList& dst) const {
count = dst.size();
status = U_ZERO_ERROR;
}
- UScriptCode primary_script = uscript_getScript(ch, &status);
+ UScriptCode primary_script = getScriptForOpenType(ch, &status);
if (U_FAILURE(status)) {
DLOG(ERROR) << "Could not get icu script data: " << status << " for 0x"
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 3e2a7a0e6eb..a792bdfb5c8 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
@@ -370,6 +370,50 @@ TEST_F(ScriptRunIteratorTest, Chinese) {
CHECK_SCRIPT_RUNS({{"萬國碼", USCRIPT_HAN}});
}
+struct JapaneseMixedScript {
+ const char* string;
+ // The expected primary_script when the string alone was evaluated.
+ UScriptCode script;
+} japanese_mixed_scripts[] = {{"あ", USCRIPT_HIRAGANA},
+ // Katakana should be normalized to Hiragana
+ {"ア", USCRIPT_HIRAGANA},
+ // Script_Extensions=Hira Kana
+ {"\u30FC", USCRIPT_HIRAGANA},
+ // Script_Extensions=Hani Hira Kana
+ {"\u303C", USCRIPT_HAN},
+ // Script_Extensions=Bopo Hang Hani Hira Kana
+ {"\u3003", USCRIPT_BOPOMOFO},
+ // Script_Extensions=Bopo Hang Hani Hira Kana Yiii
+ {"\u3001", USCRIPT_BOPOMOFO}};
+
+class JapaneseMixedScriptTest
+ : public ScriptRunIteratorTest,
+ public testing::WithParamInterface<JapaneseMixedScript> {};
+
+INSTANTIATE_TEST_CASE_P(ScriptRunIteratorTest,
+ JapaneseMixedScriptTest,
+ testing::ValuesIn(japanese_mixed_scripts));
+
+TEST_P(JapaneseMixedScriptTest, Data) {
+ const auto& data = GetParam();
+ std::string string(data.string);
+
+ CheckRuns({{string.data(), data.script}});
+
+ // If the string follows Hiragana or Katakana, or is followed by Hiragnaa or
+ // Katakana, it should be normalized as Hiragana.
+ std::string hiragana("か");
+ std::string katakana("カ");
+ CheckRuns({{(hiragana + string).data(), USCRIPT_HIRAGANA}});
+ CheckRuns({{(string + hiragana).data(), USCRIPT_HIRAGANA}});
+
+ CheckRuns({{(katakana + string).data(), USCRIPT_HIRAGANA}});
+ CheckRuns({{(string + katakana).data(), USCRIPT_HIRAGANA}});
+
+ CheckRuns({{(hiragana + string + katakana).data(), USCRIPT_HIRAGANA}});
+ CheckRuns({{(katakana + string + hiragana).data(), USCRIPT_HIRAGANA}});
+}
+
// Close bracket without matching open is ignored
TEST_F(ScriptRunIteratorTest, UnbalancedParens1) {
CHECK_SCRIPT_RUNS(
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.cc
index 2ab8d8c22be..e6a5fff8636 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.cc
@@ -38,8 +38,10 @@ CaseMappingHarfBuzzBufferFiller::CaseMappingHarfBuzzBufferFiller(
case_mapped_text.Ensure16Bit();
if (case_mapped_text.length() != text.length()) {
- FillSlowCase(case_map_intend, locale, text.Characters16(), text.length(),
- start_index, num_characters);
+ String original_text = text;
+ original_text.Ensure16Bit();
+ FillSlowCase(case_map_intend, locale, original_text.Characters16(),
+ original_text.length(), start_index, num_characters);
return;
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/glyph_bounds_accumulator.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/glyph_bounds_accumulator.h
new file mode 100644
index 00000000000..06e1adb9fff
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/glyph_bounds_accumulator.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2012 Google Inc. All rights reserved.
+ * Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_GLYPH_BOUNDS_ACCUMULATOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_GLYPH_BOUNDS_ACCUMULATOR_H_
+
+#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h"
+#include "third_party/blink/renderer/platform/geometry/float_rect.h"
+
+namespace blink {
+
+// Helper class to accumulate glyph bounding box.
+//
+// Glyph positions and bounding boxes from HarfBuzz and fonts are in physical
+// coordinate, while ShapeResult::glyph_bounding_box_ is in logical coordinate.
+// To minimize the number of conversions, this class accumulates the bounding
+// boxes in physical coordinate, and convert the accumulated box to logical.
+struct GlyphBoundsAccumulator {
+ // Construct an accumulator with the logical glyph origin.
+ explicit GlyphBoundsAccumulator(float origin) : origin(origin) {}
+
+ // The accumulated glyph bounding box in physical coordinate, until
+ // ConvertVerticalRunToLogical().
+ FloatRect bounds;
+ // The current origin, in logical coordinate.
+ float origin;
+
+ // Unite a glyph bounding box to |bounds|.
+ template <bool is_horizontal_run>
+ void Unite(const HarfBuzzRunGlyphData& glyph_data,
+ FloatRect bounds_for_glyph) {
+ if (UNLIKELY(bounds_for_glyph.IsEmpty()))
+ return;
+
+ // Glyphs are drawn at |origin + offset|. Move glyph_bounds to that point.
+ // All positions in hb_glyph_position_t are relative to the current point.
+ // https://behdad.github.io/harfbuzz/harfbuzz-Buffers.html#hb-glyph-position-t-struct
+ if (is_horizontal_run)
+ bounds_for_glyph.SetX(bounds_for_glyph.X() + origin);
+ else
+ bounds_for_glyph.SetY(bounds_for_glyph.Y() + origin);
+ bounds_for_glyph.Move(glyph_data.offset);
+
+ bounds.Unite(bounds_for_glyph);
+ }
+
+ // Non-template version of |Unite()|, see above.
+ void Unite(bool is_horizontal_run,
+ const HarfBuzzRunGlyphData& glyph,
+ FloatRect bounds_for_glyph) {
+ is_horizontal_run ? Unite<true>(glyph, bounds_for_glyph)
+ : Unite<false>(glyph, bounds_for_glyph);
+ }
+
+ // Convert vertical run glyph bounding box to logical. Horizontal runs do not
+ // need conversions because physical and logical are the same.
+ void ConvertVerticalRunToLogical(const FontMetrics& font_metrics) {
+ // Convert physical glyph_bounding_box to logical.
+ bounds = bounds.TransposedRect();
+
+ // The glyph bounding box of a vertical run uses ideographic baseline.
+ // Adjust the box Y position because the bounding box of a ShapeResult uses
+ // alphabetic baseline.
+ // See diagrams of base lines at
+ // https://drafts.csswg.org/css-writing-modes-3/#intro-baselines
+ int baseline_adjust = font_metrics.Ascent(kIdeographicBaseline) -
+ font_metrics.Ascent(kAlphabeticBaseline);
+ bounds.SetY(bounds.Y() + baseline_adjust);
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_GLYPH_BOUNDS_ACCUMULATOR_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc
index b8bdb2a2c02..12a451129b9 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc
@@ -49,9 +49,6 @@
#include <hb-ot.h>
#include <hb.h>
-#if defined(OS_MACOSX)
-#include <hb-coretext.h>
-#endif
#include <SkPaint.h>
#include <SkPath.h>
@@ -123,6 +120,14 @@ static hb_bool_t HarfBuzzGetGlyph(hb_font_t* hb_font,
variation_selector, glyph);
}
+static hb_bool_t HarfBuzzGetNominalGlyph(hb_font_t* hb_font,
+ void* font_data,
+ hb_codepoint_t unicode,
+ hb_codepoint_t* glyph,
+ void* user_data) {
+ return HarfBuzzGetGlyph(hb_font, font_data, unicode, 0, glyph, user_data);
+}
+
static hb_position_t HarfBuzzGetGlyphHorizontalAdvance(hb_font_t* hb_font,
void* font_data,
hb_codepoint_t glyph,
@@ -131,24 +136,23 @@ static hb_position_t HarfBuzzGetGlyphHorizontalAdvance(hb_font_t* hb_font,
reinterpret_cast<HarfBuzzFontData*>(font_data);
hb_position_t advance = 0;
- SkiaTextMetrics(&hb_font_data->paint_)
- .GetGlyphWidthForHarfBuzz(glyph, &advance);
+ SkFontGetGlyphWidthForHarfBuzz(hb_font_data->font_, glyph, &advance);
return advance;
}
-static void HarfBuzzGetGlyphHorizontalAdvances(hb_font_t* font,
- void* font_data,
- unsigned count,
- hb_codepoint_t* first_glyph,
- unsigned int glyph_stride,
- hb_position_t* first_advance,
- unsigned int advance_stride,
- void* user_data) {
+static void HarfBuzzGetGlyphHorizontalAdvances(
+ hb_font_t* font,
+ void* font_data,
+ unsigned count,
+ const hb_codepoint_t* first_glyph,
+ unsigned int glyph_stride,
+ hb_position_t* first_advance,
+ unsigned int advance_stride,
+ void* user_data) {
HarfBuzzFontData* hb_font_data =
reinterpret_cast<HarfBuzzFontData*>(font_data);
- SkiaTextMetrics(&hb_font_data->paint_)
- .GetGlyphWidthForHarfBuzz(count, first_glyph, glyph_stride, first_advance,
- advance_stride);
+ SkFontGetGlyphWidthForHarfBuzz(hb_font_data->font_, count, first_glyph,
+ glyph_stride, first_advance, advance_stride);
}
static hb_bool_t HarfBuzzGetGlyphVerticalOrigin(hb_font_t* hb_font,
@@ -166,10 +170,10 @@ static hb_bool_t HarfBuzzGetGlyphVerticalOrigin(hb_font_t* hb_font,
float result[] = {0, 0};
Glyph the_glyph = glyph;
- vertical_data->GetVerticalTranslationsForGlyphs(hb_font_data->paint_,
+ vertical_data->GetVerticalTranslationsForGlyphs(hb_font_data->font_,
&the_glyph, 1, result);
- *x = SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(-result[0]);
- *y = SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(-result[1]);
+ *x = SkiaScalarToHarfBuzzPosition(-result[0]);
+ *y = SkiaScalarToHarfBuzzPosition(-result[1]);
return true;
}
@@ -182,42 +186,12 @@ static hb_position_t HarfBuzzGetGlyphVerticalAdvance(hb_font_t* hb_font,
scoped_refptr<OpenTypeVerticalData> vertical_data =
hb_font_data->VerticalData();
if (!vertical_data) {
- return SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(
- hb_font_data->height_fallback_);
+ return SkiaScalarToHarfBuzzPosition(hb_font_data->height_fallback_);
}
Glyph the_glyph = glyph;
float advance_height = -vertical_data->AdvanceHeight(the_glyph);
- return SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(
- SkFloatToScalar(advance_height));
-}
-
-static hb_position_t HarfBuzzGetGlyphHorizontalKerning(
- hb_font_t*,
- void* font_data,
- hb_codepoint_t left_glyph,
- hb_codepoint_t right_glyph,
- void*) {
- HarfBuzzFontData* hb_font_data =
- reinterpret_cast<HarfBuzzFontData*>(font_data);
- if (hb_font_data->paint_.isVerticalText()) {
- // We don't support cross-stream kerning
- return 0;
- }
-
- SkTypeface* typeface = hb_font_data->paint_.getTypeface();
-
- const uint16_t glyphs[2] = {static_cast<uint16_t>(left_glyph),
- static_cast<uint16_t>(right_glyph)};
- int32_t kerning_adjustments[1] = {0};
-
- if (typeface->getKerningPairAdjustments(glyphs, 2, kerning_adjustments)) {
- return SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(
- SkIntToScalar(kerning_adjustments[0]) *
- hb_font_data->SizePerUnit(*typeface));
- }
-
- return 0;
+ return SkiaScalarToHarfBuzzPosition(SkFloatToScalar(advance_height));
}
static hb_bool_t HarfBuzzGetGlyphExtents(hb_font_t* hb_font,
@@ -228,8 +202,7 @@ static hb_bool_t HarfBuzzGetGlyphExtents(hb_font_t* hb_font,
HarfBuzzFontData* hb_font_data =
reinterpret_cast<HarfBuzzFontData*>(font_data);
- SkiaTextMetrics(&hb_font_data->paint_)
- .GetGlyphExtentsForHarfBuzz(glyph, extents);
+ SkFontGetGlyphExtentsForHarfBuzz(hb_font_data->font_, glyph, extents);
return true;
}
@@ -304,7 +277,7 @@ unsigned HarfBuzzFace::UnitsPerEmFromHeadTable() {
}
bool HarfBuzzFace::ShouldSubpixelPosition() {
- return harfbuzz_font_data_->paint_.isSubpixelText();
+ return harfbuzz_font_data_->font_.isSubpixel();
}
static hb_font_funcs_t* HarfBuzzSkiaGetFontFuncs() {
@@ -314,13 +287,16 @@ static hb_font_funcs_t* HarfBuzzSkiaGetFontFuncs() {
// HarfBuzz will use the fallback implementation if they aren't set.
if (!funcs) {
funcs = hb_font_funcs_create();
- hb_font_funcs_set_glyph_func(funcs, HarfBuzzGetGlyph, nullptr, nullptr);
+ hb_font_funcs_set_variation_glyph_func(funcs, HarfBuzzGetGlyph, nullptr,
+ nullptr);
+ hb_font_funcs_set_nominal_glyph_func(funcs, HarfBuzzGetNominalGlyph,
+ nullptr, nullptr);
hb_font_funcs_set_glyph_h_advance_func(
funcs, HarfBuzzGetGlyphHorizontalAdvance, nullptr, nullptr);
hb_font_funcs_set_glyph_h_advances_func(
funcs, HarfBuzzGetGlyphHorizontalAdvances, nullptr, nullptr);
- hb_font_funcs_set_glyph_h_kerning_func(
- funcs, HarfBuzzGetGlyphHorizontalKerning, nullptr, nullptr);
+ // TODO(https://crbug.com/899718): Replace vertical metrics callbacks with
+ // HarfBuzz VORG/VMTX internal implementation by deregistering those.
hb_font_funcs_set_glyph_v_advance_func(
funcs, HarfBuzzGetGlyphVerticalAdvance, nullptr, nullptr);
hb_font_funcs_set_glyph_v_origin_func(funcs, HarfBuzzGetGlyphVerticalOrigin,
@@ -359,30 +335,26 @@ static hb_blob_t* HarfBuzzSkiaGetTable(hb_face_t* face,
WTF::Partitions::FastFree);
}
+#if !defined(OS_MACOSX)
static void DeleteTypefaceStream(void* stream_asset_ptr) {
SkStreamAsset* stream_asset =
reinterpret_cast<SkStreamAsset*>(stream_asset_ptr);
delete stream_asset;
}
+#endif
hb_face_t* HarfBuzzFace::CreateFace() {
-#if defined(OS_MACOSX)
- // hb_face_t needs to be instantiated using the CoreText constructor for
- // compatibility with AAT font, in which case HarfBuzz' CoreText backend is
- // used. If we encounter a FreeType backed SkTypeface, for variable fonts on
- // Mac OS < 10.12, follow the regular OpenType-only codepath below.
- if (platform_data_->CgFont()) {
- hb_face_t* face = hb_coretext_face_create(platform_data_->CgFont());
- DCHECK(face);
- return face;
- }
-#endif
hb_face_t* face = nullptr;
DEFINE_THREAD_SAFE_STATIC_LOCAL(BooleanHistogram, zero_copy_success_histogram,
("Blink.Fonts.HarfBuzzFaceZeroCopyAccess"));
SkTypeface* typeface = platform_data_->Typeface();
CHECK(typeface);
+ // The attempt of doing zero copy-mmaped memory access to the font blobs does
+ // not work efficiently on Mac, since what is returned from
+ // typeface->openStream is a synthesized font assembled from copying all font
+ // tables on Mac. See the implementation of SkTypeface_Mac::onOpenStream.
+#if !defined(OS_MACOSX)
int ttc_index = 0;
SkStreamAsset* typeface_stream = typeface->openStream(&ttc_index);
if (typeface_stream && typeface_stream->getMemoryBase()) {
@@ -394,6 +366,7 @@ hb_face_t* HarfBuzzFace::CreateFace() {
hb_blob_destroy);
face = hb_face_create(face_blob.get(), ttc_index);
}
+#endif
// Fallback to table copies if there is no in-memory access.
if (!face) {
@@ -435,19 +408,15 @@ static_assert(
hb_font_t* HarfBuzzFace::GetScaledFont(
scoped_refptr<UnicodeRangeSet> range_set,
VerticalLayoutCallbacks vertical_layout) const {
- PaintFont paint_font;
- platform_data_->SetupPaintFont(&paint_font);
- paint_font.SetTextEncoding(SkPaint::kGlyphID_TextEncoding);
harfbuzz_font_data_->range_set_ = std::move(range_set);
- harfbuzz_font_data_->UpdateFallbackMetricsAndScale(
- *platform_data_, paint_font.ToSkPaint(), vertical_layout);
+ harfbuzz_font_data_->UpdateFallbackMetricsAndScale(*platform_data_,
+ vertical_layout);
- int scale =
- SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(platform_data_->size());
+ int scale = SkiaScalarToHarfBuzzPosition(platform_data_->size());
hb_font_set_scale(unscaled_font_, scale, scale);
hb_font_set_ptem(unscaled_font_, platform_data_->size() / kCssPixelsPerPoint);
- SkTypeface* typeface = harfbuzz_font_data_->paint_.getTypeface();
+ SkTypeface* typeface = harfbuzz_font_data_->font_.getTypeface();
int axis_count = typeface->getVariationDesignPosition(nullptr, 0);
if (axis_count > 0) {
Vector<SkFontArguments::VariationPosition::Coordinate> axis_values;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.h
index 69fa5f128a7..f3645969638 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.h
@@ -40,7 +40,7 @@ struct HarfBuzzFontData {
public:
HarfBuzzFontData()
- : paint_(),
+ : font_(),
space_in_gpos_(SpaceGlyphInOpenTypeTables::Unknown),
space_in_gsub_(SpaceGlyphInOpenTypeTables::Unknown),
vertical_data_(nullptr),
@@ -51,19 +51,19 @@ struct HarfBuzzFontData {
// layout information is found from the font.
void UpdateFallbackMetricsAndScale(
const FontPlatformData& platform_data,
- const SkPaint& paint,
HarfBuzzFace::VerticalLayoutCallbacks vertical_layout) {
float ascent = 0;
float descent = 0;
unsigned dummy_ascent_inflation = 0;
unsigned dummy_descent_inflation = 0;
- paint_ = paint;
+ font_ = SkFont();
+ platform_data.SetupSkFont(&font_);
if (UNLIKELY(vertical_layout == HarfBuzzFace::PrepareForVerticalLayout)) {
FontMetrics::AscentDescentWithHacks(
ascent, descent, dummy_ascent_inflation, dummy_descent_inflation,
- platform_data, paint);
+ platform_data, font_);
ascent_fallback_ = ascent;
// Simulate the rounding that FontMetrics does so far for returning the
// integer Height()
@@ -87,7 +87,7 @@ struct HarfBuzzFontData {
if (size_per_unit_ != kInvalidFallbackMetricsValue)
return size_per_unit_;
int units_per_em = typeface.getUnitsPerEm();
- size_per_unit_ = paint_.getTextSize() / units_per_em;
+ size_per_unit_ = font_.getSize() / units_per_em;
return size_per_unit_;
}
@@ -98,14 +98,14 @@ struct HarfBuzzFontData {
DCHECK_NE(size_per_unit_, kInvalidFallbackMetricsValue);
vertical_data_ =
- OpenTypeVerticalData::CreateUnscaled(paint_.refTypeface());
+ OpenTypeVerticalData::CreateUnscaled(font_.refTypeface());
}
vertical_data_->SetScaleAndFallbackMetrics(size_per_unit_, ascent_fallback_,
height_fallback_);
return vertical_data_;
}
- SkPaint paint_;
+ SkFont font_;
// Capture these scaled fallback metrics from FontPlatformData so that a
// OpenTypeVerticalData object can be constructed from them when needed.
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 8a59fbb19bc..3cef0162ce7 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
@@ -39,6 +39,7 @@
#include <utility>
#include "base/memory/ptr_util.h"
+#include "build/build_config.h"
#include "third_party/blink/renderer/platform/fonts/font.h"
#include "third_party/blink/renderer/platform/fonts/font_description.h"
#include "third_party/blink/renderer/platform/fonts/font_fallback_iterator.h"
@@ -70,8 +71,7 @@ void CheckShapeResultRange(const ShapeResult* result,
DCHECK_LE(start, end);
unsigned length = end - start;
if (length == result->NumCharacters() &&
- (!length || (start == result->StartIndexForResult() &&
- end == result->EndIndexForResult())))
+ (!length || (start == result->StartIndex() && end == result->EndIndex())))
return;
// Log font-family/size as specified.
@@ -99,8 +99,7 @@ void CheckShapeResultRange(const ShapeResult* result,
// Log the text to shape.
log.Append(String::Format(": %u-%u -> %u-%u:", start, end,
- result->StartIndexForResult(),
- result->EndIndexForResult()));
+ result->StartIndex(), result->EndIndex()));
for (unsigned i = start; i < end; ++i)
log.Append(String::Format(" %02X", text[i]));
@@ -238,14 +237,6 @@ inline bool ShapeRange(hb_buffer_t* buffer,
? HarfBuzzFace::PrepareForVerticalLayout
: HarfBuzzFace::NoVerticalLayout);
hb_shape(hb_font, buffer, font_features, font_features_size);
-
- // We cannot round all glyph positions during hb_shape because the
- // hb_font_funcs_set_glyph_h_kerning_func only works for legacy kerning.
- // OpenType uses gpos tables for kerning and harfbuzz does not call
- // the callback to let us round as we go.
- // Without this rounding, we get inconsistent spacing between kern points
- // if subpixel positioning is disabled.
- // See http://crbug.com/740385.
if (!face->ShouldSubpixelPosition())
RoundHarfBuzzBufferPositions(buffer);
@@ -336,12 +327,11 @@ void HarfBuzzShaper::CommitGlyphs(RangeData* range_data,
// Here we need to specify glyph positions.
BufferSlice next_slice;
for (const BufferSlice* current_slice = &slice;;) {
- ShapeResult::RunInfo* run = new ShapeResult::RunInfo(
+ auto run = ShapeResult::RunInfo::Create(
current_font, direction, canvas_rotation, script,
current_slice->start_character_index, current_slice->num_glyphs,
current_slice->num_characters);
- shape_result->InsertRun(base::WrapUnique(run),
- current_slice->start_glyph_index,
+ shape_result->InsertRun(run, current_slice->start_glyph_index,
current_slice->num_glyphs, range_data->buffer);
unsigned num_glyphs_inserted = run->NumGlyphs();
if (num_glyphs_inserted == current_slice->num_glyphs)
@@ -1004,9 +994,9 @@ scoped_refptr<ShapeResult> HarfBuzzShaper::Shape(
}
}
- // Ensure we have at least one run for StartIndexForResult().
- if (UNLIKELY(result->runs_.IsEmpty() && start))
- result->InsertRunForIndex(start);
+ // Ensure |start_index_| is updated even when no runs were inserted.
+ if (UNLIKELY(result->runs_.IsEmpty()))
+ result->start_index_ = start;
#if DCHECK_IS_ON()
if (result)
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 a6c267b157d..35e0d66e541 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
@@ -16,11 +16,11 @@
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_test_info.h"
-#include "third_party/blink/renderer/platform/layout_test_support.h"
#include "third_party/blink/renderer/platform/testing/font_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/text/text_break_iterator.h"
#include "third_party/blink/renderer/platform/text/text_run.h"
+#include "third_party/blink/renderer/platform/web_test_support.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
using testing::ElementsAre;
@@ -114,40 +114,40 @@ class HarfBuzzShaperTest : public testing::Test {
class ScopedSubpixelOverride {
public:
ScopedSubpixelOverride(bool b) {
- prev_layout_test_ = LayoutTestSupport::IsRunningLayoutTest();
+ prev_layout_test_ = WebTestSupport::IsRunningWebTest();
prev_subpixel_allowed_ =
- LayoutTestSupport::IsTextSubpixelPositioningAllowedForTest();
- prev_antialias_ = LayoutTestSupport::IsFontAntialiasingEnabledForTest();
+ WebTestSupport::IsTextSubpixelPositioningAllowedForTest();
+ prev_antialias_ = WebTestSupport::IsFontAntialiasingEnabledForTest();
prev_fd_subpixel_ = FontDescription::SubpixelPositioning();
- // This is required for all LayoutTestSupport settings to have effects.
- LayoutTestSupport::SetIsRunningLayoutTest(true);
+ // This is required for all WebTestSupport settings to have effects.
+ WebTestSupport::SetIsRunningWebTest(true);
if (b) {
// Allow subpixel positioning.
- LayoutTestSupport::SetTextSubpixelPositioningAllowedForTest(true);
+ WebTestSupport::SetTextSubpixelPositioningAllowedForTest(true);
// Now, enable subpixel positioning in platform-specific ways.
// Mac always enables subpixel positioning.
// On Windows, subpixel positioning also requires antialiasing.
- LayoutTestSupport::SetFontAntialiasingEnabledForTest(true);
+ WebTestSupport::SetFontAntialiasingEnabledForTest(true);
// On platforms other than Windows and Mac this needs to be set as
// well.
FontDescription::SetSubpixelPositioning(true);
} else {
// Explicitly disallow all subpixel positioning.
- LayoutTestSupport::SetTextSubpixelPositioningAllowedForTest(false);
+ WebTestSupport::SetTextSubpixelPositioningAllowedForTest(false);
}
}
~ScopedSubpixelOverride() {
FontDescription::SetSubpixelPositioning(prev_fd_subpixel_);
- LayoutTestSupport::SetFontAntialiasingEnabledForTest(prev_antialias_);
- LayoutTestSupport::SetTextSubpixelPositioningAllowedForTest(
+ WebTestSupport::SetFontAntialiasingEnabledForTest(prev_antialias_);
+ WebTestSupport::SetTextSubpixelPositioningAllowedForTest(
prev_subpixel_allowed_);
- LayoutTestSupport::SetIsRunningLayoutTest(prev_layout_test_);
+ WebTestSupport::SetIsRunningWebTest(prev_layout_test_);
// Fonts cached with a different subpixel positioning state are not
// automatically invalidated and need to be cleared between test
@@ -245,11 +245,9 @@ TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsUnicodeVariants) {
// If the specified VS is not in the font, it's mapped to .notdef.
// then hb_ot_hide_default_ignorables() swaps it to a space with zero-advance.
// http://lists.freedesktop.org/archives/harfbuzz/2015-May/004888.html
-#if !defined(OS_MACOSX)
EXPECT_EQ(TestInfo(result)->FontDataForTesting(0)->SpaceGlyph(),
TestInfo(result)->GlyphForTesting(0, 1))
<< test.name;
-#endif
EXPECT_EQ(0.f, TestInfo(result)->AdvanceForTesting(0, 1)) << test.name;
} else {
EXPECT_EQ(1u, num_glyphs) << test.name;
@@ -413,8 +411,9 @@ TEST_F(HarfBuzzShaperTest, ShapeLatinSegment) {
}
// Represents the case where a part of a cluster has a different color.
-// <div>0x647<span style="color: red;">0x64A</span></div>
-// TODO(crbug.com/689155): Still fails on Mac, AAT?
+// <div>0x647<span style="color: red;">0x64A</span></
+// Cannot be enabled on Mac yet, compare
+// https:// https://github.com/harfbuzz/harfbuzz/issues/1415
#if defined(OS_MACOSX)
#define MAYBE_ShapeArabicWithContext DISABLED_ShapeArabicWithContext
#else
@@ -517,9 +516,6 @@ TEST_F(HarfBuzzShaperTest, ShapeVerticalMixed) {
HarfBuzzShaper shaper(string);
scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
- // Check width and bounds are not too much different. ".1" is heuristic.
- EXPECT_NEAR(result->Width(), result->Bounds().Width(), result->Width() * .1);
-
// Shape each run and merge them using CopyRange. Bounds() should match.
scoped_refptr<ShapeResult> result1 = shaper.Shape(&font, direction, 0, 3);
scoped_refptr<ShapeResult> result2 =
@@ -533,15 +529,24 @@ TEST_F(HarfBuzzShaperTest, ShapeVerticalMixed) {
EXPECT_EQ(result->Bounds(), composite_result->Bounds());
}
-TEST_P(ShapeParameterTest, MissingGlyph) {
- // U+FFF0 is not assigned as of Unicode 10.0.
- String string(
- u"\uFFF0"
- u"Hello");
+class ShapeStringTest : public HarfBuzzShaperTest,
+ public testing::WithParamInterface<const char16_t*> {};
+
+INSTANTIATE_TEST_CASE_P(HarfBuzzShaperTest,
+ ShapeStringTest,
+ testing::Values(
+ // U+FFF0 is not assigned as of Unicode 10.0.
+ u"\uFFF0",
+ u"\uFFF0Hello",
+ // U+00AD SOFT HYPHEN often does not have glyphs.
+ u"\u00AD"));
+
+TEST_P(ShapeStringTest, MissingGlyph) {
+ String string(GetParam());
HarfBuzzShaper shaper(string);
- scoped_refptr<ShapeResult> result = ShapeWithParameter(&shaper);
- EXPECT_EQ(0u, result->StartIndexForResult());
- EXPECT_EQ(string.length(), result->EndIndexForResult());
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
+ EXPECT_EQ(0u, result->StartIndex());
+ EXPECT_EQ(string.length(), result->EndIndex());
}
// Test splitting runs by kMaxCharacterIndex using a simple string that has code
@@ -640,8 +645,8 @@ TEST_P(ShapeParameterTest, ZeroWidthSpace) {
const unsigned length = base::size(string);
HarfBuzzShaper shaper(String(string, length));
scoped_refptr<ShapeResult> result = ShapeWithParameter(&shaper);
- EXPECT_EQ(0u, result->StartIndexForResult());
- EXPECT_EQ(length, result->EndIndexForResult());
+ EXPECT_EQ(0u, result->StartIndex());
+ EXPECT_EQ(length, result->EndIndex());
#if DCHECK_IS_ON()
result->CheckConsistency();
#endif
@@ -717,17 +722,14 @@ static struct GlyphDataRangeTestData {
// The two code points form a grapheme cluster, which produces two glyphs.
// Character index array should be [0, 0].
{u"\u05E9\u05B0", TextDirection::kRtl, 0, 0, 1, 0, 2},
-#if !defined(OS_MACOSX)
// ZWJ tests taken from fast/text/international/zerowidthjoiner.html
// Character index array should be [6, 3, 3, 3, 0, 0, 0].
- // Mac shapes differently and that glyph index expectations do not match.
{u"\u0639\u200D\u200D\u0639\u200D\u200D\u0639", TextDirection::kRtl, 0, 0,
1, 4, 7},
{u"\u0639\u200D\u200D\u0639\u200D\u200D\u0639", TextDirection::kRtl, 0, 2,
5, 1, 4},
{u"\u0639\u200D\u200D\u0639\u200D\u200D\u0639", TextDirection::kRtl, 0, 4,
7, 0, 1},
-#endif
};
std::ostream& operator<<(std::ostream& ostream,
@@ -1106,14 +1108,14 @@ TEST_P(ShapeResultCopyRangeTest, Split) {
scoped_refptr<ShapeResult> result1 = ShapeResult::Create(&font, 0, direction);
result->CopyRange(0, test_data.break_point, result1.get());
EXPECT_EQ(test_data.break_point, result1->NumCharacters());
- EXPECT_EQ(0u, result1->StartIndexForResult());
- EXPECT_EQ(test_data.break_point, result1->EndIndexForResult());
+ EXPECT_EQ(0u, result1->StartIndex());
+ EXPECT_EQ(test_data.break_point, result1->EndIndex());
scoped_refptr<ShapeResult> result2 = ShapeResult::Create(&font, 0, direction);
result->CopyRange(test_data.break_point, string.length(), result2.get());
EXPECT_EQ(string.length() - test_data.break_point, result2->NumCharacters());
- EXPECT_EQ(test_data.break_point, result2->StartIndexForResult());
- EXPECT_EQ(string.length(), result2->EndIndexForResult());
+ EXPECT_EQ(test_data.break_point, result2->StartIndex());
+ EXPECT_EQ(string.length(), result2->EndIndex());
// Combine them.
scoped_refptr<ShapeResult> composite_result =
@@ -1301,8 +1303,8 @@ TEST_F(HarfBuzzShaperTest, SubRange) {
scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
scoped_refptr<ShapeResult> sub_range = result->SubRange(4, 7);
- DCHECK_EQ(4u, sub_range->StartIndexForResult());
- DCHECK_EQ(7u, sub_range->EndIndexForResult());
+ DCHECK_EQ(4u, sub_range->StartIndex());
+ DCHECK_EQ(7u, sub_range->EndIndex());
DCHECK_EQ(3u, sub_range->NumCharacters());
DCHECK_EQ(result->Direction(), sub_range->Direction());
}
@@ -1399,60 +1401,59 @@ TEST_F(HarfBuzzShaperTest, SafeToBreakLatinDiscretionaryLigatures) {
"third_party/MEgalopolis/MEgalopolisExtra.woff"),
16, &ligatures);
- // RA and CA form ligatures, most glyph pairs have kerning.
- String string(u"ABRACADABRA");
- HarfBuzzShaper shaper(string);
+ // $ ./hb-shape --shaper=ot --features="dlig=1,kern" --show-flags
+ // MEgalopolisExtra.ttf "RADDAYoVaDD"
+ // [R_A=0+1150|D=2+729|D=3+699|A=4+608#1|Y=5+608#1|o=6+696#1|V=7+652#1|a=8+657#1|D=9+729|D=10+729]
+ // RA Ligature, unkerned D D, D A kerns, A Y kerns, Y o kerns, o V kerns, V a
+ // kerns, no kerning with D.
+ String test_word(u"RADDAYoVaDD");
+ unsigned safe_to_break_positions[] = {2, 3, 9, 10};
+ HarfBuzzShaper shaper(test_word);
scoped_refptr<ShapeResult> result =
shaper.Shape(&testFont, TextDirection::kLtr);
- EXPECT_EQ(6u, result->NextSafeToBreakOffset(1)); // After CA ligature.
- EXPECT_EQ(6u, result->NextSafeToBreakOffset(6)); // After CA ligature.
- EXPECT_EQ(11u, result->NextSafeToBreakOffset(7)); // At end of string.
- EXPECT_EQ(11u, result->NextSafeToBreakOffset(9)); // At end of string.
- EXPECT_EQ(11u, result->NextSafeToBreakOffset(10)); // At end of string.
-
- // Add zero-width spaces at the safe to break offsets.
- String refString(u"ABRACA\u200BDAB\u200BRA");
- HarfBuzzShaper refShaper(refString);
+
+ unsigned compare_safe_to_break_position = 0;
+ for (unsigned i = 1; i < test_word.length() - 1; ++i) {
+ EXPECT_EQ(safe_to_break_positions[compare_safe_to_break_position],
+ result->NextSafeToBreakOffset(i));
+ if (i == safe_to_break_positions[compare_safe_to_break_position])
+ compare_safe_to_break_position++;
+ }
+
+ // Add zero-width spaces at some of the safe to break offsets.
+ String inserted_zero_width_spaces = test_word;
+ inserted_zero_width_spaces.Ensure16Bit();
+ unsigned enlarged_by = 0;
+ for (unsigned safe_to_break_position : safe_to_break_positions) {
+ inserted_zero_width_spaces.insert(u"\u200B",
+ safe_to_break_position + enlarged_by++);
+ }
+ HarfBuzzShaper refShaper(inserted_zero_width_spaces);
scoped_refptr<ShapeResult> referenceResult =
refShaper.Shape(&testFont, TextDirection::kLtr);
// Results should be identical if it truly is safe to break at the designated
- // safe-to-break offsets
+ // safe-to-break offsets because otherwise, the zero-width spaces would have
+ // altered the text spacing, for example by breaking apart ligatures or
+ // kerning pairs.
EXPECT_EQ(result->SnappedWidth(), referenceResult->SnappedWidth());
EXPECT_EQ(result->Bounds(), referenceResult->Bounds());
- EXPECT_EQ(result->SnappedStartPositionForOffset(0),
- referenceResult->SnappedStartPositionForOffset(0));
- EXPECT_EQ(result->SnappedStartPositionForOffset(1),
- referenceResult->SnappedStartPositionForOffset(1));
- EXPECT_EQ(result->SnappedStartPositionForOffset(2),
- referenceResult->SnappedStartPositionForOffset(2));
- EXPECT_EQ(result->SnappedStartPositionForOffset(3),
- referenceResult->SnappedStartPositionForOffset(3));
- EXPECT_EQ(result->SnappedStartPositionForOffset(4),
- referenceResult->SnappedStartPositionForOffset(4));
- EXPECT_EQ(result->SnappedStartPositionForOffset(5),
- referenceResult->SnappedStartPositionForOffset(5));
- // First zero-width space is at position 6 so the the matching character in
- // the reference results is 7.
- EXPECT_EQ(result->SnappedStartPositionForOffset(6),
- referenceResult->SnappedStartPositionForOffset(7));
- EXPECT_EQ(result->SnappedStartPositionForOffset(7),
- referenceResult->SnappedStartPositionForOffset(8));
- EXPECT_EQ(result->SnappedStartPositionForOffset(8),
- referenceResult->SnappedStartPositionForOffset(9));
-
- // Second zero-width space is at position 9 so the the matching character in
- // the reference results is 11.
- EXPECT_EQ(result->SnappedStartPositionForOffset(9),
- referenceResult->SnappedStartPositionForOffset(11));
- EXPECT_EQ(result->SnappedStartPositionForOffset(10),
- referenceResult->SnappedStartPositionForOffset(12));
+ // Zero-width spaces were inserted, so we need to account for that by
+ // offseting the index that we compare against.
+ unsigned inserts_offset = 0;
+ for (unsigned i = 0; i < test_word.length(); ++i) {
+ if (i == safe_to_break_positions[inserts_offset])
+ inserts_offset++;
+ EXPECT_EQ(
+ result->SnappedStartPositionForOffset(i),
+ referenceResult->SnappedStartPositionForOffset(i + inserts_offset));
+ }
}
-// TODO(crbug.com/870712): This test fails on Mac due to AAT shaping and
-// font fallback differences on Android.
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
+// TODO(crbug.com/870712): This test fails due to font fallback differences on
+// Android.
+#if defined(OS_ANDROID)
#define MAYBE_SafeToBreakArabicCommonLigatures \
DISABLED_SafeToBreakArabicCommonLigatures
#else
@@ -1469,33 +1470,27 @@ TEST_F(HarfBuzzShaperTest, MAYBE_SafeToBreakArabicCommonLigatures) {
HarfBuzzShaper shaper(string);
scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kRtl);
- // Safe to break at 0, 3, 4, 5, 7, and 11.
- EXPECT_EQ(0u, result->NextSafeToBreakOffset(0));
- EXPECT_EQ(3u, result->NextSafeToBreakOffset(1));
- EXPECT_EQ(3u, result->NextSafeToBreakOffset(2));
- EXPECT_EQ(3u, result->NextSafeToBreakOffset(3));
- EXPECT_EQ(4u, result->NextSafeToBreakOffset(4));
- EXPECT_EQ(5u, result->NextSafeToBreakOffset(5));
- EXPECT_EQ(7u, result->NextSafeToBreakOffset(6));
- EXPECT_EQ(7u, result->NextSafeToBreakOffset(7));
- EXPECT_EQ(11u, result->NextSafeToBreakOffset(8));
- EXPECT_EQ(11u, result->NextSafeToBreakOffset(9));
- EXPECT_EQ(11u, result->NextSafeToBreakOffset(10));
- EXPECT_EQ(11u, result->NextSafeToBreakOffset(11));
- EXPECT_EQ(12u, result->NextSafeToBreakOffset(12));
+ std::vector<unsigned> safe_to_break_positions;
+
+#if defined(OS_MACOSX)
+ safe_to_break_positions = {0, 2, 3, 4, 11};
+#else
+ safe_to_break_positions = {0, 3, 4, 5, 7, 11};
+#endif
+ unsigned compare_safe_to_break_position = 0;
+ for (unsigned i = 0; i < string.length() - 1; ++i) {
+ EXPECT_EQ(safe_to_break_positions[compare_safe_to_break_position],
+ result->NextSafeToBreakOffset(i));
+ if (i == safe_to_break_positions[compare_safe_to_break_position])
+ compare_safe_to_break_position++;
+ }
}
// TODO(layout-dev): Expand RTL test coverage and add tests for mixed
// directionality strings.
// Test when some characters are missing in |runs_|.
-// RTL on Mac may not have runs for all characters. crbug.com/774034
-#if defined(OS_MACOSX)
-#define MAYBE_SafeToBreakMissingRun DISABLED_SafeToBreakMissingRun
-#else
-#define MAYBE_SafeToBreakMissingRun SafeToBreakMissingRun
-#endif
-TEST_P(ShapeParameterTest, MAYBE_SafeToBreakMissingRun) {
+TEST_P(ShapeParameterTest, SafeToBreakMissingRun) {
TextDirection direction = GetParam();
scoped_refptr<ShapeResult> result = ShapeResult::Create(&font, 8, direction);
result->InsertRunForTesting(2, 1, direction, {0});
@@ -1506,8 +1501,8 @@ TEST_P(ShapeParameterTest, MAYBE_SafeToBreakMissingRun) {
result->CheckConsistency();
#endif
- EXPECT_EQ(2u, result->StartIndexForResult());
- EXPECT_EQ(10u, result->EndIndexForResult());
+ EXPECT_EQ(2u, result->StartIndex());
+ EXPECT_EQ(10u, result->EndIndex());
EXPECT_EQ(2u, result->NextSafeToBreakOffset(2));
EXPECT_EQ(3u, result->NextSafeToBreakOffset(3));
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 3fbc1ef3978..664b1fcf3fa 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
@@ -30,13 +30,17 @@
#include "third_party/blink/renderer/platform/fonts/shaping/shape_cache.h"
#include "third_party/blink/renderer/platform/wtf/string_hasher.h"
+#if defined(USE_FUNCTION_CITYHASH)
+#include "third_party/smhasher/src/City.h"
+#endif
namespace blink {
void ShapeCache::SmallStringKey::HashString() {
- // TODO(cavalcantii): replace this for a better hash function,
- // see crbug.com/735674.
- hash_ = StringHasher::ComputeHash(characters_, length_);
+// TODO(cavalcanti): next add xxhash.
+#if defined(USE_FUNCTION_CITYHASH)
+ hash_ = CityHash64((const char*)characters_, length_ * sizeof(UChar));
+#endif
}
} // namespace blink
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 1c84a168159..11ca1595552 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
@@ -39,9 +39,11 @@
#include "base/containers/adapters.h"
#include "base/memory/ptr_util.h"
+#include "base/numerics/safe_conversions.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/fonts/character_range.h"
#include "third_party/blink/renderer/platform/fonts/font.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/glyph_bounds_accumulator.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h"
@@ -53,6 +55,18 @@ namespace blink {
constexpr unsigned HarfBuzzRunGlyphData::kMaxCharacterIndex;
constexpr unsigned HarfBuzzRunGlyphData::kMaxGlyphs;
+struct SameSizeAsHarfBuzzRunGlyphData {
+ uint16_t unsigned_int16;
+ unsigned bit_fields : 2;
+ int16_t signed_int16[2];
+ float advance;
+ FloatSize offset;
+};
+
+static_assert(sizeof(HarfBuzzRunGlyphData) ==
+ sizeof(SameSizeAsHarfBuzzRunGlyphData),
+ "HarfBuzzRunGlyphData should stay small");
+
unsigned ShapeResult::RunInfo::NextSafeToBreakOffset(unsigned offset) const {
DCHECK_LE(offset, num_characters_);
if (!Rtl()) {
@@ -129,7 +143,7 @@ void ShapeResult::EnsureGraphemes(const StringView& text) const {
if (is_computed)
return;
- unsigned result_start_index = StartIndexForResult();
+ unsigned result_start_index = StartIndex();
for (const auto& run : runs_) {
if (!run)
continue;
@@ -321,7 +335,8 @@ void ShapeResult::RunInfo::CharacterIndexForXPosition(
// representing a sequence of glyphs, of size glyph_sequence_advance. We
// linearly interpolate how much space each character takes, and reduce the
// sequence to only match the character size.
- if (break_glyphs_option == BreakGlyphs) {
+ if (break_glyphs_option == BreakGlyphs &&
+ glyph_sequence_end > glyph_sequence_start) {
int graphemes = NumGraphemes(glyph_sequence_start, glyph_sequence_end);
if (graphemes > 1) {
float unit_size = result->advance / graphemes;
@@ -360,9 +375,23 @@ void HarfBuzzRunGlyphData::SetGlyphAndPositions(uint16_t glyph_id,
this->advance = advance;
this->offset = offset;
this->safe_to_break_before = safe_to_break_before;
+ this->bounds_before_raw_value = std::numeric_limits<int16_t>::max();
+ this->bounds_after_raw_value = std::numeric_limits<int16_t>::max();
+}
+
+void HarfBuzzRunGlyphData::SetGlyphBounds(LayoutUnit bounds_before,
+ LayoutUnit bounds_after) {
+ this->bounds_before_raw_value =
+ base::IsValueInRangeForNumericType<int16_t>(bounds_before.RawValue())
+ ? bounds_before.RawValue()
+ : std::numeric_limits<int16_t>::max();
+ this->bounds_after_raw_value =
+ base::IsValueInRangeForNumericType<int16_t>(bounds_after.RawValue())
+ ? bounds_after.RawValue()
+ : std::numeric_limits<int16_t>::max();
}
-ShapeResult::ShapeResult(const SimpleFontData* font_data,
+ShapeResult::ShapeResult(scoped_refptr<const SimpleFontData> font_data,
unsigned num_characters,
TextDirection direction)
: width_(0),
@@ -388,7 +417,7 @@ ShapeResult::ShapeResult(const ShapeResult& other)
has_vertical_offsets_(other.has_vertical_offsets_) {
runs_.ReserveCapacity(other.runs_.size());
for (const auto& run : other.runs_)
- runs_.push_back(std::make_unique<RunInfo>(*run));
+ runs_.push_back(run->Create(*run.get()));
}
ShapeResult::~ShapeResult() = default;
@@ -438,7 +467,7 @@ unsigned ShapeResult::NextSafeToBreakOffset(unsigned index) const {
}
}
- return EndIndexForResult();
+ return EndIndex();
}
unsigned ShapeResult::PreviousSafeToBreakOffset(unsigned index) const {
@@ -464,7 +493,7 @@ unsigned ShapeResult::PreviousSafeToBreakOffset(unsigned index) const {
}
}
- return StartIndexForResult();
+ return StartIndex();
}
// If the position is outside of the result, returns the start or the end offset
@@ -710,12 +739,10 @@ float ShapeResult::ForEachGlyph(float initial_advance,
return total_advance;
}
-namespace {
-
-inline unsigned CountGraphemesInCluster(const UChar* str,
- unsigned str_length,
- uint16_t start_index,
- uint16_t end_index) {
+unsigned ShapeResult::CountGraphemesInCluster(const UChar* str,
+ unsigned str_length,
+ uint16_t start_index,
+ uint16_t end_index) {
if (start_index > end_index)
std::swap(start_index, end_index);
uint16_t length = end_index - start_index;
@@ -732,8 +759,6 @@ inline unsigned CountGraphemesInCluster(const UChar* str,
return std::max(0, num_graphemes);
}
-} // anonymous namespace
-
float ShapeResult::ForEachGraphemeClusters(const StringView& text,
float initial_advance,
unsigned from,
@@ -914,66 +939,6 @@ float HarfBuzzPositionToFloat(hb_position_t value) {
return static_cast<float>(value) / (1 << 16);
}
-// This is a helper class to accumulate glyph bounding box.
-//
-// Glyph positions and bounding boxes from HarfBuzz and fonts are in physical
-// coordinate, while ShapeResult::glyph_bounding_box_ is in logical coordinate.
-// To minimize the number of conversions, this class accumulates the bounding
-// boxes in physical coordinate, and convert the accumulated box to logical.
-struct GlyphBoundsAccumulator {
- // Construct an accumulator with the logical glyph origin.
- explicit GlyphBoundsAccumulator(float origin) : origin(origin) {}
-
- // The accumulated glyph bounding box in physical coordinate, until
- // ConvertVerticalRunToLogical().
- FloatRect bounds;
- // The current origin, in logical coordinate.
- float origin;
-
- // Unite a glyph bounding box to |bounds|.
- template <bool is_horizontal_run>
- void Unite(const HarfBuzzRunGlyphData& glyph_data,
- FloatRect bounds_for_glyph) {
- if (UNLIKELY(bounds_for_glyph.IsEmpty()))
- return;
-
- // Glyphs are drawn at |origin + offset|. Move glyph_bounds to that point.
- // All positions in hb_glyph_position_t are relative to the current point.
- // https://behdad.github.io/harfbuzz/harfbuzz-Buffers.html#hb-glyph-position-t-struct
- if (is_horizontal_run)
- bounds_for_glyph.SetX(bounds_for_glyph.X() + origin);
- else
- bounds_for_glyph.SetY(bounds_for_glyph.Y() + origin);
- bounds_for_glyph.Move(glyph_data.offset);
-
- bounds.Unite(bounds_for_glyph);
- }
-
- // Non-template version of |Unite()|, see above.
- void Unite(bool is_horizontal_run,
- const HarfBuzzRunGlyphData& glyph,
- FloatRect bounds_for_glyph) {
- is_horizontal_run ? Unite<true>(glyph, bounds_for_glyph)
- : Unite<false>(glyph, bounds_for_glyph);
- }
-
- // Convert vertical run glyph bounding box to logical. Horizontal runs do not
- // need conversions because physical and logical are the same.
- void ConvertVerticalRunToLogical(const FontMetrics& font_metrics) {
- // Convert physical glyph_bounding_box to logical.
- bounds = bounds.TransposedRect();
-
- // The glyph bounding box of a vertical run uses ideographic baseline.
- // Adjust the box Y position because the bounding box of a ShapeResult uses
- // alphabetic baseline.
- // See diagrams of base lines at
- // https://drafts.csswg.org/css-writing-modes-3/#intro-baselines
- int baseline_adjust = font_metrics.Ascent(kIdeographicBaseline) -
- font_metrics.Ascent(kAlphabeticBaseline);
- bounds.SetY(bounds.Y() + baseline_adjust);
- }
-};
-
// Checks whether it's safe to break without reshaping before the given glyph.
bool IsSafeToBreakBefore(const hb_glyph_info_t* glyph_infos,
unsigned num_glyphs,
@@ -1097,7 +1062,24 @@ void ShapeResult::ComputeGlyphPositions(ShapeResult::RunInfo* run,
float total_advance = 0.0f;
bool has_vertical_offsets = !is_horizontal_run;
+ // Get glyph bounds from Skia. It's a lot faster if we give it list of glyph
+ // IDs rather than calling it for each glyph.
+ // TODO(kojii): MacOS does not benefit from batching the Skia request due to
+ // https://bugs.chromium.org/p/skia/issues/detail?id=5328, and the cost to
+ // prepare batching, which is normally much less than the benefit of batching,
+ // is not ignorable unfortunately.
+ const SimpleFontData& current_font_data = *run->font_data_;
+ DCHECK_EQ(num_glyphs, run->glyph_data_.size());
+#if !defined(OS_MACOSX)
+ Vector<Glyph, 256> glyphs(num_glyphs);
+ for (unsigned i = 0; i < num_glyphs; i++)
+ glyphs[i] = glyph_infos[start_glyph + i].codepoint;
+ Vector<SkRect, 256> bounds_list(num_glyphs);
+ current_font_data.BoundsForGlyphs(glyphs, &bounds_list);
+#endif
+
// HarfBuzz returns result in visual order, no need to flip for RTL.
+ GlyphBoundsAccumulator bounds(width_);
for (unsigned i = 0; i < num_glyphs; ++i) {
uint16_t glyph = glyph_infos[start_glyph + i].codepoint;
const hb_glyph_position_t& pos = glyph_positions[start_glyph + i];
@@ -1119,6 +1101,17 @@ void ShapeResult::ComputeGlyphPositions(ShapeResult::RunInfo* run,
glyph_data.SetGlyphAndPositions(
glyph, character_index, advance, offset,
IsSafeToBreakBefore(glyph_infos + start_glyph, num_glyphs, i));
+
+#if defined(OS_MACOSX)
+ FloatRect glyph_bounds = current_font_data.BoundsForGlyph(glyph_data.glyph);
+#else
+ FloatRect glyph_bounds(bounds_list[i]);
+#endif
+ glyph_data.SetGlyphBounds(LayoutUnit(glyph_bounds.X()),
+ LayoutUnit(glyph_bounds.MaxX()));
+ bounds.Unite<is_horizontal_run>(glyph_data, glyph_bounds);
+ bounds.origin += advance;
+
total_advance += advance;
has_vertical_offsets |= (offset.Height() != 0);
}
@@ -1126,51 +1119,17 @@ void ShapeResult::ComputeGlyphPositions(ShapeResult::RunInfo* run,
run->width_ = std::max(0.0f, total_advance);
has_vertical_offsets_ |= has_vertical_offsets;
- ComputeGlyphBounds<is_horizontal_run>(*run);
-}
-
-template <bool is_horizontal_run>
-void ShapeResult::ComputeGlyphBounds(const ShapeResult::RunInfo& run) {
- // Skia runs much faster if we give a list of glyph ID rather than calling it
- // on each glyph.
- const SimpleFontData& current_font_data = *run.font_data_;
-#if defined(OS_MACOSX)
- // TODO(kojii): MacOS does not benefit from batching the Skia request due to
- // https://bugs.chromium.org/p/skia/issues/detail?id=5328 , and the cost to
- // prepare batching, which is normally much less than the benefit of batching,
- // is not ignorable unfortunately.
- GlyphBoundsAccumulator bounds(width_);
- for (const HarfBuzzRunGlyphData& glyph_data : run.glyph_data_) {
- bounds.Unite<is_horizontal_run>(
- glyph_data, current_font_data.BoundsForGlyph(glyph_data.glyph));
- bounds.origin += glyph_data.advance;
- }
-#else
- unsigned num_glyphs = run.glyph_data_.size();
- Vector<Glyph, 256> glyphs(num_glyphs);
- for (unsigned i = 0; i < num_glyphs; i++)
- glyphs[i] = run.glyph_data_[i].glyph;
- Vector<SkRect, 256> bounds_list(num_glyphs);
- current_font_data.BoundsForGlyphs(glyphs, &bounds_list);
-
- GlyphBoundsAccumulator bounds(width_);
- for (unsigned i = 0; i < num_glyphs; i++) {
- const HarfBuzzRunGlyphData& glyph_data = run.glyph_data_[i];
- bounds.Unite<is_horizontal_run>(glyph_data, FloatRect(bounds_list[i]));
- bounds.origin += glyph_data.advance;
- }
-#endif
if (!is_horizontal_run)
bounds.ConvertVerticalRunToLogical(current_font_data.GetFontMetrics());
glyph_bounding_box_.Unite(bounds.bounds);
}
-void ShapeResult::InsertRun(std::unique_ptr<ShapeResult::RunInfo> run_to_insert,
+void ShapeResult::InsertRun(scoped_refptr<ShapeResult::RunInfo> run_to_insert,
unsigned start_glyph,
unsigned num_glyphs,
hb_buffer_t* harfbuzz_buffer) {
DCHECK_GT(num_glyphs, 0u);
- std::unique_ptr<ShapeResult::RunInfo> run(std::move(run_to_insert));
+ scoped_refptr<ShapeResult::RunInfo> run(std::move(run_to_insert));
if (run->IsHorizontal()) {
// Inserting a horizontal run into a horizontal or vertical result. In both
@@ -1190,7 +1149,7 @@ void ShapeResult::InsertRun(std::unique_ptr<ShapeResult::RunInfo> run_to_insert,
InsertRun(std::move(run));
}
-void ShapeResult::InsertRun(std::unique_ptr<ShapeResult::RunInfo> run) {
+void ShapeResult::InsertRun(scoped_refptr<ShapeResult::RunInfo> run) {
// The runs are stored in result->m_runs in visual order. For LTR, we place
// the run to be inserted before the next run with a bigger character
// start index. For RTL, we place the run before the next run with a lower
@@ -1219,24 +1178,12 @@ void ShapeResult::InsertRun(std::unique_ptr<ShapeResult::RunInfo> run) {
UpdateStartIndex();
}
-// Insert a |RunInfo| without glyphs. |StartIndexForResult()| needs a run to
-// compute the start character index. When all glyphs are missing, this function
-// synthesize a run without glyphs.
-void ShapeResult::InsertRunForIndex(unsigned start_character_index) {
- DCHECK(runs_.IsEmpty());
- runs_.push_back(std::make_unique<RunInfo>(
- primary_font_.get(), !Rtl() ? HB_DIRECTION_LTR : HB_DIRECTION_RTL,
- CanvasRotationInVertical::kRegular, HB_SCRIPT_UNKNOWN,
- start_character_index, 0, num_characters_));
- UpdateStartIndex();
-}
-
ShapeResult::RunInfo* ShapeResult::InsertRunForTesting(
unsigned start_index,
unsigned num_characters,
TextDirection direction,
Vector<uint16_t> safe_break_offsets) {
- std::unique_ptr<RunInfo> run = std::make_unique<ShapeResult::RunInfo>(
+ auto run = RunInfo::Create(
nullptr, IsLtr(direction) ? HB_DIRECTION_LTR : HB_DIRECTION_RTL,
CanvasRotationInVertical::kRegular, HB_SCRIPT_COMMON, start_index,
num_characters, num_characters);
@@ -1264,7 +1211,7 @@ void ShapeResult::ReorderRtlRuns(unsigned run_size_before) {
if (runs_.size() == run_size_before + 1) {
if (!run_size_before)
return;
- std::unique_ptr<RunInfo> new_run(std::move(runs_.back()));
+ scoped_refptr<RunInfo> new_run(std::move(runs_.back()));
runs_.Shrink(runs_.size() - 1);
runs_.push_front(std::move(new_run));
return;
@@ -1272,7 +1219,7 @@ void ShapeResult::ReorderRtlRuns(unsigned run_size_before) {
// |push_front| is O(n) that we should not call it multiple times.
// Create a new list in the correct order and swap it.
- Vector<std::unique_ptr<RunInfo>> new_runs;
+ Vector<scoped_refptr<RunInfo>> new_runs;
new_runs.ReserveInitialCapacity(runs_.size());
for (unsigned i = run_size_before; i < runs_.size(); i++)
new_runs.push_back(std::move(runs_[i]));
@@ -1346,7 +1293,8 @@ float ShapeResult::LineRightBounds() const {
void ShapeResult::CopyRange(unsigned start_offset,
unsigned end_offset,
- ShapeResult* target) const {
+ ShapeResult* target,
+ unsigned* start_run_index) const {
if (!runs_.size())
return;
@@ -1356,13 +1304,15 @@ void ShapeResult::CopyRange(unsigned start_offset,
// When |target| is empty, its character indexes are the specified sub range
// of |this|. Otherwise the character indexes are renumbered to be continuous.
- int index_diff = !target->num_characters_
- ? 0
- : target->EndIndexForResult() -
- std::max(start_offset, StartIndexForResult());
+ int index_diff =
+ !target->num_characters_
+ ? 0
+ : target->EndIndex() - std::max(start_offset, StartIndex());
unsigned target_run_size_before = target->runs_.size();
float total_width = 0;
- for (const auto& run : runs_) {
+ unsigned run_index = start_run_index ? *start_run_index : 0;
+ for (; run_index < runs_.size(); run_index++) {
+ const auto& run = runs_[run_index];
unsigned run_start = run->start_index_;
unsigned run_end = run_start + run->num_characters_;
@@ -1377,6 +1327,14 @@ void ShapeResult::CopyRange(unsigned start_offset,
target->num_characters_ += sub_run->num_characters_;
target->num_glyphs_ += sub_run->glyph_data_.size();
target->runs_.push_back(std::move(sub_run));
+
+ // 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)
+ *start_run_index = run_index;
+ break;
+ }
}
}
@@ -1397,8 +1355,8 @@ void ShapeResult::CopyRange(unsigned start_offset,
// operations. If |start_offset| or |end_offset| are the start/end of |this|,
// use the current |glyph_bounding_box_| for the side.
DCHECK(primary_font_.get() == target->primary_font_.get());
- bool know_left_edge = start_offset <= StartIndexForResult();
- bool know_right_edge = end_offset >= EndIndexForResult();
+ bool know_left_edge = start_offset <= StartIndex();
+ bool know_right_edge = end_offset >= EndIndex();
if (UNLIKELY(Rtl()))
std::swap(know_left_edge, know_right_edge);
float left = know_left_edge ? target->width_ + glyph_bounding_box_.X()
@@ -1416,19 +1374,21 @@ void ShapeResult::CopyRange(unsigned start_offset,
target->UpdateStartIndex();
#if DCHECK_IS_ON()
- DCHECK_EQ(target->num_characters_ - target_num_characters_before,
- std::min(end_offset, EndIndexForResult()) -
- std::max(start_offset, StartIndexForResult()));
+ DCHECK_EQ(
+ target->num_characters_ - target_num_characters_before,
+ std::min(end_offset, EndIndex()) - std::max(start_offset, StartIndex()));
target->CheckConsistency();
#endif
}
-scoped_refptr<ShapeResult> ShapeResult::SubRange(unsigned start_offset,
- unsigned end_offset) const {
+scoped_refptr<ShapeResult> ShapeResult::SubRange(
+ unsigned start_offset,
+ unsigned end_offset,
+ unsigned* start_run_index) const {
scoped_refptr<ShapeResult> sub_range =
Create(primary_font_.get(), 0, Direction());
- CopyRange(start_offset, end_offset, sub_range.get());
+ CopyRange(start_offset, end_offset, sub_range.get(), start_run_index);
return sub_range;
}
@@ -1436,12 +1396,12 @@ scoped_refptr<ShapeResult> ShapeResult::CopyAdjustedOffset(
unsigned start_index) const {
scoped_refptr<ShapeResult> result = base::AdoptRef(new ShapeResult(*this));
- if (start_index > result->StartIndexForResult()) {
- unsigned delta = start_index - result->StartIndexForResult();
+ if (start_index > result->StartIndex()) {
+ unsigned delta = start_index - result->StartIndex();
for (auto& run : result->runs_)
run->start_index_ += delta;
} else {
- unsigned delta = result->StartIndexForResult() - start_index;
+ unsigned delta = result->StartIndex() - start_index;
for (auto& run : result->runs_) {
DCHECK(run->start_index_ >= delta);
run->start_index_ -= delta;
@@ -1461,7 +1421,7 @@ void ShapeResult::CheckConsistency() const {
}
DCHECK_EQ(start_index_, ComputeStartIndex());
- const unsigned start_index = StartIndexForResult();
+ const unsigned start_index = StartIndex();
unsigned index = start_index;
unsigned num_glyphs = 0;
if (!Rtl()) {
@@ -1480,7 +1440,7 @@ void ShapeResult::CheckConsistency() const {
num_glyphs += run->glyph_data_.size();
}
}
- const unsigned end_index = EndIndexForResult();
+ const unsigned end_index = EndIndex();
DCHECK_LE(index, end_index);
DCHECK_EQ(end_index - start_index, num_characters_);
DCHECK_EQ(num_glyphs, num_glyphs_);
@@ -1495,7 +1455,7 @@ scoped_refptr<ShapeResult> ShapeResult::CreateForTabulationCharacters(
const SimpleFontData* font_data = font->PrimaryFont();
// Tab characters are always LTR or RTL, not TTB, even when
// isVerticalAnyUpright().
- std::unique_ptr<ShapeResult::RunInfo> run = std::make_unique<RunInfo>(
+ scoped_refptr<ShapeResult::RunInfo> run = RunInfo::Create(
font_data, text_run.Rtl() ? HB_DIRECTION_RTL : HB_DIRECTION_LTR,
CanvasRotationInVertical::kRegular, HB_SCRIPT_COMMON, 0, count, count);
float position = text_run.XPos() + position_offset;
@@ -1573,7 +1533,7 @@ std::ostream& operator<<(std::ostream& ostream,
template <bool rtl>
void ShapeResult::ComputePositionData() const {
auto& data = character_position_->data_;
- unsigned start_offset = StartIndexForResult();
+ unsigned start_offset = StartIndex();
unsigned next_character_index = 0;
float run_advance = 0;
float last_x_position = 0;
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 214f2567f75..72e7d4ee9f9 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
@@ -34,14 +34,16 @@
#include <memory>
#include "third_party/blink/renderer/platform/fonts/canvas_rotation_in_vertical.h"
#include "third_party/blink/renderer/platform/fonts/glyph.h"
+#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
-#include "third_party/blink/renderer/platform/layout_unit.h"
+#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/text/text_direction.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
struct hb_buffer_t;
@@ -52,8 +54,8 @@ struct CharacterRange;
class Font;
template <typename TextContainerType>
class PLATFORM_EXPORT ShapeResultSpacing;
-class SimpleFontData;
class TextRun;
+class ShapeResultView;
enum class AdjustMidCluster {
// Adjust the middle of a grapheme cluster to the logical end boundary.
@@ -142,8 +144,8 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
float start_x = 0) const;
// The character start/end index of a range shape result.
- unsigned StartIndexForResult() const { return start_index_; }
- unsigned EndIndexForResult() const { return start_index_ + num_characters_; }
+ unsigned StartIndex() const { return start_index_; }
+ unsigned EndIndex() const { return start_index_ + num_characters_; }
void FallbackFonts(HashSet<const SimpleFontData*>*) const;
TextDirection Direction() const {
return static_cast<TextDirection>(direction_);
@@ -162,12 +164,12 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
// Returns the next or previous offsets respectively at which it is safe to
// break without reshaping.
// The |offset| given and the return value is for the original string, between
- // |StartIndexForResult| and |EndIndexForResult|.
+ // |StartIndex| and |EndIndex|.
// TODO(eae): Remove these ones the cached versions are used everywhere.
unsigned NextSafeToBreakOffset(unsigned offset) const;
unsigned PreviousSafeToBreakOffset(unsigned offset) const;
- // Returns the offset, relative to StartIndexForResult, whose (origin,
+ // Returns the offset, relative to StartIndex, whose (origin,
// origin+advance) contains |x|.
unsigned OffsetForPosition(float x, BreakGlyphsOption) const;
// Returns the offset whose glyph boundary is nearest to |x|. Depends on
@@ -194,7 +196,7 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
return CaretOffsetForHitTest(x, text, break_glyphs_option);
}
- // Returns the position for a given offset, relative to StartIndexForResult.
+ // Returns the position for a given offset, relative to StartIndex.
float PositionForOffset(unsigned offset,
AdjustMidCluster = AdjustMidCluster::kToEnd) const;
// Similar to |PositionForOffset| with mid-glyph (mid-ligature) support.
@@ -222,7 +224,7 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
// break without reshaping. Operates on a cache (that needs to be pre-computed
// using EnsurePositionData) and does not take partial glyphs into account.
// The |offset| given and the return value is for the original string, between
- // |StartIndexForResult| and |EndIndexForResult|.
+ // |StartIndex| and |EndIndex|.
unsigned CachedNextSafeToBreakOffset(unsigned offset) const;
unsigned CachedPreviousSafeToBreakOffset(unsigned offset) const;
@@ -230,17 +232,33 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
// configured to |ShapeResultSpacing|.
// |text_start_offset| adjusts the character index in the ShapeResult before
// giving it to |ShapeResultSpacing|. It can be negative if
- // |StartIndexForResult()| is larger than the text in |ShapeResultSpacing|.
+ // |StartIndex()| is larger than the text in |ShapeResultSpacing|.
void ApplySpacing(ShapeResultSpacing<String>&, int text_start_offset = 0);
scoped_refptr<ShapeResult> ApplySpacingToCopy(ShapeResultSpacing<TextRun>&,
const TextRun&) const;
// Append a copy of a range within an existing result to another result.
- void CopyRange(unsigned start, unsigned end, ShapeResult*) const;
+ //
+ // For sequential copies the opaque_context in/out parameter can be used to
+ // improve performance by avoding a linear scan to find the first run for the
+ // range. It should be set to zero for the first call and the resulting out
+ // value for one call is the appropiate input value for the next.
+ // NOTE: opaque_context assumes non-overlapping ranges.
+ void CopyRange(unsigned start,
+ unsigned end,
+ ShapeResult*,
+ unsigned* opaque_context = nullptr) const;
// Create a new ShapeResult instance from a range within an existing result.
+ //
+ // For sequential copies the opaque_context in/out parameter can be used to
+ // improve performance by avoding a linear scan to find the first run for the
+ // range. It should be set to zero for the first call and the resulting out
+ // value for one call is the appropiate input value for the next.
+ // NOTE: opaque_context assumes non-overlapping ranges.
scoped_refptr<ShapeResult> SubRange(unsigned start_offset,
- unsigned end_offset) const;
+ unsigned end_offset,
+ unsigned* opaque_context = nullptr) const;
// Create a new ShapeResult instance with the start offset adjusted.
scoped_refptr<ShapeResult> CopyAdjustedOffset(unsigned start_offset) const;
@@ -298,7 +316,9 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
#endif
protected:
- ShapeResult(const SimpleFontData*, unsigned num_characters, TextDirection);
+ ShapeResult(scoped_refptr<const SimpleFontData>,
+ unsigned num_characters,
+ TextDirection);
ShapeResult(const Font*, unsigned num_characters, TextDirection);
ShapeResult(const ShapeResult&);
@@ -313,6 +333,11 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
// |grapheme_| is computed.
void EnsureGraphemes(const StringView& text) const;
+ static unsigned CountGraphemesInCluster(const UChar*,
+ unsigned str_length,
+ uint16_t start_index,
+ uint16_t end_index);
+
struct GlyphIndexResult {
STACK_ALLOCATED();
@@ -382,14 +407,11 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
unsigned start_glyph,
unsigned num_glyphs,
hb_buffer_t*);
- template <bool is_horizontal_run>
- void ComputeGlyphBounds(const ShapeResult::RunInfo&);
- void InsertRun(std::unique_ptr<ShapeResult::RunInfo>,
+ void InsertRun(scoped_refptr<ShapeResult::RunInfo>,
unsigned start_glyph,
unsigned num_glyphs,
hb_buffer_t*);
- void InsertRun(std::unique_ptr<ShapeResult::RunInfo>);
- void InsertRunForIndex(unsigned start_character_index);
+ void InsertRun(scoped_refptr<ShapeResult::RunInfo>);
void ReorderRtlRuns(unsigned run_size_before);
unsigned ComputeStartIndex() const;
void UpdateStartIndex();
@@ -399,7 +421,7 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
float width_;
FloatRect glyph_bounding_box_;
- Vector<std::unique_ptr<RunInfo>> runs_;
+ Vector<scoped_refptr<RunInfo>> runs_;
scoped_refptr<const SimpleFontData> primary_font_;
mutable std::unique_ptr<CharacterPositionData> character_position_;
@@ -418,6 +440,7 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
friend class HarfBuzzShaper;
friend class ShapeResultBuffer;
friend class ShapeResultBloberizer;
+ friend class ShapeResultView;
};
PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, const ShapeResult&);
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc
index d9dc7285a07..2e03906ae6a 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc
@@ -8,6 +8,7 @@
#include "third_party/blink/renderer/platform/fonts/font.h"
#include "third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
#include "third_party/blink/renderer/platform/fonts/text_run_paint_info.h"
#include "third_party/blink/renderer/platform/text/text_break_iterator.h"
#include "third_party/blink/renderer/platform/text/text_run.h"
@@ -39,15 +40,14 @@ void ShapeResultBloberizer::CommitPendingRun() {
builder_rotation_ = pending_canvas_rotation_;
}
- PaintFont run_font;
- run_font.SetTextEncoding(SkPaint::kGlyphID_TextEncoding);
- pending_font_data_->PlatformData().SetupPaintFont(
- &run_font, device_scale_factor_, &font_);
+ SkFont run_font;
+ pending_font_data_->PlatformData().SetupSkFont(&run_font,
+ device_scale_factor_, &font_);
const auto run_size = pending_glyphs_.size();
const auto& buffer = HasPendingVerticalOffsets()
- ? builder_.AllocRunPos(run_font, run_size)
- : builder_.AllocRunPosH(run_font, run_size, 0);
+ ? builder_.allocRunPos(run_font, run_size)
+ : builder_.allocRunPosH(run_font, run_size, 0);
std::copy(pending_glyphs_.begin(), pending_glyphs_.end(), buffer.glyphs);
std::copy(pending_offsets_.begin(), pending_offsets_.end(), buffer.pos);
@@ -61,7 +61,7 @@ void ShapeResultBloberizer::CommitPendingBlob() {
if (!builder_run_count_)
return;
- blobs_.emplace_back(builder_.TakeTextBlob(), builder_rotation_);
+ blobs_.emplace_back(builder_.make(), builder_rotation_);
builder_run_count_ = 0;
}
@@ -74,54 +74,6 @@ const ShapeResultBloberizer::BlobBuffer& ShapeResultBloberizer::Blobs() {
return blobs_;
}
-float ShapeResultBloberizer::FillGlyphs(
- const TextRunPaintInfo& run_info,
- const ShapeResultBuffer& result_buffer) {
- if (CanUseFastPath(run_info.from, run_info.to, run_info.run.length(),
- result_buffer.HasVerticalOffsets())) {
- return FillFastHorizontalGlyphs(result_buffer, run_info.run.Direction());
- }
-
- float advance = 0;
- auto results = result_buffer.results_;
-
- if (run_info.run.Rtl()) {
- unsigned word_offset = run_info.run.length();
- for (unsigned j = 0; j < results.size(); j++) {
- unsigned resolved_index = results.size() - 1 - j;
- const scoped_refptr<const ShapeResult>& word_result = results[resolved_index];
- word_offset -= word_result->NumCharacters();
- advance =
- FillGlyphsForResult(word_result.get(), run_info.run.ToStringView(),
- run_info.from, run_info.to, advance, word_offset);
- }
- } else {
- unsigned word_offset = 0;
- for (const auto& word_result : results) {
- advance =
- FillGlyphsForResult(word_result.get(), run_info.run.ToStringView(),
- run_info.from, run_info.to, advance, word_offset);
- word_offset += word_result->NumCharacters();
- }
- }
-
- return advance;
-}
-
-float ShapeResultBloberizer::FillGlyphs(const StringView& text,
- unsigned from,
- unsigned to,
- const ShapeResult* result) {
- DCHECK(result);
- DCHECK(to <= text.length());
- if (CanUseFastPath(from, to, result))
- return FillFastHorizontalGlyphs(result);
-
- float advance = 0;
- float word_offset = 0;
- return FillGlyphsForResult(result, text, from, to, advance, word_offset);
-}
-
namespace {
inline bool IsSkipInkException(const ShapeResultBloberizer& bloberizer,
@@ -205,6 +157,19 @@ void AddFastHorizontalGlyphToBloberizer(
advance + glyph_offset.Width());
}
+float FillGlyphsForResult(ShapeResultBloberizer* bloberizer,
+ const ShapeResult* result,
+ const StringView& text,
+ unsigned from,
+ unsigned to,
+ float initial_advance,
+ unsigned run_offset) {
+ GlyphCallbackContext context = {bloberizer, text};
+ return result->ForEachGlyph(initial_advance, from, to, run_offset,
+ AddGlyphToBloberizer,
+ static_cast<void*>(&context));
+}
+
class ClusterCallbackContext {
WTF_MAKE_NONCOPYABLE(ClusterCallbackContext);
STACK_ALLOCATED();
@@ -250,6 +215,63 @@ void AddEmphasisMarkToBloberizer(void* context,
} // namespace
+float ShapeResultBloberizer::FillGlyphs(
+ const TextRunPaintInfo& run_info,
+ const ShapeResultBuffer& result_buffer) {
+ if (CanUseFastPath(run_info.from, run_info.to, run_info.run.length(),
+ result_buffer.HasVerticalOffsets())) {
+ return FillFastHorizontalGlyphs(result_buffer, run_info.run.Direction());
+ }
+
+ float advance = 0;
+ auto results = result_buffer.results_;
+
+ if (run_info.run.Rtl()) {
+ unsigned word_offset = run_info.run.length();
+ for (unsigned j = 0; j < results.size(); j++) {
+ unsigned resolved_index = results.size() - 1 - j;
+ const scoped_refptr<const ShapeResult>& word_result =
+ results[resolved_index];
+ word_offset -= word_result->NumCharacters();
+ advance = FillGlyphsForResult(this, word_result.get(),
+ run_info.run.ToStringView(), run_info.from,
+ run_info.to, advance, word_offset);
+ }
+ } else {
+ unsigned word_offset = 0;
+ for (const auto& word_result : results) {
+ advance = FillGlyphsForResult(this, word_result.get(),
+ run_info.run.ToStringView(), run_info.from,
+ run_info.to, advance, word_offset);
+ word_offset += word_result->NumCharacters();
+ }
+ }
+
+ return advance;
+}
+
+float ShapeResultBloberizer::FillGlyphs(const StringView& text,
+ unsigned from,
+ unsigned to,
+ const ShapeResultView* result) {
+ DCHECK(result);
+ DCHECK(to <= text.length());
+ float initial_advance = 0;
+ if (CanUseFastPath(from, to, result)) {
+ DCHECK(!result->HasVerticalOffsets());
+ DCHECK_NE(GetType(), ShapeResultBloberizer::Type::kTextIntercepts);
+ return result->ForEachGlyph(initial_advance,
+ &AddFastHorizontalGlyphToBloberizer,
+ static_cast<void*>(this));
+ }
+
+ float run_offset = 0;
+ GlyphCallbackContext context = {this, text};
+ return result->ForEachGlyph(initial_advance, from, to, run_offset,
+ AddGlyphToBloberizer,
+ static_cast<void*>(&context));
+}
+
void ShapeResultBloberizer::FillTextEmphasisGlyphs(
const TextRunPaintInfo& run_info,
const GlyphData& emphasis,
@@ -286,11 +308,12 @@ void ShapeResultBloberizer::FillTextEmphasisGlyphs(
}
}
-void ShapeResultBloberizer::FillTextEmphasisGlyphs(const StringView& text,
- unsigned from,
- unsigned to,
- const GlyphData& emphasis,
- const ShapeResult* result) {
+void ShapeResultBloberizer::FillTextEmphasisGlyphs(
+ const StringView& text,
+ unsigned from,
+ unsigned to,
+ const GlyphData& emphasis,
+ const ShapeResultView* result) {
FloatPoint glyph_center =
emphasis.font_data->BoundsForGlyph(emphasis.glyph).Center();
ClusterCallbackContext context = {this, text, emphasis, glyph_center};
@@ -301,18 +324,6 @@ void ShapeResultBloberizer::FillTextEmphasisGlyphs(const StringView& text,
static_cast<void*>(&context));
}
-float ShapeResultBloberizer::FillGlyphsForResult(const ShapeResult* result,
- const StringView& text,
- unsigned from,
- unsigned to,
- float initial_advance,
- unsigned run_offset) {
- GlyphCallbackContext context = {this, text};
- return result->ForEachGlyph(initial_advance, from, to, run_offset,
- AddGlyphToBloberizer,
- static_cast<void*>(&context));
-}
-
bool ShapeResultBloberizer::CanUseFastPath(unsigned from,
unsigned to,
unsigned length,
@@ -321,11 +332,11 @@ bool ShapeResultBloberizer::CanUseFastPath(unsigned from,
GetType() != ShapeResultBloberizer::Type::kTextIntercepts;
}
-bool ShapeResultBloberizer::CanUseFastPath(unsigned from,
- unsigned to,
- const ShapeResult* shape_result) {
- return from <= shape_result->StartIndexForResult() &&
- to >= shape_result->EndIndexForResult() &&
+bool ShapeResultBloberizer::CanUseFastPath(
+ unsigned from,
+ unsigned to,
+ const ShapeResultView* shape_result) {
+ return from <= shape_result->StartIndex() && to >= shape_result->EndIndex() &&
!shape_result->HasVerticalOffsets() &&
GetType() != ShapeResultBloberizer::Type::kTextIntercepts;
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h
index 86cbcac380a..218321934a9 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h
@@ -7,7 +7,6 @@
#include "third_party/blink/renderer/platform/fonts/canvas_rotation_in_vertical.h"
#include "third_party/blink/renderer/platform/fonts/glyph.h"
-#include "third_party/blink/renderer/platform/fonts/paint_text_blob.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h"
#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
@@ -38,7 +37,7 @@ class PLATFORM_EXPORT ShapeResultBloberizer {
float FillGlyphs(const StringView&,
unsigned from,
unsigned to,
- const ShapeResult*);
+ const ShapeResultView*);
void FillTextEmphasisGlyphs(const TextRunPaintInfo&,
const GlyphData& emphasis_data,
const ShapeResultBuffer&);
@@ -46,7 +45,7 @@ class PLATFORM_EXPORT ShapeResultBloberizer {
unsigned from,
unsigned to,
const GlyphData& emphasis_data,
- const ShapeResult*);
+ const ShapeResultView*);
void Add(Glyph glyph,
const SimpleFontData* font_data,
CanvasRotationInVertical canvas_rotation,
@@ -93,9 +92,9 @@ class PLATFORM_EXPORT ShapeResultBloberizer {
}
struct BlobInfo {
- BlobInfo(scoped_refptr<PaintTextBlob> b, CanvasRotationInVertical r)
+ BlobInfo(sk_sp<SkTextBlob> b, CanvasRotationInVertical r)
: blob(std::move(b)), rotation(r) {}
- scoped_refptr<PaintTextBlob> blob;
+ sk_sp<SkTextBlob> blob;
CanvasRotationInVertical rotation;
};
@@ -105,20 +104,13 @@ class PLATFORM_EXPORT ShapeResultBloberizer {
private:
friend class ShapeResultBloberizerTestInfo;
- float FillGlyphsForResult(const ShapeResult*,
- const StringView&,
- unsigned from,
- unsigned to,
- float initial_advance,
- unsigned run_offset);
-
// Whether the FillFastHorizontalGlyphs can be used. Only applies for full
// runs with no vertical offsets and no text intercepts.
bool CanUseFastPath(unsigned from,
unsigned to,
unsigned length,
bool has_vertical_offsets);
- bool CanUseFastPath(unsigned from, unsigned to, const ShapeResult*);
+ bool CanUseFastPath(unsigned from, unsigned to, const ShapeResultView*);
float FillFastHorizontalGlyphs(const ShapeResultBuffer&, TextDirection);
float FillFastHorizontalGlyphs(const ShapeResult*, float advance = 0);
@@ -132,7 +124,7 @@ class PLATFORM_EXPORT ShapeResultBloberizer {
const Type type_;
// Current text blob state.
- PaintTextBlobBuilder builder_;
+ SkTextBlobBuilder builder_;
CanvasRotationInVertical builder_rotation_ =
CanvasRotationInVertical::kRegular;
size_t builder_run_count_ = 0;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h
index 4ad56a56899..4ad568d79e8 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h
@@ -55,6 +55,12 @@ struct HarfBuzzRunGlyphData {
uint16_t glyph;
unsigned character_index : kCharacterIndexBits;
unsigned safe_to_break_before : 1;
+
+ // LayoutUnit like fixed-point values, with 6 fractional and 10 integear bits.
+ // Can represent values between -1023.98 and 1023.96 which should be enough in
+ // the vast majority of cases. Max value is reserved to indicate invalid.
+ int16_t bounds_before_raw_value;
+ int16_t bounds_after_raw_value;
float advance;
FloatSize offset;
@@ -63,12 +69,43 @@ struct HarfBuzzRunGlyphData {
float advance,
const FloatSize& offset,
bool safe_to_break_before);
+ void SetGlyphBounds(LayoutUnit bounds_before, LayoutUnit bounds_after);
+ bool HasValidGlyphBounds() const {
+ return bounds_before_raw_value != std::numeric_limits<int16_t>::max() &&
+ bounds_after_raw_value != std::numeric_limits<int16_t>::max();
+ }
+
+ LayoutUnit GlyphBoundsBefore() const {
+ LayoutUnit bounds;
+ bounds.SetRawValue(static_cast<int>(bounds_before_raw_value));
+ return bounds;
+ }
+ LayoutUnit GlyphBoundsAfter() const {
+ LayoutUnit bounds;
+ bounds.SetRawValue(static_cast<int>(bounds_after_raw_value));
+ return bounds;
+ }
};
-struct ShapeResult::RunInfo {
+struct ShapeResult::RunInfo : public RefCounted<ShapeResult::RunInfo> {
USING_FAST_MALLOC(RunInfo);
public:
+ static scoped_refptr<RunInfo> Create(const SimpleFontData* font,
+ hb_direction_t dir,
+ CanvasRotationInVertical canvas_rotation,
+ hb_script_t script,
+ unsigned start_index,
+ unsigned num_glyphs,
+ unsigned num_characters) {
+ return base::AdoptRef(new RunInfo(font, dir, canvas_rotation, script,
+ start_index, num_glyphs, num_characters));
+ }
+
+ static scoped_refptr<RunInfo> Create(const RunInfo& other) {
+ return base::AdoptRef(new RunInfo(other));
+ }
+
RunInfo(const SimpleFontData* font,
hb_direction_t dir,
CanvasRotationInVertical canvas_rotation,
@@ -171,16 +208,16 @@ struct ShapeResult::RunInfo {
}
// Creates a new RunInfo instance representing a subset of the current run.
- std::unique_ptr<RunInfo> CreateSubRun(unsigned start, unsigned end) {
+ scoped_refptr<RunInfo> CreateSubRun(unsigned start, unsigned end) {
DCHECK(end > start);
unsigned number_of_characters = std::min(end - start, num_characters_);
auto glyphs = FindGlyphDataRange(start, end);
unsigned number_of_glyphs =
static_cast<unsigned>(std::distance(glyphs.begin, glyphs.end));
- auto run = std::make_unique<RunInfo>(
- font_data_.get(), direction_, canvas_rotation_, script_,
- start_index_ + start, number_of_glyphs, number_of_characters);
+ auto run =
+ Create(font_data_.get(), direction_, canvas_rotation_, script_,
+ start_index_ + start, number_of_glyphs, number_of_characters);
static_assert(base::is_trivially_copyable<HarfBuzzRunGlyphData>::value,
"HarfBuzzRunGlyphData should be trivially copyable");
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc
new file mode 100644
index 00000000000..fad054902a6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc
@@ -0,0 +1,472 @@
+// 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/shaping/shape_result_view.h"
+
+#include <iterator>
+#include "base/containers/adapters.h"
+#include "third_party/blink/renderer/platform/fonts/font.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/glyph_bounds_accumulator.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h"
+
+namespace blink {
+
+struct ShapeResultView::RunInfoPart {
+ USING_FAST_MALLOC(RunInfoPart);
+
+ public:
+ RunInfoPart(scoped_refptr<ShapeResult::RunInfo> run,
+ ShapeResult::RunInfo::GlyphDataRange range,
+ unsigned start_index,
+ unsigned offset,
+ unsigned num_characters,
+ float width)
+ : run_(run),
+ range_(range),
+ start_index_(start_index),
+ offset_(offset),
+ num_characters_(num_characters),
+ width_(width) {}
+
+ using const_iterator = const HarfBuzzRunGlyphData*;
+ const_iterator begin() const { return range_.begin; }
+ const_iterator end() const { return range_.end; }
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+ const_reverse_iterator rbegin() const {
+ return const_reverse_iterator(end());
+ }
+ const_reverse_iterator rend() const {
+ return const_reverse_iterator(begin());
+ }
+ const HarfBuzzRunGlyphData& GlyphAt(unsigned index) const {
+ return *(range_.begin + index);
+ }
+
+ bool Rtl() const { return run_->Rtl(); }
+ bool IsHorizontal() const { return run_->IsHorizontal(); }
+ unsigned NumCharacters() const { return num_characters_; }
+ unsigned NumGlyphs() const { return range_.end - range_.begin; }
+ float Width() const { return width_; }
+
+ unsigned PreviousSafeToBreakOffset(unsigned offset) const;
+ size_t GlyphToCharacterIndex(size_t i) const {
+ return run_->GlyphToCharacterIndex(i);
+ }
+
+ scoped_refptr<ShapeResult::RunInfo> run_;
+ ShapeResult::RunInfo::GlyphDataRange range_;
+
+ // Start index for partial run, adjusted to ensure that runs are continuous.
+ unsigned start_index_;
+
+ // Offset relative to start index for the original run.
+ unsigned offset_;
+
+ unsigned num_characters_;
+ float width_;
+};
+
+unsigned ShapeResultView::RunInfoPart::PreviousSafeToBreakOffset(
+ unsigned offset) const {
+ if (offset >= NumCharacters())
+ return NumCharacters();
+ if (!Rtl()) {
+ for (const auto& glyph : base::Reversed(*this)) {
+ if (glyph.safe_to_break_before && glyph.character_index <= offset)
+ return glyph.character_index;
+ }
+ } else {
+ for (const auto& glyph : *this) {
+ if (glyph.safe_to_break_before && glyph.character_index <= offset)
+ return glyph.character_index;
+ }
+ }
+
+ // Next safe break is at the start of the run.
+ return 0;
+}
+
+ShapeResultView::ShapeResultView(const ShapeResult* other)
+ : primary_font_(other->primary_font_),
+ start_index_(0),
+ num_characters_(0),
+ num_glyphs_(0),
+ direction_(other->direction_),
+ has_vertical_offsets_(other->has_vertical_offsets_),
+ width_(0) {}
+
+ShapeResultView::~ShapeResultView() = default;
+
+scoped_refptr<ShapeResult> ShapeResultView::CreateShapeResult() const {
+ ShapeResult* new_result =
+ new ShapeResult(primary_font_, num_characters_, Direction());
+ new_result->runs_.ReserveCapacity(parts_.size());
+ for (const auto& part : parts_) {
+ auto new_run = ShapeResult::RunInfo::Create(
+ part->run_->font_data_.get(), part->run_->direction_,
+ part->run_->canvas_rotation_, part->run_->script_, part->start_index_,
+ part->NumGlyphs(), part->num_characters_);
+ std::copy(part->range_.begin, part->range_.end,
+ new_run->glyph_data_.begin());
+ for (HarfBuzzRunGlyphData& glyph_data : new_run->glyph_data_) {
+ glyph_data.character_index -= part->offset_;
+ }
+
+ new_run->start_index_ += char_index_offset_;
+ new_run->width_ = part->width_;
+ new_run->num_characters_ = part->num_characters_;
+ new_result->runs_.push_back(std::move(new_run));
+ }
+
+ new_result->start_index_ = start_index_ + char_index_offset_;
+ new_result->num_glyphs_ = num_glyphs_;
+ new_result->has_vertical_offsets_ = has_vertical_offsets_;
+ new_result->width_ = width_;
+ new_result->glyph_bounding_box_ = glyph_bounding_box_;
+
+ return base::AdoptRef(new_result);
+}
+
+void ShapeResultView::CreateViewsForResult(const ShapeResult* other,
+ unsigned start_index,
+ unsigned end_index) {
+ bool first_result = num_characters_ == 0;
+ for (const auto& run : other->runs_) {
+ if (!run)
+ continue;
+ unsigned part_start = run->start_index_;
+ unsigned run_end = part_start + run->num_characters_;
+ if (start_index < run_end && end_index > part_start) {
+ ShapeResult::RunInfo::GlyphDataRange range;
+
+ unsigned adjusted_start =
+ start_index > part_start ? start_index - part_start : 0;
+ unsigned adjusted_end = std::min(end_index, run_end) - part_start;
+ DCHECK(adjusted_end > adjusted_start);
+ unsigned part_characters = adjusted_end - adjusted_start;
+ float part_width;
+
+ // Avoid O(log n) find operation if the entire run is in range.
+ if (part_start >= start_index && run_end <= end_index) {
+ range = {run->glyph_data_.begin(), run->glyph_data_.end()};
+ part_width = run->width_;
+ } else {
+ range = run->FindGlyphDataRange(adjusted_start, adjusted_end);
+ part_width = 0;
+ for (auto* glyph = range.begin; glyph != range.end; glyph++)
+ part_width += glyph->advance;
+ }
+
+ // Adjust start_index for runs to be continuous.
+ unsigned part_start_index;
+ unsigned part_offset;
+ if (!run->Rtl()) { // Left-to-right
+ part_start_index = start_index_ + num_characters_;
+ part_offset = adjusted_start;
+ } else { // Right-to-left
+ part_start_index = run->start_index_ + adjusted_start;
+ part_offset = adjusted_start;
+ }
+
+ parts_.push_back(std::make_unique<RunInfoPart>(
+ run, range, part_start_index, part_offset, part_characters,
+ part_width));
+
+ num_characters_ += part_characters;
+ num_glyphs_ += range.end - range.begin;
+ width_ += part_width;
+ }
+ }
+
+ if (first_result || Rtl())
+ start_index_ = ComputeStartIndex();
+}
+
+scoped_refptr<ShapeResultView> ShapeResultView::Create(const Segment* segments,
+ size_t segment_count) {
+ ShapeResultView* out = new ShapeResultView(segments[0].result);
+ out->AddSegments(segments, segment_count);
+ return base::AdoptRef(out);
+}
+
+scoped_refptr<ShapeResultView> ShapeResultView::Create(
+ const ShapeResult* result,
+ unsigned start_index,
+ unsigned end_index) {
+ Segment segment = {result, start_index, end_index};
+ return Create(&segment, 1);
+}
+
+scoped_refptr<ShapeResultView> ShapeResultView::Create(
+ const ShapeResult* result) {
+ // This specialization is an optimization to allow the bounding box to be
+ // re-used.
+ ShapeResultView* out = new ShapeResultView(result);
+ out->char_index_offset_ = out->Rtl() ? 0 : result->StartIndex();
+ out->CreateViewsForResult(result, 0, std::numeric_limits<unsigned>::max());
+ out->has_vertical_offsets_ = result->has_vertical_offsets_;
+ out->glyph_bounding_box_ = result->glyph_bounding_box_;
+ return base::AdoptRef(out);
+}
+
+void ShapeResultView::AddSegments(const Segment* segments,
+ size_t segment_count) {
+ // This method assumes that no parts have been added yet.
+ DCHECK_EQ(parts_.size(), 0u);
+
+ // Segments are in logical order, runs and parts are in visual order. Iterate
+ // over segments back-to-front for RTL.
+ DCHECK_GT(segment_count, 0u);
+ unsigned last_segment_index = segment_count - 1;
+
+ // Compute start index offset for the overall run. This is added to the start
+ // index of each glyph to ensure consistency with ShapeResult::SubRange
+ if (!Rtl()) { // Left-to-right
+ char_index_offset_ =
+ std::max(segments[0].result->StartIndex(), segments[0].start_index);
+ } else { // Right to left
+ char_index_offset_ = 0;
+ }
+
+ for (unsigned i = 0; i < segment_count; i++) {
+ const Segment& segment = segments[Rtl() ? last_segment_index - i : i];
+ DCHECK_EQ(segment.result->Direction(), Direction());
+ CreateViewsForResult(segment.result, segment.start_index,
+ segment.end_index);
+ has_vertical_offsets_ |= segment.result->has_vertical_offsets_;
+ }
+
+ float origin = 0;
+ for (const auto& part : parts_) {
+ if (part->IsHorizontal())
+ ComputeBoundsForPart<true>(*part, origin);
+ else
+ ComputeBoundsForPart<false>(*part, origin);
+ origin += part->width_;
+ }
+}
+
+template <bool is_horizontal_run>
+void ShapeResultView::ComputeBoundsForPart(const RunInfoPart& part,
+ float origin) {
+ GlyphBoundsAccumulator bounds(origin);
+ const auto& run = part.run_;
+ const SimpleFontData* font_data = run->font_data_.get();
+ for (const auto& glyph_data : part) {
+ FloatRect glyph_bounds = glyph_data.HasValidGlyphBounds()
+ ? FloatRect(glyph_data.GlyphBoundsBefore(), 0,
+ glyph_data.GlyphBoundsAfter(), 0)
+ : font_data->BoundsForGlyph(glyph_data.glyph);
+
+ bounds.Unite<is_horizontal_run>(glyph_data, glyph_bounds);
+ bounds.origin += glyph_data.advance;
+ }
+ if (!is_horizontal_run)
+ bounds.ConvertVerticalRunToLogical(font_data->GetFontMetrics());
+ glyph_bounding_box_.Unite(bounds.bounds);
+}
+
+unsigned ShapeResultView::ComputeStartIndex() const {
+ if (UNLIKELY(parts_.IsEmpty()))
+ return 0;
+ const RunInfoPart& first_part = *parts_.front();
+ if (!Rtl()) // Left-to-right.
+ return first_part.start_index_;
+ // Right-to-left.
+ unsigned end_index = first_part.start_index_ + first_part.num_characters_;
+ return end_index - num_characters_;
+}
+
+unsigned ShapeResultView::PreviousSafeToBreakOffset(unsigned index) const {
+ for (auto it = parts_.rbegin(); it != parts_.rend(); ++it) {
+ const auto& part = *it;
+ if (!part)
+ continue;
+
+ unsigned run_start = part->start_index_;
+ if (index >= run_start) {
+ unsigned offset = index - run_start;
+ if (offset <= part->num_characters_) {
+ return part->PreviousSafeToBreakOffset(offset) + run_start;
+ }
+ if (!Rtl()) {
+ return run_start + part->num_characters_;
+ }
+ } else if (Rtl()) {
+ if (it == parts_.rbegin())
+ return part->start_index_;
+ const auto& previous_run = *--it;
+ return previous_run->start_index_ + previous_run->num_characters_;
+ }
+ }
+
+ return StartIndex();
+}
+
+void ShapeResultView::GetRunFontData(
+ Vector<ShapeResult::RunFontData>* font_data) const {
+ for (const auto& part : parts_) {
+ font_data->push_back(ShapeResult::RunFontData(
+ {part->run_->font_data_.get(), part->end() - part->begin()}));
+ }
+}
+
+void ShapeResultView::FallbackFonts(
+ HashSet<const SimpleFontData*>* fallback) const {
+ DCHECK(fallback);
+ DCHECK(primary_font_);
+ for (const auto& part : parts_) {
+ if (part->run_->font_data_ && part->run_->font_data_ != primary_font_) {
+ fallback->insert(part->run_->font_data_.get());
+ }
+ }
+}
+
+float ShapeResultView::ForEachGlyph(float initial_advance,
+ GlyphCallback glyph_callback,
+ void* context) const {
+ auto total_advance = initial_advance;
+ for (const auto& part : parts_) {
+ const auto& run = part->run_;
+ bool is_horizontal = HB_DIRECTION_IS_HORIZONTAL(run->direction_);
+ const SimpleFontData* font_data = run->font_data_.get();
+ for (const auto& glyph_data : *part) {
+ unsigned character_index = glyph_data.character_index +
+ part->start_index_ + char_index_offset_ -
+ part->offset_;
+ glyph_callback(context, character_index, glyph_data.glyph,
+ glyph_data.offset, total_advance, is_horizontal,
+ run->canvas_rotation_, font_data);
+ total_advance += glyph_data.advance;
+ }
+ }
+
+ return total_advance;
+}
+
+float ShapeResultView::ForEachGlyph(float initial_advance,
+ unsigned from,
+ unsigned to,
+ unsigned index_offset,
+ GlyphCallback glyph_callback,
+ void* context) const {
+ auto total_advance = initial_advance;
+
+ for (const auto& part : parts_) {
+ const auto& run = part->run_;
+ bool is_horizontal = HB_DIRECTION_IS_HORIZONTAL(run->direction_);
+ const SimpleFontData* font_data = run->font_data_.get();
+
+ if (!run->Rtl()) { // Left-to-right
+ for (const auto& glyph_data : *part) {
+ unsigned character_index = glyph_data.character_index +
+ part->start_index_ + char_index_offset_ -
+ part->offset_;
+ if (character_index >= to)
+ break;
+ if (character_index >= from) {
+ glyph_callback(context, character_index, glyph_data.glyph,
+ glyph_data.offset, total_advance, is_horizontal,
+ run->canvas_rotation_, font_data);
+ }
+ total_advance += glyph_data.advance;
+ }
+
+ } else { // Right-to-left
+ for (const auto& glyph_data : *part) {
+ unsigned character_index = glyph_data.character_index +
+ part->start_index_ + char_index_offset_ -
+ part->offset_;
+ if (character_index < from)
+ break;
+ if (character_index < to) {
+ glyph_callback(context, character_index, glyph_data.glyph,
+ glyph_data.offset, total_advance, is_horizontal,
+ run->canvas_rotation_, font_data);
+ }
+ total_advance += glyph_data.advance;
+ }
+ }
+ }
+ return total_advance;
+}
+
+float ShapeResultView::ForEachGraphemeClusters(const StringView& text,
+ float initial_advance,
+ unsigned from,
+ unsigned to,
+ unsigned index_offset,
+ GraphemeClusterCallback callback,
+ void* context) const {
+ unsigned run_offset = index_offset;
+ float advance_so_far = initial_advance;
+
+ for (const auto& part : parts_) {
+ const auto& run = part->run_;
+ unsigned graphemes_in_cluster = 1;
+ float cluster_advance = 0;
+ bool rtl = Direction() == TextDirection::kRtl;
+
+ // A "cluster" in this context means a cluster as it is used by HarfBuzz:
+ // The minimal group of characters and corresponding glyphs, that cannot be
+ // broken down further from a text shaping point of view. A cluster can
+ // contain multiple glyphs and grapheme clusters, with mutually overlapping
+ // boundaries.
+ uint16_t cluster_start = static_cast<uint16_t>(
+ rtl ? run->start_index_ + run->num_characters_ + run_offset
+ : run->GlyphToCharacterIndex(0) + run_offset);
+
+ const unsigned num_glyphs = part->NumGlyphs();
+ for (unsigned i = 0; i < num_glyphs; ++i) {
+ const HarfBuzzRunGlyphData& glyph_data = part->GlyphAt(i);
+ uint16_t current_character_index = glyph_data.character_index +
+ part->start_index_ +
+ char_index_offset_ - part->offset_;
+
+ bool is_run_end = (i + 1 == num_glyphs);
+ bool is_cluster_end =
+ is_run_end || (run->GlyphToCharacterIndex(i + 1) + run_offset !=
+ current_character_index);
+
+ if ((rtl && current_character_index >= to) ||
+ (!rtl && current_character_index < from)) {
+ advance_so_far += glyph_data.advance;
+ rtl ? --cluster_start : ++cluster_start;
+ continue;
+ }
+
+ cluster_advance += glyph_data.advance;
+
+ if (text.Is8Bit()) {
+ callback(context, current_character_index, advance_so_far, 1,
+ glyph_data.advance, run->canvas_rotation_);
+
+ advance_so_far += glyph_data.advance;
+ } else if (is_cluster_end) {
+ uint16_t cluster_end;
+ if (rtl) {
+ cluster_end = current_character_index;
+ } else {
+ cluster_end = static_cast<uint16_t>(
+ is_run_end ? run->start_index_ + run->num_characters_ + run_offset
+ : run->GlyphToCharacterIndex(i + 1) + run_offset);
+ }
+ graphemes_in_cluster = ShapeResult::CountGraphemesInCluster(
+ text.Characters16(), text.length(), cluster_start, cluster_end);
+ if (!graphemes_in_cluster || !cluster_advance)
+ continue;
+
+ callback(context, current_character_index, advance_so_far,
+ graphemes_in_cluster, cluster_advance, run->canvas_rotation_);
+ advance_so_far += cluster_advance;
+
+ cluster_start = cluster_end;
+ cluster_advance = 0;
+ }
+ }
+ }
+ return advance_so_far;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h
new file mode 100644
index 00000000000..214fd54fbc1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h
@@ -0,0 +1,167 @@
+// 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_SHAPING_SHAPE_RESULT_VIEW_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPE_RESULT_VIEW_H_
+
+#include <memory>
+#include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h"
+#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
+#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/text/text_direction.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+class ShapeResult;
+
+// Class representing a read-only composite of views into one or more existing
+// shape results.
+// Implemented as a list of ref counted RunInfo instances and a start/end
+// offset for each, represented using the internal RunInfoPart struct.
+// This allows lines to be reference sections of the overall paragraph shape
+// results without the memory or computational overhead of a copy.
+//
+// The example below shows the shape result and the individual lines as
+// ShapeResultView instances pointing to the original paragraph results for
+// the string "Pack my box with five dozen liquor jugs.":
+// ╔═════════════════════════════════════════════════════╗
+// ║ Paragraph with single run, no re-shaping for lines. ║
+// ╟─────────────────────────────────────────────────────╢
+// ║ runs_ ╭───────────────────────────────────────────╮ ║
+// ║ 1: │ Pack my box with five dozen liquor jugs. │ ║
+// ║ ╰───────────────────────────────────────────╯ ║
+// ║ lines ╭───────────────────────────────────────────╮ ║
+// ║ 1: │ Pack my box with -> view, run 1: 0-16 │ ║
+// ║ 2: │ five dozen liquor -> view, run 1: 17-34 │ ║
+// ║ 3: │ jugs. -> view, run 1: 35-40 │ ║
+// ║ ╰───────────────────────────────────────────╯ ║
+// ╚═════════════════════════════════════════════════════╝
+//
+// In cases where a portion of the line needs re-shaping the new results are
+// added as separate runs at the beginning and/or end of the runs_ vector with a
+// reference to zero or more sub-runs in the middle representing the original
+// content that could be reused.
+//
+// In the example below the end of the first line "Jack!" needs to be re-shaped:
+// ╔═════════════════════════════════════════════════════╗
+// ║ Paragraph with single run, requiring re-shape. ║
+// ╟─────────────────────────────────────────────────────╢
+// ║ runs_ ╭───────────────────────────────────────────╮ ║
+// ║ 1: │ "Now fax quiz Jack!" my brave ghost pled. │ ║
+// ║ ╰───────────────────────────────────────────╯ ║
+// ║ lines ╭───────────────────────────────────────────╮ ║
+// ║ 1: │ "Now fax quiz -> view, run 1: 0-14 │ ║
+// ║ 1: │ Jack! -> new result/run │ ║
+// ║ 2: │ my brave ghost -> view, run 1: 21-35 │ ║
+// ║ 3: │ pled. -> view, run 1: 41-36 │ ║
+// ║ ╰───────────────────────────────────────────╯ ║
+// ╚═════════════════════════════════════════════════════╝
+//
+// In this case the beginning of the first line would be represented as a part
+// referecing the a range into the original ShapeResult while the last word wold
+// be a separate result owned by the ShapeResultView instance. The second
+// and third lines would again be represented as parts.
+class PLATFORM_EXPORT ShapeResultView final
+ : public RefCounted<ShapeResultView> {
+ public:
+ // Create a new ShapeResultView from a pre-defined list of segments.
+ // The segments list is assumed to be in logical order.
+ struct Segment {
+ const ShapeResult* result;
+ unsigned start_index;
+ unsigned end_index;
+ };
+ static scoped_refptr<ShapeResultView> Create(const Segment*, size_t);
+
+ // Creates a new ShapeResultView from a single segment.
+ static scoped_refptr<ShapeResultView> Create(const ShapeResult*);
+ static scoped_refptr<ShapeResultView> Create(const ShapeResult*,
+ unsigned start_index,
+ unsigned end_index);
+
+ ~ShapeResultView();
+
+ scoped_refptr<ShapeResult> CreateShapeResult() const;
+
+ unsigned StartIndex() const { return start_index_ + char_index_offset_; }
+ unsigned EndIndex() const { return StartIndex() + num_characters_; }
+ unsigned NumCharacters() const { return num_characters_; }
+ unsigned NumGlyphs() const { return num_glyphs_; }
+ float Width() const { return width_; }
+ LayoutUnit SnappedWidth() const { return LayoutUnit::FromFloatCeil(width_); }
+ const FloatRect& Bounds() const { return glyph_bounding_box_; }
+ TextDirection Direction() const {
+ return static_cast<TextDirection>(direction_);
+ }
+ bool Rtl() const { return Direction() == TextDirection::kRtl; }
+ bool HasVerticalOffsets() const { return has_vertical_offsets_; }
+ void FallbackFonts(HashSet<const SimpleFontData*>* fallback) const;
+
+ unsigned PreviousSafeToBreakOffset(unsigned index) const;
+
+ float ForEachGlyph(float initial_advance, GlyphCallback, void* context) const;
+ float ForEachGlyph(float initial_advance,
+ unsigned from,
+ unsigned to,
+ unsigned index_offset,
+ GlyphCallback,
+ void* context) const;
+
+ float ForEachGraphemeClusters(const StringView& text,
+ float initial_advance,
+ unsigned from,
+ unsigned to,
+ unsigned index_offset,
+ GraphemeClusterCallback,
+ void* context) const;
+
+ scoped_refptr<const SimpleFontData> PrimaryFont() const {
+ return primary_font_;
+ }
+ void GetRunFontData(Vector<ShapeResult::RunFontData>*) const;
+
+ private:
+ ShapeResultView(const ShapeResult*);
+ unsigned ComputeStartIndex() const;
+
+ struct RunInfoPart;
+ void CreateViewsForResult(const ShapeResult*,
+ unsigned start_index,
+ unsigned end_index);
+ void AddSegments(const Segment*, size_t);
+ template <bool is_horizontal_run>
+ void ComputeBoundsForPart(const RunInfoPart&, float origin);
+
+ scoped_refptr<const SimpleFontData> primary_font_;
+
+ mutable unsigned start_index_; // Cached and updated by ComputeStartIndex.
+ unsigned num_characters_;
+ unsigned num_glyphs_ : 30;
+
+ // Overall direction for the TextRun, dictates which order each individual
+ // sub run (represented by RunInfo structs in the m_runs vector) can
+ // have a different text direction.
+ unsigned direction_ : 1;
+
+ // Tracks whether any runs contain glyphs with a y-offset != 0.
+ unsigned has_vertical_offsets_ : 1;
+
+ // Offset of the first component added to the view. Used for compatibility
+ // with ShapeResult::SubRange
+ unsigned char_index_offset_;
+
+ float width_;
+ FloatRect glyph_bounding_box_;
+ Vector<std::unique_ptr<RunInfoPart>, 4> parts_;
+
+ friend class ShapeResult;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPE_RESULT_VIEW_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view_test.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view_test.cc
new file mode 100644
index 00000000000..04af141cb59
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_view_test.cc
@@ -0,0 +1,366 @@
+// 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/shaping/shaping_line_breaker.h"
+
+#include <unicode/uscript.h>
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/fonts/font.h"
+#include "third_party/blink/renderer/platform/fonts/font_cache.h"
+#include "third_party/blink/renderer/platform/fonts/font_test_utilities.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_view.h"
+
+namespace blink {
+
+class ShapeResultViewTest : public testing::Test {
+ protected:
+ void SetUp() override {
+ font_description.SetComputedSize(12.0);
+ font = Font(font_description);
+ font.Update(nullptr);
+ }
+
+ void TearDown() override {}
+
+ FontCachePurgePreventer font_cache_purge_preventer;
+ FontDescription font_description;
+ Font font;
+};
+
+namespace {
+
+struct ShapeResultViewGlyphInfo {
+ unsigned character_index;
+ Glyph glyph;
+ float advance;
+};
+
+void AddGlyphInfo(void* context,
+ unsigned character_index,
+ Glyph glyph,
+ FloatSize glyph_offset,
+ float advance,
+ bool is_horizontal,
+ CanvasRotationInVertical rotation,
+ const SimpleFontData* font_data) {
+ auto* list = static_cast<Vector<ShapeResultViewGlyphInfo>*>(context);
+ ShapeResultViewGlyphInfo glyph_info = {character_index, glyph, advance};
+ list->push_back(glyph_info);
+}
+
+bool CompareResultGlyphs(const Vector<ShapeResultViewGlyphInfo>& test,
+ const Vector<ShapeResultViewGlyphInfo>& reference,
+ unsigned reference_start,
+ unsigned num_glyphs) {
+ float advance_offset = reference[reference_start].advance;
+ bool glyphs_match = true;
+ for (unsigned i = 0; i < test.size(); i++) {
+ const auto& test_glyph = test[i];
+ const auto& reference_glyph = reference[i + reference_start];
+ if (test_glyph.character_index != reference_glyph.character_index ||
+ test_glyph.glyph != reference_glyph.glyph ||
+ test_glyph.advance != reference_glyph.advance - advance_offset) {
+ glyphs_match = false;
+ break;
+ }
+ }
+ if (!glyphs_match) {
+ fprintf(stderr, "╔══ Actual ═══════╤═══════╤═════════╗ ");
+ fprintf(stderr, "╔══ Expected ═════╤═══════╤═════════╗\n");
+ fprintf(stderr, "║ Character Index │ Glyph │ Advance ║ ");
+ fprintf(stderr, "║ Character Index │ Glyph │ Advance ║\n");
+ fprintf(stderr, "╟─────────────────┼───────┼─────────╢ ");
+ fprintf(stderr, "╟─────────────────┼───────┼─────────╢\n");
+ for (unsigned i = 0; i < test.size(); i++) {
+ const auto& test_glyph = test[i];
+ const auto& reference_glyph = reference[i + reference_start];
+
+ if (test_glyph.character_index == reference_glyph.character_index)
+ fprintf(stderr, "║ %10u │", test_glyph.character_index);
+ else
+ fprintf(stderr, "║▶ %10u◀│", test_glyph.character_index);
+
+ if (test_glyph.glyph == reference_glyph.glyph)
+ fprintf(stderr, " %04X │", test_glyph.glyph);
+ else
+ fprintf(stderr, "▶ %04X◀│", test_glyph.glyph);
+
+ if (test_glyph.advance == reference_glyph.advance)
+ fprintf(stderr, " %7.2f ║ ", test_glyph.advance);
+ else
+ fprintf(stderr, "▶%7.2f◀║ ", test_glyph.advance);
+
+ fprintf(stderr, "║ %10u │ %04X │ %7.2f ║\n",
+ reference_glyph.character_index, reference_glyph.glyph,
+ reference_glyph.advance - advance_offset);
+ }
+ fprintf(stderr, "╚═════════════════╧═══════╧═════════╝ ");
+ fprintf(stderr, "╚═════════════════╧═══════╧═════════╝\n");
+ }
+ return glyphs_match;
+}
+
+} // anonymous namespace
+
+TEST_F(ShapeResultViewTest, LatinSingleView) {
+ String string =
+ To16Bit("Test run with multiple words and breaking opportunities.", 56);
+ TextDirection direction = TextDirection::kLtr;
+
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<const ShapeResult> result = shaper.Shape(&font, direction);
+ Vector<ShapeResultViewGlyphInfo> glyphs;
+ result->ForEachGlyph(0, AddGlyphInfo, static_cast<void*>(&glyphs));
+
+ // Test view at the start of the result: "Test run with multiple"
+ ShapeResultView::Segment segment = {result.get(), 0, 22};
+ auto first4 = ShapeResultView::Create(&segment, 1);
+
+ EXPECT_EQ(first4->StartIndex(), 0u);
+ EXPECT_EQ(first4->NumCharacters(), 22u);
+ EXPECT_EQ(first4->NumGlyphs(), 22u);
+
+ Vector<ShapeResultViewGlyphInfo> first4_glyphs;
+ first4->ForEachGlyph(0, AddGlyphInfo, static_cast<void*>(&first4_glyphs));
+ EXPECT_EQ(first4_glyphs.size(), 22u);
+ EXPECT_TRUE(CompareResultGlyphs(first4_glyphs, glyphs, 0u, 22u));
+
+ // Test view in the middle of the result: "multiple words and breaking"
+ segment = {result.get(), 14, 41};
+ auto middle4 = ShapeResultView::Create(&segment, 1);
+
+ EXPECT_EQ(middle4->StartIndex(), 14u);
+ EXPECT_EQ(middle4->NumCharacters(), 27u);
+ EXPECT_EQ(middle4->NumGlyphs(), 27u);
+
+ Vector<ShapeResultViewGlyphInfo> middle4_glyphs;
+ middle4->ForEachGlyph(0, AddGlyphInfo, static_cast<void*>(&middle4_glyphs));
+ EXPECT_EQ(middle4_glyphs.size(), 27u);
+ EXPECT_TRUE(CompareResultGlyphs(middle4_glyphs, glyphs, 14u, 27u));
+
+ // Test view at the end of the result: "breaking opportunities."
+ segment = {result.get(), 33, 56};
+ auto last2 = ShapeResultView::Create(&segment, 1);
+
+ EXPECT_EQ(last2->StartIndex(), 33u);
+ EXPECT_EQ(last2->NumCharacters(), 23u);
+ EXPECT_EQ(last2->NumGlyphs(), 23u);
+
+ Vector<ShapeResultViewGlyphInfo> last2_glyphs;
+ last2->ForEachGlyph(0, AddGlyphInfo, static_cast<void*>(&last2_glyphs));
+ EXPECT_EQ(last2_glyphs.size(), 23u);
+ EXPECT_TRUE(CompareResultGlyphs(last2_glyphs, glyphs, 33u, 23u));
+}
+
+TEST_F(ShapeResultViewTest, ArabicSingleView) {
+ String string = To16Bit("عربى نص", 7);
+ TextDirection direction = TextDirection::kRtl;
+
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<const ShapeResult> result = shaper.Shape(&font, direction);
+ Vector<ShapeResultViewGlyphInfo> glyphs;
+ result->ForEachGlyph(0, AddGlyphInfo, static_cast<void*>(&glyphs));
+
+ // Test view at the start of the result: "عربى"
+ ShapeResultView::Segment segment = {result.get(), 0, 4};
+ auto first_word = ShapeResultView::Create(&segment, 1);
+ Vector<ShapeResultViewGlyphInfo> first_glyphs;
+ first_word->ForEachGlyph(0, AddGlyphInfo, static_cast<void*>(&first_glyphs));
+
+ EXPECT_EQ(first_word->StartIndex(), 0u);
+ EXPECT_EQ(first_word->NumCharacters(), 4u);
+ EXPECT_EQ(first_word->NumGlyphs(), 4u);
+ EXPECT_EQ(first_glyphs.size(), 4u);
+
+ String first_reference_string = To16Bit("عربى", 4);
+ HarfBuzzShaper first_reference_shaper(first_reference_string);
+ scoped_refptr<const ShapeResult> first_wortd_reference =
+ first_reference_shaper.Shape(&font, direction);
+ Vector<ShapeResultViewGlyphInfo> first_reference_glyphs;
+ first_wortd_reference->ForEachGlyph(
+ 0, AddGlyphInfo, static_cast<void*>(&first_reference_glyphs));
+ EXPECT_EQ(first_reference_glyphs.size(), 4u);
+
+ EXPECT_TRUE(
+ CompareResultGlyphs(first_glyphs, first_reference_glyphs, 0u, 4u));
+ EXPECT_TRUE(CompareResultGlyphs(first_glyphs, glyphs, 3u, 7u));
+
+ // Test view at the end of the result: "نص"
+ segment = {result.get(), 4, 7};
+ auto last_word = ShapeResultView::Create(&segment, 1);
+ Vector<ShapeResultViewGlyphInfo> last_glyphs;
+ last_word->ForEachGlyph(0, AddGlyphInfo, static_cast<void*>(&last_glyphs));
+
+ EXPECT_EQ(last_word->StartIndex(), 4u);
+ EXPECT_EQ(last_word->NumCharacters(), 3u);
+ EXPECT_EQ(last_word->NumGlyphs(), 3u);
+ EXPECT_EQ(last_glyphs.size(), 3u);
+}
+
+TEST_F(ShapeResultViewTest, LatinMultiRun) {
+ TextDirection direction = TextDirection::kLtr;
+ HarfBuzzShaper shaper_a(To16Bit("hello", 5));
+ HarfBuzzShaper shaper_b(To16Bit(" w", 2));
+ HarfBuzzShaper shaper_c(To16Bit("orld", 4));
+ HarfBuzzShaper shaper_d(To16Bit("!", 1));
+
+ // Combine four separate results into a single one to ensure we have a result
+ // with multiple runs: "hello world!"
+ scoped_refptr<ShapeResult> result = ShapeResult::Create(&font, 0, direction);
+ shaper_a.Shape(&font, direction)->CopyRange(0u, 5u, result.get());
+ shaper_b.Shape(&font, direction)->CopyRange(0u, 2u, result.get());
+ shaper_c.Shape(&font, direction)->CopyRange(0u, 4u, result.get());
+ shaper_d.Shape(&font, direction)->CopyRange(0u, 1u, result.get());
+
+ Vector<ShapeResultViewGlyphInfo> result_glyphs;
+ result->ForEachGlyph(0, AddGlyphInfo, static_cast<void*>(&result_glyphs));
+
+ // Create composite view out of multiple segments where at least some of the
+ // segments have multiple runs: "hello wood wold!"
+ ShapeResultView::Segment segments[5] = {
+ {result.get(), 0, 8}, // "hello wo"
+ {result.get(), 7, 8}, // "o"
+ {result.get(), 10, 11}, // "d"
+ {result.get(), 5, 8}, // " wo"
+ {result.get(), 9, 12}, // "ld!"
+ };
+ auto composite_view = ShapeResultView::Create(&segments[0], 5);
+ Vector<ShapeResultViewGlyphInfo> view_glyphs;
+ composite_view->ForEachGlyph(0, AddGlyphInfo,
+ static_cast<void*>(&view_glyphs));
+
+ EXPECT_EQ(composite_view->StartIndex(), 0u);
+ EXPECT_EQ(composite_view->NumCharacters(), 16u);
+ EXPECT_EQ(composite_view->NumGlyphs(), 16u);
+ EXPECT_EQ(view_glyphs.size(), 16u);
+
+ HarfBuzzShaper shaper2(To16Bit("hello world!", 12));
+ scoped_refptr<const ShapeResult> result2 = shaper2.Shape(&font, direction);
+ Vector<ShapeResultViewGlyphInfo> glyphs2;
+ result2->ForEachGlyph(0, AddGlyphInfo, static_cast<void*>(&glyphs2));
+ EXPECT_TRUE(CompareResultGlyphs(result_glyphs, glyphs2, 0u, 12u));
+
+ HarfBuzzShaper reference_shaper(To16Bit("hello wood wold!", 16));
+ scoped_refptr<const ShapeResult> reference_result =
+ reference_shaper.Shape(&font, direction);
+ Vector<ShapeResultViewGlyphInfo> reference_glyphs;
+ reference_result->ForEachGlyph(0, AddGlyphInfo,
+ static_cast<void*>(&reference_glyphs));
+
+ scoped_refptr<ShapeResult> composite_copy =
+ ShapeResult::Create(&font, 0, direction);
+ result->CopyRange(0, 8, composite_copy.get());
+ result->CopyRange(7, 8, composite_copy.get());
+ result->CopyRange(10, 11, composite_copy.get());
+ result->CopyRange(5, 8, composite_copy.get());
+ result->CopyRange(9, 12, composite_copy.get());
+
+ Vector<ShapeResultViewGlyphInfo> composite_copy_glyphs;
+ composite_copy->ForEachGlyph(0, AddGlyphInfo,
+ static_cast<void*>(&composite_copy_glyphs));
+
+ EXPECT_TRUE(CompareResultGlyphs(view_glyphs, reference_glyphs, 0u, 16u));
+ EXPECT_TRUE(
+ CompareResultGlyphs(composite_copy_glyphs, reference_glyphs, 0u, 16u));
+}
+
+TEST_F(ShapeResultViewTest, LatinCompositeView) {
+ String string =
+ To16Bit("Test run with multiple words and breaking opportunities.", 56);
+ TextDirection direction = TextDirection::kLtr;
+
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<const ShapeResult> result = shaper.Shape(&font, direction);
+ Vector<ShapeResultViewGlyphInfo> glyphs;
+ result->ForEachGlyph(0, AddGlyphInfo, static_cast<void*>(&glyphs));
+
+ String reference_string = To16Bit("multiple breaking opportunities Test", 36);
+ HarfBuzzShaper reference_shaper(reference_string);
+ scoped_refptr<const ShapeResult> reference_result =
+ reference_shaper.Shape(&font, direction);
+ Vector<ShapeResultViewGlyphInfo> reference_glyphs;
+
+ // Match the character index logic of ShapeResult::CopyRange where the the
+ // character index of the first result is preserved and all subsequent ones
+ // are adjusted to be sequential.
+ // TODO(layout-dev): Arguably both should be updated to renumber the first
+ // result as well but some callers depend on the existing behavior.
+ scoped_refptr<ShapeResult> composite_copy =
+ ShapeResult::Create(&font, 0, direction);
+ result->CopyRange(14, 23, composite_copy.get());
+ result->CopyRange(33, 55, composite_copy.get());
+ result->CopyRange(4, 5, composite_copy.get());
+ result->CopyRange(0, 4, composite_copy.get());
+ EXPECT_EQ(composite_copy->NumCharacters(), reference_result->NumCharacters());
+ EXPECT_EQ(composite_copy->NumGlyphs(), reference_result->NumGlyphs());
+ composite_copy->ForEachGlyph(0, AddGlyphInfo,
+ static_cast<void*>(&reference_glyphs));
+
+ // Create composite view out of multiple segments:
+ ShapeResultView::Segment segments[4] = {
+ {result.get(), 14, 23}, // "multiple "
+ {result.get(), 33, 55}, // "breaking opportunities"
+ {result.get(), 4, 5}, // " "
+ {result.get(), 0, 4} // "Test"
+ };
+ auto composite_view = ShapeResultView::Create(&segments[0], 4);
+
+ EXPECT_EQ(composite_view->StartIndex(), composite_copy->StartIndex());
+ EXPECT_EQ(composite_view->NumCharacters(), reference_result->NumCharacters());
+ EXPECT_EQ(composite_view->NumGlyphs(), reference_result->NumGlyphs());
+
+ Vector<ShapeResultViewGlyphInfo> composite_glyphs;
+ composite_view->ForEachGlyph(0, AddGlyphInfo,
+ static_cast<void*>(&composite_glyphs));
+ EXPECT_EQ(composite_glyphs.size(), 36u);
+ EXPECT_TRUE(CompareResultGlyphs(composite_glyphs, reference_glyphs, 0u, 22u));
+}
+
+TEST_F(ShapeResultViewTest, MixedScriptsCompositeView) {
+ String string_a = To16Bit("Test with multiple 字体 ", 22);
+ String string_b = To16Bit("and 本書.", 7);
+ TextDirection direction = TextDirection::kLtr;
+
+ HarfBuzzShaper shaper_a(string_a);
+ scoped_refptr<const ShapeResult> result_a = shaper_a.Shape(&font, direction);
+ HarfBuzzShaper shaper_b(string_b);
+ scoped_refptr<const ShapeResult> result_b = shaper_b.Shape(&font, direction);
+
+ String reference_string = To16Bit("Test with multiple 字体 and 本書.", 29);
+ HarfBuzzShaper reference_shaper(reference_string);
+ scoped_refptr<const ShapeResult> reference_result =
+ reference_shaper.Shape(&font, direction);
+
+ // Create a copy using CopyRange and compare with that to ensure that the same
+ // fonts are used for both the composite and the reference. The combined
+ // reference_result data might use different fonts, resulting in different
+ // glyph ids and metrics.
+ scoped_refptr<ShapeResult> composite_copy =
+ ShapeResult::Create(&font, 0, direction);
+ result_a->CopyRange(0, 22, composite_copy.get());
+ result_b->CopyRange(0, 7, composite_copy.get());
+ EXPECT_EQ(composite_copy->NumCharacters(), reference_result->NumCharacters());
+ EXPECT_EQ(composite_copy->NumGlyphs(), reference_result->NumGlyphs());
+ Vector<ShapeResultViewGlyphInfo> reference_glyphs;
+ composite_copy->ForEachGlyph(0, AddGlyphInfo,
+ static_cast<void*>(&reference_glyphs));
+
+ ShapeResultView::Segment segments[4] = {{result_a.get(), 0, 22},
+ {result_b.get(), 0, 7}};
+ auto composite_view = ShapeResultView::Create(&segments[0], 2);
+
+ EXPECT_EQ(composite_view->StartIndex(), 0u);
+ EXPECT_EQ(composite_view->NumCharacters(), reference_result->NumCharacters());
+ EXPECT_EQ(composite_view->NumGlyphs(), reference_result->NumGlyphs());
+
+ Vector<ShapeResultViewGlyphInfo> composite_glyphs;
+ composite_view->ForEachGlyph(0, AddGlyphInfo,
+ static_cast<void*>(&composite_glyphs));
+ EXPECT_TRUE(CompareResultGlyphs(composite_glyphs, reference_glyphs, 0u,
+ reference_glyphs.size()));
+}
+
+} // namespace blink
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 655112d0aee..22198066fef 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
@@ -8,6 +8,7 @@
#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 {
@@ -215,14 +216,14 @@ inline scoped_refptr<ShapeResult> ShapingLineBreaker::Shape(TextDirection direct
// If we further assume that the font kerns with space then even though it's a
// valid break opportunity reshaping is required as the combined width of the
// two segments "Line " and "breaking" may be different from "Line breaking".
-scoped_refptr<const ShapeResult> ShapingLineBreaker::ShapeLine(
+scoped_refptr<const ShapeResultView> ShapingLineBreaker::ShapeLine(
unsigned start,
LayoutUnit available_space,
unsigned options,
ShapingLineBreaker::Result* result_out) {
DCHECK_GE(available_space, LayoutUnit(0));
- unsigned range_start = result_->StartIndexForResult();
- unsigned range_end = result_->EndIndexForResult();
+ unsigned range_start = result_->StartIndex();
+ unsigned range_end = result_->EndIndex();
DCHECK_GE(start, range_start);
DCHECK_LT(start, range_end);
result_out->is_hyphenated = false;
@@ -287,7 +288,8 @@ scoped_refptr<const ShapeResult> ShapingLineBreaker::ShapeLine(
if (first_safe >= break_opportunity.offset) {
// There is no safe-to-break, reshape the whole range.
result_out->break_offset = break_opportunity.offset;
- return Shape(direction, start, break_opportunity.offset);
+ return ShapeResultView::Create(
+ Shape(direction, start, break_opportunity.offset).get());
}
LayoutUnit original_width = FlipRtl(
SnapEnd(result_->CachedPositionForOffset(first_safe - range_start),
@@ -354,14 +356,16 @@ scoped_refptr<const ShapeResult> ShapingLineBreaker::ShapeLine(
// Create shape results for the line by copying from the re-shaped result (if
// reshaping was needed) and the original shape results.
- scoped_refptr<ShapeResult> line_result = ShapeResult::Create(font_, 0, direction);
+ ShapeResultView::Segment segments[3];
unsigned max_length = std::numeric_limits<unsigned>::max();
+ unsigned count = 0;
if (line_start_result)
- line_start_result->CopyRange(0, max_length, line_result.get());
+ segments[count++] = {line_start_result.get(), 0, max_length};
if (last_safe > first_safe)
- result_->CopyRange(first_safe, last_safe, line_result.get());
+ segments[count++] = {result_.get(), first_safe, last_safe};
if (line_end_result)
- line_end_result->CopyRange(last_safe, max_length, line_result.get());
+ segments[count++] = {line_end_result.get(), last_safe, max_length};
+ auto line_result = ShapeResultView::Create(&segments[0], count);
DCHECK_GT(break_opportunity.offset, start);
DCHECK_LE(break_opportunity.offset, range_end);
@@ -376,37 +380,40 @@ scoped_refptr<const ShapeResult> ShapingLineBreaker::ShapeLine(
// Shape from the specified offset to the end of the ShapeResult.
// If |start| is safe-to-break, this copies the subset of the result.
-scoped_refptr<const ShapeResult> ShapingLineBreaker::ShapeToEnd(
+scoped_refptr<const ShapeResultView> ShapingLineBreaker::ShapeToEnd(
unsigned start,
unsigned first_safe,
unsigned range_start,
unsigned range_end) {
DCHECK(result_);
- DCHECK_EQ(range_start, result_->StartIndexForResult());
- DCHECK_EQ(range_end, result_->EndIndexForResult());
+ DCHECK_EQ(range_start, result_->StartIndex());
+ DCHECK_EQ(range_end, result_->EndIndex());
DCHECK_GE(start, range_start);
DCHECK_LT(start, range_end);
DCHECK_GE(first_safe, start);
// If |start| is at the start of the range the entire result object may be
- // reused, which avoids creating an extra copy an the sub-range logic.
+ // reused, which avoids the sub-range logic and bounds computation.
if (start == range_start)
- return result_;
+ return ShapeResultView::Create(result_.get());
// If |start| is safe-to-break, no reshape is needed.
if (start == first_safe)
- return result_->SubRange(start, range_end);
+ 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)
- return Shape(direction, start, range_end);
+ if (first_safe >= range_end) {
+ scoped_refptr<ShapeResult> line_result = Shape(direction, start, range_end);
+ return ShapeResultView::Create(line_result.get());
+ }
// Otherwise reshape to |first_safe|, then copy the rest.
- scoped_refptr<ShapeResult> line_result = Shape(direction, start, first_safe);
- result_->CopyRange(first_safe, range_end, line_result.get());
- DCHECK_EQ(range_end - start, line_result->NumCharacters());
- return line_result;
+ scoped_refptr<ShapeResult> line_start = Shape(direction, start, first_safe);
+ ShapeResultView::Segment segments[2] = {
+ {line_start.get(), 0, std::numeric_limits<unsigned>::max()},
+ {result_.get(), first_safe, range_end}};
+ return ShapeResultView::Create(&segments[0], 2);
}
} // namespace blink
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 e58db434b6e..159cd3e4068 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
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPING_LINE_BREAKER_H_
#include "third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h"
-#include "third_party/blink/renderer/platform/layout_unit.h"
+#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/text/text_direction.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -15,6 +15,7 @@ namespace blink {
class Font;
class ShapeResult;
+class ShapeResultView;
class HarfBuzzShaper;
class Hyphenation;
class LazyLineBreakIterator;
@@ -76,13 +77,13 @@ class PLATFORM_EXPORT ShapingLineBreaker final {
// suppress if ShapeResult is not needed when this line overflows.
kNoResultIfOverflow = 2,
};
- scoped_refptr<const ShapeResult> ShapeLine(unsigned start_offset,
- LayoutUnit available_space,
- unsigned options,
- Result* result_out);
- scoped_refptr<const ShapeResult> ShapeLine(unsigned start_offset,
- LayoutUnit available_space,
- Result* result_out) {
+ scoped_refptr<const ShapeResultView> ShapeLine(unsigned start_offset,
+ LayoutUnit available_space,
+ unsigned options,
+ Result* result_out);
+ scoped_refptr<const ShapeResultView> ShapeLine(unsigned start_offset,
+ LayoutUnit available_space,
+ Result* result_out) {
return ShapeLine(start_offset, available_space, kDefaultOptions,
result_out);
}
@@ -116,10 +117,10 @@ class PLATFORM_EXPORT ShapingLineBreaker final {
bool backwards) const;
scoped_refptr<ShapeResult> Shape(TextDirection, unsigned start, unsigned end);
- scoped_refptr<const ShapeResult> ShapeToEnd(unsigned start,
- unsigned first_safe,
- unsigned range_start,
- unsigned range_end);
+ scoped_refptr<const ShapeResultView> ShapeToEnd(unsigned start,
+ unsigned first_safe,
+ unsigned range_start,
+ unsigned range_end);
const HarfBuzzShaper* shaper_;
const Font* font_;
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 3b62eec89a7..25ba3d14546 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
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
#include "third_party/blink/renderer/platform/fonts/font_test_utilities.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_test_info.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
#include "third_party/blink/renderer/platform/text/text_break_iterator.h"
#include "third_party/blink/renderer/platform/text/text_run.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -19,12 +20,12 @@ namespace blink {
namespace {
-scoped_refptr<const ShapeResult> ShapeLine(ShapingLineBreaker* breaker,
- unsigned start_offset,
- LayoutUnit available_space,
- unsigned* break_offset) {
+scoped_refptr<const ShapeResultView> ShapeLine(ShapingLineBreaker* breaker,
+ unsigned start_offset,
+ LayoutUnit available_space,
+ unsigned* break_offset) {
ShapingLineBreaker::Result result;
- scoped_refptr<const ShapeResult> shape_result =
+ scoped_refptr<const ShapeResultView> shape_result =
breaker->ShapeLine(start_offset, available_space, &result);
*break_offset = result.break_offset;
return shape_result;
@@ -109,7 +110,7 @@ TEST_F(ShapingLineBreakerTest, ShapeLineLatin) {
ASSERT_LT(first1->SnappedWidth(), first2->SnappedWidth());
ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator);
- scoped_refptr<const ShapeResult> line;
+ scoped_refptr<const ShapeResultView> line;
unsigned break_offset = 0;
// Test the case where the entire string fits.
@@ -195,7 +196,7 @@ TEST_F(ShapingLineBreakerTest, ShapeLineLatinBreakAll) {
shaper.Shape(&font, direction, 0, 16);
ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator);
- scoped_refptr<const ShapeResult> line;
+ scoped_refptr<const ShapeResultView> line;
unsigned break_offset = 0;
line = ShapeLine(&breaker, 0, midpoint->SnappedWidth(), &break_offset);
@@ -216,7 +217,7 @@ TEST_F(ShapingLineBreakerTest, ShapeLineZeroAvailableWidth) {
scoped_refptr<const ShapeResult> result = shaper.Shape(&font, direction);
ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator);
- scoped_refptr<const ShapeResult> line;
+ scoped_refptr<const ShapeResultView> line;
unsigned break_offset = 0;
LayoutUnit zero(0);
@@ -288,7 +289,7 @@ TEST_F(ShapingLineBreakerTest, ShapeLineRangeEndMidWord) {
shaper.Shape(&font, direction, 0, 2);
ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator);
- scoped_refptr<const ShapeResult> line;
+ scoped_refptr<const ShapeResultView> line;
unsigned break_offset = 0;
line = ShapeLine(&breaker, 0, LayoutUnit::Max(), &break_offset);
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 520dad11c05..d742599579d 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
@@ -77,20 +77,18 @@ void SimpleFontData::PlatformInit(bool subpixel_ascent_descent) {
return;
}
- SkPaint::FontMetrics metrics;
+ SkFontMetrics metrics;
- PaintFont font;
- platform_data_.SetupPaintFont(&font);
- font.SetTextEncoding(SkPaint::kGlyphID_TextEncoding);
- paint_ = font.ToSkPaint();
- paint_.getFontMetrics(&metrics);
+ font_ = SkFont();
+ platform_data_.SetupSkFont(&font_);
+ font_.getMetrics(&metrics);
float ascent;
float descent;
FontMetrics::AscentDescentWithHacks(
ascent, descent, visual_overflow_inflation_for_ascent_,
- visual_overflow_inflation_for_descent_, platform_data_, paint_,
+ visual_overflow_inflation_for_descent_, platform_data_, font_,
subpixel_ascent_descent);
font_metrics_.SetAscent(ascent);
@@ -162,7 +160,7 @@ void SimpleFontData::PlatformInit(bool subpixel_ascent_descent) {
}
#endif
- SkTypeface* face = paint_.getTypeface();
+ SkTypeface* face = font_.getTypeface();
DCHECK(face);
if (int units_per_em = face->getUnitsPerEm())
font_metrics_.SetUnitsPerEm(units_per_em);
@@ -350,7 +348,7 @@ FloatRect SimpleFontData::PlatformBoundsForGlyph(Glyph glyph) const {
static_assert(sizeof(glyph) == 2, "Glyph id should not be truncated.");
SkRect bounds;
- SkiaTextMetrics(&paint_).GetSkiaBoundsForGlyph(glyph, &bounds);
+ SkFontGetBoundsForGlyph(font_, glyph, &bounds);
return FloatRect(bounds);
}
@@ -362,7 +360,7 @@ void SimpleFontData::BoundsForGlyphs(const Vector<Glyph, 256>& glyphs,
return;
DCHECK_EQ(bounds->size(), glyphs.size());
- SkiaTextMetrics(&paint_).GetSkiaBoundsForGlyphs(glyphs, bounds->data());
+ SkFontGetBoundsForGlyphs(font_, glyphs, bounds->data());
}
float SimpleFontData::PlatformWidthForGlyph(Glyph glyph) const {
@@ -371,7 +369,7 @@ float SimpleFontData::PlatformWidthForGlyph(Glyph glyph) const {
static_assert(sizeof(glyph) == 2, "Glyph id should not be truncated.");
- return SkiaTextMetrics(&paint_).GetSkiaWidthForGlyph(glyph);
+ return SkFontGetWidthForGlyph(font_, glyph);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/simple_font_data.h b/chromium/third_party/blink/renderer/platform/fonts/simple_font_data.h
index cc4a85d261e..055acafeff3 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/simple_font_data.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/simple_font_data.h
@@ -24,7 +24,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SIMPLE_FONT_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SIMPLE_FONT_DATA_H_
-#include <SkPaint.h>
+#include <SkFont.h>
#include <memory>
#include <utility>
@@ -170,7 +170,7 @@ class PLATFORM_EXPORT SimpleFontData : public FontData {
float avg_char_width_;
FontPlatformData platform_data_;
- SkPaint paint_;
+ SkFont font_;
Glyph space_glyph_;
float space_width_;
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 0c49c09a536..90898dbc4a8 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
@@ -166,14 +166,14 @@ scoped_refptr<SimpleFontData> FontCache::GetLastResortFallbackFont(
if (!font_platform_data) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontFaceCreationParams,
sans_creation_params,
- (FontFamilyNames::Sans));
+ (font_family_names::kSans));
font_platform_data = GetFontPlatformData(description, sans_creation_params,
AlternateFontName::kLastResort);
}
if (!font_platform_data) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontFaceCreationParams,
arial_creation_params,
- (FontFamilyNames::Arial));
+ (font_family_names::kArial));
font_platform_data = GetFontPlatformData(description, arial_creation_params,
AlternateFontName::kLastResort);
}
@@ -182,7 +182,7 @@ scoped_refptr<SimpleFontData> FontCache::GetLastResortFallbackFont(
if (!font_platform_data) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontFaceCreationParams,
msuigothic_creation_params,
- (FontFamilyNames::MS_UI_Gothic));
+ (font_family_names::kMSUIGothic));
font_platform_data =
GetFontPlatformData(description, msuigothic_creation_params,
AlternateFontName::kLastResort);
@@ -190,7 +190,7 @@ scoped_refptr<SimpleFontData> FontCache::GetLastResortFallbackFont(
if (!font_platform_data) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontFaceCreationParams,
mssansserif_creation_params,
- (FontFamilyNames::Microsoft_Sans_Serif));
+ (font_family_names::kMicrosoftSansSerif));
font_platform_data =
GetFontPlatformData(description, mssansserif_creation_params,
AlternateFontName::kLastResort);
@@ -198,21 +198,21 @@ scoped_refptr<SimpleFontData> FontCache::GetLastResortFallbackFont(
if (!font_platform_data) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontFaceCreationParams,
segoeui_creation_params,
- (FontFamilyNames::Segoe_UI));
+ (font_family_names::kSegoeUI));
font_platform_data = GetFontPlatformData(
description, segoeui_creation_params, AlternateFontName::kLastResort);
}
if (!font_platform_data) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontFaceCreationParams,
calibri_creation_params,
- (FontFamilyNames::Calibri));
+ (font_family_names::kCalibri));
font_platform_data = GetFontPlatformData(
description, calibri_creation_params, AlternateFontName::kLastResort);
}
if (!font_platform_data) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontFaceCreationParams,
timesnewroman_creation_params,
- (FontFamilyNames::Times_New_Roman));
+ (font_family_names::kTimesNewRoman));
font_platform_data =
GetFontPlatformData(description, timesnewroman_creation_params,
AlternateFontName::kLastResort);
@@ -220,7 +220,7 @@ scoped_refptr<SimpleFontData> FontCache::GetLastResortFallbackFont(
if (!font_platform_data) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontFaceCreationParams,
couriernew_creation_params,
- (FontFamilyNames::Courier_New));
+ (font_family_names::kCourierNew));
font_platform_data =
GetFontPlatformData(description, couriernew_creation_params,
AlternateFontName::kLastResort);
@@ -249,7 +249,7 @@ sk_sp<SkTypeface> FontCache::CreateTypeface(
#endif
AtomicString family = creation_params.Family();
- DCHECK_NE(family, FontFamilyNames::system_ui);
+ DCHECK_NE(family, font_family_names::kSystemUi);
// If we're creating a fallback font (e.g. "-webkit-monospace"), convert the
// name into the fallback name (like "monospace") that fontconfig understands.
if (!family.length() || family.StartsWith("-webkit-")) {
diff --git a/chromium/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.cc b/chromium/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.cc
index 77ec6209fab..73a48b721be 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.cc
@@ -7,6 +7,7 @@
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include <SkFont.h>
#include <SkPath.h>
namespace blink {
@@ -18,33 +19,37 @@ T* advance_by_byte_size(T* p, unsigned byte_size) {
return reinterpret_cast<T*>(reinterpret_cast<uint8_t*>(p) + byte_size);
}
-} // namespace
-
-SkiaTextMetrics::SkiaTextMetrics(const SkPaint* paint) : paint_(paint) {
- CHECK(paint_->getTextEncoding() == SkPaint::kGlyphID_TextEncoding);
+template <class T>
+const T* advance_by_byte_size(const T* p, unsigned byte_size) {
+ return reinterpret_cast<const T*>(reinterpret_cast<const uint8_t*>(p) +
+ byte_size);
}
-void SkiaTextMetrics::GetGlyphWidthForHarfBuzz(hb_codepoint_t codepoint,
- hb_position_t* width) {
+} // namespace
+
+void SkFontGetGlyphWidthForHarfBuzz(const SkFont& font,
+ hb_codepoint_t codepoint,
+ hb_position_t* width) {
DCHECK_LE(codepoint, 0xFFFFu);
CHECK(width);
SkScalar sk_width;
uint16_t glyph = codepoint;
- paint_->getTextWidths(&glyph, sizeof(glyph), &sk_width, nullptr);
- if (!paint_->isSubpixelText())
+ font.getWidths(&glyph, 1, &sk_width, nullptr);
+ if (!font.isSubpixel())
sk_width = SkScalarRoundToInt(sk_width);
*width = SkiaScalarToHarfBuzzPosition(sk_width);
}
-void SkiaTextMetrics::GetGlyphWidthForHarfBuzz(unsigned count,
- hb_codepoint_t* glyphs,
- unsigned glyph_stride,
- hb_position_t* advances,
- unsigned advance_stride) {
- // Batch the call to getTextWidths because its function entry cost is not
- // cheap. getTextWidths accepts multiple glyphd ID, but not from a sparse
+void SkFontGetGlyphWidthForHarfBuzz(const SkFont& font,
+ unsigned count,
+ const hb_codepoint_t* glyphs,
+ const unsigned glyph_stride,
+ hb_position_t* advances,
+ unsigned advance_stride) {
+ // Batch the call to getWidths because its function entry cost is not
+ // cheap. getWidths accepts multiple glyphd ID, but not from a sparse
// array that copy them to a regular array.
Vector<Glyph, 256> glyph_array(count);
for (unsigned i = 0; i < count;
@@ -52,10 +57,9 @@ void SkiaTextMetrics::GetGlyphWidthForHarfBuzz(unsigned count,
glyph_array[i] = *glyphs;
}
Vector<SkScalar, 256> sk_width_array(count);
- paint_->getTextWidths(glyph_array.data(), sizeof(Glyph) * count,
- sk_width_array.data(), nullptr);
+ font.getWidths(glyph_array.data(), count, sk_width_array.data(), nullptr);
- if (!paint_->isSubpixelText()) {
+ if (!font.isSubpixel()) {
for (unsigned i = 0; i < count; i++)
sk_width_array[i] = SkScalarRoundToInt(sk_width_array[i]);
}
@@ -67,21 +71,34 @@ void SkiaTextMetrics::GetGlyphWidthForHarfBuzz(unsigned count,
}
}
-void SkiaTextMetrics::GetGlyphExtentsForHarfBuzz(hb_codepoint_t codepoint,
- hb_glyph_extents_t* extents) {
+// HarfBuzz callback to retrieve glyph extents, mainly used by HarfBuzz for
+// fallback mark positioning, i.e. the situation when the font does not have
+// mark anchors or other mark positioning rules, but instead HarfBuzz is
+// supposed to heuristically place combining marks around base glyphs. HarfBuzz
+// does this by measuring "ink boxes" of glyphs, and placing them according to
+// Unicode mark classes. Above, below, centered or left or right, etc.
+void SkFontGetGlyphExtentsForHarfBuzz(const SkFont& font,
+ hb_codepoint_t codepoint,
+ hb_glyph_extents_t* extents) {
DCHECK_LE(codepoint, 0xFFFFu);
CHECK(extents);
SkRect sk_bounds;
uint16_t glyph = codepoint;
- paint_->getTextWidths(&glyph, sizeof(glyph), nullptr, &sk_bounds);
- if (!paint_->isSubpixelText()) {
+#if defined(OS_MACOSX)
+ // TODO(drott): Remove this once we have better metrics bounds
+ // on Mac, https://bugs.chromium.org/p/skia/issues/detail?id=5328
+ SkPath path;
+ font.getPath(glyph, &path);
+ sk_bounds = path.getBounds();
+#else
+ font.getWidths(&glyph, 1, nullptr, &sk_bounds);
+#endif
+ if (!font.isSubpixel()) {
// Use roundOut() rather than round() to avoid rendering glyphs
// outside the visual overflow rect. crbug.com/452914.
- SkIRect ir;
- sk_bounds.roundOut(&ir);
- sk_bounds.set(ir);
+ sk_bounds.set(sk_bounds.roundOut());
}
// Invert y-axis because Skia is y-grows-down but we set up HarfBuzz to be
@@ -92,36 +109,36 @@ void SkiaTextMetrics::GetGlyphExtentsForHarfBuzz(hb_codepoint_t codepoint,
extents->height = SkiaScalarToHarfBuzzPosition(-sk_bounds.height());
}
-void SkiaTextMetrics::GetSkiaBoundsForGlyph(Glyph glyph, SkRect* bounds) {
+void SkFontGetBoundsForGlyph(const SkFont& font, Glyph glyph, SkRect* bounds) {
#if defined(OS_MACOSX)
// TODO(drott): Remove this once we have better metrics bounds
// on Mac, https://bugs.chromium.org/p/skia/issues/detail?id=5328
SkPath path;
- paint_->getTextPath(&glyph, sizeof(glyph), 0, 0, &path);
+ font.getPath(glyph, &path);
*bounds = path.getBounds();
#else
- paint_->getTextWidths(&glyph, sizeof(glyph), nullptr, bounds);
+ font.getWidths(&glyph, 1, nullptr, bounds);
#endif
- if (!paint_->isSubpixelText()) {
+ if (!font.isSubpixel()) {
SkIRect ir;
bounds->roundOut(&ir);
bounds->set(ir);
}
}
-void SkiaTextMetrics::GetSkiaBoundsForGlyphs(const Vector<Glyph, 256>& glyphs,
- SkRect* bounds) {
+void SkFontGetBoundsForGlyphs(const SkFont& font,
+ const Vector<Glyph, 256>& glyphs,
+ SkRect* bounds) {
#if defined(OS_MACOSX)
for (unsigned i = 0; i < glyphs.size(); i++) {
- GetSkiaBoundsForGlyph(glyphs[i], &bounds[i]);
+ SkFontGetBoundsForGlyph(font, glyphs[i], &bounds[i]);
}
#else
static_assert(sizeof(Glyph) == 2, "Skia expects 2 bytes glyph id.");
- paint_->getTextWidths(glyphs.data(), sizeof(Glyph) * glyphs.size(), nullptr,
- bounds);
+ font.getWidths(glyphs.data(), glyphs.size(), nullptr, bounds);
- if (!paint_->isSubpixelText()) {
+ if (!font.isSubpixel()) {
for (unsigned i = 0; i < glyphs.size(); i++) {
SkIRect ir;
bounds[i].roundOut(&ir);
@@ -131,17 +148,17 @@ void SkiaTextMetrics::GetSkiaBoundsForGlyphs(const Vector<Glyph, 256>& glyphs,
#endif
}
-float SkiaTextMetrics::GetSkiaWidthForGlyph(Glyph glyph) {
+float SkFontGetWidthForGlyph(const SkFont& font, Glyph glyph) {
SkScalar sk_width;
- paint_->getTextWidths(&glyph, sizeof(glyph), &sk_width, nullptr);
+ font.getWidths(&glyph, 1, &sk_width, nullptr);
- if (!paint_->isSubpixelText())
+ if (!font.isSubpixel())
sk_width = SkScalarRoundToInt(sk_width);
return SkScalarToFloat(sk_width);
}
-hb_position_t SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(SkScalar value) {
+hb_position_t SkiaScalarToHarfBuzzPosition(SkScalar value) {
// We treat HarfBuzz hb_position_t as 16.16 fixed-point.
static const int kHbPosition1 = 1 << 16;
return clampTo<int>(value * kHbPosition1);
diff --git a/chromium/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.h b/chromium/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.h
index 787d8af0375..6a72122ee22 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.h
@@ -7,33 +7,34 @@
#include "third_party/blink/renderer/platform/fonts/glyph.h"
-#include <SkPaint.h>
#include <hb.h>
#include "third_party/blink/renderer/platform/wtf/vector.h"
+#include "third_party/skia/include/core/SkRect.h"
-namespace blink {
-
-class SkiaTextMetrics final {
- public:
- SkiaTextMetrics(const SkPaint*);
-
- void GetGlyphWidthForHarfBuzz(hb_codepoint_t, hb_position_t* width);
- void GetGlyphWidthForHarfBuzz(unsigned count,
- hb_codepoint_t* first_glyph,
- unsigned glyph_stride,
- hb_position_t* first_advance,
- unsigned advance_stride);
- void GetGlyphExtentsForHarfBuzz(hb_codepoint_t, hb_glyph_extents_t*);
+class SkFont;
- void GetSkiaBoundsForGlyph(Glyph, SkRect* bounds);
- void GetSkiaBoundsForGlyphs(const Vector<Glyph, 256>&, SkRect*);
- float GetSkiaWidthForGlyph(Glyph);
-
- static hb_position_t SkiaScalarToHarfBuzzPosition(SkScalar value);
+namespace blink {
- private:
- const SkPaint* paint_;
-};
+void SkFontGetGlyphWidthForHarfBuzz(const SkFont&,
+ hb_codepoint_t,
+ hb_position_t* width);
+void SkFontGetGlyphWidthForHarfBuzz(const SkFont&,
+ unsigned count,
+ const hb_codepoint_t* first_glyph,
+ unsigned glyph_stride,
+ hb_position_t* first_advance,
+ unsigned advance_stride);
+void SkFontGetGlyphExtentsForHarfBuzz(const SkFont&,
+ hb_codepoint_t,
+ hb_glyph_extents_t*);
+
+void SkFontGetBoundsForGlyph(const SkFont&, Glyph, SkRect* bounds);
+void SkFontGetBoundsForGlyphs(const SkFont&,
+ const Vector<Glyph, 256>&,
+ SkRect*);
+float SkFontGetWidthForGlyph(const SkFont&, Glyph);
+
+hb_position_t SkiaScalarToHarfBuzzPosition(SkScalar value);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/utf16_text_iterator.cc b/chromium/third_party/blink/renderer/platform/fonts/utf16_text_iterator.cc
index 3f175552aea..abceeae6a9a 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/utf16_text_iterator.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/utf16_text_iterator.cc
@@ -53,7 +53,7 @@ bool UTF16TextIterator::ConsumeSurrogatePair(UChar32& character) {
DCHECK(U16_IS_SURROGATE(character));
if (!IsValidSurrogatePair(character)) {
- character = WTF::Unicode::kReplacementCharacter;
+ character = WTF::unicode::kReplacementCharacter;
return true;
}
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 bf7f7c5d072..b63f8a2051d 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
@@ -7,14 +7,15 @@
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
#include "third_party/blink/renderer/platform/fonts/font_description.h"
-#include "third_party/blink/renderer/platform/fonts/paint_font.h"
-#include "third_party/blink/renderer/platform/layout_test_support.h"
+#include "third_party/blink/renderer/platform/web_test_support.h"
+
+#include <SkFont.h>
namespace blink {
namespace {
-SkPaint::Hinting g_skia_hinting = SkPaint::kNormal_Hinting;
+SkFontHinting g_skia_hinting = SkFontHinting::kNormal;
bool g_use_skia_auto_hint = true;
bool g_use_skia_bitmaps = true;
bool g_use_skia_anti_alias = true;
@@ -28,7 +29,7 @@ void WebFontRenderStyle::SetSkiaFontManager(sk_sp<SkFontMgr> font_mgr) {
}
// static
-void WebFontRenderStyle::SetHinting(SkPaint::Hinting hinting) {
+void WebFontRenderStyle::SetHinting(SkFontHinting hinting) {
g_skia_hinting = hinting;
}
@@ -66,8 +67,7 @@ void WebFontRenderStyle::SetSystemFontFamily(const WebString& name) {
WebFontRenderStyle WebFontRenderStyle::GetDefault() {
WebFontRenderStyle result;
result.use_anti_alias = g_use_skia_anti_alias;
- result.hint_style = SkPaint::kNo_Hinting;
- result.hint_style = g_skia_hinting;
+ result.hint_style = static_cast<char>(g_skia_hinting);
result.use_bitmaps = g_use_skia_bitmaps;
result.use_auto_hint = g_use_skia_auto_hint;
result.use_anti_alias = g_use_skia_anti_alias;
@@ -97,23 +97,46 @@ void WebFontRenderStyle::OverrideWith(const WebFontRenderStyle& other) {
use_subpixel_positioning = other.use_subpixel_positioning;
}
-void WebFontRenderStyle::ApplyToPaintFont(PaintFont& font,
- float device_scale_factor) const {
- auto sk_hint_style = static_cast<SkPaint::Hinting>(hint_style);
- font.SetAntiAlias(use_anti_alias);
- font.SetHinting(sk_hint_style);
- font.SetEmbeddedBitmapText(use_bitmaps);
- font.SetAutohinted(use_auto_hint);
+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);
+ 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);
+ font->setHinting(sk_hint_style);
+ font->setEmbeddedBitmaps(use_bitmaps);
+ font->setForceAutoHinting(use_auto_hint);
+ if (use_anti_alias && use_subpixel_rendering) {
+ font->setEdging(SkFont::Edging::kSubpixelAntiAlias);
+ } else if (use_anti_alias) {
+ font->setEdging(SkFont::Edging::kAntiAlias);
+ } else {
+ font->setEdging(SkFont::Edging::kAlias);
+ }
// Force-enable subpixel positioning, except when full hinting is requested on
- // low-dpi screen or when running layout tests.
+ // low-dpi screen or when running web tests.
bool force_subpixel_positioning =
- !LayoutTestSupport::IsRunningLayoutTest() &&
- (sk_hint_style != SkPaint::kFull_Hinting || device_scale_factor > 1.0f);
+ !WebTestSupport::IsRunningWebTest() &&
+ (sk_hint_style != SkFontHinting::kFull || device_scale_factor > 1.0f);
- font.SetSubpixelText(force_subpixel_positioning || use_subpixel_positioning);
+ font->setSubpixel(force_subpixel_positioning || use_subpixel_positioning);
}
} // namespace blink
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 e4ed5f67725..4fc4b20ddfa 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
@@ -32,35 +32,26 @@
#include "third_party/blink/renderer/platform/fonts/font_platform_data.h"
#include <windows.h>
+#include "SkFont.h"
#include "SkTypeface.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
-#include "third_party/blink/renderer/platform/layout_test_support.h"
+#include "third_party/blink/renderer/platform/web_test_support.h"
namespace blink {
-// Maximum font size, in pixels, at which embedded bitmaps will be used
-// if available.
-const float kMaxSizeForEmbeddedBitmap = 24.0f;
-
-void FontPlatformData::SetupPaintFont(PaintFont* font,
- float,
- const Font*) const {
- const float ts = text_size_ >= 0 ? text_size_ : 12;
- font->SetTextSize(SkFloatToScalar(text_size_));
- font->SetTypeface(typeface_);
- font->SetFakeBoldText(synthetic_bold_);
- font->SetTextSkewX(synthetic_italic_ ? -SK_Scalar1 / 4 : 0);
+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->flags();
+ uint32_t flags = font->getFlags();
static const uint32_t kTextFlagsMask =
SkPaint::kAntiAlias_Flag | SkPaint::kLCDRenderText_Flag |
SkPaint::kEmbeddedBitmapText_Flag | SkPaint::kSubpixelText_Flag;
flags &= ~kTextFlagsMask;
- if (ts <= kMaxSizeForEmbeddedBitmap)
- flags |= SkPaint::kEmbeddedBitmapText_Flag;
-
// 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
@@ -70,16 +61,48 @@ void FontPlatformData::SetupPaintFont(PaintFont* font,
if (text_flags & SkPaint::kAntiAlias_Flag)
flags |= SkPaint::kSubpixelText_Flag;
- if (LayoutTestSupport::IsRunningLayoutTest() &&
- !LayoutTestSupport::IsTextSubpixelPositioningAllowedForTest())
+ if (WebTestSupport::IsRunningWebTest() &&
+ !WebTestSupport::IsTextSubpixelPositioningAllowedForTest())
flags &= ~SkPaint::kSubpixelText_Flag;
SkASSERT(!(text_flags & ~kTextFlagsMask));
flags |= text_flags;
- font->SetFlags(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) {
+ font->setEdging(SkFont::Edging::kSubpixelAntiAlias);
+ } else if (text_flags & SkPaint::kAntiAlias_Flag) {
+ font->setEdging(SkFont::Edging::kAntiAlias);
+ } else {
+ font->setEdging(SkFont::Edging::kAlias);
+ }
+ font->setSubpixel(SkToBool(text_flags & SkPaint::kSubpixelText_Flag));
+
+ // 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)
+ font->setSubpixel(true);
+
+ if (WebTestSupport::IsRunningWebTest() &&
+ !WebTestSupport::IsTextSubpixelPositioningAllowedForTest())
+ font->setSubpixel(false);
- font->SetEmbeddedBitmapText(!avoid_embedded_bitmaps_);
+ font->setEmbeddedBitmaps(!avoid_embedded_bitmaps_);
}
static bool IsWebFont(const String& family_name) {
@@ -91,8 +114,8 @@ static bool IsWebFont(const String& family_name) {
}
static int ComputePaintTextFlags(String font_family_name) {
- if (LayoutTestSupport::IsRunningLayoutTest())
- return LayoutTestSupport::IsFontAntialiasingEnabledForTest()
+ if (WebTestSupport::IsRunningWebTest())
+ return WebTestSupport::IsFontAntialiasingEnabledForTest()
? SkPaint::kAntiAlias_Flag
: 0;