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_font.h"
17 
18 #include "src/utils/SkUTF.h"
19 
20 #include "drawing_canvas_utils.h"
21 #include "text/font.h"
22 
23 using namespace OHOS;
24 using namespace Rosen;
25 using namespace Drawing;
26 
CastToFont(OH_Drawing_Font * cFont)27 static Font* CastToFont(OH_Drawing_Font* cFont)
28 {
29     return reinterpret_cast<Font*>(cFont);
30 }
31 
CastToFont(const OH_Drawing_Font * cFont)32 static const Font* CastToFont(const OH_Drawing_Font* cFont)
33 {
34     return reinterpret_cast<const Font*>(cFont);
35 }
36 
CastToFont(const OH_Drawing_Font & cFont)37 static const Font& CastToFont(const OH_Drawing_Font& cFont)
38 {
39     return reinterpret_cast<const Font&>(cFont);
40 }
41 
CastToTypeface(OH_Drawing_Typeface * cTypeface)42 static Typeface* CastToTypeface(OH_Drawing_Typeface* cTypeface)
43 {
44     return reinterpret_cast<Typeface*>(cTypeface);
45 }
46 
OH_Drawing_FontSetEdging(OH_Drawing_Font * cFont,OH_Drawing_FontEdging cEdging)47 void OH_Drawing_FontSetEdging(OH_Drawing_Font* cFont, OH_Drawing_FontEdging cEdging)
48 {
49     Font* font = CastToFont(cFont);
50     if (font == nullptr) {
51         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
52         return;
53     }
54     if (cEdging < FONT_EDGING_ALIAS || cEdging > FONT_EDGING_SUBPIXEL_ANTI_ALIAS) {
55         g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
56         return;
57     }
58     font->SetEdging(static_cast<FontEdging>(cEdging));
59 }
60 
OH_Drawing_FontGetEdging(const OH_Drawing_Font * cFont)61 OH_Drawing_FontEdging OH_Drawing_FontGetEdging(const OH_Drawing_Font* cFont)
62 {
63     const Font* font = CastToFont(cFont);
64     if (font == nullptr) {
65         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
66         return FONT_EDGING_ALIAS;
67     }
68     return static_cast<OH_Drawing_FontEdging>(font->GetEdging());
69 }
70 
OH_Drawing_FontSetHinting(OH_Drawing_Font * cFont,OH_Drawing_FontHinting cHinting)71 void OH_Drawing_FontSetHinting(OH_Drawing_Font* cFont, OH_Drawing_FontHinting cHinting)
72 {
73     Font* font = CastToFont(cFont);
74     if (font == nullptr) {
75         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
76         return;
77     }
78     if (cHinting < FONT_HINTING_NONE || cHinting > FONT_HINTING_FULL) {
79         g_drawingErrorCode = OH_DRAWING_ERROR_PARAMETER_OUT_OF_RANGE;
80         return;
81     }
82     font->SetHinting(static_cast<FontHinting>(cHinting));
83 }
84 
OH_Drawing_FontGetHinting(const OH_Drawing_Font * cFont)85 OH_Drawing_FontHinting OH_Drawing_FontGetHinting(const OH_Drawing_Font* cFont)
86 {
87     const Font* font = CastToFont(cFont);
88     if (font == nullptr) {
89         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
90         return FONT_HINTING_NONE;
91     }
92     return static_cast<OH_Drawing_FontHinting>(font->GetHinting());
93 }
94 
OH_Drawing_FontSetForceAutoHinting(OH_Drawing_Font * cFont,bool isForceAutoHinting)95 void OH_Drawing_FontSetForceAutoHinting(OH_Drawing_Font* cFont, bool isForceAutoHinting)
96 {
97     Font* font = CastToFont(cFont);
98     if (font == nullptr) {
99         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
100         return;
101     }
102     font->SetForceAutoHinting(isForceAutoHinting);
103 }
104 
OH_Drawing_FontIsForceAutoHinting(const OH_Drawing_Font * cFont)105 bool OH_Drawing_FontIsForceAutoHinting(const OH_Drawing_Font* cFont)
106 {
107     const Font* font = CastToFont(cFont);
108     if (font == nullptr) {
109         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
110         return false;
111     }
112     return font->IsForceAutoHinting();
113 }
114 
OH_Drawing_FontSetBaselineSnap(OH_Drawing_Font * cFont,bool baselineSnap)115 void OH_Drawing_FontSetBaselineSnap(OH_Drawing_Font* cFont, bool baselineSnap)
116 {
117     Font* font = CastToFont(cFont);
118     if (font == nullptr) {
119         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
120         return;
121     }
122     font->SetBaselineSnap(baselineSnap);
123 }
124 
OH_Drawing_FontIsBaselineSnap(const OH_Drawing_Font * cFont)125 bool OH_Drawing_FontIsBaselineSnap(const OH_Drawing_Font* cFont)
126 {
127     const Font* font = CastToFont(cFont);
128     if (font == nullptr) {
129         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
130         return false;
131     }
132     return font->IsBaselineSnap();
133 }
134 
OH_Drawing_FontSetSubpixel(OH_Drawing_Font * cFont,bool isSubpixel)135 void OH_Drawing_FontSetSubpixel(OH_Drawing_Font* cFont, bool isSubpixel)
136 {
137     Font* font = CastToFont(cFont);
138     if (font == nullptr) {
139         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
140         return;
141     }
142     font->SetSubpixel(isSubpixel);
143 }
144 
OH_Drawing_FontIsSubpixel(const OH_Drawing_Font * cFont)145 bool OH_Drawing_FontIsSubpixel(const OH_Drawing_Font* cFont)
146 {
147     const Font* font = CastToFont(cFont);
148     if (font == nullptr) {
149         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
150         return false;
151     }
152     return font->IsSubpixel();
153 }
154 
OH_Drawing_FontCreate()155 OH_Drawing_Font* OH_Drawing_FontCreate()
156 {
157     Font* font = new Font();
158     font->SetTypeface(g_LoadZhCnTypeface());
159     return (OH_Drawing_Font*)font;
160 }
161 
OH_Drawing_FontSetTypeface(OH_Drawing_Font * cFont,OH_Drawing_Typeface * cTypeface)162 void OH_Drawing_FontSetTypeface(OH_Drawing_Font* cFont, OH_Drawing_Typeface* cTypeface)
163 {
164     Font* font = CastToFont(cFont);
165     if (font == nullptr) {
166         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
167         return;
168     }
169     font->SetTypeface(std::shared_ptr<Typeface>{CastToTypeface(cTypeface), [](auto p) {}});
170 }
171 
OH_Drawing_FontGetTypeface(OH_Drawing_Font * cFont)172 OH_Drawing_Typeface* OH_Drawing_FontGetTypeface(OH_Drawing_Font* cFont)
173 {
174     Font* font = CastToFont(cFont);
175     if (font == nullptr) {
176         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
177         return nullptr;
178     }
179     return (OH_Drawing_Typeface*)(font->GetTypeface().get());
180 }
181 
OH_Drawing_FontSetTextSize(OH_Drawing_Font * cFont,float textSize)182 void OH_Drawing_FontSetTextSize(OH_Drawing_Font* cFont, float textSize)
183 {
184     Font* font = CastToFont(cFont);
185     if (font == nullptr) {
186         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
187         return;
188     }
189     font->SetSize(textSize);
190 }
191 
OH_Drawing_FontGetTextSize(const OH_Drawing_Font * cFont)192 float OH_Drawing_FontGetTextSize(const OH_Drawing_Font* cFont)
193 {
194     const Font* font = CastToFont(cFont);
195     if (font == nullptr) {
196         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
197         return -1.0f;
198     }
199     return font->GetSize();
200 }
201 
OH_Drawing_FontCountText(OH_Drawing_Font * cFont,const void * text,size_t byteLength,OH_Drawing_TextEncoding encoding)202 int OH_Drawing_FontCountText(OH_Drawing_Font* cFont, const void* text, size_t byteLength,
203     OH_Drawing_TextEncoding encoding)
204 {
205     if (cFont == nullptr || text == nullptr) {
206         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
207         return 0;
208     }
209     Font* font = CastToFont(cFont);
210     return font->CountText(text, byteLength, static_cast<TextEncoding>(encoding));
211 }
212 
OH_Drawing_FontTextToGlyphs(const OH_Drawing_Font * cFont,const void * text,uint32_t byteLength,OH_Drawing_TextEncoding encoding,uint16_t * glyphs,int maxGlyphCount)213 uint32_t OH_Drawing_FontTextToGlyphs(const OH_Drawing_Font* cFont, const void* text, uint32_t byteLength,
214     OH_Drawing_TextEncoding encoding, uint16_t* glyphs, int maxGlyphCount)
215 {
216     if (cFont == nullptr || text == nullptr || glyphs == nullptr || byteLength == 0 || maxGlyphCount <= 0) {
217         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
218         return 0;
219     }
220     return CastToFont(*cFont).TextToGlyphs(text, byteLength,
221         static_cast<TextEncoding>(encoding), glyphs, maxGlyphCount);
222 }
223 
OH_Drawing_FontGetWidths(const OH_Drawing_Font * cFont,const uint16_t * glyphs,int count,float * widths)224 void OH_Drawing_FontGetWidths(const OH_Drawing_Font* cFont, const uint16_t* glyphs, int count, float* widths)
225 {
226     if (cFont == nullptr || glyphs == nullptr || widths == nullptr || count <= 0) {
227         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
228         return;
229     }
230     CastToFont(*cFont).GetWidths(glyphs, count, widths);
231 }
232 
OH_Drawing_FontMeasureSingleCharacter(const OH_Drawing_Font * cFont,const char * str,float * textWidth)233 OH_Drawing_ErrorCode OH_Drawing_FontMeasureSingleCharacter(const OH_Drawing_Font* cFont, const char* str,
234     float* textWidth)
235 {
236     if (cFont == nullptr || str == nullptr || textWidth == nullptr) {
237         return OH_DRAWING_ERROR_INVALID_PARAMETER;
238     }
239     size_t len = strlen(str);
240     if (len == 0) {
241         return OH_DRAWING_ERROR_INVALID_PARAMETER;
242     }
243     const char* currentStr = str;
244     int32_t unicode = SkUTF::NextUTF8(&currentStr, currentStr + len);
245     *textWidth = CastToFont(*cFont).MeasureSingleCharacter(unicode);
246     return OH_DRAWING_SUCCESS;
247 }
248 
OH_Drawing_FontMeasureText(const OH_Drawing_Font * cFont,const void * text,size_t byteLength,OH_Drawing_TextEncoding encoding,OH_Drawing_Rect * bounds,float * textWidth)249 OH_Drawing_ErrorCode OH_Drawing_FontMeasureText(const OH_Drawing_Font* cFont, const void* text, size_t byteLength,
250     OH_Drawing_TextEncoding encoding, OH_Drawing_Rect* bounds, float* textWidth)
251 {
252     if (cFont == nullptr || text == nullptr || byteLength == 0 || textWidth == nullptr) {
253         return OH_DRAWING_ERROR_INVALID_PARAMETER;
254     }
255 
256     *textWidth = CastToFont(*cFont).MeasureText(text, byteLength,
257         static_cast<TextEncoding>(encoding), reinterpret_cast<Drawing::Rect*>(bounds));
258     return OH_DRAWING_SUCCESS;
259 }
260 
OH_Drawing_FontSetLinearText(OH_Drawing_Font * cFont,bool isLinearText)261 void OH_Drawing_FontSetLinearText(OH_Drawing_Font* cFont, bool isLinearText)
262 {
263     Font* font = CastToFont(cFont);
264     if (font == nullptr) {
265         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
266         return;
267     }
268     font->SetLinearMetrics(isLinearText);
269 }
270 
OH_Drawing_FontIsLinearText(const OH_Drawing_Font * cFont)271 bool OH_Drawing_FontIsLinearText(const OH_Drawing_Font* cFont)
272 {
273     const Font* font = CastToFont(cFont);
274     if (font == nullptr) {
275         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
276         return false;
277     }
278     return font->IsLinearMetrics();
279 }
280 
OH_Drawing_FontSetTextSkewX(OH_Drawing_Font * cFont,float skewX)281 void OH_Drawing_FontSetTextSkewX(OH_Drawing_Font* cFont, float skewX)
282 {
283     Font* font = CastToFont(cFont);
284     if (font == nullptr) {
285         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
286         return;
287     }
288     font->SetSkewX(skewX);
289 }
290 
OH_Drawing_FontGetTextSkewX(const OH_Drawing_Font * cFont)291 float OH_Drawing_FontGetTextSkewX(const OH_Drawing_Font* cFont)
292 {
293     const Font* font = CastToFont(cFont);
294     if (font == nullptr) {
295         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
296         return -1.0f;
297     }
298     return font->GetSkewX();
299 }
300 
OH_Drawing_FontSetFakeBoldText(OH_Drawing_Font * cFont,bool isFakeBoldText)301 void OH_Drawing_FontSetFakeBoldText(OH_Drawing_Font* cFont, bool isFakeBoldText)
302 {
303     Font* font = CastToFont(cFont);
304     if (font == nullptr) {
305         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
306         return;
307     }
308     font->SetEmbolden(isFakeBoldText);
309 }
310 
OH_Drawing_FontIsFakeBoldText(const OH_Drawing_Font * cFont)311 bool OH_Drawing_FontIsFakeBoldText(const OH_Drawing_Font* cFont)
312 {
313     const Font* font = CastToFont(cFont);
314     if (font == nullptr) {
315         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
316         return false;
317     }
318     return font->IsEmbolden();
319 }
320 
OH_Drawing_FontSetScaleX(OH_Drawing_Font * cFont,float scaleX)321 void OH_Drawing_FontSetScaleX(OH_Drawing_Font* cFont, float scaleX)
322 {
323     Font* font = CastToFont(cFont);
324     if (font == nullptr) {
325         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
326         return;
327     }
328     font->SetScaleX(scaleX);
329 }
330 
OH_Drawing_FontGetScaleX(const OH_Drawing_Font * cFont)331 float OH_Drawing_FontGetScaleX(const OH_Drawing_Font* cFont)
332 {
333     const Font* font = CastToFont(cFont);
334     if (font == nullptr) {
335         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
336         return -1.0f;
337     }
338     return font->GetScaleX();
339 }
340 
OH_Drawing_FontSetEmbeddedBitmaps(OH_Drawing_Font * cFont,bool isEmbeddedBitmaps)341 void OH_Drawing_FontSetEmbeddedBitmaps(OH_Drawing_Font* cFont, bool isEmbeddedBitmaps)
342 {
343     Font* font = CastToFont(cFont);
344     if (font == nullptr) {
345         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
346         return;
347     }
348     font->SetEmbeddedBitmaps(isEmbeddedBitmaps);
349 }
350 
OH_Drawing_FontIsEmbeddedBitmaps(const OH_Drawing_Font * cFont)351 bool OH_Drawing_FontIsEmbeddedBitmaps(const OH_Drawing_Font* cFont)
352 {
353     const Font* font = CastToFont(cFont);
354     if (font == nullptr) {
355         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
356         return false;
357     }
358     return font->IsEmbeddedBitmaps();
359 }
360 
OH_Drawing_FontDestroy(OH_Drawing_Font * cFont)361 void OH_Drawing_FontDestroy(OH_Drawing_Font* cFont)
362 {
363     if (!cFont) {
364         return;
365     }
366     delete CastToFont(cFont);
367 }
368 
OH_Drawing_FontGetMetrics(OH_Drawing_Font * cFont,OH_Drawing_Font_Metrics * cFontMetrics)369 float OH_Drawing_FontGetMetrics(OH_Drawing_Font* cFont, OH_Drawing_Font_Metrics* cFontMetrics)
370 {
371     float ret = -1;
372     Font* font = CastToFont(cFont);
373     if (font == nullptr || cFontMetrics == nullptr) {
374         g_drawingErrorCode = OH_DRAWING_ERROR_INVALID_PARAMETER;
375         return ret;
376     }
377     FontMetrics metrics;
378     ret = font->GetMetrics(&metrics);
379 
380     cFontMetrics->top = metrics.fTop;
381     cFontMetrics->ascent = metrics.fAscent;
382     cFontMetrics->descent = metrics.fDescent;
383     cFontMetrics->leading = metrics.fLeading;
384     cFontMetrics->bottom = metrics.fBottom;
385     return ret;
386 }