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
13namespace flutter {
14
15namespace {
16
17void MappingReleaseProc(const void* ptr, void* context) {
18 delete reinterpret_cast<fml::Mapping*>(context);
19}
20
21} // anonymous namespace
22
23AssetManagerFontProvider::AssetManagerFontProvider(
24 std::shared_ptr<AssetManager> asset_manager)
25 : asset_manager_(asset_manager) {}
26
27AssetManagerFontProvider::~AssetManagerFontProvider() = default;
28
29// |FontAssetProvider|
30size_t AssetManagerFontProvider::GetFamilyCount() const {
31 return family_names_.size();
32}
33
34// |FontAssetProvider|
35std::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|
41SkFontStyleSet* 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
51void 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,
60 sk_make_sp<AssetManagerFontStyleSet>(asset_manager_, family_name));
61 family_it = registered_families_.emplace(value).first;
62 }
63
64 family_it->second->registerAsset(asset);
65}
66
67AssetManagerFontStyleSet::AssetManagerFontStyleSet(
68 std::shared_ptr<AssetManager> asset_manager,
69 std::string family_name)
70 : asset_manager_(asset_manager), family_name_(family_name) {}
71
72AssetManagerFontStyleSet::~AssetManagerFontStyleSet() = default;
73
74void AssetManagerFontStyleSet::registerAsset(std::string asset) {
75 assets_.emplace_back(asset);
76}
77
78int AssetManagerFontStyleSet::count() {
79 return assets_.size();
80}
81
82void AssetManagerFontStyleSet::getStyle(int index,
83 SkFontStyle* style,
84 SkString* name) {
85 FML_DCHECK(index < static_cast<int>(assets_.size()));
86 if (style) {
87 sk_sp<SkTypeface> typeface(createTypeface(index));
88 if (typeface) {
89 *style = typeface->fontStyle();
90 }
91 }
92 if (name) {
93 *name = family_name_.c_str();
94 }
95}
96
97SkTypeface* AssetManagerFontStyleSet::createTypeface(int i) {
98 size_t index = i;
99 if (index >= assets_.size()) {
100 return nullptr;
101 }
102
103 TypefaceAsset& asset = assets_[index];
104 if (!asset.typeface) {
105 std::unique_ptr<fml::Mapping> asset_mapping =
106 asset_manager_->GetAsMapping(asset.asset);
107 if (asset_mapping == nullptr) {
108 return nullptr;
109 }
110
111 fml::Mapping* asset_mapping_ptr = asset_mapping.release();
112 sk_sp<SkData> asset_data = SkData::MakeWithProc(
113 asset_mapping_ptr->GetMapping(), asset_mapping_ptr->GetSize(),
114 MappingReleaseProc, asset_mapping_ptr);
115 std::unique_ptr<SkMemoryStream> stream = SkMemoryStream::Make(asset_data);
116
117 // Ownership of the stream is transferred.
118 asset.typeface = SkTypeface::MakeFromStream(std::move(stream));
119 if (!asset.typeface) {
120 return nullptr;
121 }
122 }
123
124 return SkRef(asset.typeface.get());
125}
126
127SkTypeface* AssetManagerFontStyleSet::matchStyle(const SkFontStyle& pattern) {
128 return matchStyleCSS3(pattern);
129}
130
131AssetManagerFontStyleSet::TypefaceAsset::TypefaceAsset(std::string a)
132 : asset(std::move(a)) {}
133
134AssetManagerFontStyleSet::TypefaceAsset::TypefaceAsset(
135 const AssetManagerFontStyleSet::TypefaceAsset& other) = default;
136
137AssetManagerFontStyleSet::TypefaceAsset::~TypefaceAsset() = default;
138
139} // namespace flutter
140