• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright (c) 2024 Huawei Device Co., Ltd.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "drawing_text_line.h"
18 
19 #include <string>
20 
21 #include "array_mgr.h"
22 #include "drawing_rect.h"
23 #include "skia_txt/run_impl.h"
24 #include "skia_txt/text_line_base.h"
25 #include "skia_txt/txt/paragraph.h"
26 #include "utils/text_log.h"
27 
28 using namespace OHOS::Rosen;
29 
30 typedef OHOS::Rosen::AdapterTxt::TextLineBaseImpl LineImpl;
31 typedef OHOS::Rosen::AdapterTxt::RunImpl RunImpl;
32 
OH_Drawing_TypographyGetTextLines(OH_Drawing_Typography * typography)33 OH_Drawing_Array* OH_Drawing_TypographyGetTextLines(OH_Drawing_Typography* typography)
34 {
35     if (typography == nullptr) {
36         TEXT_LOGE("Null typography");
37         return nullptr;
38     }
39 
40     auto paragraph = reinterpret_cast<Typography*>(typography)->GetParagraph();
41     if (paragraph == nullptr) {
42         TEXT_LOGE("Failed to get paragraph");
43         return nullptr;
44     }
45 
46     auto textLines = reinterpret_cast<SPText::Paragraph*>(paragraph)->GetTextLines();
47     if (textLines.size() == 0) {
48         TEXT_LOGE("Failed to get text lines");
49         return nullptr;
50     }
51 
52     LineObject* lineObjectArr = new (std::nothrow) LineObject[textLines.size()];
53     if (lineObjectArr == nullptr) {
54         TEXT_LOGE("Failed to create line object");
55         return nullptr;
56     }
57     for (size_t i = 0; i < textLines.size(); ++i) {
58         auto textLine = new (std::nothrow) LineImpl(std::move(textLines[i]));
59         if (textLine == nullptr) {
60             TEXT_LOGE("Failed to create line impl");
61             for (size_t j = 0; j < i; ++j) {
62                 delete reinterpret_cast<LineImpl*>(lineObjectArr[j].line);
63                 lineObjectArr[j].line = nullptr;
64             }
65             delete[] lineObjectArr;
66             return nullptr;
67         }
68 
69         lineObjectArr[i].line = reinterpret_cast<void*>(textLine);
70         lineObjectArr[i].isArray = true;
71     }
72 
73     ObjectArray* array = new (std::nothrow) ObjectArray();
74     if (array == nullptr) {
75         TEXT_LOGE("Failed to create array");
76         for (size_t i = 0; i < textLines.size(); ++i) {
77             delete reinterpret_cast<LineImpl*>(lineObjectArr[i].line);
78         }
79         delete[] lineObjectArr;
80         return nullptr;
81     }
82     array->addr = lineObjectArr;
83     array->num = textLines.size();
84     array->type = TEXT_LINE;
85 
86     return reinterpret_cast<OH_Drawing_Array*>(array);
87 }
88 
OH_Drawing_DestroyTextLines(OH_Drawing_Array * lines)89 void OH_Drawing_DestroyTextLines(OH_Drawing_Array* lines)
90 {
91     if (lines == nullptr) {
92         TEXT_LOGE("Null lines");
93         return;
94     }
95 
96     auto arrayLines = reinterpret_cast<ObjectArray*>(lines);
97     if (arrayLines != nullptr && arrayLines->type == TEXT_LINE && arrayLines->num > 0) {
98         LineObject* lineObjectArr = reinterpret_cast<LineObject*>(arrayLines->addr);
99         if (lineObjectArr != nullptr) {
100             for (size_t i = 0; i < arrayLines->num; ++i) {
101                 delete reinterpret_cast<LineImpl*>(lineObjectArr[i].line);
102                 lineObjectArr[i].line = nullptr;
103             }
104             delete[] lineObjectArr;
105             arrayLines->addr = nullptr;
106         }
107         arrayLines->num = 0;
108         arrayLines->type = INVALID;
109         delete arrayLines;
110     }
111 }
112 
OH_Drawing_DestroyTextLine(OH_Drawing_TextLine * line)113 void OH_Drawing_DestroyTextLine(OH_Drawing_TextLine* line)
114 {
115     if (line == nullptr) {
116         TEXT_LOGE("Null line");
117         return;
118     }
119 
120     LineObject* lineObject = reinterpret_cast<LineObject*>(line);
121     if (!lineObject->isArray) {
122         delete reinterpret_cast<LineImpl*>(lineObject->line);
123         lineObject->line = nullptr;
124         delete lineObject;
125     }
126 }
127 
OH_Drawing_GetTextLineByIndex(OH_Drawing_Array * lines,size_t index)128 OH_Drawing_TextLine* OH_Drawing_GetTextLineByIndex(OH_Drawing_Array* lines, size_t index)
129 {
130     if (lines == nullptr) {
131         TEXT_LOGE("Null lines");
132         return nullptr;
133     }
134 
135     auto arrayLines = reinterpret_cast<ObjectArray*>(lines);
136     if (arrayLines != nullptr &&  arrayLines->addr != nullptr &&
137         arrayLines->type == TEXT_LINE && index < arrayLines->num) {
138         LineObject* lineObjectArr = reinterpret_cast<LineObject*>(arrayLines->addr);
139         return reinterpret_cast<OH_Drawing_TextLine*>(&lineObjectArr[index]);
140     }
141 
142     return nullptr;
143 }
144 
OH_Drawing_TextLineGetGlyphCount(OH_Drawing_TextLine * line)145 double OH_Drawing_TextLineGetGlyphCount(OH_Drawing_TextLine* line)
146 {
147     if (line == nullptr) {
148         TEXT_LOGE("Null line");
149         return 0.0;
150     }
151 
152     auto lineImpl = reinterpret_cast<LineImpl*>(reinterpret_cast<LineObject*>(line)->line);
153     if (lineImpl == nullptr) {
154         TEXT_LOGE("Failed to get line");
155         return 0.0;
156     }
157 
158     return lineImpl->GetGlyphCount();
159 }
160 
OH_Drawing_TextLineGetTextRange(OH_Drawing_TextLine * line,size_t * start,size_t * end)161 void OH_Drawing_TextLineGetTextRange(OH_Drawing_TextLine* line, size_t* start, size_t* end)
162 {
163     if (line == nullptr || start == nullptr || end == nullptr) {
164         TEXT_LOGE("Param is nullptr");
165         return;
166     }
167 
168     auto lineImpl = reinterpret_cast<LineImpl*>(reinterpret_cast<LineObject*>(line)->line);
169     if (lineImpl == nullptr) {
170         TEXT_LOGE("Failed to get line");
171         return;
172     }
173 
174     Boundary range = lineImpl->GetTextRange();
175     *start = range.leftIndex;
176     *end = range.rightIndex;
177 }
178 
OH_Drawing_TextLineGetGlyphRuns(OH_Drawing_TextLine * line)179 OH_Drawing_Array* OH_Drawing_TextLineGetGlyphRuns(OH_Drawing_TextLine* line)
180 {
181     if (line == nullptr) {
182         TEXT_LOGE("Null line");
183         return nullptr;
184     }
185 
186     auto lineImpl = reinterpret_cast<LineImpl*>(reinterpret_cast<LineObject*>(line)->line);
187     if (lineImpl == nullptr) {
188         TEXT_LOGE("Failed to get line");
189         return nullptr;
190     }
191 
192     auto spTextLines = lineImpl->GetSpTextLineBase();
193     if (spTextLines == nullptr) {
194         TEXT_LOGE("Failed to get sp text line");
195         return nullptr;
196     }
197 
198     auto runs = reinterpret_cast<SPText::TextLineBase*>(spTextLines)->GetGlyphRuns();
199     if (runs.size() == 0) {
200         TEXT_LOGE("Failed to get glyph runs");
201         return nullptr;
202     }
203 
204     RunImpl* runsArr = new (std::nothrow) RunImpl[runs.size()];
205     if (runsArr == nullptr) {
206         TEXT_LOGE("Failed to create run impl");
207         return nullptr;
208     }
209     for (size_t i = 0; i < runs.size(); ++i) {
210         runsArr[i].SetSpRunBase(runs[i]);
211     }
212 
213     ObjectArray* array = new (std::nothrow) ObjectArray();
214     if (array == nullptr) {
215         TEXT_LOGE("Failed to create array");
216         delete[] runsArr;
217         return nullptr;
218     }
219     array->addr = runsArr;
220     array->num = runs.size();
221     array->type = TEXT_RUN;
222 
223     return reinterpret_cast<OH_Drawing_Array*>(array);
224 }
225 
OH_Drawing_DestroyRuns(OH_Drawing_Array * runs)226 void OH_Drawing_DestroyRuns(OH_Drawing_Array* runs)
227 {
228     if (runs == nullptr) {
229         TEXT_LOGE("Null runs");
230         return;
231     }
232 
233     auto arrayRuns = reinterpret_cast<ObjectArray*>(runs);
234     if (arrayRuns != nullptr && arrayRuns->type == TEXT_RUN && arrayRuns->num > 0) {
235         RunImpl* runsArr = reinterpret_cast<RunImpl*>(arrayRuns->addr);
236         if (runsArr != nullptr) {
237             delete[] runsArr;
238             arrayRuns->addr = nullptr;
239         }
240         arrayRuns->num = 0;
241         arrayRuns->type = INVALID;
242         delete arrayRuns;
243     }
244 }
245 
OH_Drawing_GetRunByIndex(OH_Drawing_Array * runs,size_t index)246 OH_Drawing_Run* OH_Drawing_GetRunByIndex(OH_Drawing_Array* runs, size_t index)
247 {
248     if (runs == nullptr) {
249         TEXT_LOGE("Null runs");
250         return nullptr;
251     }
252 
253     auto arrayRuns = reinterpret_cast<ObjectArray*>(runs);
254     if (arrayRuns != nullptr &&  arrayRuns->addr != nullptr &&
255         arrayRuns->type == TEXT_RUN && index < arrayRuns->num) {
256         RunImpl* run = reinterpret_cast<RunImpl*>(arrayRuns->addr);
257         return reinterpret_cast<OH_Drawing_Run*>(&run[index]);
258     }
259 
260     return nullptr;
261 }
262 
OH_Drawing_TextLinePaint(OH_Drawing_TextLine * line,OH_Drawing_Canvas * canvas,double x,double y)263 void OH_Drawing_TextLinePaint(OH_Drawing_TextLine* line, OH_Drawing_Canvas* canvas, double x, double y)
264 {
265     if (line == nullptr || canvas == nullptr) {
266         TEXT_LOGE("Invalid parameter");
267         return;
268     }
269 
270     auto lineImpl = reinterpret_cast<LineImpl*>(reinterpret_cast<LineObject*>(line)->line);
271     if (lineImpl == nullptr) {
272         TEXT_LOGE("Failed to get line");
273         return;
274     }
275 
276     lineImpl->Paint(reinterpret_cast<OHOS::Rosen::Drawing::Canvas*>(canvas), x, y);
277 }
278 
OH_Drawing_TextLineCreateTruncatedLine(OH_Drawing_TextLine * line,double width,int mode,const char * ellipsis)279 OH_Drawing_TextLine* OH_Drawing_TextLineCreateTruncatedLine(OH_Drawing_TextLine* line, double width, int mode,
280     const char* ellipsis)
281 {
282     if (line == nullptr || ellipsis == nullptr) {
283         TEXT_LOGE("Invalid parameter");
284         return nullptr;
285     }
286 
287     auto lineImpl = reinterpret_cast<LineImpl*>(reinterpret_cast<LineObject*>(line)->line);
288     if (lineImpl == nullptr) {
289         TEXT_LOGE("Failed to get line");
290         return nullptr;
291     }
292 
293     auto spTextLines = lineImpl->GetSpTextLineBase();
294     if (spTextLines == nullptr) {
295         TEXT_LOGE("Failed to get sp text line");
296         return nullptr;
297     }
298 
299     std::string ellipsisStr(ellipsis);
300     auto truncatedTextLine = reinterpret_cast<SPText::TextLineBase*>(spTextLines)->CreateTruncatedLine(
301         width, static_cast<EllipsisModal>(mode), ellipsisStr);
302     if (truncatedTextLine == nullptr) {
303         TEXT_LOGE("Failed to create truncated line");
304         return nullptr;
305     }
306 
307     auto truncatedLine = new (std::nothrow) LineImpl(std::move(truncatedTextLine));
308     if (truncatedLine == nullptr) {
309         TEXT_LOGE("Failed to create line impl");
310         return nullptr;
311     }
312 
313     LineObject* lineObject = new (std::nothrow) LineObject();
314     if (lineObject == nullptr) {
315         TEXT_LOGE("Failed to create array");
316         delete truncatedLine;
317         return nullptr;
318     }
319 
320     lineObject->line = reinterpret_cast<void*>(truncatedLine);
321     lineObject->isArray = false;
322 
323     return reinterpret_cast<OH_Drawing_TextLine*>(lineObject);
324 }
325 
OH_Drawing_TextLineGetTypographicBounds(OH_Drawing_TextLine * line,double * ascent,double * descent,double * leading)326 double OH_Drawing_TextLineGetTypographicBounds(OH_Drawing_TextLine* line, double* ascent, double* descent,
327     double* leading)
328 {
329     if (line == nullptr || ascent == nullptr || descent == nullptr || leading == nullptr) {
330         TEXT_LOGE("Invalid parameter");
331         return 0.0;
332     }
333 
334     auto lineImpl = reinterpret_cast<LineImpl*>(reinterpret_cast<LineObject*>(line)->line);
335     if (lineImpl == nullptr) {
336         TEXT_LOGE("Failed to get line");
337         return 0.0;
338     }
339 
340     return lineImpl->GetTypographicBounds(ascent, descent, leading);
341 }
342 
OH_Drawing_TextLineGetImageBounds(OH_Drawing_TextLine * line)343 OH_Drawing_Rect* OH_Drawing_TextLineGetImageBounds(OH_Drawing_TextLine* line)
344 {
345     if (line == nullptr) {
346         TEXT_LOGE("Null line");
347         return nullptr;
348     }
349 
350     auto lineImpl = reinterpret_cast<LineImpl*>(reinterpret_cast<LineObject*>(line)->line);
351     if (lineImpl == nullptr) {
352         TEXT_LOGE("Failed to get line");
353         return nullptr;
354     }
355 
356     auto skRect = lineImpl->GetImageBounds();
357     return OH_Drawing_RectCreate(skRect.GetLeft(), skRect.GetTop(), skRect.GetRight(), skRect.GetBottom());
358 }
359 
OH_Drawing_TextLineGetTrailingSpaceWidth(OH_Drawing_TextLine * line)360 double OH_Drawing_TextLineGetTrailingSpaceWidth(OH_Drawing_TextLine* line)
361 {
362     if (line == nullptr) {
363         TEXT_LOGE("Null line");
364         return 0.0;
365     }
366 
367     auto lineImpl = reinterpret_cast<LineImpl*>(reinterpret_cast<LineObject*>(line)->line);
368     if (lineImpl == nullptr) {
369         TEXT_LOGE("Failed to get line");
370         return 0.0;
371     }
372 
373     return lineImpl->GetTrailingSpaceWidth();
374 }
375 
OH_Drawing_TextLineGetStringIndexForPosition(OH_Drawing_TextLine * line,OH_Drawing_Point * point)376 int32_t OH_Drawing_TextLineGetStringIndexForPosition(OH_Drawing_TextLine* line, OH_Drawing_Point* point)
377 {
378     if (line == nullptr || point == nullptr) {
379         TEXT_LOGE("Invalid parameter");
380         return 0;
381     }
382 
383     auto lineImpl = reinterpret_cast<LineImpl*>(reinterpret_cast<LineObject*>(line)->line);
384     if (lineImpl == nullptr) {
385         TEXT_LOGE("Failed to get line");
386         return 0;
387     }
388 
389     return lineImpl->GetStringIndexForPosition(*reinterpret_cast<SkPoint*>(point));
390 }
391 
OH_Drawing_TextLineGetOffsetForStringIndex(OH_Drawing_TextLine * line,int32_t index)392 double OH_Drawing_TextLineGetOffsetForStringIndex(OH_Drawing_TextLine* line, int32_t index)
393 {
394     if (line == nullptr) {
395         TEXT_LOGE("Null line");
396         return 0.0;
397     }
398 
399     auto lineImpl = reinterpret_cast<LineImpl*>(reinterpret_cast<LineObject*>(line)->line);
400     if (lineImpl == nullptr) {
401         TEXT_LOGE("Failed to get line");
402         return 0.0;
403     }
404 
405     return lineImpl->GetOffsetForStringIndex(index);
406 }
407 
OH_Drawing_TextLineEnumerateCaretOffsets(OH_Drawing_TextLine * line,Drawing_CaretOffsetsCallback callback)408 void OH_Drawing_TextLineEnumerateCaretOffsets(OH_Drawing_TextLine* line, Drawing_CaretOffsetsCallback callback)
409 {
410     if (line == nullptr || callback == nullptr) {
411         TEXT_LOGE("Invalid parameter");
412         return;
413     }
414 
415     auto lineImpl = reinterpret_cast<LineImpl*>(reinterpret_cast<LineObject*>(line)->line);
416     if (lineImpl == nullptr) {
417         TEXT_LOGE("Failed to get line");
418         return;
419     }
420 
421     bool isHardBreak = false;
422     std::map<int32_t, double> offsetMap = lineImpl->GetIndexAndOffsets(isHardBreak);
423     double leftOffset = 0.0;
424     const size_t twoNum = 2;
425     for (auto it = offsetMap.begin(); it != offsetMap.end(); ++it) {
426         for (size_t i = 0; i < twoNum; i++) {
427             double offset = (i == 0) ? leftOffset: it->second;
428             bool leadingEdge = (i == 0) ? true : false;
429             if (callback(offset, it->first, leadingEdge)) {
430                 return;
431             }
432         }
433         leftOffset = it->second;
434     }
435     if (isHardBreak && offsetMap.size() > 0) {
436         if (!callback(leftOffset, offsetMap.rbegin()->first + 1, true)) {
437             callback(leftOffset, offsetMap.rbegin()->first + 1, false);
438         }
439     }
440 }
441 
OH_Drawing_TextLineGetAlignmentOffset(OH_Drawing_TextLine * line,double alignmentFactor,double alignmentWidth)442 double OH_Drawing_TextLineGetAlignmentOffset(OH_Drawing_TextLine* line, double alignmentFactor, double alignmentWidth)
443 {
444     if (line == nullptr) {
445         TEXT_LOGE("Null line");
446         return 0.0;
447     }
448 
449     auto lineImpl = reinterpret_cast<LineImpl*>(reinterpret_cast<LineObject*>(line)->line);
450     if (lineImpl == nullptr) {
451         TEXT_LOGE("Failed to get line");
452         return 0.0;
453     }
454 
455     return lineImpl->GetAlignmentOffset(alignmentFactor, alignmentWidth);
456 }