Chromium Code Reviews| 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 |