Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(617)

Unified Diff: third_party/WebKit/Source/core/layout/svg/SVGTextMetricsBuilder.cpp

Issue 1847763002: Only synthesize grapheme widths once for surrogate pair characters (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address reviewer comments Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/WebKit/LayoutTests/svg/text/surrogate-pair-queries-expected.txt ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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());
« no previous file with comments | « third_party/WebKit/LayoutTests/svg/text/surrogate-pair-queries-expected.txt ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698