1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/components/font/flutter_font_loader.h"
17
18 #include "base/network/download_manager.h"
19 #include "core/components/font/flutter_font_collection.h"
20 #include "core/pipeline/base/flutter_render_context.h"
21
22 namespace OHOS::Ace {
23
FlutterFontLoader(const std::string & familyName,const std::string & familySrc)24 FlutterFontLoader::FlutterFontLoader(const std::string& familyName, const std::string& familySrc)
25 : FontLoader(familyName, familySrc) {}
26
AddFont(const RefPtr<PipelineBase> & context)27 void FlutterFontLoader::AddFont(const RefPtr<PipelineBase>& context)
28 {
29 if (familySrc_.empty()) {
30 return;
31 }
32
33 if (familySrc_.substr(0, 4) == FONT_SRC_NETWORK) {
34 // Get font from NetWork.
35 LoadFromNetwork(context);
36 } else {
37 // Get font from asset.
38 LoadFromAsset(context);
39 }
40 }
41
LoadFromNetwork(const OHOS::Ace::RefPtr<OHOS::Ace::PipelineBase> & context)42 void FlutterFontLoader::LoadFromNetwork(const OHOS::Ace::RefPtr<OHOS::Ace::PipelineBase>& context)
43 {
44 auto weakContext = AceType::WeakClaim(AceType::RawPtr(context));
45 context->GetTaskExecutor()->PostTask([weak = AceType::WeakClaim(this), weakContext] {
46 auto fontLoader = weak.Upgrade();
47 auto context = weakContext.Upgrade();
48 if (!fontLoader || !context) {
49 return;
50 }
51 std::vector<uint8_t> fontData;
52 if (!DownloadManager::GetInstance().Download(fontLoader->familySrc_, fontData) || fontData.empty()) {
53 return;
54 }
55 context->GetTaskExecutor()->PostTask([fontData, weak] {
56 auto fontLoader = weak.Upgrade();
57 if (!fontLoader) {
58 return;
59 }
60 // Load font.
61 FlutterFontCollection::GetInstance().LoadFontFromList(
62 fontData.data(), fontData.size(), fontLoader->familyName_);
63 fontLoader->isLoaded_ = true;
64
65 // When font is already loaded, notify all which used this font.
66 for (const auto& [node, callback] : fontLoader->callbacks_) {
67 if (callback) {
68 callback();
69 }
70 }
71 fontLoader->callbacks_.clear();
72 if (fontLoader->variationChanged_) {
73 fontLoader->variationChanged_();
74 }
75 }, TaskExecutor::TaskType::UI);
76 }, TaskExecutor::TaskType::BACKGROUND);
77 }
78
LoadFromAsset(const OHOS::Ace::RefPtr<OHOS::Ace::PipelineBase> & context)79 void FlutterFontLoader::LoadFromAsset(const OHOS::Ace::RefPtr<OHOS::Ace::PipelineBase>& context)
80 {
81 auto weakContext = AceType::WeakClaim(AceType::RawPtr(context));
82 context->GetTaskExecutor()->PostTask([weak = AceType::WeakClaim(this), weakContext] {
83 auto fontLoader = weak.Upgrade();
84 auto context = weakContext.Upgrade();
85 if (!fontLoader || !context) {
86 return;
87 }
88 auto assetManager = context->GetAssetManager();
89 if (!assetManager) {
90 LOGE("No asset manager!");
91 return;
92 }
93 std::string assetSrc(fontLoader->familySrc_);
94 if (assetSrc[0] == '/') {
95 assetSrc = assetSrc.substr(1); // get the asset src without '/'.
96 } else if (assetSrc[0] == '.' && assetSrc.size() > 2 && assetSrc[1] == '/') {
97 assetSrc = assetSrc.substr(2); // get the asset src without './'.
98 }
99 auto assetData = assetManager->GetAsset(assetSrc);
100 if (!assetData) {
101 LOGE("No asset data!");
102 return;
103 }
104
105 context->GetTaskExecutor()->PostTask([assetData, weak] {
106 auto fontLoader = weak.Upgrade();
107 if (!fontLoader) {
108 return;
109 }
110 // Load font.
111 FlutterFontCollection::GetInstance().LoadFontFromList(
112 assetData->GetData(), assetData->GetSize(), fontLoader->familyName_);
113 fontLoader->isLoaded_ = true;
114
115 for (const auto& [node, callback] : fontLoader->callbacks_) {
116 if (callback) {
117 callback();
118 }
119 }
120 fontLoader->callbacks_.clear();
121 if (fontLoader->variationChanged_) {
122 fontLoader->variationChanged_();
123 }
124 }, TaskExecutor::TaskType::UI);
125 }, TaskExecutor::TaskType::BACKGROUND);
126 }
127
128 } // namespace OHOS::Ace
129