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