1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "flutter/lib/ui/text/asset_manager_font_provider.h"
6
7 #include "flutter/fml/logging.h"
8 #include "third_party/skia/include/core/SkData.h"
9 #include "third_party/skia/include/core/SkStream.h"
10 #include "third_party/skia/include/core/SkString.h"
11 #include "third_party/skia/include/core/SkTypeface.h"
12
13 namespace flutter {
14
15 namespace {
16
MappingReleaseProc(const void * ptr,void * context)17 void MappingReleaseProc(const void* ptr, void* context) {
18 delete reinterpret_cast<fml::Mapping*>(context);
19 }
20
21 } // anonymous namespace
22
AssetManagerFontProvider(std::shared_ptr<AssetManager> asset_manager)23 AssetManagerFontProvider::AssetManagerFontProvider(
24 std::shared_ptr<AssetManager> asset_manager)
25 : asset_manager_(asset_manager) {}
26
27 AssetManagerFontProvider::~AssetManagerFontProvider() = default;
28
29 // |FontAssetProvider|
GetFamilyCount() const30 size_t AssetManagerFontProvider::GetFamilyCount() const {
31 return family_names_.size();
32 }
33
34 // |FontAssetProvider|
GetFamilyName(int index) const35 std::string AssetManagerFontProvider::GetFamilyName(int index) const {
36 FML_DCHECK(index >= 0 && static_cast<size_t>(index) < family_names_.size());
37 return family_names_[index];
38 }
39
40 // |FontAssetProvider|
MatchFamily(const std::string & family_name)41 SkFontStyleSet* AssetManagerFontProvider::MatchFamily(
42 const std::string& family_name) {
43 auto found = registered_families_.find(CanonicalFamilyName(family_name));
44 if (found == registered_families_.end()) {
45 return nullptr;
46 }
47 sk_sp<SkFontStyleSet> font_style_set = found->second;
48 return font_style_set.release();
49 }
50
RegisterAsset(std::string family_name,std::string asset)51 void AssetManagerFontProvider::RegisterAsset(std::string family_name,
52 std::string asset) {
53 std::string canonical_name = CanonicalFamilyName(family_name);
54 auto family_it = registered_families_.find(canonical_name);
55
56 if (family_it == registered_families_.end()) {
57 family_names_.push_back(family_name);
58 auto value = std::make_pair(
59 canonical_name, sk_make_sp<AssetManagerFontStyleSet>(asset_manager_));
60 family_it = registered_families_.emplace(value).first;
61 }
62
63 family_it->second->registerAsset(asset);
64 }
65
AssetManagerFontStyleSet(std::shared_ptr<AssetManager> asset_manager)66 AssetManagerFontStyleSet::AssetManagerFontStyleSet(
67 std::shared_ptr<AssetManager> asset_manager)
68 : asset_manager_(asset_manager) {}
69
70 AssetManagerFontStyleSet::~AssetManagerFontStyleSet() = default;
71
registerAsset(std::string asset)72 void AssetManagerFontStyleSet::registerAsset(std::string asset) {
73 assets_.emplace_back(asset);
74 }
75
count()76 int AssetManagerFontStyleSet::count() {
77 return assets_.size();
78 }
79
getStyle(int index,SkFontStyle *,SkString * style)80 void AssetManagerFontStyleSet::getStyle(int index,
81 SkFontStyle*,
82 SkString* style) {
83 FML_DCHECK(false);
84 }
85
createTypeface(int i)86 SkTypeface* AssetManagerFontStyleSet::createTypeface(int i) {
87 size_t index = i;
88 if (index >= assets_.size())
89 return nullptr;
90
91 TypefaceAsset& asset = assets_[index];
92 if (!asset.typeface) {
93 std::unique_ptr<fml::Mapping> asset_mapping =
94 asset_manager_->GetAsMapping(asset.asset);
95 if (asset_mapping == nullptr) {
96 return nullptr;
97 }
98
99 fml::Mapping* asset_mapping_ptr = asset_mapping.release();
100 sk_sp<SkData> asset_data = SkData::MakeWithProc(
101 asset_mapping_ptr->GetMapping(), asset_mapping_ptr->GetSize(),
102 MappingReleaseProc, asset_mapping_ptr);
103 std::unique_ptr<SkMemoryStream> stream = SkMemoryStream::Make(asset_data);
104
105 // Ownership of the stream is transferred.
106 asset.typeface = SkTypeface::MakeFromStream(std::move(stream));
107 if (!asset.typeface)
108 return nullptr;
109 }
110
111 return SkRef(asset.typeface.get());
112 }
113
matchStyle(const SkFontStyle & pattern)114 SkTypeface* AssetManagerFontStyleSet::matchStyle(const SkFontStyle& pattern) {
115 if (assets_.empty())
116 return nullptr;
117
118 for (const TypefaceAsset& asset : assets_)
119 if (asset.typeface && asset.typeface->fontStyle() == pattern)
120 return SkRef(asset.typeface.get());
121
122 return SkRef(assets_[0].typeface.get());
123 }
124
TypefaceAsset(std::string a)125 AssetManagerFontStyleSet::TypefaceAsset::TypefaceAsset(std::string a)
126 : asset(std::move(a)) {}
127
128 AssetManagerFontStyleSet::TypefaceAsset::TypefaceAsset(
129 const AssetManagerFontStyleSet::TypefaceAsset& other) = default;
130
131 AssetManagerFontStyleSet::TypefaceAsset::~TypefaceAsset() = default;
132
133 } // namespace flutter
134