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