Index: third_party/WebKit/Source/core/layout/ng/inline/ng_offset_mapping_builder.cc |
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_offset_mapping_builder.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_offset_mapping_builder.cc |
index 4d42e54cf8429eec5eddbf5f3518bde3e7466b46..46c551c224066683e16223b7fb2e9dc0cd94b9dd 100644 |
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_offset_mapping_builder.cc |
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_offset_mapping_builder.cc |
@@ -4,10 +4,47 @@ |
#include "core/layout/ng/inline/ng_offset_mapping_builder.h" |
+#include "core/layout/ng/inline/ng_offset_mapping_result.h" |
#include "platform/wtf/text/StringBuilder.h" |
namespace blink { |
+namespace { |
+ |
+// Returns the type of a unit-length simple offset mapping. |
+NGOffsetMappingUnitType GetUnitLengthMappingType(unsigned value) { |
+ if (value == 0u) |
+ return NGOffsetMappingUnitType::kCollapsed; |
+ if (value == 1u) |
+ return NGOffsetMappingUnitType::kIdentity; |
+ return NGOffsetMappingUnitType::kExpanded; |
+} |
+ |
+// Finds the offset mapping unit starting from index |start|. |
+std::pair<NGOffsetMappingUnitType, unsigned> GetMappingUnitTypeAndEnd( |
+ const Vector<unsigned>& mapping, |
+ const Vector<const LayoutText*>& annotation, |
+ unsigned start) { |
+ DCHECK_LT(start + 1, mapping.size()); |
+ NGOffsetMappingUnitType type = |
+ GetUnitLengthMappingType(mapping[start + 1] - mapping[start]); |
+ if (type == NGOffsetMappingUnitType::kExpanded) |
+ return std::make_pair(type, start + 1); |
+ |
+ unsigned end = start + 1; |
+ for (; end + 1 < mapping.size(); ++end) { |
+ if (annotation[end] != annotation[start]) |
+ break; |
+ NGOffsetMappingUnitType next_type = |
+ GetUnitLengthMappingType(mapping[end + 1] - mapping[end]); |
+ if (next_type != type) |
+ break; |
+ } |
+ return std::make_pair(type, end); |
+} |
+ |
+} // namespace |
+ |
NGOffsetMappingBuilder::NGOffsetMappingBuilder() { |
mapping_.push_back(0); |
} |
@@ -19,6 +56,7 @@ void NGOffsetMappingBuilder::AppendIdentityMapping(unsigned length) { |
unsigned next = mapping_.back() + 1; |
mapping_.push_back(next); |
} |
+ annotation_.resize(annotation_.size() + length); |
} |
void NGOffsetMappingBuilder::AppendCollapsedMapping(unsigned length) { |
@@ -27,6 +65,7 @@ void NGOffsetMappingBuilder::AppendCollapsedMapping(unsigned length) { |
const unsigned back = mapping_.back(); |
for (unsigned i = 0; i < length; ++i) |
mapping_.push_back(back); |
+ annotation_.resize(annotation_.size() + length); |
} |
void NGOffsetMappingBuilder::CollapseTrailingSpace(unsigned skip_length) { |
@@ -43,8 +82,77 @@ void NGOffsetMappingBuilder::CollapseTrailingSpace(unsigned skip_length) { |
} |
} |
+void NGOffsetMappingBuilder::Annotate(const LayoutText* layout_object) { |
+ std::fill(annotation_.begin(), annotation_.end(), layout_object); |
+} |
+ |
+void NGOffsetMappingBuilder::Concatenate(const NGOffsetMappingBuilder& other) { |
+ DCHECK(!mapping_.IsEmpty()); |
+ DCHECK(!other.mapping_.IsEmpty()); |
+ const unsigned shift_amount = mapping_.back(); |
+ for (unsigned i = 1; i < other.mapping_.size(); ++i) |
+ mapping_.push_back(other.mapping_[i] + shift_amount); |
+ annotation_.AppendVector(other.annotation_); |
+} |
+ |
+void NGOffsetMappingBuilder::Composite(const NGOffsetMappingBuilder& other) { |
+ DCHECK(!mapping_.IsEmpty()); |
+ DCHECK_EQ(mapping_.back() + 1, other.mapping_.size()); |
+ for (unsigned i = 0; i < mapping_.size(); ++i) |
+ mapping_[i] = other.mapping_[mapping_[i]]; |
+} |
+ |
+NGOffsetMappingResult NGOffsetMappingBuilder::Build() const { |
+ NGOffsetMappingResult result; |
+ |
+ const LayoutText* current_node = nullptr; |
+ unsigned inline_start = 0; |
+ unsigned unit_range_start = 0; |
+ for (unsigned start = 0; start + 1 < mapping_.size();) { |
+ if (annotation_[start] != current_node) { |
+ if (current_node) { |
+ result.ranges.insert(current_node, std::make_pair(unit_range_start, |
+ result.units.size())); |
+ } |
+ current_node = annotation_[start]; |
+ inline_start = start; |
+ unit_range_start = result.units.size(); |
+ } |
+ |
+ if (!annotation_[start]) { |
+ // Only extra characters are not annotated. |
+ DCHECK_EQ(mapping_[start] + 1, mapping_[start + 1]); |
+ ++start; |
+ continue; |
+ } |
+ |
+ NGOffsetMappingUnit unit; |
+ unsigned end; |
+ std::tie(unit.type, end) = |
+ GetMappingUnitTypeAndEnd(mapping_, annotation_, start); |
+ unit.owner = current_node; |
+ unit.dom_start = start - inline_start + current_node->TextStartOffset(); |
+ unit.dom_end = end - inline_start + current_node->TextStartOffset(); |
+ unit.text_content_start = mapping_[start]; |
+ unit.text_content_end = mapping_[end]; |
+ result.units.push_back(unit); |
+ |
+ start = end; |
+ } |
+ if (current_node) { |
+ result.ranges.insert(current_node, |
+ std::make_pair(unit_range_start, result.units.size())); |
+ } |
+ return result; |
+} |
+ |
Vector<unsigned> NGOffsetMappingBuilder::DumpOffsetMappingForTesting() const { |
return mapping_; |
} |
+Vector<const LayoutText*> NGOffsetMappingBuilder::DumpAnnotationForTesting() |
+ const { |
+ return annotation_; |
+} |
+ |
} // namespace blink |