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 }