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())); |
} |