1 /*
2  * Copyright (c) 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 #ifndef SPANNABLE_STRING_H
16 #define SPANNABLE_STRING_H
17 #include "font/ui_font_header.h"
18 #include "gfx_utils/color.h"
19 #include "gfx_utils/list.h"
20 #include "gfx_utils/graphic_types.h"
21 namespace OHOS {
22 struct FontSizeSpan : HeapBase {
23     uint16_t start;
24     uint16_t end;
25     uint8_t fontSize;
26 };
27 
28 /**
29  * @brief Stores the attribute information about letter height for full text.
30  */
31 struct LetterHeightSpan : HeapBase {
32     uint16_t start;
33     uint16_t end;
34     int16_t height;
35 };
36 
37 struct FontIdSpan : HeapBase {
38     uint16_t start;
39     uint16_t end;
40     uint16_t fontId;
41 };
42 
43 struct BackgroundColorSpan : public HeapBase {
44     int16_t start;
45     int16_t end;
46     ColorType backgroundColor;
47 };
48 
49 struct ForegroundColorSpan : public HeapBase {
50     int16_t start;
51     int16_t end;
52     ColorType fontColor;
53 };
54 
55 struct LineBackgroundColorSpan : public HeapBase {
56     int16_t start;
57     int16_t end;
58     ColorType linebackgroundColor;
59 };
60 
61 class StyleSpan : public HeapBase {
62 public:
StyleSpan()63     StyleSpan() {};
~StyleSpan()64     ~StyleSpan() {};
65     TextStyle textStyle_;
66     uint16_t start_;
67     uint16_t end_;
StyleSpan(TextStyle textStyle,uint16_t start,uint16_t end)68     StyleSpan(TextStyle textStyle, uint16_t start, uint16_t end)
69     {
70         textStyle_ = textStyle;
71         start_ = start;
72         end_ = end;
73     };
74 };
75 class SpannableString : public HeapBase {
76 public:
77     SpannableString();
78     ~SpannableString();
79 
80     bool GetSpannable(uint16_t index);
81     void SetTextStyle(TextStyle textStyle, uint16_t startIndex, uint16_t endIndex);
82     bool GetTextStyle(uint16_t index, TextStyle& textStyle);
83     void SetFontSize(uint8_t inputFontSize, uint16_t startIndex, uint16_t endIndex);
84     bool GetFontSize(uint16_t index, uint8_t& outputSize);
85     void SetFontId(uint16_t inputFontId, uint16_t startIndex, uint16_t endIndex);
86     bool GetFontId(uint16_t index, uint16_t& outputFontId);
87     bool GetFontHeight(uint16_t index, int16_t& outputHeight, uint16_t& defaultFontId, uint8_t defaultFontSize);
88 
89     void SetBackgroundColor(ColorType inputBackgroundColor, uint16_t startIndex, uint16_t endIndex);
90     bool GetBackgroundColor(uint16_t index, ColorType& outputBackgroundColor);
91     void SetForegroundColor(ColorType inputForegroundColor, uint16_t startIndex, uint16_t endIndex);
92     bool GetForegroundColor(uint16_t index, ColorType& outputForegroundColor);
93     void SetLineBackgroundColor(ColorType inputLineBackgroundColor, uint16_t startIndex, uint16_t endIndex);
94     bool GetLineBackgroundColor(uint16_t index, ColorType& outputLineBackgroundColor);
95 
96     void Reset();
97     void SetSpannableString(const SpannableString* input);
98 
99 private:
100     uint16_t isSpannableLen_;
101 
102     /* Record each letter having full text setting or not. */
103     bool* isSpannable_;
104     List<StyleSpan*> styleList_;
105     List<FontSizeSpan> sizeList_;
106     List<FontIdSpan> fontIdList_;
107     List<LetterHeightSpan> heightList_;
108 
109     List<BackgroundColorSpan> backgroundColorList_;
110     List<ForegroundColorSpan> foregroundColorList_;
111     List<LineBackgroundColorSpan> lineBackgroundColorList_;
112 
113     /* If endIndex larger than isSpannableLen_, the array isSpannable_ will re-malloc endIndex length memory. */
114     bool SetSpannable(bool value, uint16_t startIndex, uint16_t endIndex);
115     void SetFontHeight(int16_t inputHeight, uint16_t startIndex, uint16_t endIndex);
116     bool ExpandSpannableLen(uint16_t index);
117 
118     /* merge same value. */
119     template <typename SpanType>
EqualInsert(uint16_t & startIndex,uint16_t & endIndex,uint16_t tempStart,uint16_t tempEnd,ListNode<SpanType> ** tempSpan,List<SpanType> & tempList)120     bool EqualInsert(uint16_t& startIndex,
121                      uint16_t& endIndex,
122                      uint16_t tempStart,
123                      uint16_t tempEnd,
124                      ListNode<SpanType>** tempSpan,
125                      List<SpanType>& tempList)
126     {
127         if ((startIndex == tempStart) && endIndex == tempEnd) {
128             return false;
129         }
130         bool needAddNode = true;
131         if (startIndex <= tempStart) {
132             if (*tempSpan == nullptr) {
133                 return false;
134             }
135             if (endIndex < tempStart) {
136                 // not overlap
137             } else if (endIndex <= tempEnd) {
138                 endIndex = tempEnd;
139                 *tempSpan = tempList.Remove(*tempSpan)->prev_;
140             } else {
141                 *tempSpan = tempList.Remove(*tempSpan)->prev_;
142             }
143         } else {
144             if (*tempSpan == nullptr) {
145                 return false;
146             }
147             if (startIndex > tempEnd) {
148                 // not overlap
149             } else if (endIndex <= tempEnd) {
150                 needAddNode = false;
151             } else {
152                 startIndex = tempStart;
153                 *tempSpan = tempList.Remove(*tempSpan)->prev_;
154             }
155         }
156         return needAddNode;
157     }
158 
159     /* merge different value. */
160     template <typename SpanType>
UnequalInsert(uint16_t & startIndex,uint16_t & endIndex,uint16_t tempStart,uint16_t tempEnd,ListNode<SpanType> ** tempSpan,List<SpanType> & tempList,SpanType tempLeft,SpanType tempRight)161     bool UnequalInsert(uint16_t& startIndex,
162                        uint16_t& endIndex,
163                        uint16_t tempStart,
164                        uint16_t tempEnd,
165                        ListNode<SpanType>** tempSpan,
166                        List<SpanType>& tempList,
167                        SpanType tempLeft,
168                        SpanType tempRight)
169     {
170         bool needAddNode = true;
171         if (*tempSpan == nullptr) {
172             return false;
173         }
174         if (startIndex > tempEnd) {
175             // case A, no change
176         } else if (startIndex > tempStart && endIndex >= tempEnd) {
177             // case B
178             (*tempSpan)->data_.end = startIndex;
179         } else if (startIndex <= tempStart && endIndex >= tempEnd) {
180             // case C
181             *tempSpan = tempList.Remove(*tempSpan)->prev_;
182         } else if (startIndex <= tempStart && endIndex < tempEnd) {
183             // case D
184             (*tempSpan)->data_.start = endIndex;
185         } else if (endIndex < tempStart) {
186             // case E, no change
187         } else if (startIndex > tempStart && endIndex < tempEnd) {
188             // case F
189             tempList.Insert(*tempSpan, tempLeft);
190             tempList.Insert(*tempSpan, tempRight);
191             *tempSpan = tempList.Remove(*tempSpan)->prev_;
192         } else {
193             /* it shall not go here */
194         }
195         return needAddNode;
196     }
197 };
198 } // namespace OHOS
199 #endif
200