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