| Index: third_party/WebKit/Source/core/layout/svg/SVGTextMetricsBuilder.cpp
|
| diff --git a/third_party/WebKit/Source/core/layout/svg/SVGTextMetricsBuilder.cpp b/third_party/WebKit/Source/core/layout/svg/SVGTextMetricsBuilder.cpp
|
| index 355c8eb90c0356a5efdc739edce709a3c0a964b0..700e4223acd2e1bd5c4a6eb9e4565981c12897d5 100644
|
| --- a/third_party/WebKit/Source/core/layout/svg/SVGTextMetricsBuilder.cpp
|
| +++ b/third_party/WebKit/Source/core/layout/svg/SVGTextMetricsBuilder.cpp
|
| @@ -36,6 +36,15 @@ namespace blink {
|
|
|
| namespace {
|
|
|
| +inline bool characterStartsSurrogatePair(const TextRun& run, unsigned index)
|
| +{
|
| + if (!U16_IS_LEAD(run[index]))
|
| + return false;
|
| + if (index + 1 >= static_cast<unsigned>(run.charactersLength()))
|
| + return false;
|
| + return U16_IS_TRAIL(run[index + 1]);
|
| +}
|
| +
|
| class SVGTextMetricsCalculator {
|
| public:
|
| SVGTextMetricsCalculator(LineLayoutSVGInlineText);
|
| @@ -50,7 +59,7 @@ public:
|
| // should be unified under a single concept. See: https://crbug.com/593570
|
| bool currentCharacterStartsSurrogatePair() const
|
| {
|
| - return U16_IS_LEAD(m_run[m_currentPosition]) && m_currentPosition + 1 < characterCount() && U16_IS_TRAIL(m_run[m_currentPosition + 1]);
|
| + return characterStartsSurrogatePair(m_run, m_currentPosition);
|
| }
|
| bool currentCharacterIsWhiteSpace() const
|
| {
|
| @@ -158,6 +167,41 @@ bool SVGTextMetricsCalculator::advancePosition()
|
| return m_currentPosition < characterCount();
|
| }
|
|
|
| +// TODO(pdr): We only have per-glyph data so we need to synthesize per-grapheme
|
| +// data. E.g., if 'fi' is shaped into a single glyph, we do not know the 'i'
|
| +// position. The code below synthesizes an average glyph width when characters
|
| +// share a single position. This will incorrectly split combining diacritics.
|
| +// See: https://crbug.com/473476.
|
| +static void synthesizeGraphemeWidths(const TextRun& run, Vector<CharacterRange>& ranges)
|
| +{
|
| + unsigned distributeCount = 0;
|
| + for (int rangeIndex = static_cast<int>(ranges.size()) - 1; rangeIndex >= 0; --rangeIndex) {
|
| + CharacterRange& currentRange = ranges[rangeIndex];
|
| + if (currentRange.width() == 0) {
|
| + distributeCount++;
|
| + } else if (distributeCount != 0) {
|
| + // Only count surrogate pairs as a single character.
|
| + bool surrogatePair = characterStartsSurrogatePair(run, rangeIndex);
|
| + if (!surrogatePair)
|
| + distributeCount++;
|
| +
|
| + float newWidth = currentRange.width() / distributeCount;
|
| + currentRange.end = currentRange.start + newWidth;
|
| + float lastEndPosition = currentRange.end;
|
| + for (unsigned distribute = 1; distribute < distributeCount; distribute++) {
|
| + // This surrogate pair check will skip processing of the second
|
| + // character forming the surrogate pair.
|
| + unsigned distributeIndex = rangeIndex + distribute + (surrogatePair ? 1 : 0);
|
| + ranges[distributeIndex].start = lastEndPosition;
|
| + ranges[distributeIndex].end = lastEndPosition + newWidth;
|
| + lastEndPosition = ranges[distributeIndex].end;
|
| + }
|
| +
|
| + distributeCount = 0;
|
| + }
|
| + }
|
| +}
|
| +
|
| unsigned SVGTextMetricsCalculator::updateSubrunRangesForCurrentPosition()
|
| {
|
| ASSERT(m_bidiRun);
|
| @@ -171,33 +215,10 @@ unsigned SVGTextMetricsCalculator::updateSubrunRangesForCurrentPosition()
|
|
|
| unsigned positionInRun = m_currentPosition - m_bidiRun->start();
|
| if (positionInRun >= m_subrunRanges.size()) {
|
| - TextRun subRun = constructTextRun(m_text,
|
| - m_bidiRun->start(), m_bidiRun->stop() - m_bidiRun->start(), m_bidiRun->direction());
|
| + TextRun subRun = constructTextRun(m_text, m_bidiRun->start(),
|
| + m_bidiRun->stop() - m_bidiRun->start(), m_bidiRun->direction());
|
| m_subrunRanges = m_text.scaledFont().individualCharacterRanges(subRun);
|
| -
|
| - // TODO(pdr): We only have per-glyph data so we need to synthesize per-
|
| - // grapheme data. E.g., if 'fi' is shaped into a single glyph, we do not
|
| - // know the 'i' position. The code below synthesizes an average glyph
|
| - // width when characters share a position. This will incorrectly split
|
| - // combining diacritics. See: https://crbug.com/473476.
|
| - unsigned distributeCount = 0;
|
| - for (int rangeIndex = static_cast<int>(m_subrunRanges.size()) - 1; rangeIndex >= 0; --rangeIndex) {
|
| - CharacterRange& currentRange = m_subrunRanges[rangeIndex];
|
| - if (currentRange.width() == 0) {
|
| - distributeCount++;
|
| - } else if (distributeCount != 0) {
|
| - distributeCount++;
|
| - float newWidth = currentRange.width() / distributeCount;
|
| - currentRange.end = currentRange.start + newWidth;
|
| - for (unsigned distribute = 1; distribute < distributeCount; distribute++) {
|
| - unsigned distributeIndex = rangeIndex + distribute;
|
| - float newStartPosition = m_subrunRanges[distributeIndex - 1].end;
|
| - m_subrunRanges[distributeIndex].start = newStartPosition;
|
| - m_subrunRanges[distributeIndex].end = newStartPosition + newWidth;
|
| - }
|
| - distributeCount = 0;
|
| - }
|
| - }
|
| + synthesizeGraphemeWidths(subRun, m_subrunRanges);
|
| }
|
|
|
| ASSERT(m_subrunRanges.size() && positionInRun < m_subrunRanges.size());
|
|
|