OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/layout/ng/inline/ng_inline_items_builder.h" | 5 #include "core/layout/ng/inline/ng_inline_items_builder.h" |
6 | 6 |
7 #include "core/layout/LayoutObject.h" | 7 #include "core/layout/LayoutObject.h" |
8 #include "core/layout/ng/api/ng_offset_mapping_builder.h" | |
8 #include "core/layout/ng/inline/ng_inline_node.h" | 9 #include "core/layout/ng/inline/ng_inline_node.h" |
9 #include "core/style/ComputedStyle.h" | 10 #include "core/style/ComputedStyle.h" |
10 | 11 |
11 namespace blink { | 12 namespace blink { |
12 | 13 |
13 NGInlineItemsBuilder::~NGInlineItemsBuilder() { | 14 NGInlineItemsBuilder::~NGInlineItemsBuilder() { |
14 DCHECK_EQ(0u, exits_.size()); | 15 DCHECK_EQ(0u, exits_.size()); |
15 DCHECK_EQ(text_.length(), items_->IsEmpty() ? 0 : items_->back().EndOffset()); | 16 DCHECK_EQ(text_.length(), items_->IsEmpty() ? 0 : items_->back().EndOffset()); |
16 } | 17 } |
17 | 18 |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
149 unsigned start_offset = text_.length(); | 150 unsigned start_offset = text_.length(); |
150 for (unsigned i = start; i < end;) { | 151 for (unsigned i = start; i < end;) { |
151 UChar c = string[i]; | 152 UChar c = string[i]; |
152 if (c == kNewlineCharacter) { | 153 if (c == kNewlineCharacter) { |
153 // LayoutBR does not set preserve_newline, but should be preserved. | 154 // LayoutBR does not set preserve_newline, but should be preserved. |
154 if (!i && end == 1 && layout_object && layout_object->IsBR()) { | 155 if (!i && end == 1 && layout_object && layout_object->IsBR()) { |
155 AppendForcedBreak(style, layout_object); | 156 AppendForcedBreak(style, layout_object); |
156 return; | 157 return; |
157 } | 158 } |
158 | 159 |
159 if (last_collapsible_space_ == CollapsibleSpace::kNone) | 160 if (last_collapsible_space_ == CollapsibleSpace::kNone) { |
160 text_.Append(kSpaceCharacter); | 161 text_.Append(kSpaceCharacter); |
162 if (mapping_builder_) | |
163 mapping_builder_->AppendIdentityMapping(1); | |
164 } else { | |
165 if (mapping_builder_) | |
166 mapping_builder_->AppendCollapsedMapping(1); | |
167 } | |
161 last_collapsible_space_ = CollapsibleSpace::kNewline; | 168 last_collapsible_space_ = CollapsibleSpace::kNewline; |
162 i++; | 169 i++; |
163 continue; | 170 continue; |
164 } | 171 } |
165 | 172 |
166 if (c == kSpaceCharacter || c == kTabulationCharacter) { | 173 if (c == kSpaceCharacter || c == kTabulationCharacter) { |
167 if (last_collapsible_space_ == CollapsibleSpace::kNone) { | 174 if (last_collapsible_space_ == CollapsibleSpace::kNone) { |
168 text_.Append(kSpaceCharacter); | 175 text_.Append(kSpaceCharacter); |
169 last_collapsible_space_ = CollapsibleSpace::kSpace; | 176 last_collapsible_space_ = CollapsibleSpace::kSpace; |
177 if (mapping_builder_) | |
178 mapping_builder_->AppendIdentityMapping(1); | |
179 } else { | |
180 if (mapping_builder_) | |
181 mapping_builder_->AppendCollapsedMapping(1); | |
170 } | 182 } |
171 i++; | 183 i++; |
172 continue; | 184 continue; |
173 } | 185 } |
174 | 186 |
175 if (last_collapsible_space_ == CollapsibleSpace::kNewline) { | 187 if (last_collapsible_space_ == CollapsibleSpace::kNewline) { |
176 RemoveTrailingCollapsibleNewlineIfNeeded(string, i, style); | 188 RemoveTrailingCollapsibleNewlineIfNeeded(string, i, style); |
177 start_offset = std::min(start_offset, text_.length()); | 189 start_offset = std::min(start_offset, text_.length()); |
178 } | 190 } |
179 | 191 |
180 size_t end_of_non_space = string.Find(IsCollapsibleSpace, i + 1); | 192 size_t end_of_non_space = string.Find(IsCollapsibleSpace, i + 1); |
181 if (end_of_non_space == kNotFound) | 193 if (end_of_non_space == kNotFound) |
182 end_of_non_space = string.length(); | 194 end_of_non_space = string.length(); |
183 text_.Append(string, i, end_of_non_space - i); | 195 text_.Append(string, i, end_of_non_space - i); |
196 if (mapping_builder_) | |
197 mapping_builder_->AppendIdentityMapping(end_of_non_space - i); | |
yosin_UTC9
2017/06/28 01:44:21
So, do we call mapping builder for every word?
Xiaocheng
2017/06/28 02:05:20
Yes. To decouple the mapping builder with impl det
| |
184 i = end_of_non_space; | 198 i = end_of_non_space; |
185 last_collapsible_space_ = CollapsibleSpace::kNone; | 199 last_collapsible_space_ = CollapsibleSpace::kNone; |
186 } | 200 } |
187 | 201 |
188 if (text_.length() > start_offset) { | 202 if (text_.length() > start_offset) { |
189 AppendItem(items_, NGInlineItem::kText, start_offset, text_.length(), style, | 203 AppendItem(items_, NGInlineItem::kText, start_offset, text_.length(), style, |
190 layout_object); | 204 layout_object); |
191 } | 205 } |
192 } | 206 } |
193 | 207 |
194 // Even when without whitespace collapsing, control characters (newlines and | 208 // Even when without whitespace collapsing, control characters (newlines and |
195 // tabs) are in their own control items to make the line breaker easier. | 209 // tabs) are in their own control items to make the line breaker easier. |
196 void NGInlineItemsBuilder::AppendWithoutWhiteSpaceCollapsing( | 210 void NGInlineItemsBuilder::AppendWithoutWhiteSpaceCollapsing( |
197 const String& string, | 211 const String& string, |
198 const ComputedStyle* style, | 212 const ComputedStyle* style, |
199 LayoutObject* layout_object) { | 213 LayoutObject* layout_object) { |
200 for (unsigned start = 0; start < string.length();) { | 214 for (unsigned start = 0; start < string.length();) { |
201 UChar c = string[start]; | 215 UChar c = string[start]; |
202 if (IsControlItemCharacter(c)) { | 216 if (IsControlItemCharacter(c)) { |
203 Append(NGInlineItem::kControl, c, style, layout_object); | 217 Append(NGInlineItem::kControl, c, style, layout_object); |
204 start++; | 218 start++; |
205 continue; | 219 continue; |
206 } | 220 } |
207 | 221 |
208 size_t end = string.Find(IsControlItemCharacter, start + 1); | 222 size_t end = string.Find(IsControlItemCharacter, start + 1); |
209 if (end == kNotFound) | 223 if (end == kNotFound) |
210 end = string.length(); | 224 end = string.length(); |
211 unsigned start_offset = text_.length(); | 225 unsigned start_offset = text_.length(); |
212 text_.Append(string, start, end - start); | 226 text_.Append(string, start, end - start); |
227 if (mapping_builder_) | |
228 mapping_builder_->AppendIdentityMapping(end - start); | |
213 AppendItem(items_, NGInlineItem::kText, start_offset, text_.length(), style, | 229 AppendItem(items_, NGInlineItem::kText, start_offset, text_.length(), style, |
214 layout_object); | 230 layout_object); |
215 start = end; | 231 start = end; |
216 } | 232 } |
217 | 233 |
218 last_collapsible_space_ = CollapsibleSpace::kNone; | 234 last_collapsible_space_ = CollapsibleSpace::kNone; |
219 } | 235 } |
220 | 236 |
221 void NGInlineItemsBuilder::AppendWithPreservingNewlines( | 237 void NGInlineItemsBuilder::AppendWithPreservingNewlines( |
222 const String& string, | 238 const String& string, |
(...skipping 26 matching lines...) Expand all Loading... | |
249 } | 265 } |
250 | 266 |
251 void NGInlineItemsBuilder::Append(NGInlineItem::NGInlineItemType type, | 267 void NGInlineItemsBuilder::Append(NGInlineItem::NGInlineItemType type, |
252 UChar character, | 268 UChar character, |
253 const ComputedStyle* style, | 269 const ComputedStyle* style, |
254 LayoutObject* layout_object) { | 270 LayoutObject* layout_object) { |
255 DCHECK_NE(character, kSpaceCharacter); | 271 DCHECK_NE(character, kSpaceCharacter); |
256 DCHECK_NE(character, kZeroWidthSpaceCharacter); | 272 DCHECK_NE(character, kZeroWidthSpaceCharacter); |
257 | 273 |
258 text_.Append(character); | 274 text_.Append(character); |
275 if (mapping_builder_) | |
276 mapping_builder_->AppendIdentityMapping(1); | |
259 unsigned end_offset = text_.length(); | 277 unsigned end_offset = text_.length(); |
260 AppendItem(items_, type, end_offset - 1, end_offset, style, layout_object); | 278 AppendItem(items_, type, end_offset - 1, end_offset, style, layout_object); |
261 last_collapsible_space_ = CollapsibleSpace::kNone; | 279 last_collapsible_space_ = CollapsibleSpace::kNone; |
262 } | 280 } |
263 | 281 |
264 void NGInlineItemsBuilder::AppendOpaque(NGInlineItem::NGInlineItemType type, | 282 void NGInlineItemsBuilder::AppendOpaque(NGInlineItem::NGInlineItemType type, |
265 UChar character) { | 283 UChar character) { |
266 text_.Append(character); | 284 text_.Append(character); |
285 if (mapping_builder_) | |
286 mapping_builder_->AppendIdentityMapping(1); | |
267 unsigned end_offset = text_.length(); | 287 unsigned end_offset = text_.length(); |
268 AppendItem(items_, type, end_offset - 1, end_offset, nullptr, nullptr); | 288 AppendItem(items_, type, end_offset - 1, end_offset, nullptr, nullptr); |
269 } | 289 } |
270 | 290 |
271 void NGInlineItemsBuilder::AppendOpaque(NGInlineItem::NGInlineItemType type, | 291 void NGInlineItemsBuilder::AppendOpaque(NGInlineItem::NGInlineItemType type, |
272 const ComputedStyle* style, | 292 const ComputedStyle* style, |
273 LayoutObject* layout_object) { | 293 LayoutObject* layout_object) { |
274 unsigned end_offset = text_.length(); | 294 unsigned end_offset = text_.length(); |
275 AppendItem(items_, type, end_offset, end_offset, style, layout_object); | 295 AppendItem(items_, type, end_offset, end_offset, style, layout_object); |
276 } | 296 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
320 } | 340 } |
321 | 341 |
322 // Removes the collapsible space at the specified index. | 342 // Removes the collapsible space at the specified index. |
323 void NGInlineItemsBuilder::RemoveTrailingCollapsibleSpace(unsigned index) { | 343 void NGInlineItemsBuilder::RemoveTrailingCollapsibleSpace(unsigned index) { |
324 DCHECK_NE(last_collapsible_space_, CollapsibleSpace::kNone); | 344 DCHECK_NE(last_collapsible_space_, CollapsibleSpace::kNone); |
325 DCHECK(!text_.IsEmpty()); | 345 DCHECK(!text_.IsEmpty()); |
326 DCHECK_EQ(text_[index], kSpaceCharacter); | 346 DCHECK_EQ(text_[index], kSpaceCharacter); |
327 | 347 |
328 text_.erase(index); | 348 text_.erase(index); |
329 last_collapsible_space_ = CollapsibleSpace::kNone; | 349 last_collapsible_space_ = CollapsibleSpace::kNone; |
350 if (mapping_builder_) | |
351 mapping_builder_->CollapseTrailingSpace(text_.length() - index); | |
330 | 352 |
331 // Adjust items if the removed space is already included. | 353 // Adjust items if the removed space is already included. |
332 for (unsigned i = items_->size(); i > 0;) { | 354 for (unsigned i = items_->size(); i > 0;) { |
333 NGInlineItem& item = (*items_)[--i]; | 355 NGInlineItem& item = (*items_)[--i]; |
334 if (index >= item.EndOffset()) | 356 if (index >= item.EndOffset()) |
335 return; | 357 return; |
336 if (item.StartOffset() <= index) { | 358 if (item.StartOffset() <= index) { |
337 if (item.Length() == 1) { | 359 if (item.Length() == 1) { |
338 DCHECK_EQ(item.StartOffset(), index); | 360 DCHECK_EQ(item.StartOffset(), index); |
339 DCHECK_EQ(item.Type(), NGInlineItem::kText); | 361 DCHECK_EQ(item.Type(), NGInlineItem::kText); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
439 } | 461 } |
440 | 462 |
441 void NGInlineItemsBuilder::Exit(LayoutObject* node) { | 463 void NGInlineItemsBuilder::Exit(LayoutObject* node) { |
442 while (!exits_.IsEmpty() && exits_.back().node == node) { | 464 while (!exits_.IsEmpty() && exits_.back().node == node) { |
443 AppendOpaque(NGInlineItem::kBidiControl, exits_.back().character); | 465 AppendOpaque(NGInlineItem::kBidiControl, exits_.back().character); |
444 exits_.pop_back(); | 466 exits_.pop_back(); |
445 } | 467 } |
446 } | 468 } |
447 | 469 |
448 } // namespace blink | 470 } // namespace blink |
OLD | NEW |