OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006 Lars Knoll <lars@trolltech.com> | 2 * Copyright (C) 2006 Lars Knoll <lars@trolltech.com> |
3 * Copyright (C) 2007, 2011, 2012 Apple Inc. All rights reserved. | 3 * Copyright (C) 2007, 2011, 2012 Apple Inc. All rights reserved. |
4 * | 4 * |
5 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
6 * modify it under the terms of the GNU Library General Public | 6 * modify it under the terms of the GNU Library General Public |
7 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
8 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
9 * | 9 * |
10 * This library is distributed in the hope that it will be useful, | 10 * This library is distributed in the hope that it will be useful, |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 // letters/numbers except some south east asians'. | 73 // letters/numbers except some south east asians'. |
74 }; | 74 }; |
75 | 75 |
76 class PLATFORM_EXPORT LazyLineBreakIterator final { | 76 class PLATFORM_EXPORT LazyLineBreakIterator final { |
77 STACK_ALLOCATED(); | 77 STACK_ALLOCATED(); |
78 | 78 |
79 public: | 79 public: |
80 LazyLineBreakIterator() | 80 LazyLineBreakIterator() |
81 : iterator_(0), | 81 : iterator_(0), |
82 cached_prior_context_(0), | 82 cached_prior_context_(0), |
83 cached_prior_context_length_(0) { | 83 cached_prior_context_length_(0), |
| 84 break_type_(LineBreakType::kNormal) { |
84 ResetPriorContext(); | 85 ResetPriorContext(); |
85 } | 86 } |
86 | 87 |
87 LazyLineBreakIterator(String string, | 88 LazyLineBreakIterator(String string, |
88 const AtomicString& locale = AtomicString()) | 89 const AtomicString& locale = AtomicString(), |
| 90 LineBreakType break_type = LineBreakType::kNormal) |
89 : string_(string), | 91 : string_(string), |
90 locale_(locale), | 92 locale_(locale), |
91 iterator_(0), | 93 iterator_(0), |
92 cached_prior_context_(0), | 94 cached_prior_context_(0), |
93 cached_prior_context_length_(0) { | 95 cached_prior_context_length_(0), |
| 96 break_type_(break_type) { |
94 ResetPriorContext(); | 97 ResetPriorContext(); |
95 } | 98 } |
96 | 99 |
97 ~LazyLineBreakIterator() { | 100 ~LazyLineBreakIterator() { |
98 if (iterator_) | 101 if (iterator_) |
99 ReleaseLineBreakIterator(iterator_); | 102 ReleaseLineBreakIterator(iterator_); |
100 } | 103 } |
101 | 104 |
102 String GetString() const { return string_; } | 105 String GetString() const { return string_; } |
103 | 106 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 if (prior_context_[0]) | 146 if (prior_context_[0]) |
144 ++prior_context_length; | 147 ++prior_context_length; |
145 } | 148 } |
146 return prior_context_length; | 149 return prior_context_length; |
147 } | 150 } |
148 | 151 |
149 // Obtain text break iterator, possibly previously cached, where this iterator | 152 // Obtain text break iterator, possibly previously cached, where this iterator |
150 // is (or has been) initialized to use the previously stored string as the | 153 // is (or has been) initialized to use the previously stored string as the |
151 // primary breaking context and using previously stored prior context if | 154 // primary breaking context and using previously stored prior context if |
152 // non-empty. | 155 // non-empty. |
153 TextBreakIterator* Get(unsigned prior_context_length) { | 156 TextBreakIterator* Get(unsigned prior_context_length) const { |
154 DCHECK(prior_context_length <= kPriorContextCapacity); | 157 DCHECK(prior_context_length <= kPriorContextCapacity); |
155 const UChar* prior_context = | 158 const UChar* prior_context = |
156 prior_context_length | 159 prior_context_length |
157 ? &prior_context_[kPriorContextCapacity - prior_context_length] | 160 ? &prior_context_[kPriorContextCapacity - prior_context_length] |
158 : 0; | 161 : 0; |
159 if (!iterator_) { | 162 if (!iterator_) { |
160 if (string_.Is8Bit()) | 163 if (string_.Is8Bit()) |
161 iterator_ = AcquireLineBreakIterator( | 164 iterator_ = AcquireLineBreakIterator( |
162 string_.Characters8(), string_.length(), locale_, prior_context, | 165 string_.Characters8(), string_.length(), locale_, prior_context, |
163 prior_context_length); | 166 prior_context_length); |
164 else | 167 else |
165 iterator_ = AcquireLineBreakIterator( | 168 iterator_ = AcquireLineBreakIterator( |
166 string_.Characters16(), string_.length(), locale_, prior_context, | 169 string_.Characters16(), string_.length(), locale_, prior_context, |
167 prior_context_length); | 170 prior_context_length); |
168 cached_prior_context_ = prior_context; | 171 cached_prior_context_ = prior_context; |
169 cached_prior_context_length_ = prior_context_length; | 172 cached_prior_context_length_ = prior_context_length; |
170 } else if (prior_context != cached_prior_context_ || | 173 } else if (prior_context != cached_prior_context_ || |
171 prior_context_length != cached_prior_context_length_) { | 174 prior_context_length != cached_prior_context_length_) { |
172 this->ResetStringAndReleaseIterator(string_, locale_); | 175 ReleaseIterator(); |
173 return this->Get(prior_context_length); | 176 return Get(prior_context_length); |
174 } | 177 } |
175 return iterator_; | 178 return iterator_; |
176 } | 179 } |
177 | 180 |
178 void ResetStringAndReleaseIterator(String string, | 181 void ResetStringAndReleaseIterator(String string, |
179 const AtomicString& locale) { | 182 const AtomicString& locale) { |
180 if (iterator_) | |
181 ReleaseLineBreakIterator(iterator_); | |
182 | |
183 string_ = string; | 183 string_ = string; |
184 locale_ = locale; | 184 locale_ = locale; |
185 iterator_ = 0; | 185 |
186 cached_prior_context_ = 0; | 186 ReleaseIterator(); |
187 cached_prior_context_length_ = 0; | |
188 } | 187 } |
189 | 188 |
190 inline bool IsBreakable( | 189 void SetLocale(const AtomicString& locale) { |
191 int pos, | 190 if (locale == locale_) |
192 int& next_breakable, | 191 return; |
193 LineBreakType line_break_type = LineBreakType::kNormal) { | 192 locale_ = locale; |
| 193 ReleaseIterator(); |
| 194 } |
| 195 |
| 196 void SetBreakType(LineBreakType break_type) { break_type_ = break_type; } |
| 197 |
| 198 inline bool IsBreakable(int pos, |
| 199 int& next_breakable, |
| 200 LineBreakType line_break_type) const { |
194 if (pos > next_breakable) { | 201 if (pos > next_breakable) { |
195 switch (line_break_type) { | 202 switch (line_break_type) { |
196 case LineBreakType::kBreakAll: | 203 case LineBreakType::kBreakAll: |
197 next_breakable = NextBreakablePositionBreakAll(pos); | 204 next_breakable = NextBreakablePositionBreakAll(pos); |
198 break; | 205 break; |
199 case LineBreakType::kKeepAll: | 206 case LineBreakType::kKeepAll: |
200 next_breakable = NextBreakablePositionKeepAll(pos); | 207 next_breakable = NextBreakablePositionKeepAll(pos); |
201 break; | 208 break; |
202 default: | 209 default: |
203 next_breakable = NextBreakablePositionIgnoringNBSP(pos); | 210 next_breakable = NextBreakablePositionIgnoringNBSP(pos); |
204 } | 211 } |
205 } | 212 } |
206 return pos == next_breakable; | 213 return pos == next_breakable; |
207 } | 214 } |
208 | 215 |
| 216 inline bool IsBreakable(int pos, int& next_breakable) const { |
| 217 return IsBreakable(pos, next_breakable, break_type_); |
| 218 } |
| 219 |
| 220 // Returns the break opportunity at or after |offset|. |
| 221 unsigned NextBreakOpportunity(unsigned offset) const; |
| 222 |
| 223 // Returns the break opportunity at or before |offset|. |
| 224 unsigned PreviousBreakOpportunity(unsigned offset, unsigned min = 0) const; |
| 225 |
209 private: | 226 private: |
210 int NextBreakablePositionIgnoringNBSP(int pos); | 227 void ReleaseIterator() const { |
211 int NextBreakablePositionBreakAll(int pos); | 228 if (iterator_) |
212 int NextBreakablePositionKeepAll(int pos); | 229 ReleaseLineBreakIterator(iterator_); |
| 230 iterator_ = 0; |
| 231 cached_prior_context_ = 0; |
| 232 cached_prior_context_length_ = 0; |
| 233 } |
| 234 |
| 235 int NextBreakablePositionIgnoringNBSP(int pos) const; |
| 236 int NextBreakablePositionBreakAll(int pos) const; |
| 237 int NextBreakablePositionKeepAll(int pos) const; |
213 | 238 |
214 static const unsigned kPriorContextCapacity = 2; | 239 static const unsigned kPriorContextCapacity = 2; |
215 String string_; | 240 String string_; |
216 AtomicString locale_; | 241 AtomicString locale_; |
217 TextBreakIterator* iterator_; | 242 mutable TextBreakIterator* iterator_; |
218 UChar prior_context_[kPriorContextCapacity]; | 243 UChar prior_context_[kPriorContextCapacity]; |
219 const UChar* cached_prior_context_; | 244 mutable const UChar* cached_prior_context_; |
220 unsigned cached_prior_context_length_; | 245 mutable unsigned cached_prior_context_length_; |
| 246 LineBreakType break_type_; |
221 }; | 247 }; |
222 | 248 |
223 // Iterates over "extended grapheme clusters", as defined in UAX #29. | 249 // Iterates over "extended grapheme clusters", as defined in UAX #29. |
224 // Note that platform implementations may be less sophisticated - e.g. ICU prior | 250 // Note that platform implementations may be less sophisticated - e.g. ICU prior |
225 // to version 4.0 only supports "legacy grapheme clusters". Use this for | 251 // to version 4.0 only supports "legacy grapheme clusters". Use this for |
226 // general text processing, e.g. string truncation. | 252 // general text processing, e.g. string truncation. |
227 | 253 |
228 class PLATFORM_EXPORT NonSharedCharacterBreakIterator final { | 254 class PLATFORM_EXPORT NonSharedCharacterBreakIterator final { |
229 STACK_ALLOCATED(); | 255 STACK_ALLOCATED(); |
230 WTF_MAKE_NONCOPYABLE(NonSharedCharacterBreakIterator); | 256 WTF_MAKE_NONCOPYABLE(NonSharedCharacterBreakIterator); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
276 }; | 302 }; |
277 | 303 |
278 // Counts the number of grapheme clusters. A surrogate pair or a sequence | 304 // Counts the number of grapheme clusters. A surrogate pair or a sequence |
279 // of a non-combining character and following combining characters is | 305 // of a non-combining character and following combining characters is |
280 // counted as 1 grapheme cluster. | 306 // counted as 1 grapheme cluster. |
281 PLATFORM_EXPORT unsigned NumGraphemeClusters(const String&); | 307 PLATFORM_EXPORT unsigned NumGraphemeClusters(const String&); |
282 | 308 |
283 } // namespace blink | 309 } // namespace blink |
284 | 310 |
285 #endif | 311 #endif |
OLD | NEW |