1 /*
2 * Copyright (c) 2023-2024 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 "drawing_typeface.h"
17
18 #include <mutex>
19 #include <unordered_map>
20 #include <vector>
21
22 #include "include/core/SkTypes.h"
23
24 #include "drawing_canvas_utils.h"
25
26 #include "text/typeface.h"
27 #include "utils/log.h"
28 #include "utils/object_mgr.h"
29
30 static constexpr uint32_t AXIS_TAG_ZERO = 0;
31 static constexpr uint32_t AXIS_TAG_ONE = 1;
32 static constexpr uint32_t AXIS_TAG_TWO = 2;
33 static constexpr uint32_t AXIS_TAG_THREE = 3;
34 static constexpr uint32_t VARIATION_AXIS_LENGTH = 4;
35
36 using namespace OHOS;
37 using namespace Rosen;
38 using namespace Drawing;
39
40 static const std::string G_SYSTEM_FONT_DIR = "/system/fonts/";
41
42 struct FontArgumentsHelper {
43 struct Coordinate {
44 uint32_t axis;
45 float value;
46 };
47
48 int fontCollectionIndex_ = 0;
49 std::vector<Coordinate> coordinates_;
50 };
51
CastToMemoryStream(OH_Drawing_MemoryStream * cMemoryStream)52 static MemoryStream* CastToMemoryStream(OH_Drawing_MemoryStream* cMemoryStream)
53 {
54 return reinterpret_cast<MemoryStream*>(cMemoryStream);
55 }
56
CastToFontArgumentsHelper(const OH_Drawing_FontArguments * cFontArguments)57 static const FontArgumentsHelper* CastToFontArgumentsHelper(const OH_Drawing_FontArguments* cFontArguments)
58 {
59 return reinterpret_cast<const FontArgumentsHelper*>(cFontArguments);
60 }
61
CastToFontArgumentsHelper(OH_Drawing_FontArguments * cFontArguments)62 static FontArgumentsHelper* CastToFontArgumentsHelper(OH_Drawing_FontArguments* cFontArguments)
63 {
64 return reinterpret_cast<FontArgumentsHelper*>(cFontArguments);
65 }
66
CastToTypeface(const OH_Drawing_Typeface * cTypeface)67 static const Typeface* CastToTypeface(const OH_Drawing_Typeface* cTypeface)
68 {
69 return reinterpret_cast<const Typeface*>(cTypeface);
70 }
71
ConvertToDrawingFontArguments(const FontArgumentsHelper & fontArgumentsHelper,FontArguments & fontArguments)72 static void ConvertToDrawingFontArguments(const FontArgumentsHelper& fontArgumentsHelper, FontArguments& fontArguments)
73 {
74 fontArguments.SetCollectionIndex(fontArgumentsHelper.fontCollectionIndex_);
75 fontArguments.SetVariationDesignPosition({reinterpret_cast<const FontArguments::VariationPosition::Coordinate*>(
76 fontArgumentsHelper.coordinates_.data()), fontArgumentsHelper.coordinates_.size()});
77 }
78
RegisterAndConvertTypeface(std::shared_ptr<Typeface> typeface)79 static OH_Drawing_Typeface* RegisterAndConvertTypeface(std::shared_ptr<Typeface> typeface)
80 {
81 if (typeface == nullptr) {
82 LOGE("RegisterAndConvertTypeface: typeface nullptr.");
83 return nullptr;
84 }
85 // system font is not sent to RenderService to optimize performance.
86 if (typeface->IsCustomTypeface() && Typeface::GetTypefaceRegisterCallBack() != nullptr &&
87 !Typeface::GetTypefaceRegisterCallBack()(typeface)) {
88 LOGE("RegisterAndConvertTypeface: register typeface failed.");
89 return nullptr;
90 }
91 OH_Drawing_Typeface* drawingTypeface = reinterpret_cast<OH_Drawing_Typeface*>(typeface.get());
92 TypefaceMgr::GetInstance().Insert(drawingTypeface, typeface);
93 return drawingTypeface;
94 }
95
OH_Drawing_TypefaceCreateDefault()96 OH_Drawing_Typeface* OH_Drawing_TypefaceCreateDefault()
97 {
98 std::shared_ptr<Typeface> typeface = g_LoadZhCnTypeface();
99 if (typeface == nullptr) {
100 LOGE("OH_Drawing_TypefaceCreateDefault: create failed.");
101 return nullptr;
102 }
103 OH_Drawing_Typeface* drawingTypeface = reinterpret_cast<OH_Drawing_Typeface*>(typeface.get());
104 TypefaceMgr::GetInstance().Insert(drawingTypeface, typeface);
105 return drawingTypeface;
106 }
107
OH_Drawing_TypefaceCreateFromFile(const char * path,int index)108 OH_Drawing_Typeface* OH_Drawing_TypefaceCreateFromFile(const char* path, int index)
109 {
110 if (path == nullptr) {
111 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
112 return nullptr;
113 }
114 std::shared_ptr<Typeface> typeface = Typeface::MakeFromFile(path, index);
115 if (typeface == nullptr) {
116 return nullptr;
117 }
118 std::string pathStr(path);
119 // system font is not sent to RenderService to optimize performance.
120 if (pathStr.substr(0, G_SYSTEM_FONT_DIR.length()) != G_SYSTEM_FONT_DIR &&
121 Drawing::Typeface::GetTypefaceRegisterCallBack() != nullptr) {
122 bool ret = Drawing::Typeface::GetTypefaceRegisterCallBack()(typeface);
123 if (!ret) {
124 LOGE("OH_Drawing_TypefaceCreateFromFile: register typeface failed.");
125 return nullptr;
126 }
127 }
128 OH_Drawing_Typeface* drawingTypeface = reinterpret_cast<OH_Drawing_Typeface*>(typeface.get());
129 TypefaceMgr::GetInstance().Insert(drawingTypeface, typeface);
130 return drawingTypeface;
131 }
132
OH_Drawing_TypefaceCreateFromFileWithArguments(const char * path,const OH_Drawing_FontArguments * cFontArguments)133 OH_Drawing_Typeface* OH_Drawing_TypefaceCreateFromFileWithArguments(const char* path,
134 const OH_Drawing_FontArguments* cFontArguments)
135 {
136 const FontArgumentsHelper* fontArgumentsHelper = CastToFontArgumentsHelper(cFontArguments);
137 if (path == nullptr || fontArgumentsHelper == nullptr) {
138 return nullptr;
139 }
140 FontArguments fontArguments;
141 ConvertToDrawingFontArguments(*fontArgumentsHelper, fontArguments);
142 return RegisterAndConvertTypeface(Typeface::MakeFromFile(path, fontArguments));
143 }
144
OH_Drawing_TypefaceCreateFromCurrent(const OH_Drawing_Typeface * cCurrentTypeface,const OH_Drawing_FontArguments * cFontArguments)145 OH_Drawing_Typeface* OH_Drawing_TypefaceCreateFromCurrent(const OH_Drawing_Typeface* cCurrentTypeface,
146 const OH_Drawing_FontArguments* cFontArguments)
147 {
148 const Typeface* currentTypeface = CastToTypeface(cCurrentTypeface);
149 const FontArgumentsHelper* fontArgumentsHelper = CastToFontArgumentsHelper(cFontArguments);
150 if (currentTypeface == nullptr || fontArgumentsHelper == nullptr) {
151 return nullptr;
152 }
153 FontArguments fontArguments;
154 ConvertToDrawingFontArguments(*fontArgumentsHelper, fontArguments);
155 std::shared_ptr<Typeface> typeface = currentTypeface->MakeClone(fontArguments);
156 if (typeface == nullptr || currentTypeface->GetUniqueID() == typeface->GetUniqueID()) {
157 return nullptr;
158 }
159 return RegisterAndConvertTypeface(typeface);
160 }
161
OH_Drawing_TypefaceCreateFromStream(OH_Drawing_MemoryStream * cMemoryStream,int32_t index)162 OH_Drawing_Typeface* OH_Drawing_TypefaceCreateFromStream(OH_Drawing_MemoryStream* cMemoryStream, int32_t index)
163 {
164 if (cMemoryStream == nullptr) {
165 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
166 return nullptr;
167 }
168 std::unique_ptr<MemoryStream> memoryStream(CastToMemoryStream(cMemoryStream));
169 std::shared_ptr<Typeface> typeface = Typeface::MakeFromStream(std::move(memoryStream), index);
170 if (typeface == nullptr) {
171 return nullptr;
172 }
173 if (Drawing::Typeface::GetTypefaceRegisterCallBack() != nullptr) {
174 bool ret = Drawing::Typeface::GetTypefaceRegisterCallBack()(typeface);
175 if (!ret) {
176 LOGE("OH_Drawing_TypefaceCreateFromStream: register typeface failed.");
177 return nullptr;
178 }
179 }
180 OH_Drawing_Typeface* drawingTypeface = reinterpret_cast<OH_Drawing_Typeface*>(typeface.get());
181 TypefaceMgr::GetInstance().Insert(drawingTypeface, typeface);
182 return drawingTypeface;
183 }
184
OH_Drawing_TypefaceDestroy(OH_Drawing_Typeface * cTypeface)185 void OH_Drawing_TypefaceDestroy(OH_Drawing_Typeface* cTypeface)
186 {
187 if (cTypeface == nullptr) {
188 return;
189 }
190 auto typeface = TypefaceMgr::GetInstance().Find(cTypeface);
191 if (Drawing::Typeface::GetTypefaceUnRegisterCallBack() != nullptr && typeface) {
192 Drawing::Typeface::GetTypefaceUnRegisterCallBack()(typeface);
193 }
194 TypefaceMgr::GetInstance().Remove(cTypeface);
195 }
196
OH_Drawing_FontArgumentsCreate(void)197 OH_Drawing_FontArguments* OH_Drawing_FontArgumentsCreate(void)
198 {
199 return (OH_Drawing_FontArguments*)new FontArgumentsHelper();
200 }
201
OH_Drawing_FontArgumentsAddVariation(OH_Drawing_FontArguments * cFontArguments,const char * axis,float value)202 OH_Drawing_ErrorCode OH_Drawing_FontArgumentsAddVariation(OH_Drawing_FontArguments* cFontArguments,
203 const char* axis, float value)
204 {
205 if (axis == nullptr || strlen(axis) != VARIATION_AXIS_LENGTH) {
206 return OH_DRAWING_ERROR_INVALID_PARAMETER;
207 }
208 FontArgumentsHelper* fontArgumentsHelper = CastToFontArgumentsHelper(cFontArguments);
209 if (fontArgumentsHelper == nullptr) {
210 return OH_DRAWING_ERROR_INVALID_PARAMETER;
211 }
212 fontArgumentsHelper->coordinates_.push_back(
213 {SkSetFourByteTag(axis[AXIS_TAG_ZERO], axis[AXIS_TAG_ONE], axis[AXIS_TAG_TWO], axis[AXIS_TAG_THREE]), value});
214 return OH_DRAWING_SUCCESS;
215 }
216
OH_Drawing_FontArgumentsDestroy(OH_Drawing_FontArguments * cFontArguments)217 OH_Drawing_ErrorCode OH_Drawing_FontArgumentsDestroy(OH_Drawing_FontArguments* cFontArguments)
218 {
219 if (cFontArguments == nullptr) {
220 return OH_DRAWING_ERROR_INVALID_PARAMETER;
221 }
222 delete CastToFontArgumentsHelper(cFontArguments);
223 return OH_DRAWING_SUCCESS;
224 }