Chromium Code Reviews| Index: third_party/WebKit/Source/platform/fonts/Font.cpp |
| diff --git a/third_party/WebKit/Source/platform/fonts/Font.cpp b/third_party/WebKit/Source/platform/fonts/Font.cpp |
| index 838080911c8a562cb2cf2ca0061863304cbaf698..035677889b1f68ba97446d4378a75e702b7d2598 100644 |
| --- a/third_party/WebKit/Source/platform/fonts/Font.cpp |
| +++ b/third_party/WebKit/Source/platform/fonts/Font.cpp |
| @@ -257,18 +257,25 @@ class GlyphBufferBloberizer { |
| m_deviceScaleFactor(deviceScaleFactor), |
| m_hasVerticalOffsets(buffer.hasVerticalOffsets()), |
| m_index(0), |
| + m_endIndex(m_buffer.size()), |
| m_blobCount(0), |
| m_rotation(buffer.isEmpty() ? NoRotation : computeBlobRotation( |
| - buffer.fontDataAt(0))) {} |
| + buffer.fontDataAt(0))), |
| + m_skipGlyphs(nullptr) {} |
| - bool done() const { return m_index >= m_buffer.size(); } |
| + bool done() const { return m_index >= m_endIndex; } |
| unsigned blobCount() const { return m_blobCount; } |
| std::pair<sk_sp<SkTextBlob>, BlobRotation> next() { |
| ASSERT(!done()); |
| const BlobRotation currentRotation = m_rotation; |
| - while (m_index < m_buffer.size()) { |
| + while (m_index < m_endIndex) { |
| + if (m_skipGlyphs) { |
| + while (m_index < m_endIndex && (*m_skipGlyphs)[m_index]) |
| + m_index++; |
| + } |
| + |
| const SimpleFontData* fontData = m_buffer.fontDataAt(m_index); |
| ASSERT(fontData); |
| @@ -282,8 +289,8 @@ class GlyphBufferBloberizer { |
| } |
| const unsigned start = m_index++; |
| - while (m_index < m_buffer.size() && |
| - m_buffer.fontDataAt(m_index) == fontData) |
| + while (m_index < m_endIndex && m_buffer.fontDataAt(m_index) == fontData && |
| + !(m_skipGlyphs && (*m_skipGlyphs)[m_index])) |
| m_index++; |
| appendRun(start, m_index - start, fontData); |
| @@ -293,6 +300,15 @@ class GlyphBufferBloberizer { |
| return std::make_pair(m_builder.make(), currentRotation); |
| } |
| + void setSkipGlyphs(const Vector<bool>* skipGlyphs) { |
| + m_skipGlyphs = skipGlyphs; |
| + m_endIndex = m_buffer.size(); |
| + if (m_skipGlyphs) { |
| + while (m_endIndex > 0 && (*m_skipGlyphs)[m_endIndex - 1]) |
| + m_endIndex--; |
| + } |
| + } |
| + |
| private: |
| static BlobRotation computeBlobRotation(const SimpleFontData* font) { |
| // For vertical upright text we need to compensate the inherited 90deg CW |
| @@ -343,8 +359,10 @@ class GlyphBufferBloberizer { |
| SkTextBlobBuilder m_builder; |
| unsigned m_index; |
| + unsigned m_endIndex; |
| unsigned m_blobCount; |
| BlobRotation m_rotation; |
| + const Vector<bool>* m_skipGlyphs; |
| }; |
| } // anonymous namespace |
| @@ -386,14 +404,71 @@ void Font::drawGlyphBuffer(SkCanvas* canvas, |
| } |
| } |
| +static std::unique_ptr<Vector<bool>> glyphsToSkipIntercepts( |
| + const TextRun& run, |
| + const GlyphBuffer& glyphBuffer) { |
| + // Skipping ink leads to undesirable renderings for some scripts. Determine |
| + // glyphs not to skip ink on a character-by-character basis. |
| + DCHECK(!run.is8Bit()); |
| + std::unique_ptr<Vector<bool>> skipIndexes = |
| + WTF::makeUnique<Vector<bool>>(glyphBuffer.size()); |
| + bool hasAnySkip = false; |
| + for (unsigned index = 0; index < glyphBuffer.size(); index++) { |
| + unsigned characterIndex = glyphBuffer.characterIndex(index); |
| + UChar32 baseCharacter = run.codepointAt(characterIndex); |
|
drott
2017/01/02 15:07:45
Can we reuse Character::isCJKIdeographOrSymbol for
|
| + UBlockCode blockCode = ublock_getCode(baseCharacter); |
| + switch (blockCode) { |
| + case UBLOCK_BOPOMOFO: |
| + case UBLOCK_BOPOMOFO_EXTENDED: |
| + case UBLOCK_CJK_COMPATIBILITY: |
| + case UBLOCK_CJK_COMPATIBILITY_FORMS: |
| + case UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS: |
| + case UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT: |
| + case UBLOCK_CJK_RADICALS_SUPPLEMENT: |
| + case UBLOCK_CJK_STROKES: |
| + case UBLOCK_CJK_SYMBOLS_AND_PUNCTUATION: |
| + case UBLOCK_CJK_UNIFIED_IDEOGRAPHS: |
| + case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A: |
| + case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B: |
| + case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C: |
| + case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D: |
| + case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E: |
| + case UBLOCK_ENCLOSED_CJK_LETTERS_AND_MONTHS: |
| + case UBLOCK_ENCLOSED_IDEOGRAPHIC_SUPPLEMENT: |
| + case UBLOCK_HANGUL_COMPATIBILITY_JAMO: |
| + case UBLOCK_HANGUL_JAMO: |
| + case UBLOCK_HANGUL_JAMO_EXTENDED_A: |
| + case UBLOCK_HANGUL_JAMO_EXTENDED_B: |
| + case UBLOCK_HANGUL_SYLLABLES: |
| + case UBLOCK_HIRAGANA: |
| + case UBLOCK_IDEOGRAPHIC_DESCRIPTION_CHARACTERS: |
| + case UBLOCK_IDEOGRAPHIC_SYMBOLS_AND_PUNCTUATION: |
| + case UBLOCK_KATAKANA: |
| + case UBLOCK_LINEAR_B_IDEOGRAMS: |
| + case UBLOCK_TANGUT: |
| + case UBLOCK_TANGUT_COMPONENTS: |
| + (*skipIndexes)[index] = true; |
| + hasAnySkip = true; |
| + break; |
| + default: |
| + break; |
| + } |
| + } |
| + if (!hasAnySkip) |
| + return nullptr; |
| + return skipIndexes; |
| +} |
| + |
| static int getInterceptsFromBloberizer(const GlyphBuffer& glyphBuffer, |
| const Font* font, |
| const SkPaint& paint, |
| float deviceScaleFactor, |
| const std::tuple<float, float>& bounds, |
| + const Vector<bool>* skipGlyphs, |
| SkScalar* interceptsBuffer) { |
| SkScalar boundsArray[2] = {std::get<0>(bounds), std::get<1>(bounds)}; |
| GlyphBufferBloberizer bloberizer(glyphBuffer, font, deviceScaleFactor); |
| + bloberizer.setSkipGlyphs(skipGlyphs); |
| std::pair<sk_sp<SkTextBlob>, BlobRotation> blob; |
| int numIntervals = 0; |
| @@ -439,20 +514,28 @@ void Font::getTextIntercepts(const TextRunPaintInfo& runInfo, |
| } |
| GlyphBuffer glyphBuffer; |
| - buildGlyphBuffer(runInfo, glyphBuffer); |
| + std::unique_ptr<Vector<bool>> skipGlyphs; |
| + if (runInfo.run.is8Bit()) { |
| + buildGlyphBuffer(runInfo, glyphBuffer); |
| + } else { |
| + glyphBuffer.saveCharacterIndexes(); |
| + buildGlyphBuffer(runInfo, glyphBuffer); |
| + skipGlyphs = glyphsToSkipIntercepts(runInfo.run, glyphBuffer); |
| + } |
| // Get the number of intervals, without copying the actual values by |
| // specifying nullptr for the buffer, following the Skia allocation model for |
| // retrieving text intercepts. |
| - int numIntervals = getInterceptsFromBloberizer( |
| - glyphBuffer, this, paint, deviceScaleFactor, bounds, nullptr); |
| + int numIntervals = |
| + getInterceptsFromBloberizer(glyphBuffer, this, paint, deviceScaleFactor, |
| + bounds, skipGlyphs.get(), nullptr); |
| if (!numIntervals) |
| return; |
| DCHECK_EQ(numIntervals % 2, 0); |
| intercepts.resize(numIntervals / 2); |
| getInterceptsFromBloberizer(glyphBuffer, this, paint, deviceScaleFactor, |
| - bounds, |
| + bounds, skipGlyphs.get(), |
| reinterpret_cast<SkScalar*>(intercepts.data())); |
| } |