1 /*
2  * Copyright (c) 2020-2022 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 "draw/draw_label.h"
17 #include "common/typed_text.h"
18 #include "draw/draw_utils.h"
19 #include "engines/gfx/gfx_engine_manager.h"
20 #include "font/ui_font.h"
21 #include "font/ui_font_header.h"
22 #include "gfx_utils/graphic_log.h"
23 
24 namespace OHOS {
DrawTextOneLine(BufferInfo & gfxDstBuffer,const LabelLineInfo & labelLine,uint16_t & letterIndex)25 uint16_t DrawLabel::DrawTextOneLine(BufferInfo& gfxDstBuffer, const LabelLineInfo& labelLine, uint16_t& letterIndex)
26 {
27     if (labelLine.text == nullptr) {
28         return 0;
29     }
30     UIFont* fontEngine = UIFont::GetInstance();
31     if (labelLine.direct == TEXT_DIRECT_RTL) {
32         labelLine.pos.x -= labelLine.offset.x;
33     } else {
34         labelLine.pos.x += labelLine.offset.x;
35     }
36 
37     uint32_t i = 0;
38     uint16_t retOffsetY = 0; // ret value elipse offsetY
39     uint16_t offsetPosY = 0;
40     uint8_t maxLetterSize = GetLineMaxLetterSize(labelLine.text, labelLine.lineLength, labelLine.fontId,
41                                                  labelLine.fontSize, letterIndex, labelLine.spannableString);
42     GlyphNode glyphNode;
43     while (i < labelLine.lineLength) {
44         uint32_t letter = TypedText::GetUTF8Next(labelLine.text, i, i);
45         uint16_t fontId = labelLine.fontId;
46         uint8_t fontSize = labelLine.fontSize;
47 #if defined(ENABLE_TEXT_STYLE) && ENABLE_TEXT_STYLE
48         TextStyle textStyle = TEXT_STYLE_NORMAL;
49         if (labelLine.textStyles) {
50             textStyle = labelLine.textStyles[letterIndex];
51         }
52 #endif
53         bool haveLineBackgroundColor = false;
54         ColorType lineBackgroundColor;
55         bool havebackgroundColor = false;
56         ColorType backgroundColor;
57         ColorType foregroundColor = labelLine.style.textColor_;
58 
59         if (labelLine.spannableString != nullptr && labelLine.spannableString->GetSpannable(letterIndex)) {
60             labelLine.spannableString->GetFontId(letterIndex, fontId);
61             labelLine.spannableString->GetFontSize(letterIndex, fontSize);
62             havebackgroundColor = labelLine.spannableString->GetBackgroundColor(letterIndex, backgroundColor);
63             labelLine.spannableString->GetForegroundColor(letterIndex, foregroundColor);
64 #if defined(ENABLE_TEXT_STYLE) && ENABLE_TEXT_STYLE
65             labelLine.spannableString->GetTextStyle(letterIndex, textStyle);
66 #endif
67             haveLineBackgroundColor =
68                 labelLine.spannableString->GetLineBackgroundColor(letterIndex, lineBackgroundColor);
69         }
70         LabelLetterInfo letterInfo{labelLine.pos,
71                                    labelLine.mask,
72                                    foregroundColor,
73                                    labelLine.opaScale,
74                                    0,
75                                    0,
76                                    letter,
77                                    labelLine.direct,
78                                    fontId,
79                                    0,
80                                    fontSize,
81 #if defined(ENABLE_TEXT_STYLE) && ENABLE_TEXT_STYLE
82                                    textStyle,
83 #endif
84                                    labelLine.baseLine,
85                                    labelLine.style.letterSpace_,
86                                    labelLine.style.lineSpace_,
87                                    havebackgroundColor,
88                                    backgroundColor,
89                                    haveLineBackgroundColor,
90                                    lineBackgroundColor
91                                    };
92 #if defined(ENABLE_TEXT_STYLE) && ENABLE_TEXT_STYLE
93         glyphNode.textStyle = letterInfo.textStyle;
94 #endif
95         glyphNode.advance = 0;
96         uint8_t* fontMap = fontEngine->GetBitmap(letterInfo.letter, glyphNode, letterInfo.fontId, letterInfo.fontSize,
97                                                  letterInfo.shapingId);
98         if (fontMap != nullptr) {
99             uint8_t weight = fontEngine->GetFontWeight(glyphNode.fontId);
100             // 16: rgb565->16 rgba8888->32 font with rgba
101             if (weight >= 16) {
102                 DrawUtils::GetInstance()->DrawColorLetter(gfxDstBuffer, letterInfo, fontMap,
103                                                           glyphNode, labelLine.lineHeight);
104             } else {
105                 letterInfo.offsetY = labelLine.ellipsisOssetY == 0 ? offsetPosY : labelLine.ellipsisOssetY;
106                 retOffsetY = offsetPosY;
107                 DrawUtils::GetInstance()->DrawNormalLetter(gfxDstBuffer, letterInfo, fontMap, glyphNode, maxLetterSize);
108             }
109         }
110         if (labelLine.direct == TEXT_DIRECT_RTL) {
111             labelLine.pos.x -= (glyphNode.advance + labelLine.style.letterSpace_);
112         } else {
113             labelLine.pos.x += (glyphNode.advance + labelLine.style.letterSpace_);
114         }
115         letterIndex++;
116     }
117     return retOffsetY;
118 }
119 
GetLineMaxLetterSize(const char * text,uint16_t lineLength,uint16_t fontId,uint8_t fontSize,uint16_t letterIndex,SpannableString * spannableString)120 uint8_t DrawLabel::GetLineMaxLetterSize(const char* text, uint16_t lineLength, uint16_t fontId, uint8_t fontSize,
121                                         uint16_t letterIndex, SpannableString* spannableString)
122 {
123     if (spannableString == nullptr) {
124         return fontSize;
125     }
126     uint32_t i = 0;
127     uint8_t maxLetterSize = fontSize;
128     while (i < lineLength) {
129         uint32_t unicode = TypedText::GetUTF8Next(text, i, i);
130         if (TypedText::IsColourWord(unicode, fontId, fontSize)) {
131             letterIndex++;
132             continue;
133         }
134         if (spannableString != nullptr && spannableString->GetSpannable(letterIndex)) {
135             uint8_t tempSize = fontSize;
136             spannableString->GetFontSize(letterIndex, tempSize);
137             if (tempSize > maxLetterSize) {
138                 maxLetterSize = tempSize;
139             }
140         }
141         letterIndex++;
142     }
143     return maxLetterSize;
144 }
145 
DrawArcText(BufferInfo & gfxDstBuffer,const Rect & mask,const char * text,const Point & arcCenter,uint16_t fontId,uint8_t fontSize,const ArcTextInfo arcTextInfo,const float changeAngle,TextOrientation orientation,const Style & style,OpacityType opaScale,bool compatibilityMode)146 void DrawLabel::DrawArcText(BufferInfo& gfxDstBuffer,
147                             const Rect& mask,
148                             const char* text,
149                             const Point& arcCenter,
150                             uint16_t fontId,
151                             uint8_t fontSize,
152                             const ArcTextInfo arcTextInfo,
153                             const float changeAngle,
154                             TextOrientation orientation,
155                             const Style& style,
156                             OpacityType opaScale,
157                             bool compatibilityMode)
158 {
159     if ((text == nullptr) || (arcTextInfo.lineStart == arcTextInfo.lineEnd) || (arcTextInfo.radius == 0)) {
160         GRAPHIC_LOGE("DrawLabel::DrawArcText invalid parameter\n");
161         return;
162     }
163     OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.textOpa_);
164     if (opa == OPA_TRANSPARENT) {
165         return;
166     }
167     uint16_t letterWidth;
168     UIFont* fontEngine = UIFont::GetInstance();
169 
170     uint16_t letterHeight = fontEngine->GetHeight(fontId, fontSize);
171     uint32_t i = arcTextInfo.lineStart;
172     bool orientationFlag = (orientation == TextOrientation::INSIDE);
173     bool directFlag = (arcTextInfo.direct == TEXT_DIRECT_LTR);
174     bool xorFlag = !directFlag;
175     if (compatibilityMode) {
176         xorFlag = !((orientationFlag && directFlag) || (!orientationFlag && !directFlag));
177     }
178     float angle = directFlag ? (arcTextInfo.startAngle + changeAngle) : (arcTextInfo.startAngle - changeAngle);
179 
180     float posX;
181     float posY;
182     float rotateAngle;
183     while (i < arcTextInfo.lineEnd) {
184         uint32_t tmp = i;
185         uint32_t letter = TypedText::GetUTF8Next(text, tmp, i);
186         if (letter == 0) {
187             continue;
188         }
189         if ((letter == '\r') || (letter == '\n')) {
190             break;
191         }
192         letterWidth = fontEngine->GetWidth(letter, fontId, fontSize, 0);
193         if (!DrawLabel::CalculateAngle(letterWidth, letterHeight, style.letterSpace_,
194                                        arcTextInfo, xorFlag, tmp, orientation,
195                                        posX, posY, rotateAngle, angle,
196                                        arcCenter, compatibilityMode)) {
197             continue;
198         }
199 
200         ArcLetterInfo letterInfo;
201         letterInfo.InitData(fontId, fontSize, letter, { MATH_ROUND(posX), MATH_ROUND(posY) },
202             static_cast<int16_t>(rotateAngle), style.textColor_, opaScale, arcTextInfo.startAngle,
203             arcTextInfo.endAngle, angle, arcTextInfo.radius, compatibilityMode,
204             directFlag, orientationFlag, arcTextInfo.hasAnimator);
205 
206         DrawLetterWithRotate(gfxDstBuffer, mask, letterInfo, posX, posY);
207     }
208 }
209 
CalculateAngle(uint16_t letterWidth,uint16_t letterHeight,int16_t letterSpace,const ArcTextInfo arcTextInfo,bool xorFlag,uint32_t index,TextOrientation orientation,float & posX,float & posY,float & rotateAngle,float & angle,const Point & arcCenter,bool compatibilityMode)210 bool DrawLabel::CalculateAngle(uint16_t letterWidth,
211                                uint16_t letterHeight,
212                                int16_t letterSpace,
213                                const ArcTextInfo arcTextInfo,
214                                bool xorFlag,
215                                uint32_t index,
216                                TextOrientation orientation,
217                                float& posX,
218                                float& posY,
219                                float& rotateAngle,
220                                float& angle,
221                                const Point& arcCenter,
222                                bool compatibilityMode)
223 {
224     const int DIVIDER_BY_TWO = 2;
225     if (compatibilityMode) {
226         if ((index == arcTextInfo.lineStart) && xorFlag) {
227             angle += TypedText::GetAngleForArcLen(static_cast<float>(letterWidth), letterHeight, arcTextInfo.radius,
228                                                   arcTextInfo.direct, orientation);
229         }
230         uint16_t arcLen = letterWidth + letterSpace;
231         if (arcLen == 0) {
232             return false;
233         }
234         float incrementAngle = TypedText::GetAngleForArcLen(static_cast<float>(arcLen), letterHeight,
235                                                             arcTextInfo.radius, arcTextInfo.direct, orientation);
236 
237         rotateAngle = (orientation == TextOrientation::INSIDE) ? angle : (angle - SEMICIRCLE_IN_DEGREE);
238 
239         // 2: half
240         float fineTuningAngle = incrementAngle * (static_cast<float>(letterWidth) / (DIVIDER_BY_TWO * arcLen));
241         rotateAngle += (xorFlag ? -fineTuningAngle : fineTuningAngle);
242         TypedText::GetArcLetterPos(arcCenter, arcTextInfo.radius, angle, posX, posY);
243         angle += incrementAngle;
244     } else {
245         float incrementAngle = TypedText::GetAngleForArcLen(letterWidth, letterSpace, arcTextInfo.radius);
246         if (incrementAngle >= -EPSINON && incrementAngle <= EPSINON) {
247             return false;
248         }
249 
250         float fineTuningAngle = incrementAngle / DIVIDER_BY_TWO;
251         rotateAngle = xorFlag ? (angle - SEMICIRCLE_IN_DEGREE - fineTuningAngle) : (angle + fineTuningAngle);
252         TypedText::GetArcLetterPos(arcCenter, arcTextInfo.radius, angle, posX, posY);
253         angle = xorFlag ? (angle - incrementAngle) : (angle + incrementAngle);
254     }
255 
256     return true;
257 }
258 
DrawLetterWithRotate(BufferInfo & gfxDstBuffer,const Rect & mask,const ArcLetterInfo & letterInfo,float posX,float posY)259 void DrawLabel::DrawLetterWithRotate(BufferInfo& gfxDstBuffer,
260                                      const Rect& mask,
261                                      const ArcLetterInfo& letterInfo,
262                                      float posX,
263                                      float posY)
264 {
265     UIFont* fontEngine = UIFont::GetInstance();
266     FontHeader head;
267     GlyphNode node;
268 #if defined(ENABLE_TEXT_STYLE) && ENABLE_TEXT_STYLE
269     node.textStyle = TEXT_STYLE_NORMAL;
270 #endif
271     if (fontEngine->GetFontHeader(head, letterInfo.fontId, letterInfo.fontSize) != 0) {
272         return;
273     }
274 
275     const uint8_t* fontMap = fontEngine->GetBitmap(letterInfo.letter, node,
276         letterInfo.fontId, letterInfo.fontSize, 0);
277     if (fontMap == nullptr) {
278         return;
279     }
280     uint8_t fontWeight = fontEngine->GetFontWeight(letterInfo.fontId);
281     ColorMode colorMode = fontEngine->GetColorType(letterInfo.fontId);
282 
283     int16_t offset = letterInfo.compatibilityMode ? head.ascender : 0;
284     Rect rectLetter;
285     rectLetter.Resize(node.cols, node.rows);
286     TransformMap transMap(rectLetter);
287     // Avoiding errors caused by rounding calculations
288     transMap.Translate(Vector2<float>(posX + node.left, posY + offset - node.top));
289     transMap.Rotate(letterInfo.rotateAngle, Vector2<float>(posX, posY));
290 
291     TransformDataInfo letterTranDataInfo = {ImageHeader{colorMode, 0, 0, 0, node.cols, node.rows}, fontMap, fontWeight,
292                                             BlurLevel::LEVEL0, TransformAlgorithm::BILINEAR};
293 
294     uint8_t* buffer = nullptr;
295     if (letterInfo.hasAnimator) {
296         bool inRange = DrawLabel::CalculatedTransformDataInfo(&buffer, letterTranDataInfo, letterInfo);
297         if (inRange == false) {
298             if (buffer != nullptr) {
299                 UIFree(buffer);
300                 buffer = nullptr;
301             }
302             return;
303         }
304     }
305 
306     BaseGfxEngine::GetInstance()->DrawTransform(gfxDstBuffer, mask, Point { 0, 0 }, letterInfo.color,
307         letterInfo.opaScale, transMap, letterTranDataInfo);
308     if (buffer != nullptr) {
309         UIFree(buffer);
310         buffer = nullptr;
311     }
312 }
313 
CalculatedClipAngle(const ArcLetterInfo & letterInfo,float & angle)314 bool DrawLabel::CalculatedClipAngle(const ArcLetterInfo& letterInfo, float& angle)
315 {
316     if (letterInfo.directFlag) {
317         if ((letterInfo.compatibilityMode && letterInfo.orientationFlag) || !letterInfo.compatibilityMode) {
318             if (letterInfo.currentAngle > letterInfo.endAngle) {
319                 angle = letterInfo.currentAngle - letterInfo.endAngle;
320             } else if (letterInfo.currentAngle > letterInfo.startAngle) {
321                 angle = letterInfo.currentAngle - letterInfo.startAngle;
322             } else {
323                 return false;
324             }
325         } else {
326             if (letterInfo.currentAngle > letterInfo.endAngle) {
327                 angle = letterInfo.currentAngle - letterInfo.endAngle;
328             } else if (letterInfo.currentAngle > letterInfo.startAngle) {
329                 angle = letterInfo.currentAngle - letterInfo.startAngle;
330             } else {
331                 return false;
332             }
333         }
334     } else {
335         if (letterInfo.compatibilityMode && letterInfo.orientationFlag) {
336             if (letterInfo.currentAngle < letterInfo.endAngle) {
337                 angle = letterInfo.endAngle - letterInfo.currentAngle;
338             } else if (letterInfo.currentAngle < letterInfo.startAngle) {
339                 angle = letterInfo.startAngle - letterInfo.currentAngle;
340             } else {
341                 return false;
342             }
343         } else if ((letterInfo.compatibilityMode && !letterInfo.orientationFlag) || !letterInfo.compatibilityMode) {
344             if (letterInfo.currentAngle < letterInfo.endAngle) {
345                 angle = letterInfo.endAngle - letterInfo.currentAngle;
346             } else if (letterInfo.currentAngle < letterInfo.startAngle) {
347                 angle = letterInfo.startAngle - letterInfo.currentAngle;
348             } else {
349                 return false;
350             }
351         }
352     }
353 
354     return true;
355 }
356 
OnCalculatedClockwise(const ArcLetterInfo & letterInfo,const uint16_t sizePerPx,const uint16_t cols,const int16_t offsetX,uint16_t & begin,uint16_t & copyCols,TextInRange & range)357 void DrawLabel::OnCalculatedClockwise(const ArcLetterInfo& letterInfo, const uint16_t sizePerPx,
358                                       const uint16_t cols, const int16_t offsetX, uint16_t& begin,
359                                       uint16_t& copyCols, TextInRange& range)
360 {
361     if (!letterInfo.directFlag) {
362         return;
363     }
364     if ((letterInfo.compatibilityMode && letterInfo.orientationFlag) || !letterInfo.compatibilityMode) {
365         if (letterInfo.currentAngle > letterInfo.endAngle) {
366             if (offsetX >= cols) {
367                 range = TextInRange::OUT_RANGE;
368             }
369             copyCols = cols - offsetX;
370         } else if (letterInfo.currentAngle > letterInfo.startAngle) {
371             if (offsetX >= cols) {
372                 range = TextInRange::IN_RANGE;
373             }
374             copyCols = offsetX;
375             begin = (cols - offsetX) * sizePerPx;
376         }
377     } else {
378         if (letterInfo.currentAngle > letterInfo.endAngle) {
379             if (offsetX >= cols) {
380                 range = TextInRange::OUT_RANGE;
381             }
382             copyCols = cols - offsetX;
383             begin = offsetX * sizePerPx;
384         } else if (letterInfo.currentAngle > letterInfo.startAngle) {
385             if (offsetX >= cols) {
386                 range = TextInRange::IN_RANGE;
387             }
388             copyCols = offsetX;
389         }
390     }
391 }
392 
OnCalculatedAnticlockwise(const ArcLetterInfo & letterInfo,const uint16_t sizePerPx,const uint16_t cols,const int16_t offsetX,uint16_t & begin,uint16_t & copyCols,TextInRange & range)393 void DrawLabel::OnCalculatedAnticlockwise(const ArcLetterInfo& letterInfo, const uint16_t sizePerPx,
394                                           const uint16_t cols, const int16_t offsetX, uint16_t& begin,
395                                           uint16_t& copyCols, TextInRange& range)
396 {
397     if (letterInfo.directFlag) {
398         return;
399     }
400     if (letterInfo.compatibilityMode && letterInfo.orientationFlag) {
401         if (letterInfo.currentAngle < letterInfo.endAngle) {
402             if (offsetX >= cols) {
403                 range = TextInRange::OUT_RANGE;
404             }
405             copyCols = cols - offsetX;
406             begin = offsetX * sizePerPx;
407         } else if (letterInfo.currentAngle < letterInfo.startAngle) {
408             if (offsetX >= cols) {
409                 range = TextInRange::IN_RANGE;
410             }
411             copyCols = offsetX;
412         }
413     } else if ((letterInfo.compatibilityMode && !letterInfo.orientationFlag) || !letterInfo.compatibilityMode) {
414         if (letterInfo.currentAngle < letterInfo.endAngle) {
415             if (offsetX >= cols) {
416                 range = TextInRange::OUT_RANGE;
417             }
418             copyCols = cols - offsetX;
419         } else if (letterInfo.currentAngle < letterInfo.startAngle) {
420             if (offsetX >= cols) {
421                 range = TextInRange::IN_RANGE;
422             }
423             copyCols = offsetX;
424             begin = (cols - offsetX) * sizePerPx;
425         }
426     }
427 }
428 
CalculatedBeginAndCopySize(const ArcLetterInfo & letterInfo,const uint16_t sizePerPx,const uint16_t cols,const int16_t offsetX,uint16_t & begin,uint16_t & copyCols,TextInRange & range)429 void DrawLabel::CalculatedBeginAndCopySize(const ArcLetterInfo& letterInfo, const uint16_t sizePerPx,
430                                            const uint16_t cols, const int16_t offsetX, uint16_t& begin,
431                                            uint16_t& copyCols, TextInRange& range)
432 {
433     if (letterInfo.directFlag) {
434         OnCalculatedClockwise(letterInfo, sizePerPx, cols, offsetX, begin, copyCols, range);
435     } else {
436         OnCalculatedAnticlockwise(letterInfo, sizePerPx, cols, offsetX, begin, copyCols, range);
437     }
438 }
439 
CalculatedTransformDataInfo(uint8_t ** buffer,TransformDataInfo & letterTranDataInfo,const ArcLetterInfo & letterInfo)440 bool DrawLabel::CalculatedTransformDataInfo(uint8_t** buffer, TransformDataInfo& letterTranDataInfo,
441     const ArcLetterInfo& letterInfo)
442 {
443     float angle = 0.0f;
444     if (DrawLabel::CalculatedClipAngle(letterInfo, angle) == false) {
445         return false;
446     }
447     if (angle >= -EPSINON && angle <= EPSINON) {
448         return true;
449     }
450 
451     int16_t offsetX = static_cast<uint16_t>(angle * letterInfo.radius * UI_PI / SEMICIRCLE_IN_DEGREE);
452     uint16_t copyCols = 0;
453     uint16_t begin = 0;
454     uint16_t sizePerPx = letterTranDataInfo.pxSize / 8; // 8 bit
455     TextInRange range = TextInRange::NEED_CLIP;
456     uint16_t cols = letterTranDataInfo.header.width;
457     uint16_t rows = letterTranDataInfo.header.height;
458     DrawLabel::CalculatedBeginAndCopySize(letterInfo, sizePerPx, cols, offsetX, begin, copyCols, range);
459     if (range == TextInRange::IN_RANGE) {
460         return true;
461     } else if (range == TextInRange::OUT_RANGE) {
462         return false;
463     }
464 
465     const uint8_t* fontMap = letterTranDataInfo.data;
466 
467     uint32_t size = cols * rows * sizePerPx;
468     *buffer = static_cast<uint8_t*>(UIMalloc(size));
469     if (*buffer == nullptr) {
470         return false;
471     }
472 
473     if (memset_s(*buffer, size, 0, size) != EOK) {
474         UIFree(*buffer);
475         return false;
476     }
477 
478     for (uint16_t i = 0; i < rows; i++) {
479         uint16_t beginSize = i * cols * sizePerPx + begin;
480         uint16_t copySize = copyCols * sizePerPx;
481         if (memcpy_s(*buffer + beginSize, copySize, fontMap + beginSize, copySize) != EOK) {
482             UIFree(*buffer);
483             return false;
484         }
485     }
486     letterTranDataInfo.data = *buffer;
487     return true;
488 }
489 
GetLineBackgroundColor(uint16_t letterIndex,List<LineBackgroundColor> * linebackgroundColor,bool & havelinebackground,ColorType & linebgColor)490 void DrawLabel::GetLineBackgroundColor(uint16_t letterIndex, List<LineBackgroundColor>* linebackgroundColor,
491                                        bool& havelinebackground, ColorType& linebgColor)
492 {
493     if (linebackgroundColor->Size() > 0) {
494         ListNode<LineBackgroundColor>* lbColor = linebackgroundColor->Begin();
495         for (; lbColor != linebackgroundColor->End(); lbColor = lbColor->next_) {
496             uint32_t start = lbColor->data_.start;
497             uint32_t end = lbColor->data_.end;
498             if (letterIndex >= start && letterIndex <= end) {
499                 havelinebackground = true;
500                 linebgColor = lbColor->data_.linebackgroundColor ;
501             }
502         }
503     }
504 };
505 
GetBackgroundColor(uint16_t letterIndex,List<BackgroundColor> * backgroundColor,bool & havebackground,ColorType & bgColor)506 void DrawLabel::GetBackgroundColor(uint16_t letterIndex, List<BackgroundColor>* backgroundColor,
507                                    bool& havebackground, ColorType& bgColor)
508 {
509     if (backgroundColor->Size() > 0) {
510         ListNode<BackgroundColor>* bColor = backgroundColor->Begin();
511         for (; bColor != backgroundColor->End(); bColor = bColor->next_) {
512             uint16_t start = bColor->data_.start;
513             uint16_t end = bColor->data_.end;
514             if (letterIndex >= start && letterIndex <= end) {
515                 havebackground = true;
516                 bgColor = bColor->data_.backgroundColor ;
517             }
518         }
519     }
520 };
521 
GetForegroundColor(uint16_t letterIndex,List<ForegroundColor> * foregroundColor,ColorType & fgColor)522 void DrawLabel::GetForegroundColor(uint16_t letterIndex, List<ForegroundColor>* foregroundColor, ColorType& fgColor)
523 {
524     if (foregroundColor->Size() > 0) {
525         ListNode<ForegroundColor>* fColor = foregroundColor->Begin();
526         for (; fColor != foregroundColor->End(); fColor = fColor->next_) {
527             uint32_t start = fColor->data_.start;
528             uint32_t end = fColor->data_.end;
529             if (letterIndex >= start && letterIndex <= end) {
530                 fgColor = fColor->data_.fontColor;
531             }
532         }
533     }
534 };
535 
DrawLineBackgroundColor(BufferInfo & gfxDstBuffer,uint16_t letterIndex,const LabelLineInfo & labelLine)536 void DrawLabel::DrawLineBackgroundColor(BufferInfo& gfxDstBuffer, uint16_t letterIndex, const LabelLineInfo& labelLine)
537 {
538     uint32_t i = 0;
539     while (i < labelLine.lineLength) {
540         TypedText::GetUTF8Next(labelLine.text, i, i);
541         bool havelinebackground = false;
542         ColorType linebackgroundColor;
543         if (labelLine.spannableString != nullptr &&
544             labelLine.spannableString->GetSpannable(letterIndex)) {
545             havelinebackground =
546                 labelLine.spannableString->GetLineBackgroundColor(
547                     letterIndex, linebackgroundColor);
548         }
549         if (havelinebackground) {
550             Style style;
551             style.bgColor_ = linebackgroundColor;
552             Rect linebackground(labelLine.mask.GetLeft(), labelLine.pos.y,
553                                 labelLine.mask.GetRight(),
554                                 labelLine.pos.y + labelLine.lineHeight);
555             BaseGfxEngine::GetInstance()->DrawRect(gfxDstBuffer, labelLine.mask,
556                                                    linebackground, style,
557                                                    linebackgroundColor.alpha);
558         }
559         letterIndex++;
560     }
561 };
562 } // namespace OHOS
563