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 
16 #include "common/spannable_string.h"
17 #include "font/ui_font.h"
18 #include "gfx_utils/graphic_log.h"
19 #include "securec.h"
20 namespace OHOS {
21 namespace {
22 constexpr uint16_t DEFAULT_IS_SPANNABLE_LEN = 10;
23 constexpr uint16_t DEFAULT_EXPAND_EDGE = 1024;
24 constexpr uint16_t DEFAULT_EXPAND_TIMES = 2;
25 constexpr uint16_t DEFAULT_EXPAND_OFFSET = 1;
26 } // namespace
27 
SpannableString()28 SpannableString::SpannableString() : isSpannableLen_(0), isSpannable_(nullptr) {}
29 
~SpannableString()30 SpannableString::~SpannableString()
31 {
32     Reset();
33 }
34 
SetTextStyle(TextStyle inputTextStyle, uint16_t startIndex, uint16_t endIndex)35 void SpannableString::SetTextStyle(TextStyle inputTextStyle, uint16_t startIndex, uint16_t endIndex)
36 {
37     StyleSpan* style = new StyleSpan(inputTextStyle, startIndex, endIndex);
38     styleList_.PushBack(style);
39     SetSpannable(true, startIndex, endIndex);
40 }
GetTextStyle(uint16_t index, TextStyle& textStyle)41 bool SpannableString::GetTextStyle(uint16_t index, TextStyle& textStyle)
42 {
43     bool hasFind = false;
44     ListNode<StyleSpan*>* tempSpan = styleList_.Begin();
45     for (; tempSpan != styleList_.End(); tempSpan = tempSpan->next_) {
46         uint16_t tempStart = tempSpan->data_->start_;
47         uint16_t tempEnd = tempSpan->data_->end_;
48         if ((tempStart <= index) && (index < tempEnd)) {
49             textStyle = tempSpan->data_->textStyle_;
50             hasFind = true;
51             break;
52         }
53     }
54     return hasFind;
55 }
56 
Reset()57 void SpannableString::Reset()
58 {
59     if (isSpannable_ != nullptr) {
60         UIFree(isSpannable_);
61     }
62     isSpannable_ = nullptr;
63     isSpannableLen_ = 0;
64     if (styleList_.Size() > 0) {
65         for (auto iter = styleList_.Begin(); iter != styleList_.End(); iter = iter->next_) {
66             delete iter->data_;
67             iter->data_ = nullptr;
68         }
69         styleList_.Clear();
70     }
71     if (sizeList_.Size() > 0) {
72         sizeList_.Clear();
73     }
74     if (fontIdList_.Size() > 0) {
75         fontIdList_.Clear();
76     }
77     if (heightList_.Size() > 0) {
78         heightList_.Clear();
79     }
80     if (backgroundColorList_.Size() > 0) {
81         backgroundColorList_.Clear();
82     }
83     if (foregroundColorList_.Size() > 0) {
84         foregroundColorList_.Clear();
85     }
86     if (lineBackgroundColorList_.Size() > 0) {
87         lineBackgroundColorList_.Clear();
88     }
89 }
90 
SetSpannableString(const SpannableString* input)91 void SpannableString::SetSpannableString(const SpannableString* input)
92 {
93     Reset();
94     SetSpannable(true, 0, DEFAULT_IS_SPANNABLE_LEN);
95 
96     ListNode<FontSizeSpan>* node = input->sizeList_.Begin();
97     while (node != input->sizeList_.End()) {
98         SetFontSize(node->data_.fontSize, node->data_.start, node->data_.end);
99         node = node->next_;
100     }
101     ListNode<FontIdSpan>* node_id = input->fontIdList_.Begin();
102     while (node_id != input->fontIdList_.End()) {
103         SetFontId(node_id->data_.fontId, node_id->data_.start, node_id->data_.end);
104         node_id = node_id->next_;
105     }
106     ListNode<LetterHeightSpan>* node_height = input->heightList_.Begin();
107     while (node_height != input->heightList_.End()) {
108         SetFontHeight(node_height->data_.height, node_height->data_.start, node_height->data_.end);
109         node_height = node_height->next_;
110     }
111     ListNode<StyleSpan*>* node_span = input->styleList_.Begin();
112     while (node_span != input->styleList_.End()) {
113         SetTextStyle(node_span->data_->textStyle_, node_span->data_->start_, node_span->data_->end_);
114         node_span = node_span->next_;
115     }
116     ListNode<BackgroundColorSpan>* node_backColor = input->backgroundColorList_.Begin();
117     while (node_backColor != input->backgroundColorList_.End()) {
118         SetBackgroundColor(node_backColor->data_.backgroundColor,
119                            node_backColor->data_.start,
120                            node_backColor->data_.end);
121         node_backColor = node_backColor->next_;
122     }
123     ListNode<ForegroundColorSpan>* node_foreColor = input->foregroundColorList_.Begin();
124     while (node_foreColor != input->foregroundColorList_.End()) {
125         SetForegroundColor(node_foreColor->data_.fontColor, node_foreColor->data_.start, node_foreColor->data_.end);
126         node_foreColor = node_foreColor->next_;
127     }
128     ListNode<LineBackgroundColorSpan>* node_lineBackColor = input->lineBackgroundColorList_.Begin();
129     while (node_lineBackColor != input->lineBackgroundColorList_.End()) {
130         SetLineBackgroundColor(node_lineBackColor->data_.linebackgroundColor,
131                                node_lineBackColor->data_.start,
132                                node_lineBackColor->data_.end);
133         node_lineBackColor = node_lineBackColor->next_;
134     }
135 }
136 
ExpandSpannableLen(uint16_t index)137 bool SpannableString::ExpandSpannableLen(uint16_t index)
138 {
139     if (isSpannableLen_ < index) {
140         uint16_t preLens = isSpannableLen_;
141         while (isSpannableLen_ < index && isSpannableLen_ != 0 && isSpannableLen_ < DEFAULT_EXPAND_EDGE) {
142             isSpannableLen_ = isSpannableLen_ * DEFAULT_EXPAND_TIMES + DEFAULT_EXPAND_OFFSET;
143         }
144         bool* tempIsSpannable_ = static_cast<bool*>(UIMalloc(isSpannableLen_ * sizeof(bool)));
145         if (tempIsSpannable_ == nullptr) {
146             GRAPHIC_LOGE("SpannableString::InitSpannable() isSpannable_ == nullptr");
147             return false;
148         }
149         if (isSpannable_ != nullptr) {
150             if (memcpy_s(tempIsSpannable_, isSpannableLen_, isSpannable_, isSpannableLen_) != EOK) {
151                 UIFree(tempIsSpannable_);
152                 tempIsSpannable_ = nullptr;
153                 return false;
154             }
155             UIFree(isSpannable_);
156             isSpannable_ = nullptr;
157         }
158         for (uint16_t i = preLens; i < isSpannableLen_; i++) {
159             tempIsSpannable_[i] = false;
160         }
161         isSpannable_ = tempIsSpannable_;
162     }
163     return true;
164 }
165 
SetSpannable(bool value, uint16_t startIndex, uint16_t endIndex)166 bool SpannableString::SetSpannable(bool value, uint16_t startIndex, uint16_t endIndex)
167 {
168     if (isSpannable_ == nullptr) {
169         isSpannableLen_ = DEFAULT_IS_SPANNABLE_LEN;
170         isSpannable_ = static_cast<bool*>(UIMalloc(isSpannableLen_ * sizeof(bool)));
171         for (uint16_t i = 0; i < isSpannableLen_; i++) {
172             isSpannable_[i] = false;
173         }
174     }
175     bool isSuccess = ExpandSpannableLen(endIndex);
176     if (isSuccess && (isSpannable_ != nullptr)) {
177         for (uint16_t i = startIndex; ((i < endIndex) && (i < isSpannableLen_)); i++) {
178             isSpannable_[i] = value;
179         }
180         isSuccess = true;
181     }
182     return isSuccess;
183 }
184 
GetSpannable(uint16_t index)185 bool SpannableString::GetSpannable(uint16_t index)
186 {
187     bool result = false;
188     if ((isSpannable_ != nullptr) && (index < isSpannableLen_)) {
189         result = isSpannable_[index];
190     }
191     return result;
192 }
193 
194 /*
195  * this function merge samge value when add node
196  */
SetFontSize(uint8_t inputFontSize, uint16_t startIndex, uint16_t endIndex)197 void SpannableString::SetFontSize(uint8_t inputFontSize, uint16_t startIndex, uint16_t endIndex)
198 {
199     if (sizeList_.IsEmpty()) {
200         FontSizeSpan inputSpan;
201         inputSpan.start = startIndex;
202         inputSpan.end =  endIndex;
203         inputSpan.fontSize = inputFontSize;
204         sizeList_.PushFront(inputSpan);
205         SetSpannable(true, startIndex, endIndex);
206         return;
207     } else {
208         ListNode<FontSizeSpan>* tempSpan = sizeList_.Begin();
209         for (; tempSpan != sizeList_.End(); tempSpan = tempSpan->next_) {
210             bool needAddNode = true;
211             uint16_t tempStart = tempSpan->data_.start;
212             uint16_t tempEnd = tempSpan->data_.end;
213             uint8_t tempSize = tempSpan->data_.fontSize;
214             if (inputFontSize == tempSize) {
215                 needAddNode = EqualInsert<FontSizeSpan>(startIndex, endIndex, tempStart, tempEnd, &tempSpan, sizeList_);
216             } else {
217                 FontSizeSpan tempLeft;
218                 tempLeft.start = tempStart;
219                 tempLeft.end = startIndex;
220                 tempLeft.fontSize = tempSize;
221                 FontSizeSpan tempRight;
222                 tempRight.start = endIndex;
223                 tempRight.end = tempEnd;
224                 tempRight.fontSize = tempSize;
225                 needAddNode = UnequalInsert<FontSizeSpan>(startIndex, endIndex, tempStart, tempEnd, &tempSpan,
226                                                           sizeList_, tempLeft, tempRight);
227             }
228             if (needAddNode) {
229                 FontSizeSpan inputSpan;
230                 inputSpan.start = startIndex;
231                 inputSpan.end = endIndex;
232                 inputSpan.fontSize = inputFontSize;
233                 sizeList_.PushBack(inputSpan);
234                 SetSpannable(true, startIndex, endIndex);
235             }
236         }
237     }
238 }
239 
GetFontSize(uint16_t index, uint8_t& outputSize)240 bool SpannableString::GetFontSize(uint16_t index, uint8_t& outputSize)
241 {
242     bool hasFind = false;
243     ListNode<FontSizeSpan>* tempSpan = sizeList_.Begin();
244     for (; tempSpan != sizeList_.End(); tempSpan = tempSpan->next_) {
245         uint16_t tempStart = tempSpan->data_.start;
246         uint16_t tempEnd = tempSpan->data_.end;
247         if ((tempStart <= index) && (index < tempEnd)) {
248             outputSize = tempSpan->data_.fontSize;
249             hasFind = true;
250             break;
251         }
252     }
253     return hasFind;
254 }
255 
SetFontId(uint16_t inputFontId, uint16_t startIndex, uint16_t endIndex)256 void SpannableString::SetFontId(uint16_t inputFontId, uint16_t startIndex, uint16_t endIndex)
257 {
258     if (fontIdList_.IsEmpty()) {
259         FontIdSpan inputSpan;
260         inputSpan.start = startIndex;
261         inputSpan.end = endIndex;
262         inputSpan.fontId =  inputFontId;
263         fontIdList_.PushFront(inputSpan);
264         SetSpannable(true, startIndex, endIndex);
265         return;
266     }
267     ListNode<FontIdSpan>* tempSpan = fontIdList_.Begin();
268     for (; tempSpan != fontIdList_.End(); tempSpan = tempSpan->next_) {
269         bool needAddNode = true;
270         uint16_t tempStart = tempSpan->data_.start;
271         uint16_t tempEnd = tempSpan->data_.end;
272         uint16_t tempId = tempSpan->data_.fontId;
273         if (inputFontId == tempId) {
274             needAddNode = EqualInsert<FontIdSpan>(startIndex, endIndex, tempStart, tempEnd, &tempSpan, fontIdList_);
275         } else {
276             FontIdSpan tempLeft;
277             tempLeft.start = tempStart;
278             tempLeft.end = startIndex;
279             tempLeft.fontId = tempId;
280             FontIdSpan tempRight;
281             tempRight.start = endIndex;
282             tempRight.end = tempEnd;
283             tempRight.fontId = tempId;
284             needAddNode = UnequalInsert<FontIdSpan>(startIndex, endIndex, tempStart, tempEnd, &tempSpan, fontIdList_,
285                                                     tempLeft, tempRight);
286         }
287         if (needAddNode) {
288             FontIdSpan inputSpan;
289             inputSpan.start = startIndex;
290             inputSpan.end = endIndex;
291             inputSpan.fontId = inputFontId;
292             fontIdList_.PushBack(inputSpan);
293             SetSpannable(true, startIndex, endIndex);
294         }
295     }
296 }
297 
GetFontId(uint16_t index, uint16_t& outputFontId)298 bool SpannableString::GetFontId(uint16_t index, uint16_t& outputFontId)
299 {
300     bool hasFind = false;
301     ListNode<FontIdSpan>* tempSpan = fontIdList_.Begin();
302     for (; tempSpan != fontIdList_.End(); tempSpan = tempSpan->next_) {
303         uint16_t tempStart = tempSpan->data_.start;
304         uint16_t tempEnd = tempSpan->data_.end;
305         if ((tempStart <= index) && (index < tempEnd)) {
306             outputFontId = tempSpan->data_.fontId;
307             hasFind = true;
308             break;
309         }
310     }
311     return hasFind;
312 }
313 
SetFontHeight(int16_t inputHeight, uint16_t startIndex, uint16_t endIndex)314 void SpannableString::SetFontHeight(int16_t inputHeight, uint16_t startIndex, uint16_t endIndex)
315 {
316     if (heightList_.IsEmpty()) {
317         LetterHeightSpan inputSpan;
318         inputSpan.start = startIndex;
319         inputSpan.end = endIndex;
320         inputSpan.height = inputHeight;
321         heightList_.PushFront(inputSpan);
322         SetSpannable(true, startIndex, endIndex);
323         return;
324     }
325     ListNode<LetterHeightSpan>* tempSpan = heightList_.Begin();
326     for (; tempSpan != heightList_.End(); tempSpan = tempSpan->next_) {
327         bool needAddNode = true;
328         uint16_t tempStart = tempSpan->data_.start;
329         uint16_t tempEnd = tempSpan->data_.end;
330         int16_t tempHeight = tempSpan->data_.height;
331         if (inputHeight == tempHeight) {
332             needAddNode =
333                 EqualInsert<LetterHeightSpan>(startIndex, endIndex, tempStart, tempEnd, &tempSpan, heightList_);
334         } else {
335             LetterHeightSpan tempLeft;
336             tempLeft.start = tempStart;
337             tempLeft.end = startIndex;
338             tempLeft.height = tempHeight;
339             LetterHeightSpan tempRight;
340             tempRight.start = endIndex;
341             tempRight.end = tempEnd;
342             tempRight.height = tempHeight;
343             needAddNode = UnequalInsert<LetterHeightSpan>(startIndex, endIndex, tempStart, tempEnd, &tempSpan,
344                                                           heightList_, tempLeft, tempRight);
345         }
346         if (needAddNode) {
347             LetterHeightSpan inputSpan;
348             inputSpan.start = startIndex;
349             inputSpan.end = endIndex;
350             inputSpan.height = inputHeight;
351             heightList_.PushBack(inputSpan);
352             SetSpannable(true, startIndex, endIndex);
353         }
354     }
355 }
356 
GetFontHeight(uint16_t index, int16_t& outputHeight, uint16_t& defaultFontId, uint8_t defaultFontSize)357 bool SpannableString::GetFontHeight(uint16_t index,
358                                     int16_t& outputHeight,
359                                     uint16_t& defaultFontId,
360                                     uint8_t defaultFontSize)
361 {
362     bool hasFind = false;
363     ListNode<LetterHeightSpan>* tempSpan = heightList_.Begin();
364     for (; tempSpan != heightList_.End(); tempSpan = tempSpan->next_) {
365         uint16_t tempStart = tempSpan->data_.start;
366         uint16_t tempEnd = tempSpan->data_.end;
367         if ((tempStart <= index) && (index < tempEnd)) {
368             hasFind = true;
369             outputHeight = tempSpan->data_.height;
370             break;
371         }
372     }
373     if (!hasFind) {
374         GetFontId(index, defaultFontId);
375         GetFontSize(index, defaultFontSize);
376         UIFont* uifont = UIFont::GetInstance();
377         outputHeight = uifont->GetHeight(defaultFontId, defaultFontSize);
378         SetFontHeight(outputHeight, index, index + 1);
379     }
380     return hasFind;
381 }
382 
SetBackgroundColor(ColorType inputBackgroundColor, uint16_t startIndex, uint16_t endIndex)383 void SpannableString::SetBackgroundColor(ColorType inputBackgroundColor, uint16_t startIndex, uint16_t endIndex)
384 {
385     if (backgroundColorList_.IsEmpty()) {
386         BackgroundColorSpan inputSpan;
387         inputSpan.start = startIndex;
388         inputSpan.end =  endIndex;
389         inputSpan.backgroundColor.full = inputBackgroundColor.full;
390         backgroundColorList_.PushFront(inputSpan);
391         SetSpannable(true, startIndex, endIndex);
392         return;
393     } else {
394         ListNode<BackgroundColorSpan>* tempSpan = backgroundColorList_.Begin();
395         for (; tempSpan != backgroundColorList_.End(); tempSpan = tempSpan->next_) {
396             bool needAddNode = true;
397             uint16_t tempStart = tempSpan->data_.start;
398             uint16_t tempEnd = tempSpan->data_.end;
399             ColorType tempSize;
400             tempSize.full = tempSpan->data_.backgroundColor.full;
401             if (inputBackgroundColor.full == tempSize.full) {
402                 needAddNode = EqualInsert<BackgroundColorSpan>(
403                     startIndex, endIndex, tempStart, tempEnd, &tempSpan,
404                     backgroundColorList_);
405             } else {
406                 BackgroundColorSpan tempLeft;
407                 tempLeft.start = tempStart;
408                 tempLeft.end = startIndex;
409                 tempLeft.backgroundColor.full = tempSize.full;
410                 BackgroundColorSpan tempRight;
411                 tempRight.start = endIndex;
412                 tempRight.end = tempEnd;
413                 tempRight.backgroundColor.full = tempSize.full;
414                 needAddNode = UnequalInsert<BackgroundColorSpan>(
415                     startIndex, endIndex, tempStart, tempEnd, &tempSpan,
416                     backgroundColorList_, tempLeft, tempRight);
417             }
418             if (needAddNode) {
419                 BackgroundColorSpan inputSpan;
420                 inputSpan.start = startIndex;
421                 inputSpan.end = endIndex;
422                 inputSpan.backgroundColor.full = inputBackgroundColor.full;
423                 backgroundColorList_.PushBack(inputSpan);
424                 SetSpannable(true, startIndex, endIndex);
425             }
426         }
427     }
428 }
429 
GetBackgroundColor(uint16_t index, ColorType& outputBackgroundColor)430 bool SpannableString::GetBackgroundColor(uint16_t index, ColorType& outputBackgroundColor)
431 {
432     bool hasFind = false;
433     ListNode<BackgroundColorSpan>* tempSpan = backgroundColorList_.Begin();
434     for (; tempSpan != backgroundColorList_.End(); tempSpan = tempSpan->next_) {
435         uint16_t tempStart = tempSpan->data_.start;
436         uint16_t tempEnd = tempSpan->data_.end;
437         if ((tempStart <= index) && (index < tempEnd)) {
438             outputBackgroundColor.full = tempSpan->data_.backgroundColor.full;
439             hasFind = true;
440             break;
441         }
442     }
443     return hasFind;
444 }
445 
SetForegroundColor(ColorType inputForegroundColor, uint16_t startIndex, uint16_t endIndex)446 void SpannableString::SetForegroundColor(ColorType inputForegroundColor, uint16_t startIndex, uint16_t endIndex)
447 {
448     if (foregroundColorList_.IsEmpty()) {
449         ForegroundColorSpan inputSpan;
450         inputSpan.start = startIndex;
451         inputSpan.end =  endIndex;
452         inputSpan.fontColor.full = inputForegroundColor.full;
453         foregroundColorList_.PushFront(inputSpan);
454         SetSpannable(true, startIndex, endIndex);
455         return;
456     } else {
457         ListNode<ForegroundColorSpan>* tempSpan = foregroundColorList_.Begin();
458         for (; tempSpan != foregroundColorList_.End(); tempSpan = tempSpan->next_) {
459             bool needAddNode = true;
460             uint16_t tempStart = tempSpan->data_.start;
461             uint16_t tempEnd = tempSpan->data_.end;
462             ColorType tempSize;
463             tempSize.full= tempSpan->data_.fontColor.full;
464             if (inputForegroundColor.full == tempSize.full) {
465                 needAddNode = EqualInsert<ForegroundColorSpan>(
466                     startIndex, endIndex, tempStart, tempEnd, &tempSpan,
467                     foregroundColorList_);
468             } else {
469                 ForegroundColorSpan tempLeft;
470                 tempLeft.start = tempStart;
471                 tempLeft.end = startIndex;
472                 tempLeft.fontColor.full = tempSize.full;
473                 ForegroundColorSpan tempRight;
474                 tempRight.start = endIndex;
475                 tempRight.end = tempEnd;
476                 tempRight.fontColor.full = tempSize.full;
477                 needAddNode = UnequalInsert<ForegroundColorSpan>(startIndex, endIndex, tempStart, tempEnd, &tempSpan,
478                                                           foregroundColorList_, tempLeft, tempRight);
479             }
480             if (needAddNode) {
481                 ForegroundColorSpan inputSpan;
482                 inputSpan.start = startIndex;
483                 inputSpan.end = endIndex;
484                 inputSpan.fontColor.full = inputForegroundColor.full;
485                 foregroundColorList_.PushBack(inputSpan);
486                 SetSpannable(true, startIndex, endIndex);
487             }
488         }
489     }
490 }
491 
GetForegroundColor(uint16_t index, ColorType& outputForegroundColor)492 bool SpannableString::GetForegroundColor(uint16_t index, ColorType& outputForegroundColor)
493 {
494     bool hasFind = false;
495     ListNode<ForegroundColorSpan>* tempSpan = foregroundColorList_.Begin();
496     for (; tempSpan != foregroundColorList_.End(); tempSpan = tempSpan->next_) {
497         uint16_t tempStart = tempSpan->data_.start;
498         uint16_t tempEnd = tempSpan->data_.end;
499         if ((tempStart <= index) && (index < tempEnd)) {
500             outputForegroundColor.full = tempSpan->data_.fontColor.full;
501             hasFind = true;
502             break;
503         }
504     }
505     return hasFind;
506 }
507 
SetLineBackgroundColor(ColorType inputLineBackgroundColor, uint16_t startIndex, uint16_t endIndex)508 void SpannableString::SetLineBackgroundColor(ColorType inputLineBackgroundColor, uint16_t startIndex, uint16_t endIndex)
509 {
510     if (lineBackgroundColorList_.IsEmpty()) {
511         LineBackgroundColorSpan inputSpan;
512         inputSpan.start = startIndex;
513         inputSpan.end =  endIndex;
514         inputSpan.linebackgroundColor.full = inputLineBackgroundColor.full;
515         lineBackgroundColorList_.PushFront(inputSpan);
516         SetSpannable(true, startIndex, endIndex);
517         return;
518     } else {
519         ListNode<LineBackgroundColorSpan>* tempSpan = lineBackgroundColorList_.Begin();
520         for (; tempSpan != lineBackgroundColorList_.End(); tempSpan = tempSpan->next_) {
521             bool needAddNode = true;
522             uint16_t tempStart = tempSpan->data_.start;
523             uint16_t tempEnd = tempSpan->data_.end;
524             ColorType tempSize;
525             tempSize.full = tempSpan->data_.linebackgroundColor.full;
526             if (inputLineBackgroundColor.full == tempSize.full) {
527                 needAddNode = EqualInsert<LineBackgroundColorSpan>(
528                     startIndex, endIndex, tempStart, tempEnd, &tempSpan,
529                     lineBackgroundColorList_);
530             } else {
531                 LineBackgroundColorSpan tempLeft;
532                 tempLeft.start = tempStart;
533                 tempLeft.end = startIndex;
534                 tempLeft.linebackgroundColor.full = tempSize.full;
535                 LineBackgroundColorSpan tempRight;
536                 tempRight.start = endIndex;
537                 tempRight.end = tempEnd;
538                 tempRight.linebackgroundColor.full = tempSize.full;
539                 needAddNode = UnequalInsert<LineBackgroundColorSpan>(
540                     startIndex, endIndex, tempStart, tempEnd, &tempSpan,
541                     lineBackgroundColorList_, tempLeft, tempRight);
542             }
543             if (needAddNode) {
544                 LineBackgroundColorSpan inputSpan;
545                 inputSpan.start = startIndex;
546                 inputSpan.end = endIndex;
547                 inputSpan.linebackgroundColor.full = inputLineBackgroundColor.full;
548                 lineBackgroundColorList_.PushBack(inputSpan);
549                 SetSpannable(true, startIndex, endIndex);
550             }
551         }
552     }
553 }
554 
GetLineBackgroundColor(uint16_t index, ColorType& outputLineBackgroundColor)555 bool SpannableString::GetLineBackgroundColor(uint16_t index, ColorType& outputLineBackgroundColor)
556 {
557     bool hasFind = false;
558     ListNode<LineBackgroundColorSpan>* tempSpan = lineBackgroundColorList_.Begin();
559     for (; tempSpan != lineBackgroundColorList_.End(); tempSpan = tempSpan->next_) {
560         uint16_t tempStart = tempSpan->data_.start;
561         uint16_t tempEnd = tempSpan->data_.end;
562         if ((tempStart <= index) && (index < tempEnd)) {
563             outputLineBackgroundColor.full = tempSpan->data_.linebackgroundColor.full;
564             hasFind = true;
565             break;
566         }
567     }
568     return hasFind;
569 }
570 } // namespace OHOS
571