1 /*
2  * Copyright (c) 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_text_font_descriptor.h"
17 
18 #include "array_mgr.h"
19 #include "font_descriptor_mgr.h"
20 #include "font_utils.h"
21 #include "text/common_utils.h"
22 
23 using namespace OHOS::Rosen;
24 namespace {
CalculateDrawingStringSize(const std::string & fullName,std::u16string & utf16String)25 size_t CalculateDrawingStringSize(const std::string& fullName, std::u16string& utf16String)
26 {
27     if (fullName.empty()) {
28         return 0;
29     }
30     std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter;
31     utf16String = converter.from_bytes(fullName);
32     return utf16String.size() * sizeof(char16_t);
33 }
34 
ConvertToDrawingString(std::u16string & utf16String,OH_Drawing_String & fullNameString)35 bool ConvertToDrawingString(std::u16string& utf16String, OH_Drawing_String& fullNameString)
36 {
37     if (utf16String.empty() || fullNameString.strData == nullptr || fullNameString.strLen == 0) {
38         return false;
39     }
40     char16_t* u16Data = const_cast<char16_t*>(utf16String.c_str());
41     if (memcpy_s(fullNameString.strData, fullNameString.strLen, u16Data, fullNameString.strLen) == EOK) {
42         return true;
43     }
44     return false;
45 }
46 }
47 
48 template<typename T1, typename T2>
ConvertToOriginalText(T2 * ptr)49 inline T1* ConvertToOriginalText(T2* ptr)
50 {
51     return reinterpret_cast<T1*>(ptr);
52 }
53 
OH_Drawing_GetFontDescriptorByFullName(const OH_Drawing_String * fullName,OH_Drawing_SystemFontType fontType)54 OH_Drawing_FontDescriptor* OH_Drawing_GetFontDescriptorByFullName(const OH_Drawing_String* fullName,
55     OH_Drawing_SystemFontType fontType)
56 {
57     if (fullName == nullptr) {
58         return nullptr;
59     }
60     auto systemFontType = static_cast<int32_t>(fontType);
61     using namespace OHOS::Rosen::Drawing;
62     std::string fullNameString;
63     if (!ConvertToString(fullName->strData, fullName->strLen, fullNameString)) {
64         return nullptr;
65     }
66     std::shared_ptr<TextEngine::FontParser::FontDescriptor> result = nullptr;
67     FontDescriptorMgrInstance.GetFontDescSharedPtrByFullName(fullNameString, systemFontType, result);
68     if (result == nullptr) {
69         return nullptr;
70     }
71     OH_Drawing_FontDescriptor* descriptor = OH_Drawing_CreateFontDescriptor();
72     if (descriptor == nullptr) {
73         return nullptr;
74     }
75     if (!OHOS::Rosen::Drawing::CopyFontDescriptor(descriptor, *result)) {
76         OH_Drawing_DestroyFontDescriptor(descriptor);
77         return nullptr;
78     }
79     return descriptor;
80 }
81 
OH_Drawing_GetSystemFontFullNamesByType(OH_Drawing_SystemFontType fontType)82 OH_Drawing_Array* OH_Drawing_GetSystemFontFullNamesByType(OH_Drawing_SystemFontType fontType)
83 {
84     auto systemFontType = static_cast<int32_t>(fontType);
85     std::unordered_set<std::string> fullNameList;
86     FontDescriptorMgrInstance.GetSystemFontFullNamesByType(systemFontType, fullNameList);
87     if (fullNameList.size() == 0) {
88         return nullptr;
89     }
90     ObjectArray* array = new (std::nothrow)ObjectArray;
91     if (array == nullptr) {
92         return nullptr;
93     }
94     OH_Drawing_String* drawingStringArray = new (std::nothrow)OH_Drawing_String[fullNameList.size()];
95     if (drawingStringArray == nullptr) {
96         delete array;
97         return nullptr;
98     }
99     size_t index = 0;
100     for (const auto& fullName : fullNameList) {
101         std::u16string utf16String;
102         size_t strByteLen = CalculateDrawingStringSize(fullName, utf16String);
103         if (strByteLen > 0) {
104             drawingStringArray[index].strData = new (std::nothrow) uint8_t[strByteLen];
105             drawingStringArray[index].strLen = static_cast<uint32_t>(strByteLen);
106         }
107 
108         if (strByteLen == 0 || drawingStringArray[index].strData == nullptr ||
109             !ConvertToDrawingString(utf16String, drawingStringArray[index])) {
110             for (size_t i = 0; i <= index; ++i) {
111                 delete[] drawingStringArray[i].strData;
112             }
113             delete[] drawingStringArray;
114             drawingStringArray = nullptr;
115             delete array;
116             return nullptr;
117         }
118         ++index;
119     }
120     array->addr = drawingStringArray;
121     array->num = fullNameList.size();
122     array->type = ObjectType::STRING;
123     return reinterpret_cast<OH_Drawing_Array*>(array);
124 }
125 
OH_Drawing_GetSystemFontFullNameByIndex(OH_Drawing_Array * fullNameArray,size_t index)126 const OH_Drawing_String* OH_Drawing_GetSystemFontFullNameByIndex(OH_Drawing_Array* fullNameArray, size_t index)
127 {
128     ObjectArray* fullNameList = ConvertToOriginalText<ObjectArray>(fullNameArray);
129     if (fullNameList != nullptr && fullNameList->type == ObjectType::STRING &&
130         index < fullNameList->num && fullNameList->addr != nullptr) {
131         OH_Drawing_String* drawingString = ConvertToOriginalText<OH_Drawing_String>(fullNameList->addr);
132         if (drawingString != nullptr) {
133             return &drawingString[index];
134         }
135     }
136     return nullptr;
137 }
138 
OH_Drawing_DestroySystemFontFullNames(OH_Drawing_Array * fullNameArray)139 void OH_Drawing_DestroySystemFontFullNames(OH_Drawing_Array* fullNameArray)
140 {
141     ObjectArray* fullNameList = ConvertToOriginalText<ObjectArray>(fullNameArray);
142     if (fullNameList == nullptr || fullNameList->type != ObjectType::STRING) {
143         return;
144     }
145     OH_Drawing_String* drawingStringArray = ConvertToOriginalText<OH_Drawing_String>(fullNameList->addr);
146     if (drawingStringArray == nullptr) {
147         return;
148     }
149     for (size_t i = 0; i < fullNameList->num; ++i) {
150         if (drawingStringArray[i].strData == nullptr) {
151             continue;
152         }
153         delete[] drawingStringArray[i].strData;
154         drawingStringArray[i].strData = nullptr;
155     }
156     delete[] drawingStringArray;
157     fullNameList->addr = nullptr;
158     fullNameList->num = 0;
159     fullNameList->type = ObjectType::INVALID;
160     delete fullNameList;
161 }