Commit 84f31be1 authored by Dominik Röttsches's avatar Dominik Röttsches Committed by Commit Bot

Connect FontCache to font unique name matching

Create an abstraction for platform specific font unique name matching
and provide an implementation for Android that connect to the
FontUniqueNameLookup service in RenderProcessHost, and retrieves a
shared memory readonly region with a font lookup table. The font lookup
table comes in the form of a protobuf that can be parsed using a library
shared between content/browser and blink. On the first @font-face
declaration that contains a src: local() value and is used in the text,
connect to the service, and parse the lookup table, perform a
lookup. Subsequent lookups will reuse the same table.

After an Android firmware update which triggers a font rescan on the
browser side service side, on a Nexus 6, rebuilding the index takes
about 45ms. This is a one-time cost. After that, until the next firmware
update, the browser process only needs to read the index file back from
disk. On the renderer side, for the first font-face that uses src:
local(), there is an initial IPC cost for retrieving the shared memory
region and parsing the protobuf. Measurements on the previous
implementation indicate that this takes less than 6ms. After that for
the first and subsequent src: local() lookups, the cost is only the
search through the in-memory list.

Design doc in https://crbug.com/828317

Bug: 870223
Change-Id: I0bb200235dd7a9f29f3a5165a31e3c5c0cb7527e
Reviewed-on: https://chromium-review.googlesource.com/1162166
Commit-Queue: Dominik Röttsches <drott@chromium.org>
Reviewed-by: default avatarEmil A Eklund <eae@chromium.org>
Cr-Commit-Position: refs/heads/master@{#584429}
parent 2a5b8cad
...@@ -87,6 +87,9 @@ TEST_F(StyleEngineTest, DocumentDirtyAfterInject) { ...@@ -87,6 +87,9 @@ TEST_F(StyleEngineTest, DocumentDirtyAfterInject) {
} }
TEST_F(StyleEngineTest, AnalyzedInject) { TEST_F(StyleEngineTest, AnalyzedInject) {
// TODO(crbug.com/875805): src: local() lookups do not work in DummyPageHolder
// on platforms where out of process lookups are needed for src: local()
// lookups.
GetDocument().body()->SetInnerHTMLFromString(R"HTML( GetDocument().body()->SetInnerHTMLFromString(R"HTML(
<style> <style>
@font-face { @font-face {
......
...@@ -214,6 +214,11 @@ group("blink_platform_public_deps") { ...@@ -214,6 +214,11 @@ group("blink_platform_public_deps") {
"//v8", "//v8",
] ]
public_configs = [ "//third_party/blink/renderer:features" ] public_configs = [ "//third_party/blink/renderer:features" ]
if (is_android) {
public_deps +=
[ "//third_party/blink/public/common:font_unique_name_table_proto" ]
}
} }
declare_args() { declare_args() {
...@@ -600,6 +605,8 @@ jumbo_component("platform") { ...@@ -600,6 +605,8 @@ jumbo_component("platform") {
"file_metadata.h", "file_metadata.h",
"fonts/alternate_font_family.h", "fonts/alternate_font_family.h",
"fonts/android/font_cache_android.cc", "fonts/android/font_cache_android.cc",
"fonts/android/font_unique_name_lookup_android.cc",
"fonts/android/font_unique_name_lookup_android.h",
"fonts/bitmap_glyphs_blacklist.cc", "fonts/bitmap_glyphs_blacklist.cc",
"fonts/bitmap_glyphs_blacklist.h", "fonts/bitmap_glyphs_blacklist.h",
"fonts/canvas_rotation_in_vertical.h", "fonts/canvas_rotation_in_vertical.h",
...@@ -651,6 +658,8 @@ jumbo_component("platform") { ...@@ -651,6 +658,8 @@ jumbo_component("platform") {
"fonts/font_selector_client.h", "fonts/font_selector_client.h",
"fonts/font_smoothing_mode.cc", "fonts/font_smoothing_mode.cc",
"fonts/font_smoothing_mode.h", "fonts/font_smoothing_mode.h",
"fonts/font_unique_name_lookup.cc",
"fonts/font_unique_name_lookup.h",
"fonts/font_variant_east_asian.cc", "fonts/font_variant_east_asian.cc",
"fonts/font_variant_east_asian.h", "fonts/font_variant_east_asian.h",
"fonts/font_variant_numeric.cc", "fonts/font_variant_numeric.cc",
...@@ -1466,6 +1475,7 @@ jumbo_component("platform") { ...@@ -1466,6 +1475,7 @@ jumbo_component("platform") {
"//skia:skcms", "//skia:skcms",
"//third_party:freetype_harfbuzz", "//third_party:freetype_harfbuzz",
"//third_party/blink/public:embedded_frame_sink_mojo_bindings_blink", "//third_party/blink/public:embedded_frame_sink_mojo_bindings_blink",
"//third_party/blink/public/common",
"//third_party/ced", "//third_party/ced",
"//third_party/icu", "//third_party/icu",
"//ui/gfx", "//ui/gfx",
......
// 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/android/font_unique_name_lookup_android.h"
#include "mojo/public/mojom/base/shared_memory.mojom-blink.h"
#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/modules/font_unique_name_lookup/font_unique_name_lookup.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
namespace blink {
FontUniqueNameLookupAndroid::~FontUniqueNameLookupAndroid() = default;
bool FontUniqueNameLookupAndroid::EnsureMatchingServiceConnected() {
if (font_table_matcher_)
return true;
mojom::blink::FontUniqueNameLookupPtr service;
Platform::Current()->GetInterfaceProvider()->GetInterface(
mojo::MakeRequest(&service));
base::ReadOnlySharedMemoryRegion region_ptr;
if (!service->GetUniqueNameLookupTable(&region_ptr)) {
// Tests like StyleEngineTest do not set up a full browser where Blink can
// connect to a browser side service for font lookups. Placing a DCHECK here
// is too strict for such a case.
LOG(ERROR) << "Unable to connect to browser side service for src: local() "
"font lookup.";
return false;
}
font_table_matcher_ = std::make_unique<FontTableMatcher>(region_ptr.Map());
return true;
}
sk_sp<SkTypeface> FontUniqueNameLookupAndroid::MatchUniqueName(
const String& font_unique_name) {
if (!EnsureMatchingServiceConnected())
return nullptr;
base::Optional<FontTableMatcher::MatchResult> match_result =
font_table_matcher_->MatchName(font_unique_name.Utf8().data());
if (!match_result)
return nullptr;
return SkTypeface::MakeFromFile(match_result->font_path.c_str(),
match_result->ttc_index);
}
} // namespace blink
// 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_ANDROID_FONT_UNIQUE_NAME_LOOKUP_ANDROID_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_ANDROID_FONT_UNIQUE_NAME_LOOKUP_ANDROID_H_
#include "third_party/blink/public/common/font_unique_name_lookup/font_table_matcher.h"
#include "third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h"
#include <memory>
namespace blink {
class FontUniqueNameLookupAndroid : public FontUniqueNameLookup {
public:
FontUniqueNameLookupAndroid() = default;
~FontUniqueNameLookupAndroid() override;
sk_sp<SkTypeface> MatchUniqueName(const String& font_unique_name) override;
private:
bool EnsureMatchingServiceConnected();
std::unique_ptr<FontTableMatcher> font_table_matcher_;
DISALLOW_COPY_AND_ASSIGN(FontUniqueNameLookupAndroid);
};
} // namespace blink
#endif
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/platform/fonts/font_global_context.h" #include "third_party/blink/renderer/platform/fonts/font_global_context.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h" #include "third_party/blink/renderer/platform/fonts/font_cache.h"
#include "third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h"
#include "third_party/blink/renderer/platform/wtf/thread_specific.h" #include "third_party/blink/renderer/platform/wtf/thread_specific.h"
namespace blink { namespace blink {
...@@ -20,6 +21,16 @@ FontGlobalContext* FontGlobalContext::Get(CreateIfNeeded create_if_needed) { ...@@ -20,6 +21,16 @@ FontGlobalContext* FontGlobalContext::Get(CreateIfNeeded create_if_needed) {
FontGlobalContext::FontGlobalContext() : harfbuzz_font_funcs_(nullptr) {} FontGlobalContext::FontGlobalContext() : harfbuzz_font_funcs_(nullptr) {}
FontGlobalContext::~FontGlobalContext() = default;
FontUniqueNameLookup* FontGlobalContext::GetFontUniqueNameLookup() {
if (!Get()->font_unique_name_lookup_) {
Get()->font_unique_name_lookup_ =
FontUniqueNameLookup::GetPlatformUniqueNameLookup();
}
return Get()->font_unique_name_lookup_.get();
}
void FontGlobalContext::ClearMemory() { void FontGlobalContext::ClearMemory() {
if (!Get(kDoNotCreate)) if (!Get(kDoNotCreate))
return; return;
......
...@@ -15,6 +15,7 @@ struct hb_font_funcs_t; ...@@ -15,6 +15,7 @@ struct hb_font_funcs_t;
namespace blink { namespace blink {
class FontCache; class FontCache;
class FontUniqueNameLookup;
enum CreateIfNeeded { kDoNotCreate, kCreate }; enum CreateIfNeeded { kDoNotCreate, kCreate };
...@@ -40,6 +41,8 @@ class PLATFORM_EXPORT FontGlobalContext { ...@@ -40,6 +41,8 @@ class PLATFORM_EXPORT FontGlobalContext {
Get()->harfbuzz_font_funcs_ = funcs; Get()->harfbuzz_font_funcs_ = funcs;
} }
static FontUniqueNameLookup* GetFontUniqueNameLookup();
// Called by MemoryCoordinator to clear memory. // Called by MemoryCoordinator to clear memory.
static void ClearMemory(); static void ClearMemory();
...@@ -49,11 +52,12 @@ class PLATFORM_EXPORT FontGlobalContext { ...@@ -49,11 +52,12 @@ class PLATFORM_EXPORT FontGlobalContext {
friend class WTF::ThreadSpecific<FontGlobalContext>; friend class WTF::ThreadSpecific<FontGlobalContext>;
FontGlobalContext(); FontGlobalContext();
~FontGlobalContext() = default; ~FontGlobalContext();
FontCache font_cache_; FontCache font_cache_;
HarfBuzzFontCache harfbuzz_font_cache_; HarfBuzzFontCache harfbuzz_font_cache_;
hb_font_funcs_t* harfbuzz_font_funcs_; hb_font_funcs_t* harfbuzz_font_funcs_;
std::unique_ptr<FontUniqueNameLookup> font_unique_name_lookup_;
}; };
} // namespace blink } // namespace blink
......
// 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/font_unique_name_lookup.h"
#include "base/macros.h"
#include "build/build_config.h"
#if defined(OS_ANDROID)
#include "third_party/blink/renderer/platform/fonts/android/font_unique_name_lookup_android.h"
#endif
namespace blink {
FontUniqueNameLookup::FontUniqueNameLookup() = default;
// static
std::unique_ptr<FontUniqueNameLookup>
FontUniqueNameLookup::GetPlatformUniqueNameLookup() {
#if defined(OS_ANDROID)
return std::make_unique<FontUniqueNameLookupAndroid>();
#else
NOTREACHED();
return nullptr;
#endif
}
} // namespace blink
// 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_FONT_UNIQUE_NAME_LOOKUP_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_UNIQUE_NAME_LOOKUP_H_
#include "base/macros.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include <SkRefCnt.h>
#include <SkTypeface.h>
#include <memory>
namespace blink {
class FontUniqueNameLookup {
public:
// Factory function to construct a platform specific font unique name lookup
// instance. Client must not use this directly as it is thread
// specific. Retrieve it from FontGlobalContext instead.
static std::unique_ptr<FontUniqueNameLookup> GetPlatformUniqueNameLookup();
virtual sk_sp<SkTypeface> MatchUniqueName(const String& font_unique_name) = 0;
virtual ~FontUniqueNameLookup() = default;
protected:
FontUniqueNameLookup();
DISALLOW_COPY_AND_ASSIGN(FontUniqueNameLookup);
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_UNIQUE_NAME_LOOKUP_
/* /*
* Copyright (c) 2006, 2007, 2008, 2009 Google Inc. All rights reserved. * Copyright (c) 2006, 2007, 2008, 2009 Google Inc. All rights reserved.
* *
...@@ -43,9 +42,12 @@ ...@@ -43,9 +42,12 @@
#include "third_party/blink/renderer/platform/fonts/font_cache.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/font_description.h"
#include "third_party/blink/renderer/platform/fonts/font_face_creation_params.h" #include "third_party/blink/renderer/platform/fonts/font_face_creation_params.h"
#include "third_party/blink/renderer/platform/fonts/font_global_context.h"
#include "third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h"
#include "third_party/blink/renderer/platform/fonts/simple_font_data.h" #include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h" #include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/language.h" #include "third_party/blink/renderer/platform/language.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h" #include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/text/cstring.h" #include "third_party/blink/renderer/platform/wtf/text/cstring.h"
...@@ -55,6 +57,25 @@ ...@@ -55,6 +57,25 @@
namespace blink { namespace blink {
#if defined(OS_ANDROID)
namespace {
static PaintTypeface CreateTypefaceFromUniqueName(
const FontFaceCreationParams& creation_params,
CString& name) {
FontUniqueNameLookup* unique_name_lookup =
FontGlobalContext::Get()->GetFontUniqueNameLookup();
DCHECK(unique_name_lookup);
sk_sp<SkTypeface> uniquely_identified_font =
unique_name_lookup->MatchUniqueName(creation_params.Family());
if (uniquely_identified_font) {
return PaintTypeface::FromSkTypeface(uniquely_identified_font);
}
return PaintTypeface();
}
} // namespace
#endif
AtomicString ToAtomicString(const SkString& str) { AtomicString ToAtomicString(const SkString& str) {
return AtomicString::FromUTF8(str.c_str(), str.size()); return AtomicString::FromUTF8(str.c_str(), str.size());
} }
...@@ -274,10 +295,21 @@ std::unique_ptr<FontPlatformData> FontCache::CreateFontPlatformData( ...@@ -274,10 +295,21 @@ std::unique_ptr<FontPlatformData> FontCache::CreateFontPlatformData(
const FontDescription& font_description, const FontDescription& font_description,
const FontFaceCreationParams& creation_params, const FontFaceCreationParams& creation_params,
float font_size, float font_size,
AlternateFontName) { AlternateFontName alternate_name) {
CString name; CString name;
PaintTypeface paint_tf =
CreateTypeface(font_description, creation_params, name); PaintTypeface paint_tf;
#if defined(OS_ANDROID)
if (alternate_name == AlternateFontName::kLocalUniqueFace &&
RuntimeEnabledFeatures::FontSrcLocalMatchingEnabled()) {
paint_tf = CreateTypefaceFromUniqueName(creation_params, name);
} else {
paint_tf = CreateTypeface(font_description, creation_params, name);
}
#else
paint_tf = CreateTypeface(font_description, creation_params, name);
#endif
if (!paint_tf) if (!paint_tf)
return nullptr; return nullptr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment