123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406 |
- /*
- * 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 "include/ports/SkFontMgr_fuchsia.h"
- #include <fuchsia/fonts/cpp/fidl.h>
- #include <lib/zx/vmar.h>
- #include <strings.h>
- #include <memory>
- #include <unordered_map>
- #include "src/core/SkFontDescriptor.h"
- #include "src/ports/SkFontMgr_custom.h"
- #include "include/core/SkFontMgr.h"
- #include "include/core/SkStream.h"
- #include "include/core/SkTypeface.h"
- #include "src/core/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<std::string>(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 {
- SkAutoMutexExclusive mutexLock(fCacheMutex);
- sk_sp<SkTypeface> cached = fTypefaceCache.findByProcAndRef(FindByTypefaceId, &id);
- if (cached) return cached;
- sk_sp<SkData> data = GetOrCreateSkData(id.bufferId, buffer);
- if (!data) return nullptr;
- auto result = CreateTypefaceFromSkData(std::move(data), id);
- fTypefaceCache.add(result);
- return result;
- }
- SK_API sk_sp<SkFontMgr> SkFontMgr_New_Fuchsia(fuchsia::fonts::ProviderSyncPtr provider) {
- return sk_make_sp<SkFontMgr_Fuchsia>(std::move(provider));
- }
|