• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 #ifndef ROSEN_MODULES_TEXGINE_SRC_CHAR_GROUPS_H
17 #define ROSEN_MODULES_TEXGINE_SRC_CHAR_GROUPS_H
18 
19 #include "typeface.h"
20 
21 #include <array>
22 #include <cstdint>
23 #include <memory>
24 #include <ostream>
25 #include <vector>
26 #include <unicode/uchar.h>
27 
28 namespace OHOS {
29 namespace Rosen {
30 namespace TextEngine {
31 struct Glyph {
32     uint32_t codepoint;
33     double advanceX;
34     double advanceY;
35     double offsetX;
36     double offsetY;
37 };
38 
39 enum SpacesModel : uint8_t {
40     NORMAL = 0, // no handle of spaces
41     LEFT = 1, // handle the whitespace at the end of the string on the left
42     RIGHT = 2, // handle whitespace at the begin of the string on the right
43 };
44 
45 struct CharGroup {
46     std::vector<uint16_t> chars;
47     std::vector<struct Glyph> glyphs;
48     std::shared_ptr<Typeface> typeface;
49     double visibleWidth = 0;
50     double invisibleWidth = 0;
51     bool isWordEnd = false;
52 
GetWidthCharGroup53     double GetWidth() const
54     {
55         return visibleWidth + invisibleWidth;
56     }
57 
GetHeightCharGroup58     double GetHeight() const
59     {
60         double maxAdvanceY = 0;
61         for (const auto &glyph : glyphs) {
62             maxAdvanceY = std::max(maxAdvanceY, glyph.advanceY);
63         }
64         return maxAdvanceY;
65     }
66 
CheckCodePointCharGroup67     bool CheckCodePoint() const
68     {
69         if (!glyphs.size()) {
70             return false;
71         }
72         for (const auto& glyph : glyphs) {
73             if (!glyph.codepoint) {
74                 return false;
75             }
76         }
77         return true;
78     };
79 
IsHardBreakCharGroup80     bool IsHardBreak()
81     {
82         ULineBreak lineBreak = static_cast<ULineBreak>(
83             u_getIntPropertyValue(chars[0], UCHAR_LINE_BREAK));
84         return (lineBreak == U_LB_LINE_FEED || lineBreak == U_LB_MANDATORY_BREAK);
85     }
86 
IsEmojiCharGroup87     bool IsEmoji() const
88     {
89         bool isEmoji = false;
90         for (size_t i = 0; i < chars.size(); i++) {
91             isEmoji = (u_hasBinaryProperty(chars[i], UCHAR_EMOJI) ||
92                 u_hasBinaryProperty(chars[i], UCHAR_EMOJI_PRESENTATION) ||
93                 u_hasBinaryProperty(chars[i], UCHAR_EMOJI_MODIFIER) ||
94                 u_hasBinaryProperty(chars[i], UCHAR_EMOJI_MODIFIER_BASE));
95             if (isEmoji) {
96                 return isEmoji;
97             }
98         }
99         return isEmoji;
100     }
101 
HasWhitesSpaceCharGroup102     bool HasWhitesSpace() const
103     {
104         for (const auto &ch : chars) {
105             if (u_isWhitespace(ch)) {
106                 return true;
107             }
108         }
109         return false;
110     }
111 
JudgeOnlyHardBreakCharGroup112     bool JudgeOnlyHardBreak() const
113     {
114         if (chars.empty()) {
115             return false;
116         }
117         bool onlyHardBreak = true;
118         for (size_t i = 0; i < chars.size(); i++) {
119             ULineBreak lineBreak = static_cast<ULineBreak>(
120                 u_getIntPropertyValue(chars[i], UCHAR_LINE_BREAK));
121             onlyHardBreak = (lineBreak == U_LB_LINE_FEED || lineBreak == U_LB_MANDATORY_BREAK);
122             if (!onlyHardBreak) {
123                 break;
124             }
125         }
126         return onlyHardBreak;
127     }
128 
HasHardBreakCharGroup129     bool HasHardBreak() const
130     {
131         if (chars.empty()) {
132             return false;
133         }
134         bool isHardBreak = false;
135         for (size_t i = 0; i < chars.size(); i++) {
136             ULineBreak lineBreak = static_cast<ULineBreak>(
137                 u_getIntPropertyValue(chars[i], UCHAR_LINE_BREAK));
138             isHardBreak = (lineBreak == U_LB_LINE_FEED || lineBreak == U_LB_MANDATORY_BREAK);
139             if (isHardBreak) {
140                 break;
141             }
142         }
143         return isHardBreak;
144     }
145 };
146 
147 struct IndexRange {
148     int start = 0;
149     int end = 0;
150 
151     bool operator==(IndexRange const &range) const
152     {
153         return range.start == start && range.end == end;
154     }
155 };
156 
157 std::ostream &operator<<(std::ostream &os, const struct IndexRange &range);
158 class CharGroups;
159 // 2 is the count of CharGroups in the return value
160 using CharGroupsPair = std::array<CharGroups, 2>;
161 class CharGroups {
162 public:
163     static CharGroups CreateEmpty();
164     static CharGroups CreateWithInvalidRange(IndexRange range);
165 
166     size_t GetNumberOfGlyph() const;
167     size_t GetNumberOfCharGroup() const;
168     const IndexRange &GetRange() const;
169     CharGroup &GetBack() const;
170     size_t GetSize() const;
171 
172     bool IsValid() const;
173     bool IsSameCharGroups(const CharGroups &right) const;
174     bool IsIntersect(const CharGroups &right) const;
175 
176     CharGroupsPair GetSplit(const int &index) const;
177     CharGroupsPair GetSplitAll(const int &index) const;
178     CharGroups GetSub(const int &start, const int &end) const;
179     CharGroups GetSubAll(const int &start, const int &end) const;
180     CharGroups GetSubFromU16RangeAll(const int &u16start, const int &u16end) const;
181     CharGroups GetIntersect(const CharGroups &right) const;
182     struct CharGroup &Get(const int32_t &index) const;
183     struct CharGroup &GetAll(const int32_t &index) const;
184 
185     std::vector<uint16_t> ToUTF16() const;
186     std::vector<uint16_t> ToUTF16All() const;
187 
188     std::vector<struct CharGroup>::iterator begin() const;
189     std::vector<struct CharGroup>::iterator end() const;
190 
191     CharGroups Clone() const;
192 
193     void Merge(const CharGroups &right);
194     void PushBack(const struct CharGroup &cg);
195     void ReverseAll();
196     bool operator==(CharGroups const &cgs) const
197     {
198         return IsSameCharGroups(cgs) && range_ == cgs.range_;
199     }
200 
201     bool CheckCodePoint() const;
202     std::string GetTypefaceName();
203     double GetAllCharWidth() const;
204     double GetCharWidth(const size_t index) const;
205     std::vector<uint16_t> GetCharsToU16(size_t start, size_t end, const SpacesModel &spacesModel);
206     bool IsSingleWord() const;
207     bool JudgeOnlyHardBreak() const;
208     int FindHardBreakPos() const;
209     std::vector<uint16_t> GetSubCharsToU16(const int start, const int end);
210 private:
211     friend void ReportMemoryUsage(const std::string &member, const CharGroups &that, bool needThis);
212 
213     std::shared_ptr<std::vector<struct CharGroup>> pcgs_ = nullptr;
214     struct IndexRange range_ = {0, 0};
215 };
216 } // namespace TextEngine
217 } // namespace Rosen
218 } // namespace OHOS
219 
220 #endif // ROSEN_MODULES_TEXGINE_SRC_CHAR_GROUPS_H
221