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