| Index: third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBuffer.cpp | 
| diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBuffer.cpp b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBuffer.cpp | 
| index 7eec345ae57611b423706af4cfc7e19a5292ffa7..7e4a4da7f1fb2d2478c9eec2d2ddd8c74373b88c 100644 | 
| --- a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBuffer.cpp | 
| +++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBuffer.cpp | 
| @@ -5,8 +5,8 @@ | 
| #include "platform/fonts/shaping/ShapeResultBuffer.h" | 
|  | 
| #include "platform/fonts/CharacterRange.h" | 
| -#include "platform/fonts/GlyphBuffer.h" | 
| #include "platform/fonts/SimpleFontData.h" | 
| +#include "platform/fonts/shaping/ShapeResultBloberizer.h" | 
| #include "platform/fonts/shaping/ShapeResultInlineHeaders.h" | 
| #include "platform/geometry/FloatPoint.h" | 
| #include "platform/text/Character.h" | 
| @@ -17,50 +17,47 @@ namespace blink { | 
|  | 
| namespace { | 
|  | 
| -inline bool isSkipInkException(const GlyphBuffer& glyphBuffer, | 
| +inline bool isSkipInkException(const ShapeResultBloberizer& bloberizer, | 
| const TextRun& run, | 
| unsigned characterIndex) { | 
| // We want to skip descenders in general, but it is undesirable renderings for | 
| // CJK characters. | 
| -  return glyphBuffer.type() == GlyphBuffer::Type::TextIntercepts && | 
| +  return bloberizer.type() == ShapeResultBloberizer::Type::TextIntercepts && | 
| !run.is8Bit() && | 
| Character::isCJKIdeographOrSymbol(run.codepointAt(characterIndex)); | 
| } | 
|  | 
| -inline void addGlyphToBuffer(GlyphBuffer* glyphBuffer, | 
| -                             float advance, | 
| -                             hb_direction_t direction, | 
| -                             const SimpleFontData* fontData, | 
| -                             const HarfBuzzRunGlyphData& glyphData, | 
| -                             const TextRun& run, | 
| -                             unsigned characterIndex) { | 
| +inline void addGlyphToBloberizer(ShapeResultBloberizer& bloberizer, | 
| +                                 float advance, | 
| +                                 hb_direction_t direction, | 
| +                                 const SimpleFontData* fontData, | 
| +                                 const HarfBuzzRunGlyphData& glyphData, | 
| +                                 const TextRun& run, | 
| +                                 unsigned characterIndex) { | 
| FloatPoint startOffset = HB_DIRECTION_IS_HORIZONTAL(direction) | 
| ? FloatPoint(advance, 0) | 
| : FloatPoint(0, advance); | 
| -  if (!isSkipInkException(*glyphBuffer, run, characterIndex)) { | 
| -    glyphBuffer->add(glyphData.glyph, fontData, startOffset + glyphData.offset); | 
| -  } | 
| +  if (!isSkipInkException(bloberizer, run, characterIndex)) | 
| +    bloberizer.add(glyphData.glyph, fontData, startOffset + glyphData.offset); | 
| } | 
|  | 
| -inline void addEmphasisMark(GlyphBuffer* buffer, | 
| -                            const GlyphData* emphasisData, | 
| +inline void addEmphasisMark(ShapeResultBloberizer& bloberizer, | 
| +                            const GlyphData& emphasisData, | 
| FloatPoint glyphCenter, | 
| float midGlyphOffset) { | 
| -  ASSERT(buffer); | 
| -  ASSERT(emphasisData); | 
| - | 
| -  const SimpleFontData* emphasisFontData = emphasisData->fontData; | 
| -  ASSERT(emphasisFontData); | 
| +  const SimpleFontData* emphasisFontData = emphasisData.fontData; | 
| +  DCHECK(emphasisFontData); | 
|  | 
| bool isVertical = emphasisFontData->platformData().isVerticalAnyUpright() && | 
| emphasisFontData->verticalData(); | 
|  | 
| if (!isVertical) { | 
| -    buffer->add(emphasisData->glyph, emphasisFontData, | 
| -                midGlyphOffset - glyphCenter.x()); | 
| +    bloberizer.add(emphasisData.glyph, emphasisFontData, | 
| +                   midGlyphOffset - glyphCenter.x()); | 
| } else { | 
| -    buffer->add(emphasisData->glyph, emphasisFontData, | 
| -                FloatPoint(-glyphCenter.x(), midGlyphOffset - glyphCenter.y())); | 
| +    bloberizer.add( | 
| +        emphasisData.glyph, emphasisFontData, | 
| +        FloatPoint(-glyphCenter.x(), midGlyphOffset - glyphCenter.y())); | 
| } | 
| } | 
|  | 
| @@ -89,24 +86,22 @@ inline unsigned countGraphemesInCluster(const UChar* str, | 
|  | 
| }  // anonymous namespace | 
|  | 
| -float ShapeResultBuffer::fillGlyphBufferForResult(GlyphBuffer* glyphBuffer, | 
| -                                                  const ShapeResult& result, | 
| -                                                  const TextRun& textRun, | 
| -                                                  float initialAdvance, | 
| -                                                  unsigned from, | 
| -                                                  unsigned to, | 
| -                                                  unsigned runOffset) { | 
| +float ShapeResultBuffer::fillGlyphsForResult(ShapeResultBloberizer& bloberizer, | 
| +                                             const ShapeResult& result, | 
| +                                             const TextRunPaintInfo& runInfo, | 
| +                                             float initialAdvance, | 
| +                                             unsigned runOffset) { | 
| auto totalAdvance = initialAdvance; | 
|  | 
| for (const auto& run : result.m_runs) { | 
| totalAdvance = run->forEachGlyphInRange( | 
| -        totalAdvance, from, to, runOffset, | 
| +        totalAdvance, runInfo.from, runInfo.to, runOffset, | 
| [&](const HarfBuzzRunGlyphData& glyphData, float totalAdvance, | 
| uint16_t characterIndex) -> bool { | 
|  | 
| -          addGlyphToBuffer(glyphBuffer, totalAdvance, run->m_direction, | 
| -                           run->m_fontData.get(), glyphData, textRun, | 
| -                           characterIndex); | 
| +          addGlyphToBloberizer(bloberizer, totalAdvance, run->m_direction, | 
| +                               run->m_fontData.get(), glyphData, runInfo.run, | 
| +                               characterIndex); | 
| return true; | 
| }); | 
| } | 
| @@ -114,14 +109,12 @@ float ShapeResultBuffer::fillGlyphBufferForResult(GlyphBuffer* glyphBuffer, | 
| return totalAdvance; | 
| } | 
|  | 
| -float ShapeResultBuffer::fillGlyphBufferForTextEmphasisRun( | 
| -    GlyphBuffer* glyphBuffer, | 
| +float ShapeResultBuffer::fillTextEmphasisGlyphsForRun( | 
| +    ShapeResultBloberizer& bloberizer, | 
| const ShapeResult::RunInfo* run, | 
| -    const TextRun& textRun, | 
| -    const GlyphData* emphasisData, | 
| +    const TextRunPaintInfo& runInfo, | 
| +    const GlyphData& emphasisData, | 
| float initialAdvance, | 
| -    unsigned from, | 
| -    unsigned to, | 
| unsigned runOffset) { | 
| if (!run) | 
| return 0; | 
| @@ -130,7 +123,11 @@ float ShapeResultBuffer::fillGlyphBufferForTextEmphasisRun( | 
| float clusterAdvance = 0; | 
|  | 
| FloatPoint glyphCenter = | 
| -      emphasisData->fontData->boundsForGlyph(emphasisData->glyph).center(); | 
| +      emphasisData.fontData->boundsForGlyph(emphasisData.glyph).center(); | 
| + | 
| +  const auto& textRun = runInfo.run; | 
| +  const auto from = runInfo.from; | 
| +  const auto to = runInfo.to; | 
|  | 
| TextDirection direction = textRun.direction(); | 
|  | 
| @@ -169,7 +166,7 @@ float ShapeResultBuffer::fillGlyphBufferForTextEmphasisRun( | 
| if (textRun.is8Bit()) { | 
| float glyphAdvanceX = glyphData.advance; | 
| if (Character::canReceiveTextEmphasis(textRun[currentCharacterIndex])) { | 
| -        addEmphasisMark(glyphBuffer, emphasisData, glyphCenter, | 
| +        addEmphasisMark(bloberizer, emphasisData, glyphCenter, | 
| advanceSoFar + glyphAdvanceX / 2); | 
| } | 
| advanceSoFar += glyphAdvanceX; | 
| @@ -193,7 +190,7 @@ float ShapeResultBuffer::fillGlyphBufferForTextEmphasisRun( | 
| // Do not put emphasis marks on space, separator, and control | 
| // characters. | 
| if (Character::canReceiveTextEmphasis(textRun[currentCharacterIndex])) | 
| -          addEmphasisMark(glyphBuffer, emphasisData, glyphCenter, | 
| +          addEmphasisMark(bloberizer, emphasisData, glyphCenter, | 
| advanceSoFar + glyphAdvanceX / 2); | 
| advanceSoFar += glyphAdvanceX; | 
| } | 
| @@ -204,11 +201,11 @@ float ShapeResultBuffer::fillGlyphBufferForTextEmphasisRun( | 
| return advanceSoFar - initialAdvance; | 
| } | 
|  | 
| -float ShapeResultBuffer::fillFastHorizontalGlyphBuffer( | 
| -    GlyphBuffer* glyphBuffer, | 
| -    const TextRun& textRun) const { | 
| +float ShapeResultBuffer::fillFastHorizontalGlyphs( | 
| +    const TextRun& textRun, | 
| +    ShapeResultBloberizer& bloberizer) const { | 
| DCHECK(!hasVerticalOffsets()); | 
| -  DCHECK_NE(glyphBuffer->type(), GlyphBuffer::Type::TextIntercepts); | 
| +  DCHECK_NE(bloberizer.type(), ShapeResultBloberizer::Type::TextIntercepts); | 
|  | 
| float advance = 0; | 
|  | 
| @@ -227,44 +224,41 @@ float ShapeResultBuffer::fillFastHorizontalGlyphBuffer( | 
| [&](const HarfBuzzRunGlyphData& glyphData, | 
| float totalAdvance) -> bool { | 
| DCHECK(!glyphData.offset.height()); | 
| - | 
| -            glyphBuffer->add(glyphData.glyph, run->m_fontData.get(), | 
| -                             totalAdvance + glyphData.offset.width()); | 
| +            bloberizer.add(glyphData.glyph, run->m_fontData.get(), | 
| +                           totalAdvance + glyphData.offset.width()); | 
| return true; | 
| }); | 
| } | 
| } | 
|  | 
| -  ASSERT(!glyphBuffer->hasVerticalOffsets()); | 
| - | 
| return advance; | 
| } | 
|  | 
| -float ShapeResultBuffer::fillGlyphBuffer(GlyphBuffer* glyphBuffer, | 
| -                                         const TextRun& textRun, | 
| -                                         unsigned from, | 
| -                                         unsigned to) const { | 
| +float ShapeResultBuffer::fillGlyphs(const TextRunPaintInfo& runInfo, | 
| +                                    ShapeResultBloberizer& bloberizer) const { | 
| // Fast path: full run with no vertical offsets, no text intercepts. | 
| -  if (!from && to == textRun.length() && !hasVerticalOffsets() && | 
| -      glyphBuffer->type() != GlyphBuffer::Type::TextIntercepts) | 
| -    return fillFastHorizontalGlyphBuffer(glyphBuffer, textRun); | 
| +  if (!runInfo.from && runInfo.to == runInfo.run.length() && | 
| +      !hasVerticalOffsets() && | 
| +      bloberizer.type() != ShapeResultBloberizer::Type::TextIntercepts) { | 
| +    return fillFastHorizontalGlyphs(runInfo.run, bloberizer); | 
| +  } | 
|  | 
| float advance = 0; | 
|  | 
| -  if (textRun.rtl()) { | 
| -    unsigned wordOffset = textRun.length(); | 
| +  if (runInfo.run.rtl()) { | 
| +    unsigned wordOffset = runInfo.run.length(); | 
| for (unsigned j = 0; j < m_results.size(); j++) { | 
| unsigned resolvedIndex = m_results.size() - 1 - j; | 
| const RefPtr<const ShapeResult>& wordResult = m_results[resolvedIndex]; | 
| wordOffset -= wordResult->numCharacters(); | 
| -      advance = fillGlyphBufferForResult(glyphBuffer, *wordResult, textRun, | 
| -                                         advance, from, to, wordOffset); | 
| +      advance = fillGlyphsForResult(bloberizer, *wordResult, runInfo, advance, | 
| +                                    wordOffset); | 
| } | 
| } else { | 
| unsigned wordOffset = 0; | 
| for (const auto& wordResult : m_results) { | 
| -      advance = fillGlyphBufferForResult(glyphBuffer, *wordResult, textRun, | 
| -                                         advance, from, to, wordOffset); | 
| +      advance = fillGlyphsForResult(bloberizer, *wordResult, runInfo, advance, | 
| +                                    wordOffset); | 
| wordOffset += wordResult->numCharacters(); | 
| } | 
| } | 
| @@ -272,29 +266,25 @@ float ShapeResultBuffer::fillGlyphBuffer(GlyphBuffer* glyphBuffer, | 
| return advance; | 
| } | 
|  | 
| -float ShapeResultBuffer::fillGlyphBufferForTextEmphasis( | 
| -    GlyphBuffer* glyphBuffer, | 
| -    const TextRun& textRun, | 
| -    const GlyphData* emphasisData, | 
| -    unsigned from, | 
| -    unsigned to) const { | 
| +void ShapeResultBuffer::fillTextEmphasisGlyphs( | 
| +    const TextRunPaintInfo& runInfo, | 
| +    const GlyphData& emphasisData, | 
| +    ShapeResultBloberizer& bloberizer) const { | 
| float advance = 0; | 
| -  unsigned wordOffset = textRun.rtl() ? textRun.length() : 0; | 
| +  unsigned wordOffset = runInfo.run.rtl() ? runInfo.run.length() : 0; | 
|  | 
| for (unsigned j = 0; j < m_results.size(); j++) { | 
| -    unsigned resolvedIndex = textRun.rtl() ? m_results.size() - 1 - j : j; | 
| +    unsigned resolvedIndex = runInfo.run.rtl() ? m_results.size() - 1 - j : j; | 
| const RefPtr<const ShapeResult>& wordResult = m_results[resolvedIndex]; | 
| for (unsigned i = 0; i < wordResult->m_runs.size(); i++) { | 
| unsigned resolvedOffset = | 
| -          wordOffset - (textRun.rtl() ? wordResult->numCharacters() : 0); | 
| -      advance += fillGlyphBufferForTextEmphasisRun( | 
| -          glyphBuffer, wordResult->m_runs[i].get(), textRun, emphasisData, | 
| -          advance, from, to, resolvedOffset); | 
| +          wordOffset - (runInfo.run.rtl() ? wordResult->numCharacters() : 0); | 
| +      advance += fillTextEmphasisGlyphsForRun( | 
| +          bloberizer, wordResult->m_runs[i].get(), runInfo, emphasisData, | 
| +          advance, resolvedOffset); | 
| } | 
| -    wordOffset += wordResult->numCharacters() * (textRun.rtl() ? -1 : 1); | 
| +    wordOffset += wordResult->numCharacters() * (runInfo.run.rtl() ? -1 : 1); | 
| } | 
| - | 
| -  return advance; | 
| } | 
|  | 
| // TODO(eae): This is a bit of a hack to allow reuse of the implementation | 
|  |