SkFontMgr_fuchsia.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. /*
  2. * Copyright 2018 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "include/ports/SkFontMgr_fuchsia.h"
  8. #include <fuchsia/fonts/cpp/fidl.h>
  9. #include <lib/zx/vmar.h>
  10. #include <strings.h>
  11. #include <memory>
  12. #include <unordered_map>
  13. #include "src/core/SkFontDescriptor.h"
  14. #include "src/ports/SkFontMgr_custom.h"
  15. #include "include/core/SkFontMgr.h"
  16. #include "include/core/SkStream.h"
  17. #include "include/core/SkTypeface.h"
  18. #include "src/core/SkTypefaceCache.h"
  19. void UnmapMemory(const void* buffer, uint64_t size) {
  20. static_assert(sizeof(void*) == sizeof(uint64_t), "pointers aren't 64-bit");
  21. zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(buffer), size);
  22. }
  23. struct ReleaseSkDataContext {
  24. uint64_t fBufferSize;
  25. std::function<void()> releaseProc;
  26. ReleaseSkDataContext(uint64_t bufferSize, const std::function<void()>& releaseProc)
  27. : fBufferSize(bufferSize), releaseProc(releaseProc) {}
  28. };
  29. void ReleaseSkData(const void* buffer, void* context) {
  30. auto releaseSkDataContext = reinterpret_cast<ReleaseSkDataContext*>(context);
  31. SkASSERT(releaseSkDataContext);
  32. UnmapMemory(buffer, releaseSkDataContext->fBufferSize);
  33. releaseSkDataContext->releaseProc();
  34. delete releaseSkDataContext;
  35. }
  36. sk_sp<SkData> MakeSkDataFromBuffer(const fuchsia::mem::Buffer& data,
  37. std::function<void()> release_proc) {
  38. uint64_t size = data.size;
  39. uintptr_t buffer = 0;
  40. zx_status_t status = zx::vmar::root_self()->map(0, data.vmo, 0, size, ZX_VM_PERM_READ, &buffer);
  41. if (status != ZX_OK) return nullptr;
  42. auto context = new ReleaseSkDataContext(size, release_proc);
  43. return SkData::MakeWithProc(reinterpret_cast<void*>(buffer), size, ReleaseSkData, context);
  44. }
  45. fuchsia::fonts::Slant SkToFuchsiaSlant(SkFontStyle::Slant slant) {
  46. switch (slant) {
  47. case SkFontStyle::kOblique_Slant:
  48. return fuchsia::fonts::Slant::OBLIQUE;
  49. case SkFontStyle::kItalic_Slant:
  50. return fuchsia::fonts::Slant::ITALIC;
  51. case SkFontStyle::kUpright_Slant:
  52. default:
  53. return fuchsia::fonts::Slant::UPRIGHT;
  54. }
  55. }
  56. SkFontStyle::Slant FuchsiaToSkSlant(fuchsia::fonts::Slant slant) {
  57. switch (slant) {
  58. case fuchsia::fonts::Slant::OBLIQUE:
  59. return SkFontStyle::kOblique_Slant;
  60. case fuchsia::fonts::Slant::ITALIC:
  61. return SkFontStyle::kItalic_Slant;
  62. case fuchsia::fonts::Slant::UPRIGHT:
  63. default:
  64. return SkFontStyle::kUpright_Slant;
  65. }
  66. }
  67. constexpr struct {
  68. const char* fName;
  69. fuchsia::fonts::FallbackGroup fFallbackGroup;
  70. } kFallbackGroupsByName[] = {
  71. {"serif", fuchsia::fonts::FallbackGroup::SERIF},
  72. {"sans", fuchsia::fonts::FallbackGroup::SANS_SERIF},
  73. {"sans-serif", fuchsia::fonts::FallbackGroup::SANS_SERIF},
  74. {"mono", fuchsia::fonts::FallbackGroup::MONOSPACE},
  75. {"monospace", fuchsia::fonts::FallbackGroup::MONOSPACE},
  76. {"cursive", fuchsia::fonts::FallbackGroup::CURSIVE},
  77. {"fantasy", fuchsia::fonts::FallbackGroup::FANTASY},
  78. };
  79. fuchsia::fonts::FallbackGroup GetFallbackGroupByName(const char* name) {
  80. if (!name) return fuchsia::fonts::FallbackGroup::NONE;
  81. for (auto& group : kFallbackGroupsByName) {
  82. if (strcasecmp(group.fName, name) == 0) {
  83. return group.fFallbackGroup;
  84. }
  85. }
  86. return fuchsia::fonts::FallbackGroup::NONE;
  87. }
  88. struct TypefaceId {
  89. uint32_t bufferId;
  90. uint32_t ttcIndex;
  91. bool operator==(TypefaceId& other) {
  92. return std::tie(bufferId, ttcIndex) == std::tie(other.bufferId, other.ttcIndex);
  93. }
  94. }
  95. constexpr kNullTypefaceId = {0xFFFFFFFF, 0xFFFFFFFF};
  96. class SkTypeface_Fuchsia : public SkTypeface_Stream {
  97. public:
  98. SkTypeface_Fuchsia(std::unique_ptr<SkFontData> fontData, const SkFontStyle& style,
  99. bool isFixedPitch, const SkString familyName, TypefaceId id)
  100. : SkTypeface_Stream(std::move(fontData), style, isFixedPitch,
  101. /*sys_font=*/true, familyName)
  102. , fId(id) {}
  103. TypefaceId id() { return fId; }
  104. private:
  105. TypefaceId fId;
  106. };
  107. sk_sp<SkTypeface> CreateTypefaceFromSkStream(std::unique_ptr<SkStreamAsset> stream,
  108. const SkFontArguments& args, TypefaceId id) {
  109. using Scanner = SkTypeface_FreeType::Scanner;
  110. Scanner scanner;
  111. bool isFixedPitch;
  112. SkFontStyle style;
  113. SkString name;
  114. Scanner::AxisDefinitions axisDefinitions;
  115. if (!scanner.scanFont(stream.get(), args.getCollectionIndex(), &name, &style, &isFixedPitch,
  116. &axisDefinitions)) {
  117. return nullptr;
  118. }
  119. const SkFontArguments::VariationPosition position = args.getVariationDesignPosition();
  120. SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
  121. Scanner::computeAxisValues(axisDefinitions, position, axisValues, name);
  122. auto fontData = std::make_unique<SkFontData>(std::move(stream), args.getCollectionIndex(),
  123. axisValues.get(), axisDefinitions.count());
  124. return sk_make_sp<SkTypeface_Fuchsia>(std::move(fontData), style, isFixedPitch, name, id);
  125. }
  126. sk_sp<SkTypeface> CreateTypefaceFromSkData(sk_sp<SkData> data, TypefaceId id) {
  127. return CreateTypefaceFromSkStream(std::make_unique<SkMemoryStream>(std::move(data)),
  128. SkFontArguments().setCollectionIndex(id.ttcIndex), id);
  129. }
  130. class SkFontMgr_Fuchsia final : public SkFontMgr {
  131. public:
  132. SkFontMgr_Fuchsia(fuchsia::fonts::ProviderSyncPtr provider);
  133. ~SkFontMgr_Fuchsia() override;
  134. protected:
  135. // SkFontMgr overrides.
  136. int onCountFamilies() const override;
  137. void onGetFamilyName(int index, SkString* familyName) const override;
  138. SkFontStyleSet* onMatchFamily(const char familyName[]) const override;
  139. SkFontStyleSet* onCreateStyleSet(int index) const override;
  140. SkTypeface* onMatchFamilyStyle(const char familyName[], const SkFontStyle&) const override;
  141. SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
  142. const char* bcp47[], int bcp47Count,
  143. SkUnichar character) const override;
  144. SkTypeface* onMatchFaceStyle(const SkTypeface*, const SkFontStyle&) const override;
  145. sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int ttcIndex) const override;
  146. sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>,
  147. int ttcIndex) const override;
  148. sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>,
  149. const SkFontArguments&) const override;
  150. sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override;
  151. sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle) const override;
  152. private:
  153. friend class SkFontStyleSet_Fuchsia;
  154. sk_sp<SkTypeface> FetchTypeface(const char familyName[], const SkFontStyle& style,
  155. const char* bcp47[], int bcp47Count, SkUnichar character,
  156. bool allow_fallback, bool exact_style_match) const;
  157. sk_sp<SkData> GetOrCreateSkData(int bufferId, const fuchsia::mem::Buffer& buffer) const;
  158. void OnSkDataDeleted(int bufferId) const;
  159. sk_sp<SkTypeface> GetOrCreateTypeface(TypefaceId id, const fuchsia::mem::Buffer& buffer) const;
  160. mutable fuchsia::fonts::ProviderSyncPtr fFontProvider;
  161. mutable SkMutex fCacheMutex;
  162. // Must be accessed only with fCacheMutex acquired.
  163. mutable std::unordered_map<int, SkData*> fBufferCache;
  164. mutable SkTypefaceCache fTypefaceCache;
  165. };
  166. class SkFontStyleSet_Fuchsia : public SkFontStyleSet {
  167. public:
  168. SkFontStyleSet_Fuchsia(sk_sp<SkFontMgr_Fuchsia> font_manager, std::string familyName,
  169. std::vector<SkFontStyle> styles)
  170. : fFontManager(font_manager), fFamilyName(familyName), fStyles(styles) {}
  171. ~SkFontStyleSet_Fuchsia() override = default;
  172. int count() override { return fStyles.size(); }
  173. void getStyle(int index, SkFontStyle* style, SkString* styleName) override {
  174. SkASSERT(index >= 0 && index < static_cast<int>(fStyles.size()));
  175. if (style) *style = fStyles[index];
  176. // We don't have style names. Return an empty name.
  177. if (styleName) styleName->reset();
  178. }
  179. SkTypeface* createTypeface(int index) override {
  180. SkASSERT(index >= 0 && index < static_cast<int>(fStyles.size()));
  181. if (fTypefaces.empty()) fTypefaces.resize(fStyles.size());
  182. if (!fTypefaces[index]) {
  183. fTypefaces[index] = fFontManager->FetchTypeface(
  184. fFamilyName.c_str(), fStyles[index], /*bcp47=*/nullptr,
  185. /*bcp47Count=*/0, /*character=*/0,
  186. /*allow_fallback=*/false, /*exact_style_match=*/true);
  187. }
  188. return SkSafeRef(fTypefaces[index].get());
  189. }
  190. SkTypeface* matchStyle(const SkFontStyle& pattern) override { return matchStyleCSS3(pattern); }
  191. private:
  192. sk_sp<SkFontMgr_Fuchsia> fFontManager;
  193. std::string fFamilyName;
  194. std::vector<SkFontStyle> fStyles;
  195. std::vector<sk_sp<SkTypeface>> fTypefaces;
  196. };
  197. SkFontMgr_Fuchsia::SkFontMgr_Fuchsia(fuchsia::fonts::ProviderSyncPtr provider)
  198. : fFontProvider(std::move(provider)) {}
  199. SkFontMgr_Fuchsia::~SkFontMgr_Fuchsia() = default;
  200. int SkFontMgr_Fuchsia::onCountFamilies() const {
  201. // Family enumeration is not supported.
  202. return 0;
  203. }
  204. void SkFontMgr_Fuchsia::onGetFamilyName(int index, SkString* familyName) const {
  205. // Family enumeration is not supported.
  206. familyName->reset();
  207. }
  208. SkFontStyleSet* SkFontMgr_Fuchsia::onCreateStyleSet(int index) const {
  209. // Family enumeration is not supported.
  210. return nullptr;
  211. }
  212. SkFontStyleSet* SkFontMgr_Fuchsia::onMatchFamily(const char familyName[]) const {
  213. fuchsia::fonts::FamilyInfoPtr familyInfo;
  214. int result = fFontProvider->GetFamilyInfo(familyName, &familyInfo);
  215. if (result != ZX_OK || !familyInfo) return nullptr;
  216. std::vector<SkFontStyle> styles;
  217. for (auto& style : familyInfo->styles) {
  218. styles.push_back(SkFontStyle(style.weight, style.width, FuchsiaToSkSlant(style.slant)));
  219. }
  220. return new SkFontStyleSet_Fuchsia(sk_ref_sp(this), familyInfo->name, std::move(styles));
  221. }
  222. SkTypeface* SkFontMgr_Fuchsia::onMatchFamilyStyle(const char familyName[],
  223. const SkFontStyle& style) const {
  224. sk_sp<SkTypeface> typeface =
  225. FetchTypeface(familyName, style, /*bcp47=*/nullptr,
  226. /*bcp47Count=*/0, /*character=*/0,
  227. /*allow_fallback=*/false, /*exact_style_match=*/false);
  228. return typeface.release();
  229. }
  230. SkTypeface* SkFontMgr_Fuchsia::onMatchFamilyStyleCharacter(const char familyName[],
  231. const SkFontStyle& style,
  232. const char* bcp47[], int bcp47Count,
  233. SkUnichar character) const {
  234. sk_sp<SkTypeface> typeface =
  235. FetchTypeface(familyName, style, bcp47, bcp47Count, character, /*allow_fallback=*/true,
  236. /*exact_style_match=*/false);
  237. return typeface.release();
  238. }
  239. SkTypeface* SkFontMgr_Fuchsia::onMatchFaceStyle(const SkTypeface*, const SkFontStyle&) const {
  240. return nullptr;
  241. }
  242. sk_sp<SkTypeface> SkFontMgr_Fuchsia::onMakeFromData(sk_sp<SkData>, int ttcIndex) const {
  243. SkASSERT(false);
  244. return nullptr;
  245. }
  246. sk_sp<SkTypeface> SkFontMgr_Fuchsia::onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> asset,
  247. int ttcIndex) const {
  248. return makeFromStream(std::move(asset), SkFontArguments().setCollectionIndex(ttcIndex));
  249. }
  250. sk_sp<SkTypeface> SkFontMgr_Fuchsia::onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> asset,
  251. const SkFontArguments& args) const {
  252. return CreateTypefaceFromSkStream(std::move(asset), args, kNullTypefaceId);
  253. }
  254. sk_sp<SkTypeface> SkFontMgr_Fuchsia::onMakeFromFile(const char path[], int ttcIndex) const {
  255. return makeFromStream(std::make_unique<SkFILEStream>(path), ttcIndex);
  256. }
  257. sk_sp<SkTypeface> SkFontMgr_Fuchsia::onLegacyMakeTypeface(const char familyName[],
  258. SkFontStyle style) const {
  259. return sk_sp<SkTypeface>(matchFamilyStyle(familyName, style));
  260. }
  261. sk_sp<SkTypeface> SkFontMgr_Fuchsia::FetchTypeface(const char familyName[],
  262. const SkFontStyle& style, const char* bcp47[],
  263. int bcp47Count, SkUnichar character,
  264. bool allow_fallback,
  265. bool exact_style_match) const {
  266. fuchsia::fonts::Request request;
  267. request.weight = style.weight();
  268. request.width = style.width();
  269. request.slant = SkToFuchsiaSlant(style.slant());
  270. request.language.reset(std::vector<std::string>(bcp47, bcp47 + bcp47Count));
  271. request.character = character;
  272. request.fallback_group = GetFallbackGroupByName(familyName);
  273. // If family name is not specified or it is a generic fallback group name (e.g. "serif") then
  274. // enable fallback, otherwise pass the family name as is.
  275. if (!familyName || *familyName == '\0' ||
  276. request.fallback_group != fuchsia::fonts::FallbackGroup::NONE) {
  277. request.family = "";
  278. allow_fallback = true;
  279. } else {
  280. request.family = familyName;
  281. }
  282. request.flags = 0;
  283. if (!allow_fallback) request.flags |= fuchsia::fonts::REQUEST_FLAG_NO_FALLBACK;
  284. if (exact_style_match) request.flags |= fuchsia::fonts::REQUEST_FLAG_EXACT_MATCH;
  285. fuchsia::fonts::ResponsePtr response;
  286. int result = fFontProvider->GetFont(std::move(request), &response);
  287. if (result != ZX_OK) return nullptr;
  288. // The service may return null response if there is no font matching the request.
  289. if (!response) return nullptr;
  290. return GetOrCreateTypeface(TypefaceId{response->buffer_id, response->font_index},
  291. response->buffer);
  292. }
  293. sk_sp<SkData> SkFontMgr_Fuchsia::GetOrCreateSkData(int bufferId,
  294. const fuchsia::mem::Buffer& buffer) const {
  295. fCacheMutex.assertHeld();
  296. auto iter = fBufferCache.find(bufferId);
  297. if (iter != fBufferCache.end()) {
  298. return sk_ref_sp(iter->second);
  299. }
  300. auto font_mgr = sk_ref_sp(this);
  301. auto data = MakeSkDataFromBuffer(buffer,
  302. [font_mgr, bufferId]() { font_mgr->OnSkDataDeleted(bufferId); });
  303. if (!data) {
  304. return nullptr;
  305. }
  306. fBufferCache[bufferId] = data.get();
  307. return data;
  308. }
  309. void SkFontMgr_Fuchsia::OnSkDataDeleted(int bufferId) const {
  310. SK_UNUSED bool wasFound = fBufferCache.erase(bufferId) != 0;
  311. SkASSERT(wasFound);
  312. }
  313. static bool FindByTypefaceId(SkTypeface* cachedTypeface, void* ctx) {
  314. SkTypeface_Fuchsia* cachedFuchsiaTypeface = static_cast<SkTypeface_Fuchsia*>(cachedTypeface);
  315. TypefaceId* id = static_cast<TypefaceId*>(ctx);
  316. return cachedFuchsiaTypeface->id() == *id;
  317. }
  318. sk_sp<SkTypeface> SkFontMgr_Fuchsia::GetOrCreateTypeface(TypefaceId id,
  319. const fuchsia::mem::Buffer& buffer) const {
  320. SkAutoMutexExclusive mutexLock(fCacheMutex);
  321. sk_sp<SkTypeface> cached = fTypefaceCache.findByProcAndRef(FindByTypefaceId, &id);
  322. if (cached) return cached;
  323. sk_sp<SkData> data = GetOrCreateSkData(id.bufferId, buffer);
  324. if (!data) return nullptr;
  325. auto result = CreateTypefaceFromSkData(std::move(data), id);
  326. fTypefaceCache.add(result);
  327. return result;
  328. }
  329. SK_API sk_sp<SkFontMgr> SkFontMgr_New_Fuchsia(fuchsia::fonts::ProviderSyncPtr provider) {
  330. return sk_make_sp<SkFontMgr_Fuchsia>(std::move(provider));
  331. }