1 /*
2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
3 * (C) 2000 Antti Koivisto (koivisto@kde.org)
4 * (C) 2000 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2003, 2006, 2007, 2011 Apple Inc. All rights reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TEXT_TEXT_RUN_H_
25 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TEXT_TEXT_RUN_H_
26
27 #include <unicode/utf16.h>
28
29 #include "base/containers/span.h"
30 #include "base/optional.h"
31 #include "third_party/blink/renderer/platform/heap/heap.h"
32 #include "third_party/blink/renderer/platform/platform_export.h"
33 #include "third_party/blink/renderer/platform/text/tab_size.h"
34 #include "third_party/blink/renderer/platform/text/text_direction.h"
35 #include "third_party/blink/renderer/platform/text/text_justify.h"
36 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
37 #include "third_party/blink/renderer/platform/wtf/text/string_view.h"
38 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
39 #include "third_party/skia/include/core/SkRefCnt.h"
40
41 namespace blink {
42
43 class PLATFORM_EXPORT TextRun final {
44 DISALLOW_NEW();
45
46 public:
47 enum ExpansionBehaviorFlags {
48 kForbidTrailingExpansion = 0 << 0,
49 kAllowTrailingExpansion = 1 << 0,
50 kForbidLeadingExpansion = 0 << 1,
51 kAllowLeadingExpansion = 1 << 1,
52 };
53
54 typedef unsigned ExpansionBehavior;
55
56 TextRun(const LChar* c,
57 unsigned len,
58 float xpos = 0,
59 float expansion = 0,
60 ExpansionBehavior expansion_behavior = kAllowTrailingExpansion |
61 kForbidLeadingExpansion,
62 TextDirection direction = TextDirection::kLtr,
63 bool directional_override = false)
characters_length_(len)64 : characters_length_(len),
65 len_(len),
66 xpos_(xpos),
67 expansion_(expansion),
68 expansion_behavior_(expansion_behavior),
69 is_8bit_(true),
70 allow_tabs_(false),
71 direction_(static_cast<unsigned>(direction)),
72 directional_override_(directional_override),
73 disable_spacing_(false),
74 text_justify_(static_cast<unsigned>(TextJustify::kAuto)),
75 normalize_space_(false),
76 tab_size_(0) {
77 data_.characters8 = c;
78 }
79
80 TextRun(const UChar* c,
81 unsigned len,
82 float xpos = 0,
83 float expansion = 0,
84 ExpansionBehavior expansion_behavior = kAllowTrailingExpansion |
85 kForbidLeadingExpansion,
86 TextDirection direction = TextDirection::kLtr,
87 bool directional_override = false)
characters_length_(len)88 : characters_length_(len),
89 len_(len),
90 xpos_(xpos),
91 expansion_(expansion),
92 expansion_behavior_(expansion_behavior),
93 is_8bit_(false),
94 allow_tabs_(false),
95 direction_(static_cast<unsigned>(direction)),
96 directional_override_(directional_override),
97 disable_spacing_(false),
98 text_justify_(static_cast<unsigned>(TextJustify::kAuto)),
99 normalize_space_(false),
100 tab_size_(0) {
101 data_.characters16 = c;
102 }
103
104 TextRun(const StringView& string,
105 float xpos = 0,
106 float expansion = 0,
107 ExpansionBehavior expansion_behavior = kAllowTrailingExpansion |
108 kForbidLeadingExpansion,
109 TextDirection direction = TextDirection::kLtr,
110 bool directional_override = false)
111 : characters_length_(string.length()),
112 len_(string.length()),
113 xpos_(xpos),
114 expansion_(expansion),
115 expansion_behavior_(expansion_behavior),
116 allow_tabs_(false),
117 direction_(static_cast<unsigned>(direction)),
118 directional_override_(directional_override),
119 disable_spacing_(false),
120 text_justify_(static_cast<unsigned>(TextJustify::kAuto)),
121 normalize_space_(false),
122 tab_size_(0) {
123 if (!characters_length_) {
124 is_8bit_ = true;
125 data_.characters8 = nullptr;
126 } else if (string.Is8Bit()) {
127 data_.characters8 = string.Characters8();
128 is_8bit_ = true;
129 } else {
130 data_.characters16 = string.Characters16();
131 is_8bit_ = false;
132 }
133 }
134
SubRun(unsigned start_offset,unsigned length)135 TextRun SubRun(unsigned start_offset, unsigned length) const {
136 DCHECK_LT(start_offset, len_);
137
138 TextRun result = *this;
139
140 if (Is8Bit()) {
141 result.SetText(Data8(start_offset), length);
142 return result;
143 }
144 result.SetText(Data16(start_offset), length);
145 return result;
146 }
147
148 // Returns the start index of a sub run if it was created by |SubRun|.
149 // std::numeric_limits<unsigned>::max() if not a sub run.
150 unsigned IndexOfSubRun(const TextRun&) const;
151
152 UChar operator[](unsigned i) const {
153 SECURITY_DCHECK(i < len_);
154 return Is8Bit() ? data_.characters8[i] : data_.characters16[i];
155 }
Data8(unsigned i)156 const LChar* Data8(unsigned i) const {
157 SECURITY_DCHECK(i < len_);
158 DCHECK(Is8Bit());
159 return &data_.characters8[i];
160 }
Data16(unsigned i)161 const UChar* Data16(unsigned i) const {
162 SECURITY_DCHECK(i < len_);
163 DCHECK(!Is8Bit());
164 return &data_.characters16[i];
165 }
166
167 // Prefer Span8() and Span16() to Characters8() and Characters16().
Span8()168 base::span<const LChar> Span8() const {
169 DCHECK(Is8Bit());
170 return {data_.characters8, len_};
171 }
Span16()172 base::span<const UChar> Span16() const {
173 DCHECK(!Is8Bit());
174 return {data_.characters16, len_};
175 }
176
Characters8()177 const LChar* Characters8() const {
178 DCHECK(Is8Bit());
179 return data_.characters8;
180 }
Characters16()181 const UChar* Characters16() const {
182 DCHECK(!Is8Bit());
183 return data_.characters16;
184 }
185
ToStringView()186 StringView ToStringView() const {
187 return Is8Bit() ? StringView(data_.characters8, len_)
188 : StringView(data_.characters16, len_);
189 }
190
CodepointAt(unsigned i)191 UChar32 CodepointAt(unsigned i) const {
192 SECURITY_DCHECK(i < len_);
193 if (Is8Bit())
194 return (*this)[i];
195 UChar32 codepoint;
196 U16_GET(Characters16(), 0, i, len_, codepoint);
197 return codepoint;
198 }
199
CodepointAtAndNext(unsigned & i)200 UChar32 CodepointAtAndNext(unsigned& i) const {
201 SECURITY_DCHECK(i < len_);
202 if (Is8Bit())
203 return (*this)[i++];
204 UChar32 codepoint;
205 U16_NEXT(Characters16(), i, len_, codepoint);
206 return codepoint;
207 }
208
Bytes()209 const void* Bytes() const { return data_.bytes_; }
210
Is8Bit()211 bool Is8Bit() const { return is_8bit_; }
length()212 unsigned length() const { return len_; }
CharactersLength()213 unsigned CharactersLength() const { return characters_length_; }
214
NormalizeSpace()215 bool NormalizeSpace() const { return normalize_space_; }
SetNormalizeSpace(bool normalize_space)216 void SetNormalizeSpace(bool normalize_space) {
217 normalize_space_ = normalize_space;
218 }
219
SetText(const LChar * c,unsigned len)220 void SetText(const LChar* c, unsigned len) {
221 data_.characters8 = c;
222 len_ = len;
223 is_8bit_ = true;
224 }
SetText(const UChar * c,unsigned len)225 void SetText(const UChar* c, unsigned len) {
226 data_.characters16 = c;
227 len_ = len;
228 is_8bit_ = false;
229 }
230 void SetText(const String&);
SetCharactersLength(unsigned characters_length)231 void SetCharactersLength(unsigned characters_length) {
232 characters_length_ = characters_length;
233 }
234
SetExpansionBehavior(ExpansionBehavior behavior)235 void SetExpansionBehavior(ExpansionBehavior behavior) {
236 expansion_behavior_ = behavior;
237 }
238
AllowTabs()239 bool AllowTabs() const { return allow_tabs_; }
GetTabSize()240 TabSize GetTabSize() const { return tab_size_; }
241 void SetTabSize(bool, TabSize);
242
XPos()243 float XPos() const { return xpos_; }
SetXPos(float x_pos)244 void SetXPos(float x_pos) { xpos_ = x_pos; }
Expansion()245 float Expansion() const { return expansion_; }
SetExpansion(float expansion)246 void SetExpansion(float expansion) { expansion_ = expansion; }
AllowsLeadingExpansion()247 bool AllowsLeadingExpansion() const {
248 return expansion_behavior_ & kAllowLeadingExpansion;
249 }
AllowsTrailingExpansion()250 bool AllowsTrailingExpansion() const {
251 return expansion_behavior_ & kAllowTrailingExpansion;
252 }
Direction()253 TextDirection Direction() const {
254 return static_cast<TextDirection>(direction_);
255 }
Rtl()256 bool Rtl() const { return Direction() == TextDirection::kRtl; }
Ltr()257 bool Ltr() const { return Direction() == TextDirection::kLtr; }
DirectionalOverride()258 bool DirectionalOverride() const { return directional_override_; }
SpacingDisabled()259 bool SpacingDisabled() const { return disable_spacing_; }
260
DisableSpacing()261 void DisableSpacing() { disable_spacing_ = true; }
SetDirection(TextDirection direction)262 void SetDirection(TextDirection direction) {
263 direction_ = static_cast<unsigned>(direction);
264 }
SetDirectionalOverride(bool override)265 void SetDirectionalOverride(bool override) {
266 directional_override_ = override;
267 }
268
SetTextJustify(TextJustify text_justify)269 void SetTextJustify(TextJustify text_justify) {
270 text_justify_ = static_cast<unsigned>(text_justify);
271 }
GetTextJustify()272 TextJustify GetTextJustify() const {
273 return static_cast<TextJustify>(text_justify_);
274 }
275
276 // Up-converts to UTF-16 as needed and normalizes spaces and Unicode control
277 // characters as per the CSS Text Module Level 3 specification.
278 // https://drafts.csswg.org/css-text-3/#white-space-processing
279 String NormalizedUTF16() const;
280
281 private:
282 union {
283 const LChar* characters8;
284 const UChar* characters16;
285 const void* bytes_;
286 } data_;
287 // Marks the end of the characters buffer. Default equals to m_len.
288 unsigned characters_length_;
289 unsigned len_;
290
291 // m_xpos is the x position relative to the left start of the text line, not
292 // relative to the left start of the containing block. In the case of right
293 // alignment or center alignment, left start of the text line is not the same
294 // as left start of the containing block.
295 float xpos_;
296
297 float expansion_;
298 ExpansionBehavior expansion_behavior_ : 2;
299 unsigned is_8bit_ : 1;
300 unsigned allow_tabs_ : 1;
301 unsigned direction_ : 1;
302 // Was this direction set by an override character.
303 unsigned directional_override_ : 1;
304 unsigned disable_spacing_ : 1;
305 unsigned text_justify_ : 2;
306 unsigned normalize_space_ : 1;
307 TabSize tab_size_;
308 };
309
SetTabSize(bool allow,TabSize size)310 inline void TextRun::SetTabSize(bool allow, TabSize size) {
311 allow_tabs_ = allow;
312 tab_size_ = size;
313 }
314
315 } // namespace blink
316
317 #endif
318