| Index: third_party/WebKit/Source/core/layout/ng/inline/ng_inline_items_builder.cc | 
| diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_items_builder.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_items_builder.cc | 
| index 8533bd9907a97669386f62a25511a084d274f610..a01621dc912888df7cabb8eea436204bf3b02173 100644 | 
| --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_items_builder.cc | 
| +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_items_builder.cc | 
| @@ -10,12 +10,15 @@ | 
|  | 
| namespace blink { | 
|  | 
| -NGInlineItemsBuilder::~NGInlineItemsBuilder() { | 
| +template <typename OffsetMappingBuilder> | 
| +NGInlineItemsBuilderTemplate< | 
| +    OffsetMappingBuilder>::~NGInlineItemsBuilderTemplate() { | 
| DCHECK_EQ(0u, exits_.size()); | 
| DCHECK_EQ(text_.length(), items_->IsEmpty() ? 0 : items_->back().EndOffset()); | 
| } | 
|  | 
| -String NGInlineItemsBuilder::ToString() { | 
| +template <typename OffsetMappingBuilder> | 
| +String NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::ToString() { | 
| // Segment Break Transformation Rules[1] defines to keep trailing new lines, | 
| // but it will be removed in Phase II[2]. We prefer not to add trailing new | 
| // lines and collapsible spaces in Phase I. | 
| @@ -123,9 +126,11 @@ static inline bool IsControlItemCharacter(UChar c) { | 
| return c == kTabulationCharacter || c == kNewlineCharacter; | 
| } | 
|  | 
| -void NGInlineItemsBuilder::Append(const String& string, | 
| -                                  const ComputedStyle* style, | 
| -                                  LayoutObject* layout_object) { | 
| +template <typename OffsetMappingBuilder> | 
| +void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::Append( | 
| +    const String& string, | 
| +    const ComputedStyle* style, | 
| +    LayoutObject* layout_object) { | 
| if (string.IsEmpty()) | 
| return; | 
| text_.ReserveCapacity(string.length()); | 
| @@ -140,12 +145,13 @@ void NGInlineItemsBuilder::Append(const String& string, | 
| layout_object); | 
| } | 
|  | 
| -void NGInlineItemsBuilder::AppendWithWhiteSpaceCollapsing( | 
| -    const String& string, | 
| -    unsigned start, | 
| -    unsigned end, | 
| -    const ComputedStyle* style, | 
| -    LayoutObject* layout_object) { | 
| +template <typename OffsetMappingBuilder> | 
| +void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>:: | 
| +    AppendWithWhiteSpaceCollapsing(const String& string, | 
| +                                   unsigned start, | 
| +                                   unsigned end, | 
| +                                   const ComputedStyle* style, | 
| +                                   LayoutObject* layout_object) { | 
| unsigned start_offset = text_.length(); | 
| for (unsigned i = start; i < end;) { | 
| UChar c = string[i]; | 
| @@ -193,10 +199,11 @@ void NGInlineItemsBuilder::AppendWithWhiteSpaceCollapsing( | 
|  | 
| // Even when without whitespace collapsing, control characters (newlines and | 
| // tabs) are in their own control items to make the line breaker easier. | 
| -void NGInlineItemsBuilder::AppendWithoutWhiteSpaceCollapsing( | 
| -    const String& string, | 
| -    const ComputedStyle* style, | 
| -    LayoutObject* layout_object) { | 
| +template <typename OffsetMappingBuilder> | 
| +void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>:: | 
| +    AppendWithoutWhiteSpaceCollapsing(const String& string, | 
| +                                      const ComputedStyle* style, | 
| +                                      LayoutObject* layout_object) { | 
| for (unsigned start = 0; start < string.length();) { | 
| UChar c = string[start]; | 
| if (IsControlItemCharacter(c)) { | 
| @@ -218,10 +225,11 @@ void NGInlineItemsBuilder::AppendWithoutWhiteSpaceCollapsing( | 
| last_collapsible_space_ = CollapsibleSpace::kNone; | 
| } | 
|  | 
| -void NGInlineItemsBuilder::AppendWithPreservingNewlines( | 
| -    const String& string, | 
| -    const ComputedStyle* style, | 
| -    LayoutObject* layout_object) { | 
| +template <typename OffsetMappingBuilder> | 
| +void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>:: | 
| +    AppendWithPreservingNewlines(const String& string, | 
| +                                 const ComputedStyle* style, | 
| +                                 LayoutObject* layout_object) { | 
| for (unsigned start = 0; start < string.length();) { | 
| if (string[start] == kNewlineCharacter) { | 
| AppendForcedBreak(style, layout_object); | 
| @@ -237,8 +245,10 @@ void NGInlineItemsBuilder::AppendWithPreservingNewlines( | 
| } | 
| } | 
|  | 
| -void NGInlineItemsBuilder::AppendForcedBreak(const ComputedStyle* style, | 
| -                                             LayoutObject* layout_object) { | 
| +template <typename OffsetMappingBuilder> | 
| +void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendForcedBreak( | 
| +    const ComputedStyle* style, | 
| +    LayoutObject* layout_object) { | 
| // Remove collapsible spaces immediately before a preserved newline. | 
| RemoveTrailingCollapsibleSpaceIfExists(); | 
|  | 
| @@ -248,10 +258,12 @@ void NGInlineItemsBuilder::AppendForcedBreak(const ComputedStyle* style, | 
| last_collapsible_space_ = CollapsibleSpace::kSpace; | 
| } | 
|  | 
| -void NGInlineItemsBuilder::Append(NGInlineItem::NGInlineItemType type, | 
| -                                  UChar character, | 
| -                                  const ComputedStyle* style, | 
| -                                  LayoutObject* layout_object) { | 
| +template <typename OffsetMappingBuilder> | 
| +void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::Append( | 
| +    NGInlineItem::NGInlineItemType type, | 
| +    UChar character, | 
| +    const ComputedStyle* style, | 
| +    LayoutObject* layout_object) { | 
| DCHECK_NE(character, kSpaceCharacter); | 
| DCHECK_NE(character, kZeroWidthSpaceCharacter); | 
|  | 
| @@ -261,26 +273,31 @@ void NGInlineItemsBuilder::Append(NGInlineItem::NGInlineItemType type, | 
| last_collapsible_space_ = CollapsibleSpace::kNone; | 
| } | 
|  | 
| -void NGInlineItemsBuilder::AppendOpaque(NGInlineItem::NGInlineItemType type, | 
| -                                        UChar character) { | 
| +template <typename OffsetMappingBuilder> | 
| +void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendOpaque( | 
| +    NGInlineItem::NGInlineItemType type, | 
| +    UChar character) { | 
| text_.Append(character); | 
| unsigned end_offset = text_.length(); | 
| AppendItem(items_, type, end_offset - 1, end_offset, nullptr, nullptr); | 
| } | 
|  | 
| -void NGInlineItemsBuilder::AppendOpaque(NGInlineItem::NGInlineItemType type, | 
| -                                        const ComputedStyle* style, | 
| -                                        LayoutObject* layout_object) { | 
| +template <typename OffsetMappingBuilder> | 
| +void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendOpaque( | 
| +    NGInlineItem::NGInlineItemType type, | 
| +    const ComputedStyle* style, | 
| +    LayoutObject* layout_object) { | 
| unsigned end_offset = text_.length(); | 
| AppendItem(items_, type, end_offset, end_offset, style, layout_object); | 
| } | 
|  | 
| // Removes the collapsible newline at the end of |text_| if exists and the | 
| // removal conditions met. | 
| -void NGInlineItemsBuilder::RemoveTrailingCollapsibleNewlineIfNeeded( | 
| -    const String& after, | 
| -    unsigned after_index, | 
| -    const ComputedStyle* after_style) { | 
| +template <typename OffsetMappingBuilder> | 
| +void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>:: | 
| +    RemoveTrailingCollapsibleNewlineIfNeeded(const String& after, | 
| +                                             unsigned after_index, | 
| +                                             const ComputedStyle* after_style) { | 
| DCHECK_EQ(last_collapsible_space_, CollapsibleSpace::kNewline); | 
|  | 
| if (text_.IsEmpty() || text_[text_.length() - 1] != kSpaceCharacter) | 
| @@ -298,7 +315,9 @@ void NGInlineItemsBuilder::RemoveTrailingCollapsibleNewlineIfNeeded( | 
| } | 
|  | 
| // Removes the collapsible space at the end of |text_| if exists. | 
| -void NGInlineItemsBuilder::RemoveTrailingCollapsibleSpaceIfExists() { | 
| +template <typename OffsetMappingBuilder> | 
| +void NGInlineItemsBuilderTemplate< | 
| +    OffsetMappingBuilder>::RemoveTrailingCollapsibleSpaceIfExists() { | 
| if (last_collapsible_space_ == CollapsibleSpace::kNone || text_.IsEmpty()) | 
| return; | 
|  | 
| @@ -320,7 +339,9 @@ void NGInlineItemsBuilder::RemoveTrailingCollapsibleSpaceIfExists() { | 
| } | 
|  | 
| // Removes the collapsible space at the specified index. | 
| -void NGInlineItemsBuilder::RemoveTrailingCollapsibleSpace(unsigned index) { | 
| +template <typename OffsetMappingBuilder> | 
| +void NGInlineItemsBuilderTemplate< | 
| +    OffsetMappingBuilder>::RemoveTrailingCollapsibleSpace(unsigned index) { | 
| DCHECK_NE(last_collapsible_space_, CollapsibleSpace::kNone); | 
| DCHECK(!text_.IsEmpty()); | 
| DCHECK_EQ(text_[index], kSpaceCharacter); | 
| @@ -350,14 +371,18 @@ void NGInlineItemsBuilder::RemoveTrailingCollapsibleSpace(unsigned index) { | 
| } | 
| } | 
|  | 
| -void NGInlineItemsBuilder::AppendBidiControl(const ComputedStyle* style, | 
| -                                             UChar ltr, | 
| -                                             UChar rtl) { | 
| +template <typename OffsetMappingBuilder> | 
| +void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendBidiControl( | 
| +    const ComputedStyle* style, | 
| +    UChar ltr, | 
| +    UChar rtl) { | 
| AppendOpaque(NGInlineItem::kBidiControl, | 
| IsLtr(style->Direction()) ? ltr : rtl); | 
| } | 
|  | 
| -void NGInlineItemsBuilder::EnterBlock(const ComputedStyle* style) { | 
| +template <typename OffsetMappingBuilder> | 
| +void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::EnterBlock( | 
| +    const ComputedStyle* style) { | 
| // Handle bidi-override on the block itself. | 
| switch (style->GetUnicodeBidi()) { | 
| case UnicodeBidi::kNormal: | 
| @@ -384,7 +409,9 @@ void NGInlineItemsBuilder::EnterBlock(const ComputedStyle* style) { | 
| } | 
| } | 
|  | 
| -void NGInlineItemsBuilder::EnterInline(LayoutObject* node) { | 
| +template <typename OffsetMappingBuilder> | 
| +void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::EnterInline( | 
| +    LayoutObject* node) { | 
| // https://drafts.csswg.org/css-writing-modes-3/#bidi-control-codes-injection-table | 
| const ComputedStyle* style = node->Style(); | 
| switch (style->GetUnicodeBidi()) { | 
| @@ -421,16 +448,22 @@ void NGInlineItemsBuilder::EnterInline(LayoutObject* node) { | 
| AppendOpaque(NGInlineItem::kOpenTag, style, node); | 
| } | 
|  | 
| -void NGInlineItemsBuilder::Enter(LayoutObject* node, UChar character_to_exit) { | 
| +template <typename OffsetMappingBuilder> | 
| +void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::Enter( | 
| +    LayoutObject* node, | 
| +    UChar character_to_exit) { | 
| exits_.push_back(OnExitNode{node, character_to_exit}); | 
| has_bidi_controls_ = true; | 
| } | 
|  | 
| -void NGInlineItemsBuilder::ExitBlock() { | 
| +template <typename OffsetMappingBuilder> | 
| +void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::ExitBlock() { | 
| Exit(nullptr); | 
| } | 
|  | 
| -void NGInlineItemsBuilder::ExitInline(LayoutObject* node) { | 
| +template <typename OffsetMappingBuilder> | 
| +void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::ExitInline( | 
| +    LayoutObject* node) { | 
| DCHECK(node); | 
|  | 
| AppendOpaque(NGInlineItem::kCloseTag, node->Style(), node); | 
| @@ -438,11 +471,16 @@ void NGInlineItemsBuilder::ExitInline(LayoutObject* node) { | 
| Exit(node); | 
| } | 
|  | 
| -void NGInlineItemsBuilder::Exit(LayoutObject* node) { | 
| +template <typename OffsetMappingBuilder> | 
| +void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::Exit( | 
| +    LayoutObject* node) { | 
| while (!exits_.IsEmpty() && exits_.back().node == node) { | 
| AppendOpaque(NGInlineItem::kBidiControl, exits_.back().character); | 
| exits_.pop_back(); | 
| } | 
| } | 
|  | 
| +template class CORE_TEMPLATE_EXPORT | 
| +    NGInlineItemsBuilderTemplate<EmptyOffsetMappingBuilder>; | 
| + | 
| }  // namespace blink | 
|  |