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

Side by Side 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, 8 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved. 2 * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved.
3 * 3 *
4 * This library is free software; you can redistribute it and/or 4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public 5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either 6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version. 7 * version 2 of the License, or (at your option) any later version.
8 * 8 *
9 * This library is distributed in the hope that it will be useful, 9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
(...skipping 18 matching lines...) Expand all
29 #include "platform/text/BidiResolver.h" 29 #include "platform/text/BidiResolver.h"
30 #include "platform/text/TextDirection.h" 30 #include "platform/text/TextDirection.h"
31 #include "platform/text/TextRun.h" 31 #include "platform/text/TextRun.h"
32 #include "platform/text/TextRunIterator.h" 32 #include "platform/text/TextRunIterator.h"
33 #include "wtf/Vector.h" 33 #include "wtf/Vector.h"
34 34
35 namespace blink { 35 namespace blink {
36 36
37 namespace { 37 namespace {
38 38
39 inline bool characterStartsSurrogatePair(const TextRun& run, unsigned index)
40 {
41 if (!U16_IS_LEAD(run[index]))
42 return false;
43 if (index + 1 >= static_cast<unsigned>(run.charactersLength()))
44 return false;
45 return U16_IS_TRAIL(run[index + 1]);
46 }
47
39 class SVGTextMetricsCalculator { 48 class SVGTextMetricsCalculator {
40 public: 49 public:
41 SVGTextMetricsCalculator(LineLayoutSVGInlineText); 50 SVGTextMetricsCalculator(LineLayoutSVGInlineText);
42 ~SVGTextMetricsCalculator(); 51 ~SVGTextMetricsCalculator();
43 52
44 bool advancePosition(); 53 bool advancePosition();
45 unsigned currentPosition() const { return m_currentPosition; } 54 unsigned currentPosition() const { return m_currentPosition; }
46 55
47 SVGTextMetrics currentCharacterMetrics(); 56 SVGTextMetrics currentCharacterMetrics();
48 57
49 // TODO(pdr): Character-based iteration is ambiguous and error-prone. It 58 // TODO(pdr): Character-based iteration is ambiguous and error-prone. It
50 // should be unified under a single concept. See: https://crbug.com/593570 59 // should be unified under a single concept. See: https://crbug.com/593570
51 bool currentCharacterStartsSurrogatePair() const 60 bool currentCharacterStartsSurrogatePair() const
52 { 61 {
53 return U16_IS_LEAD(m_run[m_currentPosition]) && m_currentPosition + 1 < characterCount() && U16_IS_TRAIL(m_run[m_currentPosition + 1]); 62 return characterStartsSurrogatePair(m_run, m_currentPosition);
54 } 63 }
55 bool currentCharacterIsWhiteSpace() const 64 bool currentCharacterIsWhiteSpace() const
56 { 65 {
57 return m_run[m_currentPosition] == ' '; 66 return m_run[m_currentPosition] == ' ';
58 } 67 }
59 unsigned characterCount() const 68 unsigned characterCount() const
60 { 69 {
61 return static_cast<unsigned>(m_run.charactersLength()); 70 return static_cast<unsigned>(m_run.charactersLength());
62 } 71 }
63 72
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 } 160 }
152 m_bidiRun = bidiRuns.firstRun(); 161 m_bidiRun = bidiRuns.firstRun();
153 } 162 }
154 163
155 bool SVGTextMetricsCalculator::advancePosition() 164 bool SVGTextMetricsCalculator::advancePosition()
156 { 165 {
157 m_currentPosition += currentCharacterStartsSurrogatePair() ? 2 : 1; 166 m_currentPosition += currentCharacterStartsSurrogatePair() ? 2 : 1;
158 return m_currentPosition < characterCount(); 167 return m_currentPosition < characterCount();
159 } 168 }
160 169
170 // TODO(pdr): We only have per-glyph data so we need to synthesize per-grapheme
171 // data. E.g., if 'fi' is shaped into a single glyph, we do not know the 'i'
172 // position. The code below synthesizes an average glyph width when characters
173 // share a single position. This will incorrectly split combining diacritics.
174 // See: https://crbug.com/473476.
175 static void synthesizeGraphemeWidths(const TextRun& run, Vector<CharacterRange>& ranges)
176 {
177 unsigned distributeCount = 0;
178 for (int rangeIndex = static_cast<int>(ranges.size()) - 1; rangeIndex >= 0; --rangeIndex) {
179 CharacterRange& currentRange = ranges[rangeIndex];
180 if (currentRange.width() == 0) {
181 distributeCount++;
182 } else if (distributeCount != 0) {
183 // Only count surrogate pairs as a single character.
184 bool surrogatePair = characterStartsSurrogatePair(run, rangeIndex);
185 if (!surrogatePair)
186 distributeCount++;
187
188 float newWidth = currentRange.width() / distributeCount;
189 currentRange.end = currentRange.start + newWidth;
190 float lastEndPosition = currentRange.end;
191 for (unsigned distribute = 1; distribute < distributeCount; distribu te++) {
192 // This surrogate pair check will skip processing of the second
193 // character forming the surrogate pair.
194 unsigned distributeIndex = rangeIndex + distribute + (surrogateP air ? 1 : 0);
195 ranges[distributeIndex].start = lastEndPosition;
196 ranges[distributeIndex].end = lastEndPosition + newWidth;
197 lastEndPosition = ranges[distributeIndex].end;
198 }
199
200 distributeCount = 0;
201 }
202 }
203 }
204
161 unsigned SVGTextMetricsCalculator::updateSubrunRangesForCurrentPosition() 205 unsigned SVGTextMetricsCalculator::updateSubrunRangesForCurrentPosition()
162 { 206 {
163 ASSERT(m_bidiRun); 207 ASSERT(m_bidiRun);
164 if (m_currentPosition >= static_cast<unsigned>(m_bidiRun->stop())) { 208 if (m_currentPosition >= static_cast<unsigned>(m_bidiRun->stop())) {
165 m_bidiRun = m_bidiRun->next(); 209 m_bidiRun = m_bidiRun->next();
166 // Ensure new subrange ranges are computed below. 210 // Ensure new subrange ranges are computed below.
167 m_subrunRanges.clear(); 211 m_subrunRanges.clear();
168 } 212 }
169 ASSERT(m_bidiRun); 213 ASSERT(m_bidiRun);
170 ASSERT(static_cast<int>(m_currentPosition) < m_bidiRun->stop()); 214 ASSERT(static_cast<int>(m_currentPosition) < m_bidiRun->stop());
171 215
172 unsigned positionInRun = m_currentPosition - m_bidiRun->start(); 216 unsigned positionInRun = m_currentPosition - m_bidiRun->start();
173 if (positionInRun >= m_subrunRanges.size()) { 217 if (positionInRun >= m_subrunRanges.size()) {
174 TextRun subRun = constructTextRun(m_text, 218 TextRun subRun = constructTextRun(m_text, m_bidiRun->start(),
175 m_bidiRun->start(), m_bidiRun->stop() - m_bidiRun->start(), m_bidiRu n->direction()); 219 m_bidiRun->stop() - m_bidiRun->start(), m_bidiRun->direction());
176 m_subrunRanges = m_text.scaledFont().individualCharacterRanges(subRun); 220 m_subrunRanges = m_text.scaledFont().individualCharacterRanges(subRun);
177 221 synthesizeGraphemeWidths(subRun, m_subrunRanges);
178 // TODO(pdr): We only have per-glyph data so we need to synthesize per-
179 // grapheme data. E.g., if 'fi' is shaped into a single glyph, we do not
180 // know the 'i' position. The code below synthesizes an average glyph
181 // width when characters share a position. This will incorrectly split
182 // combining diacritics. See: https://crbug.com/473476.
183 unsigned distributeCount = 0;
184 for (int rangeIndex = static_cast<int>(m_subrunRanges.size()) - 1; range Index >= 0; --rangeIndex) {
185 CharacterRange& currentRange = m_subrunRanges[rangeIndex];
186 if (currentRange.width() == 0) {
187 distributeCount++;
188 } else if (distributeCount != 0) {
189 distributeCount++;
190 float newWidth = currentRange.width() / distributeCount;
191 currentRange.end = currentRange.start + newWidth;
192 for (unsigned distribute = 1; distribute < distributeCount; dist ribute++) {
193 unsigned distributeIndex = rangeIndex + distribute;
194 float newStartPosition = m_subrunRanges[distributeIndex - 1] .end;
195 m_subrunRanges[distributeIndex].start = newStartPosition;
196 m_subrunRanges[distributeIndex].end = newStartPosition + new Width;
197 }
198 distributeCount = 0;
199 }
200 }
201 } 222 }
202 223
203 ASSERT(m_subrunRanges.size() && positionInRun < m_subrunRanges.size()); 224 ASSERT(m_subrunRanges.size() && positionInRun < m_subrunRanges.size());
204 return positionInRun; 225 return positionInRun;
205 } 226 }
206 227
207 SVGTextMetrics SVGTextMetricsCalculator::currentCharacterMetrics() 228 SVGTextMetrics SVGTextMetricsCalculator::currentCharacterMetrics()
208 { 229 {
209 unsigned currentSubrunPosition = updateSubrunRangesForCurrentPosition(); 230 unsigned currentSubrunPosition = updateSubrunRangesForCurrentPosition();
210 unsigned length = currentCharacterStartsSurrogatePair() ? 2 : 1; 231 unsigned length = currentCharacterStartsSurrogatePair() ? 2 : 1;
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 walkTree(textRoot, text); 349 walkTree(textRoot, text);
329 } 350 }
330 351
331 void SVGTextMetricsBuilder::buildMetricsAndLayoutAttributes(LayoutSVGText* textR oot, LayoutSVGInlineText* stopAtText, SVGCharacterDataMap& allCharactersMap) 352 void SVGTextMetricsBuilder::buildMetricsAndLayoutAttributes(LayoutSVGText* textR oot, LayoutSVGInlineText* stopAtText, SVGCharacterDataMap& allCharactersMap)
332 { 353 {
333 ASSERT(textRoot); 354 ASSERT(textRoot);
334 walkTree(textRoot, stopAtText, &allCharactersMap); 355 walkTree(textRoot, stopAtText, &allCharactersMap);
335 } 356 }
336 357
337 } // namespace blink 358 } // namespace blink
OLDNEW
« 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