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