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