[fuchsia] Migrate from custom FuchsiaFontManager to SkFontMgr_fuchsia (#10700)

Use Skia's own implementation of SkFontMgr for Fuchsia, for consistency with
other Skia clients on Fuchsia.

FL-290
This commit is contained in:
Konstantin Pozin 2019-08-09 11:04:43 -07:00 committed by Jason Simmons
parent e0beaff619
commit 70de3ec2c3
7 changed files with 4 additions and 758 deletions

View File

@ -897,9 +897,6 @@ FILE: ../../../flutter/shell/platform/fuchsia/flutter/compositor_context.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/compositor_context.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/engine.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/engine.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/fuchsia_font_manager.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/fuchsia_font_manager.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/fuchsia_font_manager_unittest.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/isolate_configurator.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/isolate_configurator.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/kernel/extract_far.dart

View File

@ -56,8 +56,6 @@ template("flutter_runner") {
"compositor_context.h",
"engine.cc",
"engine.h",
"fuchsia_font_manager.cc",
"fuchsia_font_manager.h",
"isolate_configurator.cc",
"isolate_configurator.h",
"logging.h",
@ -128,6 +126,7 @@ template("flutter_runner") {
"$fuchsia_sdk_root/pkg:zx",
"$fuchsia_sdk_root/pkg/lib/sys/cpp",
"$fuchsia_sdk_root/pkg/lib/vfs/cpp",
"//third_party/skia",
"//third_party/tonic",
] + extra_deps

View File

@ -14,11 +14,10 @@
#include "flutter/runtime/dart_vm_lifecycle.h"
#include "flutter/shell/common/rasterizer.h"
#include "flutter/shell/common/run_configuration.h"
#include "runtime/dart/utils/files.h"
#include "fuchsia_font_manager.h"
#include "platform_view.h"
#include "runtime/dart/utils/files.h"
#include "task_runner_adapter.h"
#include "third_party/skia/include/ports/SkFontMgr_fuchsia.h"
#include "thread.h"
namespace flutter_runner {
@ -275,7 +274,7 @@ Engine::Engine(Delegate& delegate,
// Set default font manager.
engine->GetFontCollection().GetFontCollection()->SetDefaultFontManager(
sk_make_sp<txt::FuchsiaFontManager>(std::move(sync_font_provider)));
SkFontMgr_New_Fuchsia(std::move(sync_font_provider)));
if (engine->Run(std::move(run_configuration)) ==
flutter::Engine::RunStatus::Failure) {

View File

@ -1,454 +0,0 @@
// Copyright 2013 The Flutter 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 "fuchsia_font_manager.h"
#include <lib/fit/function.h>
#include <lib/zx/vmar.h>
#include <unordered_map>
#include "flutter/fml/trace_event.h"
#include "logging.h"
#include "runtime/dart/utils/inlines.h"
#include "runtime/dart/utils/vmo.h"
#include "third_party/icu/source/common/unicode/uchar.h"
namespace txt {
namespace {
constexpr char kDefaultFontFamily[] = "Roboto";
void UnmapMemory(const void* buffer, uint64_t size) {
static_assert(sizeof(void*) == sizeof(uint64_t), "pointers aren't 64-bit");
zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(buffer), size);
}
struct ReleaseSkDataContext {
uint64_t buffer_size;
int buffer_id;
fit::function<void()> release_proc;
ReleaseSkDataContext(uint64_t buffer_size,
int buffer_id,
fit::function<void()> release_proc)
: buffer_size(buffer_size),
buffer_id(buffer_id),
release_proc(std::move(release_proc)) {}
};
void ReleaseSkData(const void* buffer, void* context) {
auto skdata_context = reinterpret_cast<ReleaseSkDataContext*>(context);
DEBUG_CHECK(skdata_context != nullptr, LOG_TAG, "");
UnmapMemory(buffer, skdata_context->buffer_size);
skdata_context->release_proc();
delete skdata_context;
}
sk_sp<SkData> MakeSkDataFromBuffer(const fuchsia::mem::Buffer& data,
int buffer_id,
fit::function<void()> release_proc) {
bool is_valid;
zx_status_t status = dart_utils::IsSizeValid(data, &is_valid);
if (!is_valid || data.size > std::numeric_limits<size_t>::max()) {
return nullptr;
}
uint64_t size = data.size;
uintptr_t buffer = 0;
status = zx::vmar::root_self()->map(0, data.vmo, 0, size, ZX_VM_PERM_READ,
&buffer);
if (status != ZX_OK)
return nullptr;
auto context =
new ReleaseSkDataContext(size, buffer_id, std::move(release_proc));
return SkData::MakeWithProc(reinterpret_cast<void*>(buffer), size,
ReleaseSkData, context);
}
fuchsia::fonts::Slant SkToFuchsiaSlant(SkFontStyle::Slant slant) {
switch (slant) {
case SkFontStyle::kOblique_Slant:
return fuchsia::fonts::Slant::OBLIQUE;
case SkFontStyle::kItalic_Slant:
return fuchsia::fonts::Slant::ITALIC;
case SkFontStyle::kUpright_Slant:
default:
return fuchsia::fonts::Slant::UPRIGHT;
}
}
SkFontStyle::Slant FuchsiaToSkSlant(fuchsia::fonts::Slant slant) {
switch (slant) {
case fuchsia::fonts::Slant::OBLIQUE:
return SkFontStyle::kOblique_Slant;
case fuchsia::fonts::Slant::ITALIC:
return SkFontStyle::kItalic_Slant;
case fuchsia::fonts::Slant::UPRIGHT:
default:
return SkFontStyle::kUpright_Slant;
}
}
fidl::VectorPtr<std::string> BuildLanguageList(const char* bcp47[],
int bcp47_count) {
DEBUG_CHECK(bcp47 != nullptr || bcp47_count == 0, LOG_TAG, "");
auto languages = fidl::VectorPtr<std::string>::New(0);
for (int i = 0; i < bcp47_count; i++) {
languages.push_back(bcp47[i]);
}
return languages;
}
sk_sp<SkTypeface> CreateTypefaceFromSkData(sk_sp<SkData> data, int font_index) {
return SkFontMgr::RefDefault()->makeFromData(std::move(data), font_index);
}
} // anonymous namespace
class FuchsiaFontManager::TypefaceCache {
public:
TypefaceCache() {}
~TypefaceCache();
// Get an SkTypeface with the given buffer id, font index, and buffer
// data. Creates a new SkTypeface if one does not already exist.
sk_sp<SkTypeface> GetOrCreateTypeface(
int buffer_id,
int font_index,
const fuchsia::mem::Buffer& buffer) const;
// Callback called when an SkData with the given buffer id is deleted.
void OnSkDataDeleted(int buffer_id) const;
private:
// Used to identify an SkTypeface in the cache.
struct TypefaceId {
int buffer_id;
int font_index;
// Needed by std::unordered_map.
bool operator==(const TypefaceId& other) const {
return (buffer_id == other.buffer_id && font_index == other.font_index);
}
// Used for debugging.
friend std::ostream& operator<<(std::ostream& os, const TypefaceId& id) {
return os << "TypfaceId: [buffer_id: " << id.buffer_id
<< ", font_index: " << id.font_index << "]";
}
};
// Needed by std::unordered_map.
struct TypefaceIdHash {
std::size_t operator()(const TypefaceId& id) const {
return std::hash<int>()(id.buffer_id) ^
(std::hash<int>()(id.font_index) << 1);
}
};
// Try to get an SkData with the given buffer id from the cache. If an
// SkData is not found, create it and add it to the cache.
sk_sp<SkData> GetOrCreateSkData(int buffer_id,
const fuchsia::mem::Buffer& buffer) const;
// Create a new SkTypeface for the given TypefaceId and SkData and add it to
// the cache.
sk_sp<SkTypeface> CreateSkTypeface(TypefaceId id, sk_sp<SkData> buffer) const;
mutable std::unordered_map<TypefaceId, SkTypeface*, TypefaceIdHash>
typeface_cache_;
mutable std::unordered_map<int, std::shared_ptr<BufferHolder>> buffer_cache_;
// Disallow copy and assignment.
TypefaceCache(const TypefaceCache&) = delete;
TypefaceCache& operator=(const TypefaceCache&) = delete;
};
class FuchsiaFontManager::BufferHolder {
public:
BufferHolder(const TypefaceCache* cache, int buffer_id)
: cache_(cache), buffer_id_(buffer_id) {}
~BufferHolder() {}
void SetData(SkData* data) { data_ = data; }
SkData* GetData() const { return data_; }
void OnDataDeleted() { cache_->OnSkDataDeleted(buffer_id_); }
private:
const TypefaceCache* cache_;
int buffer_id_;
SkData* data_;
// Disallow copy and assignment.
BufferHolder(const BufferHolder&) = delete;
BufferHolder& operator=(const BufferHolder&) = delete;
};
FuchsiaFontManager::TypefaceCache::~TypefaceCache() {
for (const auto& entry : typeface_cache_) {
entry.second->weak_unref();
}
}
void FuchsiaFontManager::TypefaceCache::OnSkDataDeleted(int buffer_id) const {
bool was_found = buffer_cache_.erase(buffer_id) != 0;
DEBUG_CHECK(was_found, LOG_TAG, "");
}
sk_sp<SkData> FuchsiaFontManager::TypefaceCache::GetOrCreateSkData(
int buffer_id,
const fuchsia::mem::Buffer& buffer) const {
auto iter = buffer_cache_.find(buffer_id);
if (iter != buffer_cache_.end()) {
return sk_ref_sp(iter->second->GetData());
}
auto holder = std::make_shared<BufferHolder>(this, buffer_id);
std::weak_ptr<BufferHolder> weak_holder = holder;
auto data = MakeSkDataFromBuffer(buffer, buffer_id, [weak_holder]() {
if (auto holder = weak_holder.lock()) {
holder->OnDataDeleted();
}
});
if (!data) {
return nullptr;
}
holder->SetData(data.get());
buffer_cache_[buffer_id] = std::move(holder);
return data;
}
sk_sp<SkTypeface> FuchsiaFontManager::TypefaceCache::CreateSkTypeface(
TypefaceId id,
sk_sp<SkData> buffer) const {
auto result = CreateTypefaceFromSkData(std::move(buffer), id.font_index);
result->weak_ref();
typeface_cache_[id] = result.get();
return result;
}
sk_sp<SkTypeface> FuchsiaFontManager::TypefaceCache::GetOrCreateTypeface(
int buffer_id,
int font_index,
const fuchsia::mem::Buffer& buffer) const {
auto id = TypefaceId{buffer_id, font_index};
auto iter = typeface_cache_.find(id);
if (iter != typeface_cache_.end()) {
if (iter->second->try_ref()) {
return sk_ref_sp(iter->second);
} else {
iter->second->weak_unref();
typeface_cache_.erase(iter);
}
}
sk_sp<SkData> data = GetOrCreateSkData(buffer_id, buffer);
if (!data) {
return nullptr;
}
return CreateSkTypeface(id, std::move(data));
}
class FuchsiaFontManager::FontStyleSet : public SkFontStyleSet {
public:
FontStyleSet(sk_sp<FuchsiaFontManager> font_manager,
std::string family_name,
std::vector<SkFontStyle> styles)
: font_manager_(font_manager),
family_name_(family_name),
styles_(styles) {}
~FontStyleSet() override = default;
int count() override { return styles_.size(); }
void getStyle(int index, SkFontStyle* style, SkString* style_name) override {
DEBUG_CHECK(index >= 0 && index < static_cast<int>(styles_.size()), LOG_TAG,
"");
if (style)
*style = styles_[index];
// We don't have style names. Return an empty name.
if (style_name)
style_name->reset();
}
SkTypeface* createTypeface(int index) override {
DEBUG_CHECK(index >= 0 && index < static_cast<int>(styles_.size()), LOG_TAG,
"");
if (typefaces_.empty())
typefaces_.resize(styles_.size());
if (!typefaces_[index]) {
typefaces_[index] = font_manager_->FetchTypeface(
family_name_.c_str(), styles_[index], /*bcp47=*/nullptr,
/*bcp47_count=*/0, /*character=*/0,
fuchsia::fonts::REQUEST_FLAG_NO_FALLBACK |
fuchsia::fonts::REQUEST_FLAG_EXACT_MATCH);
}
return SkSafeRef(typefaces_[index].get());
}
SkTypeface* matchStyle(const SkFontStyle& pattern) override {
return matchStyleCSS3(pattern);
}
private:
sk_sp<FuchsiaFontManager> font_manager_;
std::string family_name_;
std::vector<SkFontStyle> styles_;
std::vector<sk_sp<SkTypeface>> typefaces_;
// Disallow copy and assignment.
FontStyleSet(const FontStyleSet&) = delete;
FontStyleSet& operator=(const FontStyleSet&) = delete;
};
FuchsiaFontManager::FuchsiaFontManager(fuchsia::fonts::ProviderSyncPtr provider)
: font_provider_(std::move(provider)),
typeface_cache_(new FuchsiaFontManager::TypefaceCache()) {}
FuchsiaFontManager::~FuchsiaFontManager() = default;
int FuchsiaFontManager::onCountFamilies() const {
DEBUG_CHECK(false, LOG_TAG, "");
return 0;
}
void FuchsiaFontManager::onGetFamilyName(int index,
SkString* familyName) const {
DEBUG_CHECK(false, LOG_TAG, "");
}
SkFontStyleSet* FuchsiaFontManager::onCreateStyleSet(int index) const {
DEBUG_CHECK(false, LOG_TAG, "");
return nullptr;
}
SkFontStyleSet* FuchsiaFontManager::onMatchFamily(
const char family_name[]) const {
fuchsia::fonts::FamilyInfoPtr family_info;
int err = font_provider_->GetFamilyInfo(family_name, &family_info);
if (err != ZX_OK) {
#ifndef NDEBUG
FX_LOGF(ERROR, LOG_TAG,
"Error fetching family from provider [err=%d]. Did "
"you run Flutter in an environment that has a font manager?",
err);
#endif
return nullptr;
}
if (!family_info)
return nullptr;
std::vector<SkFontStyle> styles;
for (auto& style : family_info->styles) {
styles.push_back(
SkFontStyle(style.weight, style.width, FuchsiaToSkSlant(style.slant)));
}
return new FontStyleSet(sk_ref_sp(this), family_info->name,
std::move(styles));
}
SkTypeface* FuchsiaFontManager::onMatchFamilyStyle(
const char familyName[],
const SkFontStyle& style) const {
sk_sp<SkTypeface> typeface = FetchTypeface(familyName, style, nullptr, 0, 0);
return typeface.release();
}
SkTypeface* FuchsiaFontManager::onMatchFamilyStyleCharacter(
const char familyName[],
const SkFontStyle& style,
const char* bcp47[],
int bcp47_count,
SkUnichar character) const {
sk_sp<SkTypeface> typeface =
FetchTypeface(kDefaultFontFamily, style, bcp47, bcp47_count, character);
return typeface.release();
}
SkTypeface* FuchsiaFontManager::onMatchFaceStyle(const SkTypeface*,
const SkFontStyle&) const {
DEBUG_CHECK(false, LOG_TAG, "");
return nullptr;
}
sk_sp<SkTypeface> FuchsiaFontManager::onMakeFromData(sk_sp<SkData>,
int ttcIndex) const {
DEBUG_CHECK(false, LOG_TAG, "");
return nullptr;
}
sk_sp<SkTypeface> FuchsiaFontManager::onMakeFromStreamIndex(
std::unique_ptr<SkStreamAsset>,
int ttcIndex) const {
DEBUG_CHECK(false, LOG_TAG, "");
return nullptr;
}
sk_sp<SkTypeface> FuchsiaFontManager::onMakeFromStreamArgs(
std::unique_ptr<SkStreamAsset>,
const SkFontArguments&) const {
DEBUG_CHECK(false, LOG_TAG, "");
return nullptr;
}
sk_sp<SkTypeface> FuchsiaFontManager::onMakeFromFile(const char path[],
int ttcIndex) const {
DEBUG_CHECK(false, LOG_TAG, "");
return nullptr;
}
sk_sp<SkTypeface> FuchsiaFontManager::onLegacyMakeTypeface(
const char familyName[],
SkFontStyle) const {
DEBUG_CHECK(false, LOG_TAG, "");
return nullptr;
}
sk_sp<SkTypeface> FuchsiaFontManager::FetchTypeface(const char family_name[],
const SkFontStyle& style,
const char* bcp47[],
int bcp47_count,
SkUnichar character,
uint32_t flags) const {
TRACE_EVENT0("flutter", "FuchsiaFontManager::FetchTypeface");
fuchsia::fonts::Request request;
request.family = family_name;
request.weight = style.weight();
request.width = style.width();
request.slant = SkToFuchsiaSlant(style.slant());
request.language = BuildLanguageList(bcp47, bcp47_count);
request.character = character;
request.flags = flags;
fuchsia::fonts::ResponsePtr response;
int err = font_provider_->GetFont(std::move(request), &response);
if (err != ZX_OK) {
#ifndef NDEBUG
FX_LOGF(ERROR, LOG_TAG,
"Error fetching font from provider [err=%d]. Did "
"you run Flutter in an environment that has a font manager?",
err);
#endif
return nullptr;
}
// The service may return null response if there is no font matching the
// request.
if (!response) {
return nullptr;
}
return typeface_cache_->GetOrCreateTypeface(
response->buffer_id, response->font_index, response->buffer);
}
} // namespace txt

View File

@ -1,92 +0,0 @@
// Copyright 2013 The Flutter 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 TXT_FUCHSIA_FONT_MANAGER_H_
#define TXT_FUCHSIA_FONT_MANAGER_H_
#include <fuchsia/fonts/cpp/fidl.h>
#include <memory>
#include "third_party/skia/include/core/SkFontMgr.h"
#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/core/SkTypeface.h"
namespace txt {
class FuchsiaFontManager final : public SkFontMgr {
public:
FuchsiaFontManager(fuchsia::fonts::ProviderSyncPtr provider);
~FuchsiaFontManager() override;
protected:
// |SkFontMgr|
int onCountFamilies() const override;
// |SkFontMgr|
void onGetFamilyName(int index, SkString* familyName) const override;
// |SkFontMgr|
SkFontStyleSet* onMatchFamily(const char familyName[]) const override;
// |SkFontMgr|
SkFontStyleSet* onCreateStyleSet(int index) const override;
// |SkFontMgr|
SkTypeface* onMatchFamilyStyle(const char familyName[],
const SkFontStyle&) const override;
// |SkFontMgr|
SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
const SkFontStyle&,
const char* bcp47[],
int bcp47Count,
SkUnichar character) const override;
// |SkFontMgr|
SkTypeface* onMatchFaceStyle(const SkTypeface*,
const SkFontStyle&) const override;
// |SkFontMgr|
sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int ttcIndex) const override;
// |SkFontMgr|
sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>,
int ttcIndex) const override;
// |SkFontMgr|
sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>,
const SkFontArguments&) const override;
// |SkFontMgr|
sk_sp<SkTypeface> onMakeFromFile(const char path[],
int ttcIndex) const override;
// |SkFontMgr|
sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[],
SkFontStyle) const override;
private:
class BufferHolder;
class TypefaceCache;
class FontStyleSet;
friend class FontStyleSet;
sk_sp<SkTypeface> FetchTypeface(const char family_name[],
const SkFontStyle& style,
const char* bcp47[],
int bcp47_count,
SkUnichar character,
uint32_t flags = 0) const;
mutable fuchsia::fonts::ProviderSyncPtr font_provider_;
std::unique_ptr<TypefaceCache> typeface_cache_;
// Disallow copy and assignment.
FuchsiaFontManager(const FuchsiaFontManager&) = delete;
FuchsiaFontManager& operator=(const FuchsiaFontManager&) = delete;
};
} // namespace txt
#endif // TXT_FUCHSIA_FONT_MANAGER_H_

View File

@ -1,202 +0,0 @@
// Copyright 2013 The Flutter 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 "topaz/runtime/flutter_runner/fuchsia_font_manager.h"
#include <fcntl.h>
#include <fuchsia/fonts/cpp/fidl.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/fdio/fd.h>
#include <lib/gtest/real_loop_fixture.h>
#include <lib/sys/cpp/service_directory.h>
#include <lib/zx/channel.h>
#include <lib/zx/handle.h>
#include <memory>
#include "gtest/gtest.h"
#include "third_party/skia/include/core/SkFontMgr.h"
#include "third_party/skia/include/core/SkTypeface.h"
namespace {
zx::channel CloneChannelFromFileDescriptor(int fd) {
zx::handle handle;
zx_status_t status = fdio_fd_clone(fd, handle.reset_and_get_address());
if (status != ZX_OK)
return zx::channel();
zx_info_handle_basic_t info = {};
status =
handle.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), NULL, NULL);
if (status != ZX_OK || info.type != ZX_OBJ_TYPE_CHANNEL)
return zx::channel();
return zx::channel(handle.release());
}
} // namespace
namespace txt {
namespace {
// A codepoint guaranteed to be unknown in any font/family.
constexpr SkUnichar kUnknownUnicodeCharacter = 0xFFF0;
// Font family to use for tests.
constexpr char kTestFontFamily[] = "Roboto";
// URL for the fonts service.
constexpr char kFontsServiceUrl[] =
"fuchsia-pkg://fuchsia.com/fonts#meta/fonts.cmx";
class FuchsiaFontManagerTest : public gtest::RealLoopFixture {
public:
FuchsiaFontManagerTest() {
auto services = sys::ServiceDirectory::CreateFromNamespace();
// Grab launcher and launch font provider.
fuchsia::sys::LauncherPtr launcher;
services->Connect(launcher.NewRequest());
zx::channel out_services_request;
auto font_services =
sys::ServiceDirectory::CreateWithRequest(&out_services_request);
auto launch_info_font_service = GetLaunchInfoForFontService();
launch_info_font_service.directory_request =
std::move(out_services_request);
launcher->CreateComponent(std::move(launch_info_font_service),
font_service_controller_.NewRequest());
// Connect to the font provider service and then wrap it inside the font
// manager we will be testing.
fuchsia::fonts::ProviderSyncPtr provider_ptr;
font_services->Connect(provider_ptr.NewRequest());
font_manager_ = sk_make_sp<FuchsiaFontManager>(std::move(provider_ptr));
}
fuchsia::sys::LaunchInfo GetLaunchInfoForFontService() {
fuchsia::sys::LaunchInfo launch_info;
launch_info.url = kFontsServiceUrl;
launch_info.arguments.reset(
{"--no-default-fonts", "--font-manifest=/test_fonts/manifest.json"});
auto tmp_dir_fd =
open("/pkg/data/testdata/test_fonts", O_DIRECTORY | O_RDONLY);
launch_info.flat_namespace = fuchsia::sys::FlatNamespace::New();
launch_info.flat_namespace->paths.push_back("/test_fonts");
launch_info.flat_namespace->directories.push_back(
CloneChannelFromFileDescriptor(tmp_dir_fd));
close(tmp_dir_fd);
return launch_info;
}
protected:
fuchsia::sys::ComponentControllerPtr font_service_controller_;
sk_sp<SkFontMgr> font_manager_;
};
// Verify that a typeface is returned for a found character.
TEST_F(FuchsiaFontManagerTest, ValidResponseWhenCharacterFound) {
sk_sp<SkTypeface> typeface(font_manager_->matchFamilyStyleCharacter(
"", SkFontStyle(), nullptr, 0, '&'));
EXPECT_TRUE(typeface.get() != nullptr);
}
// Verify that a codepoint that doesn't map to a character correctly returns
// an empty typeface.
TEST_F(FuchsiaFontManagerTest, EmptyResponseWhenCharacterNotFound) {
sk_sp<SkTypeface> typeface(font_manager_->matchFamilyStyleCharacter(
"", SkFontStyle(), nullptr, 0, kUnknownUnicodeCharacter));
EXPECT_TRUE(typeface.get() == nullptr);
}
// Verify that SkTypeface objects are cached.
TEST_F(FuchsiaFontManagerTest, Caching) {
sk_sp<SkTypeface> typeface(
font_manager_->matchFamilyStyle(kTestFontFamily, SkFontStyle()));
sk_sp<SkTypeface> typeface2(
font_manager_->matchFamilyStyle(kTestFontFamily, SkFontStyle()));
// Expect that the same SkTypeface is returned for both requests.
EXPECT_EQ(typeface.get(), typeface2.get());
// Request a different typeface and verify that a different SkTypeface is
// returned.
sk_sp<SkTypeface> typeface3(
font_manager_->matchFamilyStyle("Roboto Slab", SkFontStyle()));
EXPECT_NE(typeface.get(), typeface3.get());
}
// Verify that SkTypeface can outlive the manager.
TEST_F(FuchsiaFontManagerTest, TypefaceOutlivesManager) {
sk_sp<SkTypeface> typeface(
font_manager_->matchFamilyStyle(kTestFontFamily, SkFontStyle()));
font_manager_.reset();
EXPECT_TRUE(typeface.get() != nullptr);
}
// Verify that we can query a font after releasing a previous instance.
TEST_F(FuchsiaFontManagerTest, ReleaseThenCreateAgain) {
sk_sp<SkTypeface> typeface(
font_manager_->matchFamilyStyle(kTestFontFamily, SkFontStyle()));
EXPECT_TRUE(typeface != nullptr);
typeface.reset();
sk_sp<SkTypeface> typeface2(
font_manager_->matchFamilyStyle(kTestFontFamily, SkFontStyle()));
EXPECT_TRUE(typeface2 != nullptr);
}
// Verify that we get a new typeface instance after releasing a previous
// instance of the same typeface (i.e. the cache purges the released typeface).
TEST_F(FuchsiaFontManagerTest, ReleasedTypefaceIsPurged) {
sk_sp<SkTypeface> typeface(
font_manager_->matchFamilyStyle(kTestFontFamily, SkFontStyle()));
EXPECT_TRUE(typeface != nullptr);
typeface.reset();
sk_sp<SkTypeface> typeface2(
font_manager_->matchFamilyStyle(kTestFontFamily, SkFontStyle()));
EXPECT_TRUE(typeface2 != nullptr);
EXPECT_NE(typeface.get(), typeface2.get());
}
// Verify that unknown font families are handled correctly.
TEST_F(FuchsiaFontManagerTest, MatchUnknownFamily) {
SkFontStyleSet* style_set = font_manager_->matchFamily("unknown");
EXPECT_TRUE(style_set == nullptr || style_set->count() == 0);
}
// Verify that a style set is returned for a known family.
TEST_F(FuchsiaFontManagerTest, MatchKnownFamily) {
SkFontStyleSet* style_set = font_manager_->matchFamily(kTestFontFamily);
EXPECT_GT(style_set->count(), 0);
}
// Verify getting an SkFontStyle from a matched family.
TEST_F(FuchsiaFontManagerTest, FontFamilyGetStyle) {
SkFontStyleSet* style_set = font_manager_->matchFamily(kTestFontFamily);
SkFontStyle style;
style_set->getStyle(0, &style, nullptr);
EXPECT_EQ(style.weight(), 400);
EXPECT_EQ(style.width(), 5);
EXPECT_EQ(style.slant(), SkFontStyle::kUpright_Slant);
}
// Verify creating a typeface from a matched family.
TEST_F(FuchsiaFontManagerTest, FontFamilyCreateTypeface) {
SkFontStyleSet* style_set = font_manager_->matchFamily(kTestFontFamily);
SkTypeface* typeface = style_set->createTypeface(0);
EXPECT_TRUE(typeface != nullptr);
SkFontStyle style = typeface->fontStyle();
EXPECT_EQ(style.weight(), 400);
EXPECT_EQ(style.width(), 5);
EXPECT_EQ(style.slant(), SkFontStyle::kUpright_Slant);
}
} // namespace
} // namespace txt

View File

@ -16,7 +16,6 @@
#include "flutter/fml/make_copyable.h"
#include "flutter/lib/ui/text/font_collection.h"
#include "flutter/runtime/dart_vm.h"
#include "fuchsia_font_manager.h"
#include "runtime/dart/utils/vmo.h"
#include "runtime/dart/utils/vmservice_object.h"
#include "third_party/icu/source/common/unicode/udata.h"