Reland "Add SkFontMgr implementation for Fuchsia"
This is a reland of 309f1deddf
PS2 excludes the new file from Google3 build.
Original change's description:
> Add SkFontMgr implementation for Fuchsia
>
> The new SkFontMgr implementation will be used by Flutter and Chromium on
> Fuchsia.
>
> Change-Id: Ibd60a622282556e8557058e92fe865857f7024f9
> Reviewed-on: https://skia-review.googlesource.com/c/173800
> Reviewed-by: Ben Wagner <bungeman@google.com>
> Commit-Queue: Mike Klein <mtklein@google.com>
Change-Id: I1ea948b644dee4414b7a12a4b354f0a61a5e47ea
Reviewed-on: https://skia-review.googlesource.com/c/175431
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Mike Klein <mtklein@google.com>
This commit is contained in:
parent
e6b5b710fc
commit
f3babcd0af
18
BUILD.gn
18
BUILD.gn
@ -73,6 +73,7 @@ declare_args() {
|
||||
skia_use_freetype && !skia_use_fontconfig
|
||||
skia_enable_fontmgr_custom_empty = is_fuchsia && skia_use_freetype
|
||||
skia_enable_fontmgr_android = skia_use_expat && skia_use_freetype
|
||||
skia_enable_fontmgr_fuchsia = is_fuchsia
|
||||
|
||||
if (is_android) {
|
||||
skia_use_vulkan = defined(ndk_api) && ndk_api >= 24
|
||||
@ -411,6 +412,18 @@ optional("fontmgr_custom") {
|
||||
]
|
||||
}
|
||||
|
||||
optional("fontmgr_fuchsia") {
|
||||
enabled = skia_enable_fontmgr_fuchsia
|
||||
|
||||
deps = [
|
||||
"//garnet/public/fidl/fuchsia.fonts",
|
||||
]
|
||||
sources = [
|
||||
"src/ports/SkFontMgr_fuchsia.cpp",
|
||||
"src/ports/SkFontMgr_fuchsia.h",
|
||||
]
|
||||
}
|
||||
|
||||
optional("fontmgr_empty") {
|
||||
enabled = skia_enable_fontmgr_empty
|
||||
sources = [
|
||||
@ -854,6 +867,7 @@ component("skia") {
|
||||
":fontmgr_custom_empty",
|
||||
":fontmgr_empty",
|
||||
":fontmgr_fontconfig",
|
||||
":fontmgr_fuchsia",
|
||||
":heif",
|
||||
":hsw",
|
||||
":jpeg",
|
||||
@ -983,9 +997,7 @@ component("skia") {
|
||||
}
|
||||
|
||||
if (skia_use_fonthost_mac) {
|
||||
sources += [
|
||||
"src/ports/SkFontHost_mac.cpp",
|
||||
]
|
||||
sources += [ "src/ports/SkFontHost_mac.cpp" ]
|
||||
}
|
||||
|
||||
if (is_mac) {
|
||||
|
19
include/ports/SkFontMgr_fuchsia.h
Normal file
19
include/ports/SkFontMgr_fuchsia.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkFontMgr_fuchsia_DEFINED
|
||||
#define SkFontMgr_fuchsia_DEFINED
|
||||
|
||||
#include <fuchsia/fonts/cpp/fidl.h>
|
||||
|
||||
#include "SkRefCnt.h"
|
||||
|
||||
class SkFontMgr;
|
||||
|
||||
SK_API sk_sp<SkFontMgr> SkFontMgr_New_Fuchsia(fuchsia::fonts::ProviderSyncPtr provider);
|
||||
|
||||
#endif // SkFontMgr_fuchsia_DEFINED
|
@ -300,6 +300,7 @@ BASE_SRCS_UNIX = struct(
|
||||
"src/ports/SkFontMgr_empty_factory.cpp",
|
||||
"src/ports/SkFontMgr_fontconfig.cpp",
|
||||
"src/ports/SkFontMgr_fontconfig_factory.cpp",
|
||||
"src/ports/SkFontMgr_fuchsia.cpp",
|
||||
"src/ports/SkImageGenerator_none.cpp",
|
||||
"src/ports/SkTLS_none.cpp",
|
||||
],
|
||||
@ -327,6 +328,7 @@ BASE_SRCS_ANDROID = struct(
|
||||
"src/ports/SkFontMgr_custom_embedded_factory.cpp",
|
||||
"src/ports/SkFontMgr_custom_empty_factory.cpp",
|
||||
"src/ports/SkFontMgr_empty_factory.cpp",
|
||||
"src/ports/SkFontMgr_fuchsia.cpp",
|
||||
"src/ports/SkImageGenerator_none.cpp",
|
||||
"src/ports/SkTLS_none.cpp",
|
||||
],
|
||||
@ -358,6 +360,7 @@ BASE_SRCS_IOS = struct(
|
||||
"src/ports/SkFontMgr_custom_embedded_factory.cpp",
|
||||
"src/ports/SkFontMgr_custom_empty_factory.cpp",
|
||||
"src/ports/SkFontMgr_empty_factory.cpp",
|
||||
"src/ports/SkFontMgr_fuchsia.cpp",
|
||||
"src/ports/SkImageGenerator_none.cpp",
|
||||
"src/ports/SkTLS_none.cpp",
|
||||
],
|
||||
|
406
src/ports/SkFontMgr_fuchsia.cpp
Normal file
406
src/ports/SkFontMgr_fuchsia.cpp
Normal file
@ -0,0 +1,406 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkFontMgr_fuchsia.h"
|
||||
|
||||
#include <fuchsia/fonts/cpp/fidl.h>
|
||||
#include <lib/zx/vmar.h>
|
||||
#include <strings.h>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "third_party/skia/src/core/SkFontDescriptor.h"
|
||||
#include "third_party/skia/src/ports/SkFontMgr_custom.h"
|
||||
|
||||
#include "SkFontMgr.h"
|
||||
#include "SkStream.h"
|
||||
#include "SkTypeface.h"
|
||||
#include "SkTypefaceCache.h"
|
||||
|
||||
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 fBufferSize;
|
||||
std::function<void()> releaseProc;
|
||||
|
||||
ReleaseSkDataContext(uint64_t bufferSize, const std::function<void()>& releaseProc)
|
||||
: fBufferSize(bufferSize), releaseProc(releaseProc) {}
|
||||
};
|
||||
|
||||
void ReleaseSkData(const void* buffer, void* context) {
|
||||
auto releaseSkDataContext = reinterpret_cast<ReleaseSkDataContext*>(context);
|
||||
SkASSERT(releaseSkDataContext);
|
||||
UnmapMemory(buffer, releaseSkDataContext->fBufferSize);
|
||||
releaseSkDataContext->releaseProc();
|
||||
delete releaseSkDataContext;
|
||||
}
|
||||
|
||||
sk_sp<SkData> MakeSkDataFromBuffer(const fuchsia::mem::Buffer& data,
|
||||
std::function<void()> release_proc) {
|
||||
uint64_t size = data.size;
|
||||
uintptr_t buffer = 0;
|
||||
zx_status_t 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, 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;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr struct {
|
||||
const char* fName;
|
||||
fuchsia::fonts::FallbackGroup fFallbackGroup;
|
||||
} kFallbackGroupsByName[] = {
|
||||
{"serif", fuchsia::fonts::FallbackGroup::SERIF},
|
||||
{"sans", fuchsia::fonts::FallbackGroup::SANS_SERIF},
|
||||
{"sans-serif", fuchsia::fonts::FallbackGroup::SANS_SERIF},
|
||||
{"mono", fuchsia::fonts::FallbackGroup::MONOSPACE},
|
||||
{"monospace", fuchsia::fonts::FallbackGroup::MONOSPACE},
|
||||
{"cursive", fuchsia::fonts::FallbackGroup::CURSIVE},
|
||||
{"fantasy", fuchsia::fonts::FallbackGroup::FANTASY},
|
||||
};
|
||||
|
||||
fuchsia::fonts::FallbackGroup GetFallbackGroupByName(const char* name) {
|
||||
if (!name) return fuchsia::fonts::FallbackGroup::NONE;
|
||||
for (auto& group : kFallbackGroupsByName) {
|
||||
if (strcasecmp(group.fName, name) == 0) {
|
||||
return group.fFallbackGroup;
|
||||
}
|
||||
}
|
||||
return fuchsia::fonts::FallbackGroup::NONE;
|
||||
}
|
||||
|
||||
struct TypefaceId {
|
||||
uint32_t bufferId;
|
||||
uint32_t ttcIndex;
|
||||
|
||||
bool operator==(TypefaceId& other) {
|
||||
return std::tie(bufferId, ttcIndex) == std::tie(other.bufferId, other.ttcIndex);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr kNullTypefaceId = {0xFFFFFFFF, 0xFFFFFFFF};
|
||||
|
||||
class SkTypeface_Fuchsia : public SkTypeface_Stream {
|
||||
public:
|
||||
SkTypeface_Fuchsia(std::unique_ptr<SkFontData> fontData, const SkFontStyle& style,
|
||||
bool isFixedPitch, const SkString familyName, TypefaceId id)
|
||||
: SkTypeface_Stream(std::move(fontData), style, isFixedPitch,
|
||||
/*sys_font=*/true, familyName)
|
||||
, fId(id) {}
|
||||
|
||||
TypefaceId id() { return fId; }
|
||||
|
||||
private:
|
||||
TypefaceId fId;
|
||||
};
|
||||
|
||||
sk_sp<SkTypeface> CreateTypefaceFromSkStream(std::unique_ptr<SkStreamAsset> stream,
|
||||
const SkFontArguments& args, TypefaceId id) {
|
||||
using Scanner = SkTypeface_FreeType::Scanner;
|
||||
Scanner scanner;
|
||||
bool isFixedPitch;
|
||||
SkFontStyle style;
|
||||
SkString name;
|
||||
Scanner::AxisDefinitions axisDefinitions;
|
||||
if (!scanner.scanFont(stream.get(), args.getCollectionIndex(), &name, &style, &isFixedPitch,
|
||||
&axisDefinitions)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const SkFontArguments::VariationPosition position = args.getVariationDesignPosition();
|
||||
SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
|
||||
Scanner::computeAxisValues(axisDefinitions, position, axisValues, name);
|
||||
|
||||
auto fontData = std::make_unique<SkFontData>(std::move(stream), args.getCollectionIndex(),
|
||||
axisValues.get(), axisDefinitions.count());
|
||||
return sk_make_sp<SkTypeface_Fuchsia>(std::move(fontData), style, isFixedPitch, name, id);
|
||||
}
|
||||
|
||||
sk_sp<SkTypeface> CreateTypefaceFromSkData(sk_sp<SkData> data, TypefaceId id) {
|
||||
return CreateTypefaceFromSkStream(std::make_unique<SkMemoryStream>(std::move(data)),
|
||||
SkFontArguments().setCollectionIndex(id.ttcIndex), id);
|
||||
}
|
||||
|
||||
class SkFontMgr_Fuchsia final : public SkFontMgr {
|
||||
public:
|
||||
SkFontMgr_Fuchsia(fuchsia::fonts::ProviderSyncPtr provider);
|
||||
~SkFontMgr_Fuchsia() override;
|
||||
|
||||
protected:
|
||||
// SkFontMgr overrides.
|
||||
int onCountFamilies() const override;
|
||||
void onGetFamilyName(int index, SkString* familyName) const override;
|
||||
SkFontStyleSet* onMatchFamily(const char familyName[]) const override;
|
||||
SkFontStyleSet* onCreateStyleSet(int index) const override;
|
||||
SkTypeface* onMatchFamilyStyle(const char familyName[], const SkFontStyle&) const override;
|
||||
SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
|
||||
const char* bcp47[], int bcp47Count,
|
||||
SkUnichar character) const override;
|
||||
SkTypeface* onMatchFaceStyle(const SkTypeface*, const SkFontStyle&) const override;
|
||||
sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int ttcIndex) const override;
|
||||
sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>,
|
||||
int ttcIndex) const override;
|
||||
sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>,
|
||||
const SkFontArguments&) const override;
|
||||
sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override;
|
||||
sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle) const override;
|
||||
|
||||
private:
|
||||
friend class SkFontStyleSet_Fuchsia;
|
||||
|
||||
sk_sp<SkTypeface> FetchTypeface(const char familyName[], const SkFontStyle& style,
|
||||
const char* bcp47[], int bcp47Count, SkUnichar character,
|
||||
bool allow_fallback, bool exact_style_match) const;
|
||||
|
||||
sk_sp<SkData> GetOrCreateSkData(int bufferId, const fuchsia::mem::Buffer& buffer) const;
|
||||
void OnSkDataDeleted(int bufferId) const;
|
||||
|
||||
sk_sp<SkTypeface> GetOrCreateTypeface(TypefaceId id, const fuchsia::mem::Buffer& buffer) const;
|
||||
|
||||
mutable fuchsia::fonts::ProviderSyncPtr fFontProvider;
|
||||
|
||||
mutable SkMutex fCacheMutex;
|
||||
|
||||
// Must be accessed only with fCacheMutex acquired.
|
||||
mutable std::unordered_map<int, SkData*> fBufferCache;
|
||||
mutable SkTypefaceCache fTypefaceCache;
|
||||
};
|
||||
|
||||
class SkFontStyleSet_Fuchsia : public SkFontStyleSet {
|
||||
public:
|
||||
SkFontStyleSet_Fuchsia(sk_sp<SkFontMgr_Fuchsia> font_manager, std::string familyName,
|
||||
std::vector<SkFontStyle> styles)
|
||||
: fFontManager(font_manager), fFamilyName(familyName), fStyles(styles) {}
|
||||
|
||||
~SkFontStyleSet_Fuchsia() override = default;
|
||||
|
||||
int count() override { return fStyles.size(); }
|
||||
|
||||
void getStyle(int index, SkFontStyle* style, SkString* styleName) override {
|
||||
SkASSERT(index >= 0 && index < static_cast<int>(fStyles.size()));
|
||||
if (style) *style = fStyles[index];
|
||||
|
||||
// We don't have style names. Return an empty name.
|
||||
if (styleName) styleName->reset();
|
||||
}
|
||||
|
||||
SkTypeface* createTypeface(int index) override {
|
||||
SkASSERT(index >= 0 && index < static_cast<int>(fStyles.size()));
|
||||
|
||||
if (fTypefaces.empty()) fTypefaces.resize(fStyles.size());
|
||||
|
||||
if (!fTypefaces[index]) {
|
||||
fTypefaces[index] = fFontManager->FetchTypeface(
|
||||
fFamilyName.c_str(), fStyles[index], /*bcp47=*/nullptr,
|
||||
/*bcp47Count=*/0, /*character=*/0,
|
||||
/*allow_fallback=*/false, /*exact_style_match=*/true);
|
||||
}
|
||||
|
||||
return SkSafeRef(fTypefaces[index].get());
|
||||
}
|
||||
|
||||
SkTypeface* matchStyle(const SkFontStyle& pattern) override { return matchStyleCSS3(pattern); }
|
||||
|
||||
private:
|
||||
sk_sp<SkFontMgr_Fuchsia> fFontManager;
|
||||
std::string fFamilyName;
|
||||
std::vector<SkFontStyle> fStyles;
|
||||
std::vector<sk_sp<SkTypeface>> fTypefaces;
|
||||
};
|
||||
|
||||
SkFontMgr_Fuchsia::SkFontMgr_Fuchsia(fuchsia::fonts::ProviderSyncPtr provider)
|
||||
: fFontProvider(std::move(provider)) {}
|
||||
|
||||
SkFontMgr_Fuchsia::~SkFontMgr_Fuchsia() = default;
|
||||
|
||||
int SkFontMgr_Fuchsia::onCountFamilies() const {
|
||||
// Family enumeration is not supported.
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SkFontMgr_Fuchsia::onGetFamilyName(int index, SkString* familyName) const {
|
||||
// Family enumeration is not supported.
|
||||
familyName->reset();
|
||||
}
|
||||
|
||||
SkFontStyleSet* SkFontMgr_Fuchsia::onCreateStyleSet(int index) const {
|
||||
// Family enumeration is not supported.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SkFontStyleSet* SkFontMgr_Fuchsia::onMatchFamily(const char familyName[]) const {
|
||||
fuchsia::fonts::FamilyInfoPtr familyInfo;
|
||||
int result = fFontProvider->GetFamilyInfo(familyName, &familyInfo);
|
||||
if (result != ZX_OK || !familyInfo) return nullptr;
|
||||
|
||||
std::vector<SkFontStyle> styles;
|
||||
for (auto& style : *(familyInfo->styles)) {
|
||||
styles.push_back(SkFontStyle(style.weight, style.width, FuchsiaToSkSlant(style.slant)));
|
||||
}
|
||||
|
||||
return new SkFontStyleSet_Fuchsia(sk_ref_sp(this), familyInfo->name, std::move(styles));
|
||||
}
|
||||
|
||||
SkTypeface* SkFontMgr_Fuchsia::onMatchFamilyStyle(const char familyName[],
|
||||
const SkFontStyle& style) const {
|
||||
sk_sp<SkTypeface> typeface =
|
||||
FetchTypeface(familyName, style, /*bcp47=*/nullptr,
|
||||
/*bcp47Count=*/0, /*character=*/0,
|
||||
/*allow_fallback=*/false, /*exact_style_match=*/false);
|
||||
return typeface.release();
|
||||
}
|
||||
|
||||
SkTypeface* SkFontMgr_Fuchsia::onMatchFamilyStyleCharacter(const char familyName[],
|
||||
const SkFontStyle& style,
|
||||
const char* bcp47[], int bcp47Count,
|
||||
SkUnichar character) const {
|
||||
sk_sp<SkTypeface> typeface =
|
||||
FetchTypeface(familyName, style, bcp47, bcp47Count, character, /*allow_fallback=*/true,
|
||||
/*exact_style_match=*/false);
|
||||
return typeface.release();
|
||||
}
|
||||
|
||||
SkTypeface* SkFontMgr_Fuchsia::onMatchFaceStyle(const SkTypeface*, const SkFontStyle&) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<SkTypeface> SkFontMgr_Fuchsia::onMakeFromData(sk_sp<SkData>, int ttcIndex) const {
|
||||
SkASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<SkTypeface> SkFontMgr_Fuchsia::onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> asset,
|
||||
int ttcIndex) const {
|
||||
return makeFromStream(std::move(asset), SkFontArguments().setCollectionIndex(ttcIndex));
|
||||
}
|
||||
|
||||
sk_sp<SkTypeface> SkFontMgr_Fuchsia::onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> asset,
|
||||
const SkFontArguments& args) const {
|
||||
return CreateTypefaceFromSkStream(std::move(asset), args, kNullTypefaceId);
|
||||
}
|
||||
|
||||
sk_sp<SkTypeface> SkFontMgr_Fuchsia::onMakeFromFile(const char path[], int ttcIndex) const {
|
||||
return makeFromStream(std::make_unique<SkFILEStream>(path), ttcIndex);
|
||||
}
|
||||
|
||||
sk_sp<SkTypeface> SkFontMgr_Fuchsia::onLegacyMakeTypeface(const char familyName[],
|
||||
SkFontStyle style) const {
|
||||
return sk_sp<SkTypeface>(matchFamilyStyle(familyName, style));
|
||||
}
|
||||
|
||||
sk_sp<SkTypeface> SkFontMgr_Fuchsia::FetchTypeface(const char familyName[],
|
||||
const SkFontStyle& style, const char* bcp47[],
|
||||
int bcp47Count, SkUnichar character,
|
||||
bool allow_fallback,
|
||||
bool exact_style_match) const {
|
||||
fuchsia::fonts::Request request;
|
||||
request.weight = style.weight();
|
||||
request.width = style.width();
|
||||
request.slant = SkToFuchsiaSlant(style.slant());
|
||||
request.language.reset(std::vector<fidl::StringPtr>(bcp47, bcp47 + bcp47Count));
|
||||
request.character = character;
|
||||
request.fallback_group = GetFallbackGroupByName(familyName);
|
||||
|
||||
// If family name is not specified or it is a generic fallback group name (e.g. "serif") then
|
||||
// enable fallback, otherwise pass the family name as is.
|
||||
if (!familyName || *familyName == '\0' ||
|
||||
request.fallback_group != fuchsia::fonts::FallbackGroup::NONE) {
|
||||
request.family = "";
|
||||
allow_fallback = true;
|
||||
} else {
|
||||
request.family = familyName;
|
||||
}
|
||||
|
||||
request.flags = 0;
|
||||
if (!allow_fallback) request.flags |= fuchsia::fonts::REQUEST_FLAG_NO_FALLBACK;
|
||||
if (exact_style_match) request.flags |= fuchsia::fonts::REQUEST_FLAG_EXACT_MATCH;
|
||||
|
||||
fuchsia::fonts::ResponsePtr response;
|
||||
int result = fFontProvider->GetFont(std::move(request), &response);
|
||||
if (result != ZX_OK) return nullptr;
|
||||
|
||||
// The service may return null response if there is no font matching the request.
|
||||
if (!response) return nullptr;
|
||||
|
||||
return GetOrCreateTypeface(TypefaceId{response->buffer_id, response->font_index},
|
||||
response->buffer);
|
||||
}
|
||||
|
||||
sk_sp<SkData> SkFontMgr_Fuchsia::GetOrCreateSkData(int bufferId,
|
||||
const fuchsia::mem::Buffer& buffer) const {
|
||||
fCacheMutex.assertHeld();
|
||||
|
||||
auto iter = fBufferCache.find(bufferId);
|
||||
if (iter != fBufferCache.end()) {
|
||||
return sk_ref_sp(iter->second);
|
||||
}
|
||||
auto font_mgr = sk_ref_sp(this);
|
||||
auto data = MakeSkDataFromBuffer(buffer,
|
||||
[font_mgr, bufferId]() { font_mgr->OnSkDataDeleted(bufferId); });
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
fBufferCache[bufferId] = data.get();
|
||||
return data;
|
||||
}
|
||||
|
||||
void SkFontMgr_Fuchsia::OnSkDataDeleted(int bufferId) const {
|
||||
SK_UNUSED bool wasFound = fBufferCache.erase(bufferId) != 0;
|
||||
SkASSERT(wasFound);
|
||||
}
|
||||
|
||||
static bool FindByTypefaceId(SkTypeface* cachedTypeface, void* ctx) {
|
||||
SkTypeface_Fuchsia* cachedFuchsiaTypeface = static_cast<SkTypeface_Fuchsia*>(cachedTypeface);
|
||||
TypefaceId* id = static_cast<TypefaceId*>(ctx);
|
||||
|
||||
return cachedFuchsiaTypeface->id() == *id;
|
||||
}
|
||||
|
||||
sk_sp<SkTypeface> SkFontMgr_Fuchsia::GetOrCreateTypeface(TypefaceId id,
|
||||
const fuchsia::mem::Buffer& buffer) const {
|
||||
SkAutoMutexAcquire mutexLock(fCacheMutex);
|
||||
|
||||
SkTypeface* cached = fTypefaceCache.findByProcAndRef(FindByTypefaceId, &id);
|
||||
if (cached) return sk_sp<SkTypeface>(cached);
|
||||
|
||||
sk_sp<SkData> data = GetOrCreateSkData(id.bufferId, buffer);
|
||||
if (!data) return nullptr;
|
||||
|
||||
auto result = CreateTypefaceFromSkData(std::move(data), id);
|
||||
fTypefaceCache.add(result.get());
|
||||
return result;
|
||||
}
|
||||
|
||||
SK_API sk_sp<SkFontMgr> SkFontMgr_New_Fuchsia(fuchsia::fonts::ProviderSyncPtr provider) {
|
||||
return sk_make_sp<SkFontMgr_Fuchsia>(std::move(provider));
|
||||
}
|
Loading…
Reference in New Issue
Block a user