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/rosen_font_loader.h"
17
18 #include "base/network/download_manager.h"
19 #include "core/components/font/rosen_font_collection.h"
20 #include "core/pipeline/base/rosen_render_context.h"
21
22 namespace OHOS::Ace {
23
24 const std::regex RAWFILE_APP_RES_PATH_REGEX(R"(^resource://RAWFILE/(.*)$)");
25 constexpr uint32_t RAWFILE_RESOURCE_MATCH_SIZE = 2;
26
RosenFontLoader(const std::string & familyName,const std::string & familySrc)27 RosenFontLoader::RosenFontLoader(const std::string& familyName, const std::string& familySrc)
28 : FontLoader(familyName, familySrc) {}
29
AddFont(const RefPtr<PipelineBase> & context)30 void RosenFontLoader::AddFont(const RefPtr<PipelineBase>& context)
31 {
32 if (familySrc_.empty()) {
33 return;
34 }
35
36 if (familySrc_.substr(0, strlen(FONT_SRC_NETWORK)) == FONT_SRC_NETWORK) {
37 // Get font from NetWork.
38 LoadFromNetwork(context);
39 } else if (familySrc_.substr(0, strlen(FONT_SRC_RESOURCE)) == FONT_SRC_RESOURCE) {
40 // Get font from Resource.
41 LoadFromResource(context);
42 } else {
43 // Get font from asset.
44 LoadFromAsset(context);
45 }
46 }
47
LoadFromNetwork(const OHOS::Ace::RefPtr<OHOS::Ace::PipelineBase> & context)48 void RosenFontLoader::LoadFromNetwork(const OHOS::Ace::RefPtr<OHOS::Ace::PipelineBase>& context)
49 {
50 auto weakContext = AceType::WeakClaim(AceType::RawPtr(context));
51 context->GetTaskExecutor()->PostTask(
52 [weak = AceType::WeakClaim(this), weakContext] {
53 auto fontLoader = weak.Upgrade();
54 auto context = weakContext.Upgrade();
55 if (!fontLoader || !context) {
56 return;
57 }
58 std::vector<uint8_t> fontData;
59 if (!DownloadManager::GetInstance().Download(fontLoader->familySrc_, fontData) || fontData.empty()) {
60 return;
61 }
62 context->GetTaskExecutor()->PostTask(
63 [fontData, weak] {
64 auto fontLoader = weak.Upgrade();
65 if (!fontLoader) {
66 return;
67 }
68 // Load font.
69 RosenFontCollection::GetInstance().LoadFontFromList(
70 fontData.data(), fontData.size(), fontLoader->familyName_);
71 fontLoader->isLoaded_ = true;
72
73 // When font is already loaded, notify all which used this font.
74 fontLoader->NotifyCallbacks();
75 },
76 TaskExecutor::TaskType::UI);
77 },
78 TaskExecutor::TaskType::BACKGROUND);
79 }
80
LoadFromResource(const OHOS::Ace::RefPtr<OHOS::Ace::PipelineBase> & context)81 void RosenFontLoader::LoadFromResource(const OHOS::Ace::RefPtr<OHOS::Ace::PipelineBase>& context)
82 {
83 auto weakContext = AceType::WeakClaim(AceType::RawPtr(context));
84 context->GetTaskExecutor()->PostTask(
85 [weak = AceType::WeakClaim(this), weakContext] {
86 auto fontLoader = weak.Upgrade();
87 auto context = weakContext.Upgrade();
88 if (!fontLoader || !context) {
89 return;
90 }
91 auto themeManager = context->GetThemeManager();
92 if (!themeManager) {
93 LOGE("No theme manager!");
94 return;
95 }
96 auto themeConstants = themeManager->GetThemeConstants();
97 std::string rawFile;
98 std::unique_ptr<uint8_t[]> data;
99 size_t dataLen = 0;
100 std::smatch matches;
101 if (std::regex_match(fontLoader->familySrc_, matches, RAWFILE_APP_RES_PATH_REGEX)
102 && matches.size() == RAWFILE_RESOURCE_MATCH_SIZE) {
103 rawFile = matches[1].str();
104 }
105 if (rawFile.empty()) {
106 return;
107 }
108 if (!themeConstants->GetRawFileData(rawFile, dataLen, data) || !data.get()) {
109 LOGE("Get raw file data failed!");
110 return;
111 }
112
113 auto fontDataPtr = data.get();
114 std::vector<uint8_t> fontData;
115 for (size_t i = 0; i < dataLen; i++) {
116 fontData.emplace_back(fontDataPtr[i]);
117 }
118 context->GetTaskExecutor()->PostTask(
119 [fontData, weak] {
120 auto fontLoader = weak.Upgrade();
121 if (!fontLoader) {
122 return;
123 }
124 // Load font.
125 RosenFontCollection::GetInstance().LoadFontFromList(fontData.data(), fontData.size(),
126 fontLoader->familyName_);
127 fontLoader->isLoaded_ = true;
128
129 // When font is already loaded, notify all which used this font.
130 fontLoader->NotifyCallbacks();
131 },
132 TaskExecutor::TaskType::UI);
133 },
134 TaskExecutor::TaskType::BACKGROUND);
135 }
136
LoadFromAsset(const OHOS::Ace::RefPtr<OHOS::Ace::PipelineBase> & context)137 void RosenFontLoader::LoadFromAsset(const OHOS::Ace::RefPtr<OHOS::Ace::PipelineBase>& context)
138 {
139 auto weakContext = AceType::WeakClaim(AceType::RawPtr(context));
140 context->GetTaskExecutor()->PostTask(
141 [weak = AceType::WeakClaim(this), weakContext] {
142 auto fontLoader = weak.Upgrade();
143 auto context = weakContext.Upgrade();
144 if (!fontLoader || !context) {
145 return;
146 }
147 auto assetManager = context->GetAssetManager();
148 if (!assetManager) {
149 LOGE("No asset manager!");
150 return;
151 }
152 std::string assetSrc(fontLoader->familySrc_);
153 if (assetSrc[0] == '/') {
154 assetSrc = assetSrc.substr(1); // get the asset src without '/'.
155 } else if (assetSrc[0] == '.' && assetSrc.size() > 2 && assetSrc[1] == '/') {
156 assetSrc = assetSrc.substr(2); // get the asset src without './'.
157 }
158 auto assetData = assetManager->GetAsset(assetSrc);
159 if (!assetData) {
160 LOGE("No asset data!");
161 return;
162 }
163
164 context->GetTaskExecutor()->PostTask(
165 [assetData, weak] {
166 auto fontLoader = weak.Upgrade();
167 if (!fontLoader) {
168 return;
169 }
170 // Load font.
171 RosenFontCollection::GetInstance().LoadFontFromList(
172 assetData->GetData(), assetData->GetSize(), fontLoader->familyName_);
173 fontLoader->isLoaded_ = true;
174
175 // When font is already loaded, notify all which used this font.
176 fontLoader->NotifyCallbacks();
177 },
178 TaskExecutor::TaskType::UI);
179 },
180 TaskExecutor::TaskType::BACKGROUND);
181 }
182
NotifyCallbacks()183 void RosenFontLoader::NotifyCallbacks()
184 {
185 for (const auto& [node, callback] : callbacksNG_) {
186 if (callback) {
187 callback();
188 }
189 }
190 callbacksNG_.clear();
191 if (variationChanged_) {
192 variationChanged_();
193 }
194 }
195
196 } // namespace OHOS::Ace
197