• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 != nullptr) && (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         if (isSpannable_ == nullptr) {
172             GRAPHIC_LOGE("SpannableString::SetSpannable() isSpannable_ == nullptr");
173             return false;
174         }
175         for (uint16_t i = 0; i < isSpannableLen_; i++) {
176             isSpannable_[i] = false;
177         }
178     }
179     bool isSuccess = ExpandSpannableLen(endIndex);
180     if (isSuccess && (isSpannable_ != nullptr)) {
181         for (uint16_t i = startIndex; ((i < endIndex) && (i < isSpannableLen_)); i++) {
182             isSpannable_[i] = value;
183         }
184         isSuccess = true;
185     }
186     return isSuccess;
187 }
188 
GetSpannable(uint16_t index)189 bool SpannableString::GetSpannable(uint16_t index)
190 {
191     bool result = false;
192     if ((isSpannable_ != nullptr) && (index < isSpannableLen_)) {
193         result = isSpannable_[index];
194     }
195     return result;
196 }
197 
198 /*
199  * this function merge samge value when add node
200  */
SetFontSize(uint8_t inputFontSize,uint16_t startIndex,uint16_t endIndex)201 void SpannableString::SetFontSize(uint8_t inputFontSize, uint16_t startIndex, uint16_t endIndex)
202 {
203     if (sizeList_.IsEmpty()) {
204         FontSizeSpan inputSpan;
205         inputSpan.start = startIndex;
206         inputSpan.end =  endIndex;
207         inputSpan.fontSize = inputFontSize;
208         sizeList_.PushFront(inputSpan);
209         SetSpannable(true, startIndex, endIndex);
210         return;
211     } else {
212         ListNode<FontSizeSpan>* tempSpan = sizeList_.Begin();
213         for (; ((tempSpan != nullptr) && (tempSpan != sizeList_.End())); tempSpan = tempSpan->next_) {
214             bool needAddNode = true;
215             uint16_t tempStart = tempSpan->data_.start;
216             uint16_t tempEnd = tempSpan->data_.end;
217             uint8_t tempSize = tempSpan->data_.fontSize;
218             if (inputFontSize == tempSize) {
219                 needAddNode = EqualInsert<FontSizeSpan>(startIndex, endIndex, tempStart, tempEnd, &tempSpan, sizeList_);
220             } else {
221                 FontSizeSpan tempLeft;
222                 tempLeft.start = tempStart;
223                 tempLeft.end = startIndex;
224                 tempLeft.fontSize = tempSize;
225                 FontSizeSpan tempRight;
226                 tempRight.start = endIndex;
227                 tempRight.end = tempEnd;
228                 tempRight.fontSize = tempSize;
229                 needAddNode = UnequalInsert<FontSizeSpan>(startIndex, endIndex, tempStart, tempEnd, &tempSpan,
230                                                           sizeList_, tempLeft, tempRight);
231             }
232             if (needAddNode) {
233                 FontSizeSpan inputSpan;
234                 inputSpan.start = startIndex;
235                 inputSpan.end = endIndex;
236                 inputSpan.fontSize = inputFontSize;
237                 sizeList_.PushBack(inputSpan);
238                 SetSpannable(true, startIndex, endIndex);
239             }
240         }
241     }
242 }
243 
GetFontSize(uint16_t index,uint8_t & outputSize)244 bool SpannableString::GetFontSize(uint16_t index, uint8_t& outputSize)
245 {
246     bool hasFind = false;
247     ListNode<FontSizeSpan>* tempSpan = sizeList_.Begin();
248     for (; ((tempSpan != nullptr) && (tempSpan != sizeList_.End())); tempSpan = tempSpan->next_) {
249         uint16_t tempStart = tempSpan->data_.start;
250         uint16_t tempEnd = tempSpan->data_.end;
251         if ((tempStart <= index) && (index < tempEnd)) {
252             outputSize = tempSpan->data_.fontSize;
253             hasFind = true;
254             break;
255         }
256     }
257     return hasFind;
258 }
259 
SetFontId(uint16_t inputFontId,uint16_t startIndex,uint16_t endIndex)260 void SpannableString::SetFontId(uint16_t inputFontId, uint16_t startIndex, uint16_t endIndex)
261 {
262     if (fontIdList_.IsEmpty()) {
263         FontIdSpan inputSpan;
264         inputSpan.start = startIndex;
265         inputSpan.end = endIndex;
266         inputSpan.fontId =  inputFontId;
267         fontIdList_.PushFront(inputSpan);
268         SetSpannable(true, startIndex, endIndex);
269         return;
270     }
271     ListNode<FontIdSpan>* tempSpan = fontIdList_.Begin();
272     for (; ((tempSpan != nullptr) && (tempSpan != fontIdList_.End())); tempSpan = tempSpan->next_) {
273         bool needAddNode = true;
274         uint16_t tempStart = tempSpan->data_.start;
275         uint16_t tempEnd = tempSpan->data_.end;
276         uint16_t tempId = tempSpan->data_.fontId;
277         if (inputFontId == tempId) {
278             needAddNode = EqualInsert<FontIdSpan>(startIndex, endIndex, tempStart, tempEnd, &tempSpan, fontIdList_);
279         } else {
280             FontIdSpan tempLeft;
281             tempLeft.start = tempStart;
282             tempLeft.end = startIndex;
283             tempLeft.fontId = tempId;
284             FontIdSpan tempRight;
285             tempRight.start = endIndex;
286             tempRight.end = tempEnd;
287             tempRight.fontId = tempId;
288             needAddNode = UnequalInsert<FontIdSpan>(startIndex, endIndex, tempStart, tempEnd, &tempSpan, fontIdList_,
289                                                     tempLeft, tempRight);
290         }
291         if (needAddNode) {
292             FontIdSpan inputSpan;
293             inputSpan.start = startIndex;
294             inputSpan.end = endIndex;
295             inputSpan.fontId = inputFontId;
296             fontIdList_.PushBack(inputSpan);
297             SetSpannable(true, startIndex, endIndex);
298         }
299     }
300 }
301 
GetFontId(uint16_t index,uint16_t & outputFontId)302 bool SpannableString::GetFontId(uint16_t index, uint16_t& outputFontId)
303 {
304     bool hasFind = false;
305     ListNode<FontIdSpan>* tempSpan = fontIdList_.Begin();
306     for (; ((tempSpan != nullptr) && (tempSpan != fontIdList_.End())); tempSpan = tempSpan->next_) {
307         uint16_t tempStart = tempSpan->data_.start;
308         uint16_t tempEnd = tempSpan->data_.end;
309         if ((tempStart <= index) && (index < tempEnd)) {
310             outputFontId = tempSpan->data_.fontId;
311             hasFind = true;
312             break;
313         }
314     }
315     return hasFind;
316 }
317 
SetFontHeight(int16_t inputHeight,uint16_t startIndex,uint16_t endIndex)318 void SpannableString::SetFontHeight(int16_t inputHeight, uint16_t startIndex, uint16_t endIndex)
319 {
320     if (heightList_.IsEmpty()) {
321         LetterHeightSpan inputSpan;
322         inputSpan.start = startIndex;
323         inputSpan.end = endIndex;
324         inputSpan.height = inputHeight;
325         heightList_.PushFront(inputSpan);
326         SetSpannable(true, startIndex, endIndex);
327         return;
328     }
329     ListNode<LetterHeightSpan>* tempSpan = heightList_.Begin();
330     for (; ((tempSpan != nullptr) && (tempSpan != heightList_.End())); tempSpan = tempSpan->next_) {
331         bool needAddNode = true;
332         uint16_t tempStart = tempSpan->data_.start;
333         uint16_t tempEnd = tempSpan->data_.end;
334         int16_t tempHeight = tempSpan->data_.height;
335         if (inputHeight == tempHeight) {
336             needAddNode =
337                 EqualInsert<LetterHeightSpan>(startIndex, endIndex, tempStart, tempEnd, &tempSpan, heightList_);
338         } else {
339             LetterHeightSpan tempLeft;
340             tempLeft.start = tempStart;
341             tempLeft.end = startIndex;
342             tempLeft.height = tempHeight;
343             LetterHeightSpan tempRight;
344             tempRight.start = endIndex;
345             tempRight.end = tempEnd;
346             tempRight.height = tempHeight;
347             needAddNode = UnequalInsert<LetterHeightSpan>(startIndex, endIndex, tempStart, tempEnd, &tempSpan,
348                                                           heightList_, tempLeft, tempRight);
349         }
350         if (needAddNode) {
351             LetterHeightSpan inputSpan;
352             inputSpan.start = startIndex;
353             inputSpan.end = endIndex;
354             inputSpan.height = inputHeight;
355             heightList_.PushBack(inputSpan);
356             SetSpannable(true, startIndex, endIndex);
357         }
358     }
359 }
360 
GetFontHeight(uint16_t index,int16_t & outputHeight,uint16_t & defaultFontId,uint8_t defaultFontSize)361 bool SpannableString::GetFontHeight(uint16_t index,
362                                     int16_t& outputHeight,
363                                     uint16_t& defaultFontId,
364                                     uint8_t defaultFontSize)
365 {
366     bool hasFind = false;
367     ListNode<LetterHeightSpan>* tempSpan = heightList_.Begin();
368     for (; ((tempSpan != nullptr) && (tempSpan != heightList_.End())); tempSpan = tempSpan->next_) {
369         uint16_t tempStart = tempSpan->data_.start;
370         uint16_t tempEnd = tempSpan->data_.end;
371         if ((tempStart <= index) && (index < tempEnd)) {
372             hasFind = true;
373             outputHeight = tempSpan->data_.height;
374             break;
375         }
376     }
377     if (!hasFind) {
378         GetFontId(index, defaultFontId);
379         GetFontSize(index, defaultFontSize);
380         UIFont* uifont = UIFont::GetInstance();
381         outputHeight = uifont->GetHeight(defaultFontId, defaultFontSize);
382         SetFontHeight(outputHeight, index, index + 1);
383     }
384     return hasFind;
385 }
386 
SetBackgroundColor(ColorType inputBackgroundColor,uint16_t startIndex,uint16_t endIndex)387 void SpannableString::SetBackgroundColor(ColorType inputBackgroundColor, uint16_t startIndex, uint16_t endIndex)
388 {
389     if (backgroundColorList_.IsEmpty()) {
390         BackgroundColorSpan inputSpan;
391         inputSpan.start = startIndex;
392         inputSpan.end =  endIndex;
393         inputSpan.backgroundColor.full = inputBackgroundColor.full;
394         backgroundColorList_.PushFront(inputSpan);
395         SetSpannable(true, startIndex, endIndex);
396         return;
397     } else {
398         ListNode<BackgroundColorSpan>* tempSpan = backgroundColorList_.Begin();
399         for (; ((tempSpan != nullptr) && (tempSpan != backgroundColorList_.End())); tempSpan = tempSpan->next_) {
400             bool needAddNode = true;
401             uint16_t tempStart = tempSpan->data_.start;
402             uint16_t tempEnd = tempSpan->data_.end;
403             ColorType tempSize;
404             tempSize.full = tempSpan->data_.backgroundColor.full;
405             if (inputBackgroundColor.full == tempSize.full) {
406                 needAddNode = EqualInsert<BackgroundColorSpan>(
407                     startIndex, endIndex, tempStart, tempEnd, &tempSpan,
408                     backgroundColorList_);
409             } else {
410                 BackgroundColorSpan tempLeft;
411                 tempLeft.start = tempStart;
412                 tempLeft.end = startIndex;
413                 tempLeft.backgroundColor.full = tempSize.full;
414                 BackgroundColorSpan tempRight;
415                 tempRight.start = endIndex;
416                 tempRight.end = tempEnd;
417                 tempRight.backgroundColor.full = tempSize.full;
418                 needAddNode = UnequalInsert<BackgroundColorSpan>(
419                     startIndex, endIndex, tempStart, tempEnd, &tempSpan,
420                     backgroundColorList_, tempLeft, tempRight);
421             }
422             if (needAddNode) {
423                 BackgroundColorSpan inputSpan;
424                 inputSpan.start = startIndex;
425                 inputSpan.end = endIndex;
426                 inputSpan.backgroundColor.full = inputBackgroundColor.full;
427                 backgroundColorList_.PushBack(inputSpan);
428                 SetSpannable(true, startIndex, endIndex);
429             }
430         }
431     }
432 }
433 
GetBackgroundColor(uint16_t index,ColorType & outputBackgroundColor)434 bool SpannableString::GetBackgroundColor(uint16_t index, ColorType& outputBackgroundColor)
435 {
436     bool hasFind = false;
437     ListNode<BackgroundColorSpan>* tempSpan = backgroundColorList_.Begin();
438     for (; ((tempSpan != nullptr) && (tempSpan != backgroundColorList_.End())); tempSpan = tempSpan->next_) {
439         uint16_t tempStart = tempSpan->data_.start;
440         uint16_t tempEnd = tempSpan->data_.end;
441         if ((tempStart <= index) && (index < tempEnd)) {
442             outputBackgroundColor.full = tempSpan->data_.backgroundColor.full;
443             hasFind = true;
444             break;
445         }
446     }
447     return hasFind;
448 }
449 
SetForegroundColor(ColorType inputForegroundColor,uint16_t startIndex,uint16_t endIndex)450 void SpannableString::SetForegroundColor(ColorType inputForegroundColor, uint16_t startIndex, uint16_t endIndex)
451 {
452     if (foregroundColorList_.IsEmpty()) {
453         ForegroundColorSpan inputSpan;
454         inputSpan.start = startIndex;
455         inputSpan.end =  endIndex;
456         inputSpan.fontColor.full = inputForegroundColor.full;
457         foregroundColorList_.PushFront(inputSpan);
458         SetSpannable(true, startIndex, endIndex);
459         return;
460     } else {
461         ListNode<ForegroundColorSpan>* tempSpan = foregroundColorList_.Begin();
462         for (; ((tempSpan != nullptr) && (tempSpan != foregroundColorList_.End())); tempSpan = tempSpan->next_) {
463             bool needAddNode = true;
464             uint16_t tempStart = tempSpan->data_.start;
465             uint16_t tempEnd = tempSpan->data_.end;
466             ColorType tempSize;
467             tempSize.full= tempSpan->data_.fontColor.full;
468             if (inputForegroundColor.full == tempSize.full) {
469                 needAddNode = EqualInsert<ForegroundColorSpan>(
470                     startIndex, endIndex, tempStart, tempEnd, &tempSpan,
471                     foregroundColorList_);
472             } else {
473                 ForegroundColorSpan tempLeft;
474                 tempLeft.start = tempStart;
475                 tempLeft.end = startIndex;
476                 tempLeft.fontColor.full = tempSize.full;
477                 ForegroundColorSpan tempRight;
478                 tempRight.start = endIndex;
479                 tempRight.end = tempEnd;
480                 tempRight.fontColor.full = tempSize.full;
481                 needAddNode = UnequalInsert<ForegroundColorSpan>(startIndex, endIndex, tempStart, tempEnd, &tempSpan,
482                                                           foregroundColorList_, tempLeft, tempRight);
483             }
484             if (needAddNode) {
485                 ForegroundColorSpan inputSpan;
486                 inputSpan.start = startIndex;
487                 inputSpan.end = endIndex;
488                 inputSpan.fontColor.full = inputForegroundColor.full;
489                 foregroundColorList_.PushBack(inputSpan);
490                 SetSpannable(true, startIndex, endIndex);
491             }
492         }
493     }
494 }
495 
GetForegroundColor(uint16_t index,ColorType & outputForegroundColor)496 bool SpannableString::GetForegroundColor(uint16_t index, ColorType& outputForegroundColor)
497 {
498     bool hasFind = false;
499     ListNode<ForegroundColorSpan>* tempSpan = foregroundColorList_.Begin();
500     for (; ((tempSpan != nullptr) && (tempSpan != foregroundColorList_.End())); tempSpan = tempSpan->next_) {
501         uint16_t tempStart = tempSpan->data_.start;
502         uint16_t tempEnd = tempSpan->data_.end;
503         if ((tempStart <= index) && (index < tempEnd)) {
504             outputForegroundColor.full = tempSpan->data_.fontColor.full;
505             hasFind = true;
506             break;
507         }
508     }
509     return hasFind;
510 }
511 
SetLineBackgroundColor(ColorType inputLineBackgroundColor,uint16_t startIndex,uint16_t endIndex)512 void SpannableString::SetLineBackgroundColor(ColorType inputLineBackgroundColor, uint16_t startIndex, uint16_t endIndex)
513 {
514     if (lineBackgroundColorList_.IsEmpty()) {
515         LineBackgroundColorSpan inputSpan;
516         inputSpan.start = startIndex;
517         inputSpan.end =  endIndex;
518         inputSpan.linebackgroundColor.full = inputLineBackgroundColor.full;
519         lineBackgroundColorList_.PushFront(inputSpan);
520         SetSpannable(true, startIndex, endIndex);
521         return;
522     } else {
523         ListNode<LineBackgroundColorSpan>* tempSpan = lineBackgroundColorList_.Begin();
524         for (; ((tempSpan != nullptr) && (tempSpan != lineBackgroundColorList_.End())); tempSpan = tempSpan->next_) {
525             bool needAddNode = true;
526             uint16_t tempStart = tempSpan->data_.start;
527             uint16_t tempEnd = tempSpan->data_.end;
528             ColorType tempSize;
529             tempSize.full = tempSpan->data_.linebackgroundColor.full;
530             if (inputLineBackgroundColor.full == tempSize.full) {
531                 needAddNode = EqualInsert<LineBackgroundColorSpan>(
532                     startIndex, endIndex, tempStart, tempEnd, &tempSpan,
533                     lineBackgroundColorList_);
534             } else {
535                 LineBackgroundColorSpan tempLeft;
536                 tempLeft.start = tempStart;
537                 tempLeft.end = startIndex;
538                 tempLeft.linebackgroundColor.full = tempSize.full;
539                 LineBackgroundColorSpan tempRight;
540                 tempRight.start = endIndex;
541                 tempRight.end = tempEnd;
542                 tempRight.linebackgroundColor.full = tempSize.full;
543                 needAddNode = UnequalInsert<LineBackgroundColorSpan>(
544                     startIndex, endIndex, tempStart, tempEnd, &tempSpan,
545                     lineBackgroundColorList_, tempLeft, tempRight);
546             }
547             if (needAddNode) {
548                 LineBackgroundColorSpan inputSpan;
549                 inputSpan.start = startIndex;
550                 inputSpan.end = endIndex;
551                 inputSpan.linebackgroundColor.full = inputLineBackgroundColor.full;
552                 lineBackgroundColorList_.PushBack(inputSpan);
553                 SetSpannable(true, startIndex, endIndex);
554             }
555         }
556     }
557 }
558 
GetLineBackgroundColor(uint16_t index,ColorType & outputLineBackgroundColor)559 bool SpannableString::GetLineBackgroundColor(uint16_t index, ColorType& outputLineBackgroundColor)
560 {
561     bool hasFind = false;
562     ListNode<LineBackgroundColorSpan>* tempSpan = lineBackgroundColorList_.Begin();
563     for (; ((tempSpan != nullptr) && (tempSpan != lineBackgroundColorList_.End())); tempSpan = tempSpan->next_) {
564         uint16_t tempStart = tempSpan->data_.start;
565         uint16_t tempEnd = tempSpan->data_.end;
566         if ((tempStart <= index) && (index < tempEnd)) {
567             outputLineBackgroundColor.full = tempSpan->data_.linebackgroundColor.full;
568             hasFind = true;
569             break;
570         }
571     }
572     return hasFind;
573 }
574 } // namespace OHOS
575