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 /**
17  * @addtogroup UI_Common
18  * @{
19  *
20  * @brief Defines common UI capabilities, such as image and text processing.
21  *
22  * @since 1.0
23  * @version 1.0
24  */
25 
26 /**
27  * @file text.h
28  *
29  * @brief Declares the <b>Text</b> class that provides functions to set basic text attributes, such as the text
30  *        direction and alignment mode.
31  *
32  * @since 1.0
33  * @version 1.0
34  */
35 
36 #ifndef GRAPHIC_LITE_TEXT_H
37 #define GRAPHIC_LITE_TEXT_H
38 
39 #include <cstring>
40 #include "common/spannable_string.h"
41 #include "engines/gfx/gfx_engine_manager.h"
42 #include "font/ui_font_header.h"
43 
44 #include "gfx_utils/geometry2d.h"
45 #include "gfx_utils/graphic_types.h"
46 #include "gfx_utils/list.h"
47 #include "gfx_utils/style.h"
48 #include "gfx_utils/vector.h"
49 
50 namespace OHOS {
51 namespace {
52 const std::string PASSWORD_DOT = "*"; // dot for password type
53 constexpr uint16_t DEFAULT_TEXT_OFFSET = 5;
54 constexpr uint16_t BOTH_SIDE_TEXT_OFFSET = DEFAULT_TEXT_OFFSET * 2; // 2: left and right space
55 constexpr uint16_t DEFAULT_CURSOR_OFFSET = 1;
56 constexpr uint16_t DEFAULT_CURSOR_WIDTH = 2;
57 } // namespace name
58 
59 /**
60  * @brief Enumerates text alignment modes.
61  */
62 enum UITextLanguageAlignment : uint8_t {
63     /** Left-aligned */
64     TEXT_ALIGNMENT_LEFT = 0,
65     /** Right-aligned */
66     TEXT_ALIGNMENT_RIGHT,
67     /** Centered */
68     TEXT_ALIGNMENT_CENTER,
69     /** Top-aligned */
70     TEXT_ALIGNMENT_TOP,
71     /** Bottom-aligned */
72     TEXT_ALIGNMENT_BOTTOM,
73 };
74 
75 /**
76  * @brief Enumerates text directions.
77  */
78 enum UITextLanguageDirect : uint8_t {
79     /** Left-to-right */
80     TEXT_DIRECT_LTR = 0,
81     /** Right-to-left */
82     TEXT_DIRECT_RTL,
83     TEXT_DIRECT_MIXED,
84 };
85 
86 /**
87  * @brief Stores the attribute information about this arc text to draw.
88  */
89 struct ArcTextInfo {
90     uint16_t radius;
91     float startAngle;
92     float endAngle;
93     Point arcCenter;
94     uint32_t lineStart;
95     uint32_t lineEnd;
96     UITextLanguageDirect direct;
97     bool hasAnimator;
98     uint32_t* codePoints;
99     uint16_t codePointsNum;
100     uint8_t shapingFontId;
101 };
102 
103 /**
104  * @brief Stores attribute information for this arc text to be drawn.
105  */
106 struct ArcLetterInfo {
InitDataArcLetterInfo107     void InitData(uint16_t inFontId, uint8_t inFontSize, uint32_t inLetter, Point inPos,
108         int16_t inRotateAngle, ColorType inColor, OpacityType inOpaScale,
109         float inStartAngle, float inEndAngle, float inCurrentAngle, uint16_t inRadius,
110         bool inCompatibilityMode, bool inDirectFlag, bool inOrientationFlag, bool inHasAnimator)
111     {
112         fontId = inFontId;
113         fontSize = inFontSize;
114         letter = inLetter;
115         pos = inPos;
116         rotateAngle = inRotateAngle;
117         color = inColor;
118         opaScale = inOpaScale;
119         startAngle = inStartAngle;
120         endAngle = inEndAngle;
121         currentAngle = inCurrentAngle;
122         radius = inRadius;
123         compatibilityMode = inCompatibilityMode;
124         directFlag = inDirectFlag;
125         orientationFlag = inOrientationFlag;
126         hasAnimator = inHasAnimator;
127     }
128     uint16_t fontId;
129     uint8_t fontSize;
130     uint32_t letter;
131     Point pos;
132     int16_t rotateAngle;
133     ColorType color;
134     OpacityType opaScale;
135     float startAngle;
136     float endAngle;
137     float currentAngle;
138     uint16_t radius;
139     bool compatibilityMode;
140     bool directFlag;
141     bool orientationFlag;
142     bool hasAnimator;
143 };
144 
145 /**
146  * @brief Enumerates text orientations.
147  */
148 enum TextInRange {
149     IN_RANGE,
150     OUT_RANGE,
151     NEED_CLIP
152 };
153 
154 /**
155  * @brief Enumerates text orientations.
156  */
157 enum class TextOrientation : uint8_t {
158     /** Inside */
159     INSIDE,
160     /** Outside */
161     OUTSIDE,
162 };
163 
164 struct BackgroundColor : public HeapBase {
165     int16_t start;
166     int16_t end;
167     ColorType backgroundColor;
168 };
169 
170 struct ForegroundColor : public HeapBase {
171     int16_t start;
172     int16_t end;
173     ColorType fontColor;
174 };
175 
176 struct LineBackgroundColor : public HeapBase {
177     int16_t start;
178     int16_t end;
179     ColorType linebackgroundColor;
180 };
181 
182 struct LabelLineInfo;
183 
184 /**
185  * @brief Represents the base class of <b>Text</b>, providing the text attribute setting and text drawing
186  *        capabilities for components that require font display.
187  *
188  * @since 1.0
189  * @version 1.0
190  */
191 class Text : public HeapBase {
192 public:
193     /** Invalid value for the ellipsis position */
194     static constexpr uint16_t TEXT_ELLIPSIS_END_INV = 0xFFFF;
195     static constexpr uint16_t TEXT_ELLIPSIS_UNICODE = 0x2026;
196 
197     /**
198      * @brief A constructor used to create a <b>Text</b> instance.
199      *
200      * @since 1.0
201      * @version 1.0
202      */
203     Text();
204 
205     /**
206      * @brief A destructor used to delete the <b>Text</b> instance.
207      *
208      * @since 1.0
209      * @version 1.0
210      */
211     virtual ~Text();
212 
213     /**
214      * @brief Sets the content for this text.
215      *
216      * @param text Indicates the pointer to the text content.
217      * @since 1.0
218      * @version 1.0
219      */
220     virtual void SetText(const char* text);
221 
222     /**
223      * @brief Sets the SpannableString for this text.
224      *
225      * @param text Indicates the pointer to the text content.
226      * @since 1.0
227      * @version 1.0
228      */
229     void SetSpannableString(const SpannableString* spannableString);
230 
231     /**
232      * @brief Obtains the content of this text.
233      *
234      * @return Returns the text content.
235      * @since 1.0
236      * @version 1.0
237      */
GetText()238     const char* GetText() const
239     {
240         return text_;
241     }
242 
243     /**
244      * @brief Sets the font name and size.
245      *
246      * @param name Indicates the pointer to the font name.
247      * @param size Indicates the font size to set.
248      * @since 1.0
249      * @version 1.0
250      */
251     void SetFont(const char* name, uint8_t size);
252 
253     static void SetFont(const char* name, uint8_t size, char*& destName, uint8_t& destSize);
254 
255     /**
256      * @brief Sets the font ID.
257      *
258      * @param fontId Indicates the font ID to set.
259      * @since 1.0
260      * @version 1.0
261      */
262     void SetFontId(uint16_t fontId);
263 
264     /**
265      * @brief Obtains the font ID.
266      *
267      * @return Returns the front ID.
268      * @since 1.0
269      * @version 1.0
270      */
GetFontId()271     uint16_t GetFontId() const
272     {
273         return fontId_;
274     }
275 
276     /**
277      * @brief Obtains the font size.
278      *
279      * @return Returns the front size.
280      * @since 1.0
281      * @version 1.0
282      */
GetFontSize()283     uint8_t GetFontSize() const
284     {
285         return fontSize_;
286     }
287 
288     /**
289      * @brief Sets the direction for this text.
290      *
291      * @param direct Indicates the text direction, as defined in {@link UITextLanguageDirect}.
292      * @since 1.0
293      * @version 1.0
294      */
SetDirect(UITextLanguageDirect direct)295     void SetDirect(UITextLanguageDirect direct)
296     {
297         direct_ = direct;
298     }
299 
300     /**
301      * @brief Obtains the direction of this text.
302      *
303      * @return Returns the text direction, as defined in {@link UITextLanguageDirect}.
304      * @since 1.0
305      * @version 1.0
306      */
GetDirect()307     UITextLanguageDirect GetDirect() const
308     {
309         return static_cast<UITextLanguageDirect>(direct_);
310     }
311 
312     /**
313      * @brief Sets the alignment mode for this text.
314      *
315      * @param horizontalAlign Indicates the horizontal alignment mode to set,
316      *                        which can be {@link TEXT_ALIGNMENT_LEFT},
317      *                        {@link TEXT_ALIGNMENT_CENTER}, or {@link TEXT_ALIGNMENT_RIGHT}.
318      * @param verticalAlign Indicates the vertical alignment mode to set, which can be
319      *                      {@link TEXT_ALIGNMENT_TOP} (default mode), {@link TEXT_ALIGNMENT_CENTER},
320      *                      or {@link TEXT_ALIGNMENT_BOTTOM}.
321      * @since 1.0
322      * @version 1.0
323      */
324     void SetAlign(UITextLanguageAlignment horizontalAlign, UITextLanguageAlignment verticalAlign = TEXT_ALIGNMENT_TOP)
325     {
326         if ((horizontalAlign_ != horizontalAlign) || (verticalAlign_ != verticalAlign)) {
327             needRefresh_ = true;
328             horizontalAlign_ = horizontalAlign;
329             verticalAlign_ = verticalAlign;
330         }
331     }
332 
333     /**
334      * @brief Obtains the horizontal alignment mode.
335      *
336      * @return Returns the horizontal alignment mode.
337      * @since 1.0
338      * @version 1.0
339      */
GetHorAlign()340     UITextLanguageAlignment GetHorAlign() const
341     {
342         return static_cast<UITextLanguageAlignment>(horizontalAlign_);
343     }
344 
345     /**
346      * @brief Obtains the vertical alignment mode.
347      *
348      * @return Returns the vertical alignment mode.
349      * @since 1.0
350      * @version 1.0
351      */
GetVerAlign()352     UITextLanguageAlignment GetVerAlign() const
353     {
354         return static_cast<UITextLanguageAlignment>(verticalAlign_);
355     }
356 
357     /**
358      * @brief Obtains the size of this text.
359      *
360      * @return Returns the text size.
361      * @since 1.0
362      * @version 1.0
363      */
GetTextSize()364     Point GetTextSize() const
365     {
366         return textSize_;
367     }
368 
369     virtual void ReMeasureTextSize(const Rect& textRect, const Style& style);
370 
371     void ReMeasureTextWidthInEllipsisMode(const Rect& textRect, const Style& style, uint16_t ellipsisIndex);
372 
373     void OnDraw(BufferInfo& gfxDstBuffer,
374                 const Rect& invalidatedArea,
375                 const Rect& viewOrigRect,
376                 const Rect& textRect,
377                 int16_t offsetX,
378                 const Style& style,
379                 uint16_t ellipsisIndex,
380                 OpacityType opaScale);
381 
382     /**
383      * @brief Sets whether to adapt the component width to this text.
384      *
385      * @param expand Specifies whether to adapt the component width to this text. The value <b>true</b> indicates
386      *               that the component width will adapt to this text, and <b>false</b> indicates not.
387      * @since 1.0
388      * @version 1.0
389      */
SetExpandWidth(bool expand)390     void SetExpandWidth(bool expand)
391     {
392         expandWidth_ = expand;
393     }
394 
395     /**
396      * @brief Checks whether the component width adapts to this text.
397      *
398      * @return Returns <b>true</b> if the component width adapts to this text; returns <b>false</b> otherwise.
399      * @since 1.0
400      * @version 1.0
401      */
IsExpandWidth()402     bool IsExpandWidth() const
403     {
404         return expandWidth_;
405     }
406 
407     /**
408      * @brief Sets whether to adapt the component height to this text.
409      *
410      * @param expand Specifies whether to adapt the component height to this text. The value <b>true</b> indicates
411      *               that the component height will adapt to this text, and <b>false</b> indicates not.
412      * @since 1.0
413      * @version 1.0
414      */
SetExpandHeight(bool expand)415     void SetExpandHeight(bool expand)
416     {
417         expandHeight_ = expand;
418     }
419 
420     /**
421      * @brief Checks whether the component height adapts to this text.
422      *
423      * @return Returns <b>true</b> if the component height adapts to this text; returns <b>false</b> otherwise.
424      * @since 1.0
425      * @version 1.0
426      */
IsExpandHeight()427     bool IsExpandHeight() const
428     {
429         return expandHeight_;
430     }
431 
IsNeedRefresh()432     bool IsNeedRefresh() const
433     {
434         return needRefresh_;
435     }
436 
437     /**
438      * @brief Obtains the index of the character from where text will be replaced by ellipses based on
439      *        the text rectangle and style.
440      *
441      * @param textRect Indicates the text rectangle.
442      * @param style Indicates the text style.
443      * @since 1.0
444      * @version 1.0
445      */
446     uint16_t GetEllipsisIndex(const Rect& textRect, const Style& style);
447 
448     /**
449      * @brief Get the GetShapingFontId of text
450      *
451      * @return Return ShapingFontId
452      */
GetShapingFontId()453     virtual uint8_t GetShapingFontId() const
454     {
455         return 0;
456     }
457 
458     /**
459      * @brief Get the GetCodePointNum of text
460      *
461      * @return Return num of CodePoints
462      */
GetCodePointNum()463     virtual uint16_t GetCodePointNum() const
464     {
465         return 0;
466     }
467 
468     /**
469      * @brief Get the GetCodePoints of text
470      *
471      * @return Return CodePoints of text
472      */
GetCodePoints()473     virtual uint32_t* GetCodePoints() const
474     {
475         return nullptr;
476     }
477 
SetSupportBaseLine(bool baseLine)478     void SetSupportBaseLine(bool baseLine)
479     {
480         baseLine_ = baseLine;
481     }
482 
SetBackgroundColorSpan(ColorType backgroundColor,int16_t start,int16_t end)483     void SetBackgroundColorSpan(ColorType backgroundColor, int16_t start, int16_t end)
484     {
485         if (spannableString_ == nullptr) {
486             spannableString_ = new SpannableString();
487         }
488         spannableString_->SetBackgroundColor(backgroundColor, (uint16_t)start, (uint16_t)end);
489     }
490 
GetBackgroundColorSpan()491     List<BackgroundColor> GetBackgroundColorSpan()
492     {
493         return backgroundColor_;
494     }
495 
SetForegroundColorSpan(ColorType fontColor,int16_t start,int16_t end)496     void SetForegroundColorSpan(ColorType fontColor, int16_t start, int16_t end)
497     {
498         if (spannableString_ == nullptr) {
499             spannableString_ = new SpannableString();
500         }
501         spannableString_->SetForegroundColor(fontColor, (uint16_t)start, (uint16_t)end);
502     }
503 
GetForegroundColorSpan()504     List<ForegroundColor> GetForegroundColorSpan()
505     {
506         return foregroundColor_;
507     }
508 
SetLineBackgroundSpan(ColorType linebackgroundColor,int16_t start,int16_t end)509     void SetLineBackgroundSpan(ColorType linebackgroundColor, int16_t start, int16_t end)
510     {
511         if (spannableString_ == nullptr) {
512             spannableString_ = new SpannableString();
513         }
514         spannableString_->SetLineBackgroundColor(linebackgroundColor, (uint16_t)start, (uint16_t)end);
515     }
516 
GetLineBackgroundSpan()517     List<LineBackgroundColor> GetLineBackgroundSpan()
518     {
519         return linebackgroundColor_;
520     }
521 
522     void SetAbsoluteSizeSpan(uint16_t start, uint16_t end, uint8_t size);
523     void SetRelativeSizeSpan(uint16_t start, uint16_t end, float size);
524     virtual uint16_t GetLetterIndexByLinePosition(const Style& style, int16_t contentWidth,
525                                                   const int16_t& posX, int16_t offsetX);
526     virtual uint16_t GetPosXByLetterIndex(const Rect& textRect, const Style& style,
527                                           uint16_t beginIndex, uint16_t count);
528 
SetEliminateTrailingSpaces(bool eliminateTrailingSpaces)529     void SetEliminateTrailingSpaces(bool eliminateTrailingSpaces)
530     {
531         eliminateTrailingSpaces_ = eliminateTrailingSpaces;
532     }
533 
IsEliminateTrailingSpaces()534     bool IsEliminateTrailingSpaces()
535     {
536         return eliminateTrailingSpaces_;
537     }
GetSizeSpan()538     uint16_t GetSizeSpan()
539     {
540         return characterSize_;
541     }
542 
543     /**
544      * @brief Get next character full dispaly offset.
545      *
546      * @param textRect Indicates size of input box.
547      * @param style Indicates the style of text.
548      * @param beginIndex Indicates index at the beginning of the text.
549      * @param num Indicates num of text.
550      *
551      * @return Return text offset.
552      *
553      */
554     virtual uint16_t GetNextCharacterFullDispalyOffset(const Rect& textRect,
555         const Style& style, uint16_t beginIndex, uint16_t num);
556 
557     /**
558      * @brief Obtains the width of the meta text.
559      *
560      * @param style Indicates the style of text.
561      *
562      * @return Return meta text width.
563      */
564     virtual int16_t GetMetaTextWidth(const Style& style);
565 
566 protected:
567     struct TextLine {
568         uint16_t lineBytes;
569         uint16_t linePixelWidth;
570     };
571 
572     /** Maximum number of lines */
573     static constexpr uint16_t MAX_LINE_COUNT = 50;
574     static TextLine textLine_[MAX_LINE_COUNT];
575 
576     static constexpr const char* TEXT_ELLIPSIS = "…";
577 
578     virtual uint32_t GetTextStrLen();
579 
580     virtual uint32_t
581         GetTextLine(uint32_t begin, uint32_t textLen, int16_t width, uint16_t lineNum, uint8_t letterSpace,
582                     uint16_t& letterIndex, SpannableString* spannableString, TextLine& textLine);
583 
584     virtual uint16_t GetLetterIndexByPosition(const Rect& textRect, const Style& style, const Point& pos);
585 
586     virtual void Draw(BufferInfo& gfxDstBuffer,
587                       const Rect& mask,
588                       const Rect& coords,
589                       const Style& style,
590                       int16_t offsetX,
591                       uint16_t ellipsisIndex,
592                       OpacityType opaScale);
593 
594     uint16_t GetLine(int16_t width, uint8_t letterSpace, uint16_t ellipsisIndex, uint32_t& maxLineBytes);
595     int16_t TextPositionY(const Rect& textRect, int16_t textHeight);
596     int16_t LineStartPos(const Rect& textRect, uint16_t lineWidth);
597     void DrawEllipsis(BufferInfo& gfxDstBuffer, LabelLineInfo& labelLine, uint16_t& letterIndex);
598     uint32_t CalculateLineWithEllipsis(uint32_t begin, uint32_t textLen, int16_t width,
599                                        uint8_t letterSpace, uint16_t& lineNum,
600                                        uint16_t& letterIndex,
601                                        SpannableString* spannableString);
602     uint16_t GetSpanFontIdBySize(uint8_t size);
603     SpannableString* CreateSpannableString();
604 #if defined(ENABLE_TEXT_STYLE) && ENABLE_TEXT_STYLE
605     TextStyle* textStyles_;
606 #endif
607     char* text_;
608     uint16_t fontId_;
609     uint8_t fontSize_; // Only the vector font library has a valid value.
610     Point textSize_;
611     bool needRefresh_ : 1;
612     bool expandWidth_ : 1;
613     bool expandHeight_ : 1;
614     bool baseLine_ : 1;
615     uint8_t direct_ : 4; // UITextLanguageDirect
616     List<BackgroundColor> backgroundColor_;
617     List<ForegroundColor> foregroundColor_;
618     List<LineBackgroundColor> linebackgroundColor_;
619     uint32_t characterSize_;
620     SpannableString* spannableString_;
621     TextLine preIndexLine_;
622 
623 private:
624     uint8_t horizontalAlign_ : 4; // UITextLanguageAlignment
625     uint8_t verticalAlign_ : 4;   // UITextLanguageAlignment
626     bool eliminateTrailingSpaces_;
627     static constexpr uint8_t FONT_ID_MAX = 0xFF;
628 #if defined(ENABLE_ICU) && ENABLE_ICU
629     void SetLineBytes(uint16_t& lineBytes, uint16_t lineBegin);
630 #endif
631     void CalculatedCurLineHeight(int16_t& lineHeight, int16_t& curLineHeight,
632                                  uint16_t fontHeight, const Style& style, uint16_t lineMaxHeight);
633     void SetNextLineBegin(const Style& style, uint16_t lineMaxHeight, int16_t& curLineHeight, Point& pos,
634                           int16_t& tempLetterIndex, int16_t& lineHeight, uint16_t& lineBegin, uint16_t letterIndex);
635     Point GetPos(int16_t& lineHeight, const Style& style, uint16_t& lineCount, const Rect& coords);
636 };
637 } // namespace OHOS
638 #endif // GRAPHIC_LITE_TEXT_H
639