• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <cstdio>
18 #include "common/typed_text.h"
19 #include "draw/draw_utils.h"
20 #include "engines/gfx/gfx_engine_manager.h"
21 #include "font/ui_font.h"
22 #include "font/ui_font_header.h"
23 #include "gfx_utils/graphic_log.h"
24 
25 namespace OHOS {
DrawTextOneLine(BufferInfo & gfxDstBuffer,const LabelLineInfo & labelLine,uint16_t & letterIndex)26 uint16_t DrawLabel::DrawTextOneLine(BufferInfo& gfxDstBuffer, const LabelLineInfo& labelLine,
27                                     uint16_t& letterIndex)
28 {
29     if (labelLine.text == nullptr) {
30         return 0;
31     }
32     UIFont* fontEngine = UIFont::GetInstance();
33     if (labelLine.direct == TEXT_DIRECT_RTL) {
34         labelLine.pos.x -= labelLine.offset.x;
35     } else {
36         labelLine.pos.x += labelLine.offset.x;
37     }
38 
39     uint32_t i = 0;
40     uint16_t retOffsetY = 0; // ret value elipse offsetY
41     uint16_t offsetPosY = 0;
42     uint8_t maxLetterSize = GetLineMaxLetterSize(labelLine.text, labelLine.lineLength, labelLine.fontId,
43                                                  labelLine.fontSize, letterIndex, labelLine.sizeSpans);
44     DrawLineBackgroundColor(gfxDstBuffer, letterIndex, labelLine);
45     GlyphNode glyphNode;
46     while (i < labelLine.lineLength) {
47         uint32_t letter = TypedText::GetUTF8Next(labelLine.text, i, i);
48         uint16_t fontId = labelLine.fontId;
49         uint8_t fontSize = labelLine.fontSize;
50         if (labelLine.sizeSpans != nullptr && labelLine.sizeSpans[letterIndex].isSizeSpan) {
51             fontId = labelLine.sizeSpans[letterIndex].fontId;
52             fontSize = labelLine.sizeSpans[letterIndex].size;
53         }
54         bool havebackgroundColor = false;
55         ColorType backgroundColor;
56         GetBackgroundColor(letterIndex, labelLine.backgroundColor, havebackgroundColor, backgroundColor);
57 
58         ColorType foregroundColor = labelLine.style.textColor_;
59         GetForegroundColor(letterIndex, labelLine.foregroundColor, foregroundColor);
60 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
61         TextStyle textStyle = TEXT_STYLE_NORMAL;
62         if (labelLine.textStyles) {
63             textStyle = labelLine.textStyles[letterIndex];
64         }
65 #endif
66         LabelLetterInfo letterInfo{labelLine.pos,
67                                    labelLine.mask,
68                                    foregroundColor,
69                                    labelLine.opaScale,
70                                    0,
71                                    0,
72                                    letter,
73                                    labelLine.direct,
74                                    fontId,
75                                    0,
76                                    fontSize,
77 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
78                                    textStyle,
79 #endif
80                                    labelLine.baseLine,
81                                    labelLine.style.letterSpace_,
82                                    labelLine.style.lineSpace_,
83                                    havebackgroundColor,
84                                    backgroundColor};
85 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
86         glyphNode.textStyle = letterInfo.textStyle;
87 #endif
88         glyphNode.advance = 0;
89         uint8_t* fontMap = fontEngine->GetBitmap(letterInfo.letter, glyphNode, letterInfo.fontId, letterInfo.fontSize,
90                                                  letterInfo.shapingId);
91         if (fontMap != nullptr) {
92             uint8_t weight = UIFont::GetInstance()->GetFontWeight(glyphNode.fontId);
93             // 16: rgb565->16 rgba8888->32 font with rgba
94             if (weight >= 16) {
95                 DrawUtils::GetInstance()->DrawColorLetter(gfxDstBuffer, letterInfo, fontMap, glyphNode, maxLetterSize);
96             } else {
97                 letterInfo.offsetY = labelLine.ellipsisOssetY == 0 ? offsetPosY : labelLine.ellipsisOssetY;
98                 retOffsetY = offsetPosY;
99                 DrawUtils::GetInstance()->DrawNormalLetter(gfxDstBuffer, letterInfo, fontMap, glyphNode, maxLetterSize);
100             }
101         }
102         if (labelLine.direct == TEXT_DIRECT_RTL) {
103             labelLine.pos.x -= (glyphNode.advance + labelLine.style.letterSpace_);
104         } else {
105             labelLine.pos.x += (glyphNode.advance + labelLine.style.letterSpace_);
106         }
107 
108         letterIndex++;
109     }
110     return retOffsetY;
111 }
112 
GetLineMaxLetterSize(const char * text,uint16_t lineLength,uint16_t fontId,uint8_t fontSize,uint16_t letterIndex,SizeSpan * sizeSpans)113 uint8_t DrawLabel::GetLineMaxLetterSize(const char* text, uint16_t lineLength, uint16_t fontId, uint8_t fontSize,
114                                         uint16_t letterIndex, SizeSpan* sizeSpans)
115 {
116     if (sizeSpans == nullptr) {
117         return fontSize;
118     }
119     uint32_t i = 0;
120     uint8_t maxLetterSize = fontSize;
121     while (i < lineLength) {
122         uint32_t unicode = TypedText::GetUTF8Next(text, i, i);
123         if (TypedText::IsColourWord(unicode, fontId, fontSize)) {
124             letterIndex++;
125             continue;
126         }
127         if (sizeSpans != nullptr && sizeSpans[letterIndex].isSizeSpan) {
128             uint8_t tempSize = sizeSpans[letterIndex].size;
129             if (tempSize > maxLetterSize) {
130                 maxLetterSize = tempSize;
131             }
132         }
133         letterIndex++;
134     }
135     return maxLetterSize;
136 }
137 
DrawArcText(BufferInfo & gfxDstBuffer,const Rect & mask,const char * text,const Point & arcCenter,uint16_t fontId,uint8_t fontSize,const ArcTextInfo arcTextInfo,TextOrientation orientation,const Style & style,OpacityType opaScale)138 void DrawLabel::DrawArcText(BufferInfo& gfxDstBuffer,
139                             const Rect& mask,
140                             const char* text,
141                             const Point& arcCenter,
142                             uint16_t fontId,
143                             uint8_t fontSize,
144                             const ArcTextInfo arcTextInfo,
145                             TextOrientation orientation,
146                             const Style& style,
147                             OpacityType opaScale)
148 {
149     if ((text == nullptr) || (arcTextInfo.lineStart == arcTextInfo.lineEnd) || (arcTextInfo.radius == 0)) {
150         GRAPHIC_LOGE("DrawLabel::DrawArcText invalid parameter\n");
151         return;
152     }
153     OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.textOpa_);
154     if (opa == OPA_TRANSPARENT) {
155         return;
156     }
157     uint16_t letterWidth;
158     uint16_t letterHeight = UIFont::GetInstance()->GetHeight(fontId, fontSize);
159     uint32_t i = arcTextInfo.lineStart;
160     float angle = arcTextInfo.startAngle;
161     float posX;
162     float posY;
163     float rotateAngle;
164 
165     bool orientationFlag = (orientation == TextOrientation::INSIDE);
166     bool directFlag = (arcTextInfo.direct == TEXT_DIRECT_LTR);
167     bool xorFlag = !((orientationFlag && directFlag) || (!orientationFlag && !directFlag));
168 
169     while (i < arcTextInfo.lineEnd) {
170         uint32_t tmp = i;
171         uint32_t letter = TypedText::GetUTF8Next(text, tmp, i);
172         if (letter == 0) {
173             continue;
174         }
175         if ((letter == '\r') || (letter == '\n')) {
176             break;
177         }
178         letterWidth = UIFont::GetInstance()->GetWidth(letter, fontId, fontSize, 0);
179         if ((tmp == arcTextInfo.lineStart) && xorFlag) {
180             angle += TypedText::GetAngleForArcLen(static_cast<float>(letterWidth), letterHeight, arcTextInfo.radius,
181                                                   arcTextInfo.direct, orientation);
182         }
183         uint16_t arcLen = letterWidth + style.letterSpace_;
184         if (arcLen == 0) {
185             continue;
186         }
187         float incrementAngle = TypedText::GetAngleForArcLen(static_cast<float>(arcLen), letterHeight,
188                                                             arcTextInfo.radius, arcTextInfo.direct, orientation);
189 
190         rotateAngle = (orientation == TextOrientation::INSIDE) ? angle : (angle - SEMICIRCLE_IN_DEGREE);
191 
192         // 2: half
193         float fineTuningAngle = incrementAngle * (static_cast<float>(letterWidth) / (2 * arcLen));
194         rotateAngle += (xorFlag ? -fineTuningAngle : fineTuningAngle);
195         TypedText::GetArcLetterPos(arcCenter, arcTextInfo.radius, angle, posX, posY);
196         angle += incrementAngle;
197 
198         DrawLetterWithRotate(gfxDstBuffer, mask, fontId, fontSize, letter, Point { MATH_ROUND(posX), MATH_ROUND(posY) },
199                              static_cast<int16_t>(rotateAngle), style.textColor_, opaScale);
200     }
201 }
202 
DrawLetterWithRotate(BufferInfo & gfxDstBuffer,const Rect & mask,uint16_t fontId,uint8_t fontSize,uint32_t letter,const Point & pos,int16_t rotateAngle,const ColorType & color,OpacityType opaScale)203 void DrawLabel::DrawLetterWithRotate(BufferInfo& gfxDstBuffer,
204                                      const Rect& mask,
205                                      uint16_t fontId,
206                                      uint8_t fontSize,
207                                      uint32_t letter,
208                                      const Point& pos,
209                                      int16_t rotateAngle,
210                                      const ColorType& color,
211                                      OpacityType opaScale)
212 {
213     UIFont* fontEngine = UIFont::GetInstance();
214     FontHeader head;
215     GlyphNode node;
216 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
217     node.textStyle = TEXT_STYLE_NORMAL;
218 #endif
219     if (fontEngine->GetFontHeader(head, fontId, fontSize) != 0) {
220         return;
221     }
222 
223     const uint8_t* fontMap = fontEngine->GetBitmap(letter, node, fontId, fontSize, 0);
224     if (fontMap == nullptr) {
225         return;
226     }
227     uint8_t fontWeight = fontEngine->GetFontWeight(fontId);
228     ColorMode colorMode = fontEngine->GetColorType(fontId);
229     Rect rectLetter;
230     rectLetter.SetPosition(pos.x + node.left, pos.y + head.ascender - node.top);
231     rectLetter.Resize(node.cols, node.rows);
232     TransformMap transMap(rectLetter);
233     transMap.Rotate(rotateAngle, Vector2<float>(-node.left, node.top - head.ascender));
234     TransformDataInfo letterTranDataInfo = {ImageHeader{colorMode, 0, 0, 0, node.cols, node.rows}, fontMap, fontWeight,
235                                             BlurLevel::LEVEL0, TransformAlgorithm::BILINEAR};
236     BaseGfxEngine::GetInstance()->DrawTransform(gfxDstBuffer, mask, Point { 0, 0 }, color, opaScale, transMap,
237                                                 letterTranDataInfo);
238 }
239 
GetLineBackgroundColor(uint16_t letterIndex,List<LineBackgroundColor> * linebackgroundColor,bool & havelinebackground,ColorType & linebgColor)240 void DrawLabel::GetLineBackgroundColor(uint16_t letterIndex, List<LineBackgroundColor>* linebackgroundColor,
241                                        bool& havelinebackground, ColorType& linebgColor)
242 {
243     if (linebackgroundColor->Size() > 0) {
244         ListNode<LineBackgroundColor>* lbColor = linebackgroundColor->Begin();
245         for (; lbColor != linebackgroundColor->End(); lbColor = lbColor->next_) {
246             uint32_t start = lbColor->data_.start;
247             uint32_t end = lbColor->data_.end;
248             if (letterIndex >= start && letterIndex <= end) {
249                 havelinebackground = true;
250                 linebgColor = lbColor->data_.linebackgroundColor ;
251             }
252         }
253     }
254 };
255 
GetBackgroundColor(uint16_t letterIndex,List<BackgroundColor> * backgroundColor,bool & havebackground,ColorType & bgColor)256 void DrawLabel::GetBackgroundColor(uint16_t letterIndex, List<BackgroundColor>* backgroundColor,
257                                    bool& havebackground, ColorType& bgColor)
258 {
259     if (backgroundColor->Size() > 0) {
260         ListNode<BackgroundColor>* bColor = backgroundColor->Begin();
261         for (; bColor != backgroundColor->End(); bColor = bColor->next_) {
262             uint16_t start = bColor->data_.start;
263             uint16_t end = bColor->data_.end;
264             if (letterIndex >= start && letterIndex <= end) {
265                 havebackground = true;
266                 bgColor = bColor->data_.backgroundColor ;
267             }
268         }
269     }
270 };
271 
GetForegroundColor(uint16_t letterIndex,List<ForegroundColor> * foregroundColor,ColorType & fgColor)272 void DrawLabel::GetForegroundColor(uint16_t letterIndex, List<ForegroundColor>* foregroundColor, ColorType& fgColor)
273 {
274     if (foregroundColor->Size() > 0) {
275         ListNode<ForegroundColor>* fColor = foregroundColor->Begin();
276         for (; fColor != foregroundColor->End(); fColor = fColor->next_) {
277             uint32_t start = fColor->data_.start;
278             uint32_t end = fColor->data_.end;
279             if (letterIndex >= start && letterIndex <= end) {
280                 fgColor = fColor->data_.fontColor;
281             }
282         }
283     }
284 };
285 
DrawLineBackgroundColor(BufferInfo & gfxDstBuffer,uint16_t letterIndex,const LabelLineInfo & labelLine)286 void DrawLabel::DrawLineBackgroundColor(BufferInfo& gfxDstBuffer, uint16_t letterIndex, const LabelLineInfo& labelLine)
287 {
288     uint32_t i = 0;
289     while (i < labelLine.lineLength) {
290         TypedText::GetUTF8Next(labelLine.text, i, i);
291         bool havelinebackground = false;
292         ColorType linebackgroundColor;
293         GetLineBackgroundColor(letterIndex, labelLine.linebackgroundColor, havelinebackground, linebackgroundColor);
294         if (havelinebackground) {
295                 Style style;
296                 style.bgColor_ = linebackgroundColor;
297                 Rect linebackground(labelLine.mask.GetLeft(), labelLine.pos.y,
298                                     labelLine.mask.GetRight(), labelLine.pos.y + labelLine.lineHeight);
299                 BaseGfxEngine::GetInstance()->DrawRect(gfxDstBuffer, labelLine.mask,
300                                                        linebackground, style, linebackgroundColor.alpha);
301         }
302         letterIndex++;
303     }
304 };
305 } // namespace OHOS
306