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 <string_ex.h>
19
20 #include "array_mgr.h"
21 #include "font_descriptor_mgr.h"
22 #include "font_utils.h"
23 #include "text/common_utils.h"
24 #include "utils/text_log.h"
25
26 using namespace OHOS::Rosen;
27 template<typename T1, typename T2>
ConvertToOriginalText(T2 * ptr)28 inline T1* ConvertToOriginalText(T2* ptr)
29 {
30 return reinterpret_cast<T1*>(ptr);
31 }
32
OH_Drawing_MatchFontDescriptors(OH_Drawing_FontDescriptor * desc,size_t * num)33 OH_Drawing_FontDescriptor* OH_Drawing_MatchFontDescriptors(OH_Drawing_FontDescriptor* desc, size_t* num)
34 {
35 if (desc == nullptr || num == nullptr) {
36 return nullptr;
37 }
38 using namespace OHOS::Rosen::TextEngine;
39 std::shared_ptr<FontParser::FontDescriptor> condition = std::make_shared<FontParser::FontDescriptor>();
40 condition->postScriptName = (desc->postScriptName == nullptr) ? "" : desc->postScriptName;
41 condition->fullName = (desc->fullName == nullptr) ? "" : desc->fullName;
42 condition->fontFamily = (desc->fontFamily == nullptr) ? "" : desc->fontFamily;
43 condition->fontSubfamily = (desc->fontSubfamily == nullptr) ? "" : desc->fontSubfamily;
44 condition->weight = desc->weight;
45 condition->width = desc->width;
46 condition->italic = desc->italic;
47 condition->monoSpace = desc->monoSpace;
48 condition->symbolic = desc->symbolic;
49
50 std::set<std::shared_ptr<FontParser::FontDescriptor>> result;
51 FontDescriptorMgrInstance.MatchFontDescriptors(condition, result);
52 if (result.empty()) {
53 *num = 0;
54 return nullptr;
55 }
56
57 *num = result.size();
58 OH_Drawing_FontDescriptor* descriptors = new (std::nothrow) OH_Drawing_FontDescriptor[*num];
59 if (descriptors == nullptr) {
60 *num = 0;
61 return nullptr;
62 }
63
64 size_t i = 0;
65 for (const auto& item : result) {
66 if (!OHOS::Rosen::Drawing::CopyFontDescriptor(&descriptors[i], *item)) {
67 break;
68 }
69 ++i;
70 }
71 if (i != result.size()) {
72 OH_Drawing_DestroyFontDescriptors(descriptors, i);
73 *num = 0;
74 return nullptr;
75 }
76 return descriptors;
77 }
78
OH_Drawing_DestroyFontDescriptors(OH_Drawing_FontDescriptor * descriptors,size_t num)79 void OH_Drawing_DestroyFontDescriptors(OH_Drawing_FontDescriptor* descriptors, size_t num)
80 {
81 if (descriptors == nullptr || num == 0) {
82 return;
83 }
84 for (size_t i = 0; i < num; ++i) {
85 free(descriptors[i].path);
86 free(descriptors[i].postScriptName);
87 free(descriptors[i].fullName);
88 free(descriptors[i].fontFamily);
89 free(descriptors[i].fontSubfamily);
90 }
91 delete[] descriptors;
92 }
93
OH_Drawing_GetFontDescriptorByFullName(const OH_Drawing_String * fullName,OH_Drawing_SystemFontType fontType)94 OH_Drawing_FontDescriptor* OH_Drawing_GetFontDescriptorByFullName(const OH_Drawing_String* fullName,
95 OH_Drawing_SystemFontType fontType)
96 {
97 if (fullName == nullptr) {
98 return nullptr;
99 }
100 auto systemFontType = static_cast<int32_t>(fontType);
101 using namespace OHOS::Rosen::Drawing;
102 std::string fullNameString;
103 if (!ConvertToString(fullName->strData, fullName->strLen, fullNameString)) {
104 return nullptr;
105 }
106 std::shared_ptr<TextEngine::FontParser::FontDescriptor> result = nullptr;
107 FontDescriptorMgrInstance.GetFontDescSharedPtrByFullName(fullNameString, systemFontType, result);
108 if (result == nullptr) {
109 return nullptr;
110 }
111 OH_Drawing_FontDescriptor* descriptor = OH_Drawing_CreateFontDescriptor();
112 if (descriptor == nullptr) {
113 return nullptr;
114 }
115 if (!OHOS::Rosen::Drawing::CopyFontDescriptor(descriptor, *result)) {
116 OH_Drawing_DestroyFontDescriptor(descriptor);
117 return nullptr;
118 }
119 return descriptor;
120 }
121
OH_Drawing_GetSystemFontFullNamesByType(OH_Drawing_SystemFontType fontType)122 OH_Drawing_Array* OH_Drawing_GetSystemFontFullNamesByType(OH_Drawing_SystemFontType fontType)
123 {
124 auto systemFontType = static_cast<int32_t>(fontType);
125 std::unordered_set<std::string> fullNameList;
126 FontDescriptorMgrInstance.GetSystemFontFullNamesByType(systemFontType, fullNameList);
127 std::unique_ptr array = std::make_unique<ObjectArray>();
128 std::unique_ptr addr = std::make_unique<OH_Drawing_String[]>(fullNameList.size());
129 array->type = ObjectType::STRING;
130 size_t num = 0;
131 for (const auto& fullName : fullNameList) {
132 std::u16string utf16String = OHOS::Str8ToStr16(fullName);
133 if (utf16String.empty()) {
134 TEXT_LOGE("Failed to convert string to utf16: %{public}s", fullName);
135 continue;
136 }
137 addr[num].strLen = utf16String.size() * sizeof(char16_t);
138 std::unique_ptr strData = std::make_unique<uint8_t[]>(addr[num].strLen);
139 if (memcpy_s(strData.get(), addr[num].strLen, utf16String.c_str(), addr[num].strLen) != EOK) {
140 TEXT_LOGE("Failed to memcpy_s length: %{public}u", addr[num].strLen);
141 continue;
142 }
143 addr[num].strData = strData.release();
144 num += 1;
145 }
146 if (num == 0) {
147 TEXT_LOGI("Failed to get font full name, font type: %{public}d", static_cast<int32_t>(fontType));
148 return nullptr;
149 }
150 array->num = num;
151 array->addr = addr.release();
152 return reinterpret_cast<OH_Drawing_Array*>(array.release());
153 }
154
OH_Drawing_GetSystemFontFullNameByIndex(OH_Drawing_Array * fullNameArray,size_t index)155 const OH_Drawing_String* OH_Drawing_GetSystemFontFullNameByIndex(OH_Drawing_Array* fullNameArray, size_t index)
156 {
157 ObjectArray* fullNameList = ConvertToOriginalText<ObjectArray>(fullNameArray);
158 if (fullNameList != nullptr && fullNameList->type == ObjectType::STRING &&
159 index < fullNameList->num && fullNameList->addr != nullptr) {
160 OH_Drawing_String* drawingString = ConvertToOriginalText<OH_Drawing_String>(fullNameList->addr);
161 if (drawingString != nullptr) {
162 return &drawingString[index];
163 }
164 }
165 return nullptr;
166 }
167
OH_Drawing_DestroySystemFontFullNames(OH_Drawing_Array * fullNameArray)168 void OH_Drawing_DestroySystemFontFullNames(OH_Drawing_Array* fullNameArray)
169 {
170 ObjectArray* fullNameList = ConvertToOriginalText<ObjectArray>(fullNameArray);
171 if (fullNameList == nullptr || fullNameList->type != ObjectType::STRING) {
172 return;
173 }
174 OH_Drawing_String* drawingStringArray = ConvertToOriginalText<OH_Drawing_String>(fullNameList->addr);
175 if (drawingStringArray == nullptr) {
176 return;
177 }
178 for (size_t i = 0; i < fullNameList->num; ++i) {
179 if (drawingStringArray[i].strData == nullptr) {
180 continue;
181 }
182 delete[] drawingStringArray[i].strData;
183 drawingStringArray[i].strData = nullptr;
184 }
185 delete[] drawingStringArray;
186 fullNameList->addr = nullptr;
187 fullNameList->num = 0;
188 fullNameList->type = ObjectType::INVALID;
189 delete fullNameList;
190 }