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_text_blob.h"
17
18 #include <mutex>
19 #include <unordered_map>
20
21 #include "drawing_canvas_utils.h"
22 #include "drawing_font_utils.h"
23
24 #include "text/text_blob_builder.h"
25 #include "utils/log.h"
26
27 using namespace OHOS;
28 using namespace Rosen;
29 using namespace Drawing;
30
31 static std::mutex g_textBlobLockMutex;
32 static std::unordered_map<void*, std::shared_ptr<TextBlob>> g_textBlobMap;
33
CastToTextBlobBuilder(OH_Drawing_TextBlobBuilder * cTextBlobBuilder)34 static TextBlobBuilder* CastToTextBlobBuilder(OH_Drawing_TextBlobBuilder* cTextBlobBuilder)
35 {
36 return reinterpret_cast<TextBlobBuilder*>(cTextBlobBuilder);
37 }
38
CastToFont(const OH_Drawing_Font * cFont)39 static const Font* CastToFont(const OH_Drawing_Font* cFont)
40 {
41 return reinterpret_cast<const Font*>(cFont);
42 }
43
CastToTextBlob(OH_Drawing_TextBlob * cTextBlob)44 static TextBlob* CastToTextBlob(OH_Drawing_TextBlob* cTextBlob)
45 {
46 return reinterpret_cast<TextBlob*>(cTextBlob);
47 }
48
CastToTextBlob(const OH_Drawing_TextBlob * cTextBlob)49 static const TextBlob* CastToTextBlob(const OH_Drawing_TextBlob* cTextBlob)
50 {
51 return reinterpret_cast<const TextBlob*>(cTextBlob);
52 }
53
CastToRect(const OH_Drawing_Rect * cRect)54 static const Rect* CastToRect(const OH_Drawing_Rect* cRect)
55 {
56 return reinterpret_cast<const Rect*>(cRect);
57 }
58
CastToPoint(const OH_Drawing_Point2D & cPoint)59 static const Point CastToPoint(const OH_Drawing_Point2D& cPoint)
60 {
61 return {cPoint.x, cPoint.y};
62 }
63
OH_Drawing_TextBlobBuilderCreate()64 OH_Drawing_TextBlobBuilder* OH_Drawing_TextBlobBuilderCreate()
65 {
66 return (OH_Drawing_TextBlobBuilder*)new TextBlobBuilder;
67 }
68
OH_Drawing_TextBlobCreateFromText(const void * text,size_t byteLength,const OH_Drawing_Font * cFont,OH_Drawing_TextEncoding cTextEncoding)69 OH_Drawing_TextBlob* OH_Drawing_TextBlobCreateFromText(const void* text, size_t byteLength,
70 const OH_Drawing_Font* cFont, OH_Drawing_TextEncoding cTextEncoding)
71 {
72 if (text == nullptr || cFont == nullptr) {
73 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
74 return nullptr;
75 }
76 if (cTextEncoding < TEXT_ENCODING_UTF8 || cTextEncoding > TEXT_ENCODING_GLYPH_ID) {
77 g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
78 return nullptr;
79 }
80 const Font* font = CastToFont(cFont);
81 std::shared_ptr<Font> themeFont = DrawingFontUtils::GetThemeFont(font);
82 if (themeFont != nullptr) {
83 font = themeFont.get();
84 }
85 std::shared_ptr<TextBlob> textBlob = TextBlob::MakeFromText(text,
86 byteLength, *font, static_cast<TextEncoding>(cTextEncoding));
87 if (textBlob == nullptr) {
88 return nullptr;
89 }
90 std::lock_guard<std::mutex> lock(g_textBlobLockMutex);
91 g_textBlobMap.insert({textBlob.get(), textBlob});
92 return (OH_Drawing_TextBlob*)textBlob.get();
93 }
94
OH_Drawing_TextBlobCreateFromPosText(const void * text,size_t byteLength,OH_Drawing_Point2D * cPoints,const OH_Drawing_Font * cFont,OH_Drawing_TextEncoding cTextEncoding)95 OH_Drawing_TextBlob* OH_Drawing_TextBlobCreateFromPosText(const void* text, size_t byteLength,
96 OH_Drawing_Point2D* cPoints, const OH_Drawing_Font* cFont, OH_Drawing_TextEncoding cTextEncoding)
97 {
98 if (text == nullptr || cFont == nullptr || cPoints == nullptr || byteLength == 0) {
99 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
100 return nullptr;
101 }
102 if (cTextEncoding < TEXT_ENCODING_UTF8 || cTextEncoding > TEXT_ENCODING_GLYPH_ID) {
103 g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
104 return nullptr;
105 }
106 const Font* font = CastToFont(cFont);
107 std::shared_ptr<Font> themeFont = DrawingFontUtils::GetThemeFont(font);
108 if (themeFont != nullptr) {
109 font = themeFont.get();
110 }
111 const int count = font->CountText(text, byteLength, static_cast<TextEncoding>(cTextEncoding));
112 if (count <= 0) {
113 return nullptr;
114 }
115 Point* pts = new (std::nothrow) Point[count];
116 if (pts == nullptr) {
117 return nullptr;
118 }
119 for (int i = 0; i < count; ++i) {
120 pts[i] = CastToPoint(cPoints[i]);
121 }
122 std::shared_ptr<TextBlob> textBlob = TextBlob::MakeFromPosText(text, byteLength,
123 pts, *font, static_cast<TextEncoding>(cTextEncoding));
124 if (textBlob == nullptr) {
125 delete [] pts;
126 return nullptr;
127 }
128 std::lock_guard<std::mutex> lock(g_textBlobLockMutex);
129 g_textBlobMap.insert({textBlob.get(), textBlob});
130 delete [] pts;
131 return (OH_Drawing_TextBlob*)textBlob.get();
132 }
133
OH_Drawing_TextBlobCreateFromString(const char * str,const OH_Drawing_Font * cFont,OH_Drawing_TextEncoding cTextEncoding)134 OH_Drawing_TextBlob* OH_Drawing_TextBlobCreateFromString(const char* str,
135 const OH_Drawing_Font* cFont, OH_Drawing_TextEncoding cTextEncoding)
136 {
137 if (str == nullptr || cFont == nullptr) {
138 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
139 return nullptr;
140 }
141 if (cTextEncoding < TEXT_ENCODING_UTF8 || cTextEncoding > TEXT_ENCODING_GLYPH_ID) {
142 g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
143 return nullptr;
144 }
145 const Font* font = CastToFont(cFont);
146 std::shared_ptr<Font> themeFont = DrawingFontUtils::GetThemeFont(font);
147 if (themeFont != nullptr) {
148 font = themeFont.get();
149 }
150 std::shared_ptr<TextBlob> textBlob = TextBlob::MakeFromString(str,
151 *font, static_cast<TextEncoding>(cTextEncoding));
152 if (textBlob == nullptr) {
153 return nullptr;
154 }
155 std::lock_guard<std::mutex> lock(g_textBlobLockMutex);
156 g_textBlobMap.insert({textBlob.get(), textBlob});
157 return (OH_Drawing_TextBlob*)textBlob.get();
158 }
159
OH_Drawing_TextBlobGetBounds(OH_Drawing_TextBlob * cTextBlob,OH_Drawing_Rect * cRect)160 void OH_Drawing_TextBlobGetBounds(OH_Drawing_TextBlob* cTextBlob, OH_Drawing_Rect* cRect)
161 {
162 Rect* outRect = const_cast<Rect*>(CastToRect(cRect));
163 if (outRect == nullptr) {
164 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
165 return;
166 }
167 TextBlob* textblob = CastToTextBlob(cTextBlob);
168 if (textblob == nullptr) {
169 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
170 return;
171 }
172 std::shared_ptr<Rect> rect = textblob->Bounds();
173 if (rect == nullptr) {
174 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
175 return;
176 }
177 *outRect = Rect(rect->GetLeft(), rect->GetTop(), rect->GetRight(), rect->GetBottom());
178 }
179
OH_Drawing_TextBlobUniqueID(const OH_Drawing_TextBlob * cTextBlob)180 uint32_t OH_Drawing_TextBlobUniqueID(const OH_Drawing_TextBlob* cTextBlob)
181 {
182 if (cTextBlob == nullptr) {
183 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
184 return 0;
185 }
186 const TextBlob* textblob = CastToTextBlob(cTextBlob);
187 return textblob->UniqueID();
188 }
189
OH_Drawing_TextBlobBuilderAllocRunPos(OH_Drawing_TextBlobBuilder * cTextBlobBuilder,const OH_Drawing_Font * cFont,int32_t count,const OH_Drawing_Rect * cRect)190 const OH_Drawing_RunBuffer* OH_Drawing_TextBlobBuilderAllocRunPos(OH_Drawing_TextBlobBuilder* cTextBlobBuilder,
191 const OH_Drawing_Font* cFont, int32_t count, const OH_Drawing_Rect* cRect)
192 {
193 if (cFont == nullptr || count <= 0) {
194 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
195 return nullptr;
196 }
197 TextBlobBuilder* textBlobBuilder = CastToTextBlobBuilder(cTextBlobBuilder);
198 if (textBlobBuilder == nullptr) {
199 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
200 return nullptr;
201 }
202 const Font* font = CastToFont(cFont);
203 std::shared_ptr<Font> themeFont = DrawingFontUtils::GetThemeFont(font);
204 if (themeFont != nullptr) {
205 font = themeFont.get();
206 }
207 return (const OH_Drawing_RunBuffer*)&textBlobBuilder->AllocRunPos(*font, count, CastToRect(cRect));
208 }
209
OH_Drawing_TextBlobBuilderMake(OH_Drawing_TextBlobBuilder * cTextBlobBuilder)210 OH_Drawing_TextBlob* OH_Drawing_TextBlobBuilderMake(OH_Drawing_TextBlobBuilder* cTextBlobBuilder)
211 {
212 TextBlobBuilder* textBlobBuilder = CastToTextBlobBuilder(cTextBlobBuilder);
213 if (textBlobBuilder == nullptr) {
214 g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
215 return nullptr;
216 }
217 std::shared_ptr<TextBlob> textBlob = textBlobBuilder->Make();
218 if (textBlob == nullptr) {
219 return nullptr;
220 }
221 std::lock_guard<std::mutex> lock(g_textBlobLockMutex);
222 g_textBlobMap.insert({textBlob.get(), textBlob});
223 return (OH_Drawing_TextBlob*)textBlob.get();
224 }
225
OH_Drawing_TextBlobDestroy(OH_Drawing_TextBlob * cTextBlob)226 void OH_Drawing_TextBlobDestroy(OH_Drawing_TextBlob* cTextBlob)
227 {
228 std::lock_guard<std::mutex> lock(g_textBlobLockMutex);
229 auto it = g_textBlobMap.find(cTextBlob);
230 if (it == g_textBlobMap.end()) {
231 return;
232 }
233 g_textBlobMap.erase(it);
234 }
235
OH_Drawing_TextBlobBuilderDestroy(OH_Drawing_TextBlobBuilder * cTextBlobBuilder)236 void OH_Drawing_TextBlobBuilderDestroy(OH_Drawing_TextBlobBuilder* cTextBlobBuilder)
237 {
238 if (!cTextBlobBuilder) {
239 return;
240 }
241 delete CastToTextBlobBuilder(cTextBlobBuilder);
242 }
243