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

Side by Side Diff: third_party/WebKit/Source/platform/fonts/shaping/HarfBuzzShaper.cpp

Issue 1420043007: Fix ShapeResult::selectionRect handles RTL runs in wrong order (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebaseline 1px diff on Mac Created 5 years, 1 month 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/fast/text/international/rtl-selection-rect-with-fallback.html ('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) 2012 Google Inc. All rights reserved. 2 * Copyright (c) 2012 Google Inc. All rights reserved.
3 * Copyright (C) 2013 BlackBerry Limited. All rights reserved. 3 * Copyright (C) 2013 BlackBerry Limited. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are 6 * modification, are permitted provided that the following conditions are
7 * met: 7 * met:
8 * 8 *
9 * * Redistributions of source code must retain the above copyright 9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 struct ShapeResult::RunInfo { 68 struct ShapeResult::RunInfo {
69 RunInfo(const SimpleFontData* font, hb_direction_t dir, hb_script_t script, 69 RunInfo(const SimpleFontData* font, hb_direction_t dir, hb_script_t script,
70 unsigned startIndex, unsigned numGlyphs, unsigned numCharacters) 70 unsigned startIndex, unsigned numGlyphs, unsigned numCharacters)
71 : m_fontData(const_cast<SimpleFontData*>(font)), m_direction(dir), m_scr ipt(script) 71 : m_fontData(const_cast<SimpleFontData*>(font)), m_direction(dir), m_scr ipt(script)
72 , m_startIndex(startIndex), m_numCharacters(numCharacters) 72 , m_startIndex(startIndex), m_numCharacters(numCharacters)
73 , m_numGlyphs(numGlyphs), m_width(0.0f) 73 , m_numGlyphs(numGlyphs), m_width(0.0f)
74 { 74 {
75 m_glyphData.resize(m_numGlyphs); 75 m_glyphData.resize(m_numGlyphs);
76 } 76 }
77 77
78 bool rtl() const { return HB_DIRECTION_IS_BACKWARD(m_direction); }
79 float xPositionForVisualOffset(unsigned) const;
78 float xPositionForOffset(unsigned) const; 80 float xPositionForOffset(unsigned) const;
79 int characterIndexForXPosition(float) const; 81 int characterIndexForXPosition(float) const;
80 void setGlyphAndPositions(unsigned index, uint16_t glyphId, float advance, 82 void setGlyphAndPositions(unsigned index, uint16_t glyphId, float advance,
81 float offsetX, float offsetY); 83 float offsetX, float offsetY);
82 84
83 void addAdvance(unsigned index, float advance) 85 void addAdvance(unsigned index, float advance)
84 { 86 {
85 m_glyphData[index].advance += advance; 87 m_glyphData[index].advance += advance;
86 } 88 }
87 89
88 size_t glyphToCharacterIndex(size_t i) const 90 size_t glyphToCharacterIndex(size_t i) const
89 { 91 {
90 return m_startIndex + m_glyphData[i].characterIndex; 92 return m_startIndex + m_glyphData[i].characterIndex;
91 } 93 }
92 94
93 RefPtr<SimpleFontData> m_fontData; 95 RefPtr<SimpleFontData> m_fontData;
94 hb_direction_t m_direction; 96 hb_direction_t m_direction;
95 hb_script_t m_script; 97 hb_script_t m_script;
96 Vector<HarfBuzzRunGlyphData> m_glyphData; 98 Vector<HarfBuzzRunGlyphData> m_glyphData;
97 unsigned m_startIndex; 99 unsigned m_startIndex;
98 unsigned m_numCharacters; 100 unsigned m_numCharacters;
99 unsigned m_numGlyphs; 101 unsigned m_numGlyphs;
100 float m_width; 102 float m_width;
101 }; 103 };
102 104
105 float ShapeResult::RunInfo::xPositionForVisualOffset(unsigned offset) const
106 {
107 ASSERT(offset < m_numCharacters);
108 if (rtl())
109 offset = m_numCharacters - offset - 1;
110 return xPositionForOffset(offset);
111 }
112
103 float ShapeResult::RunInfo::xPositionForOffset(unsigned offset) const 113 float ShapeResult::RunInfo::xPositionForOffset(unsigned offset) const
104 { 114 {
105 ASSERT(offset <= m_numCharacters); 115 ASSERT(offset <= m_numCharacters);
106 unsigned glyphIndex = 0; 116 unsigned glyphIndex = 0;
107 float position = 0; 117 float position = 0;
108 if (m_direction == HB_DIRECTION_RTL) { 118 if (rtl()) {
109 while (glyphIndex < m_numGlyphs && m_glyphData[glyphIndex].characterInde x > offset) { 119 while (glyphIndex < m_numGlyphs && m_glyphData[glyphIndex].characterInde x > offset) {
110 position += m_glyphData[glyphIndex].advance; 120 position += m_glyphData[glyphIndex].advance;
111 ++glyphIndex; 121 ++glyphIndex;
112 } 122 }
113 // For RTL, we need to return the right side boundary of the character. 123 // For RTL, we need to return the right side boundary of the character.
114 // Add advance of glyphs which are part of the character. 124 // Add advance of glyphs which are part of the character.
115 while (glyphIndex < m_numGlyphs - 1 && m_glyphData[glyphIndex].character Index == m_glyphData[glyphIndex + 1].characterIndex) { 125 while (glyphIndex < m_numGlyphs - 1 && m_glyphData[glyphIndex].character Index == m_glyphData[glyphIndex + 1].characterIndex) {
116 position += m_glyphData[glyphIndex].advance; 126 position += m_glyphData[glyphIndex].advance;
117 ++glyphIndex; 127 ++glyphIndex;
118 } 128 }
(...skipping 12 matching lines...) Expand all
131 ASSERT(targetX <= m_width); 141 ASSERT(targetX <= m_width);
132 float currentX = 0; 142 float currentX = 0;
133 float currentAdvance = m_glyphData[0].advance; 143 float currentAdvance = m_glyphData[0].advance;
134 unsigned glyphIndex = 0; 144 unsigned glyphIndex = 0;
135 145
136 // Sum up advances that belong to the first character. 146 // Sum up advances that belong to the first character.
137 while (glyphIndex < m_numGlyphs - 1 && m_glyphData[glyphIndex].characterInde x == m_glyphData[glyphIndex + 1].characterIndex) 147 while (glyphIndex < m_numGlyphs - 1 && m_glyphData[glyphIndex].characterInde x == m_glyphData[glyphIndex + 1].characterIndex)
138 currentAdvance += m_glyphData[++glyphIndex].advance; 148 currentAdvance += m_glyphData[++glyphIndex].advance;
139 currentAdvance = currentAdvance / 2.0; 149 currentAdvance = currentAdvance / 2.0;
140 if (targetX <= currentAdvance) 150 if (targetX <= currentAdvance)
141 return m_direction == HB_DIRECTION_RTL ? m_numCharacters : 0; 151 return rtl() ? m_numCharacters : 0;
142 152
143 currentX = currentAdvance; 153 currentX = currentAdvance;
144 ++glyphIndex; 154 ++glyphIndex;
145 while (glyphIndex < m_numGlyphs) { 155 while (glyphIndex < m_numGlyphs) {
146 unsigned prevCharacterIndex = m_glyphData[glyphIndex - 1].characterIndex ; 156 unsigned prevCharacterIndex = m_glyphData[glyphIndex - 1].characterIndex ;
147 float prevAdvance = currentAdvance; 157 float prevAdvance = currentAdvance;
148 currentAdvance = m_glyphData[glyphIndex].advance; 158 currentAdvance = m_glyphData[glyphIndex].advance;
149 while (glyphIndex < m_numGlyphs - 1 && m_glyphData[glyphIndex].character Index == m_glyphData[glyphIndex + 1].characterIndex) 159 while (glyphIndex < m_numGlyphs - 1 && m_glyphData[glyphIndex].character Index == m_glyphData[glyphIndex + 1].characterIndex)
150 currentAdvance += m_glyphData[++glyphIndex].advance; 160 currentAdvance += m_glyphData[++glyphIndex].advance;
151 currentAdvance = currentAdvance / 2.0; 161 currentAdvance = currentAdvance / 2.0;
152 float nextX = currentX + prevAdvance + currentAdvance; 162 float nextX = currentX + prevAdvance + currentAdvance;
153 if (currentX <= targetX && targetX <= nextX) 163 if (currentX <= targetX && targetX <= nextX)
154 return m_direction == HB_DIRECTION_RTL ? prevCharacterIndex : m_glyp hData[glyphIndex].characterIndex; 164 return rtl() ? prevCharacterIndex : m_glyphData[glyphIndex].characte rIndex;
155 currentX = nextX; 165 currentX = nextX;
156 ++glyphIndex; 166 ++glyphIndex;
157 } 167 }
158 168
159 return m_direction == HB_DIRECTION_RTL ? 0 : m_numCharacters; 169 return rtl() ? 0 : m_numCharacters;
160 } 170 }
161 171
162 void ShapeResult::RunInfo::setGlyphAndPositions(unsigned index, 172 void ShapeResult::RunInfo::setGlyphAndPositions(unsigned index,
163 uint16_t glyphId, float advance, float offsetX, float offsetY) 173 uint16_t glyphId, float advance, float offsetX, float offsetY)
164 { 174 {
165 HarfBuzzRunGlyphData& data = m_glyphData[index]; 175 HarfBuzzRunGlyphData& data = m_glyphData[index];
166 data.glyph = glyphId; 176 data.glyph = glyphId;
167 data.advance = advance; 177 data.advance = advance;
168 data.offset = FloatSize(offsetX, offsetY); 178 data.offset = FloatSize(offsetX, offsetY);
169 } 179 }
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 413
404 // The absoluteFrom and absoluteTo arguments represent the start/end offset 414 // The absoluteFrom and absoluteTo arguments represent the start/end offset
405 // for the entire run, from/to are continuously updated to be relative to 415 // for the entire run, from/to are continuously updated to be relative to
406 // the current word (ShapeResult instance). 416 // the current word (ShapeResult instance).
407 int from = absoluteFrom; 417 int from = absoluteFrom;
408 int to = absoluteTo; 418 int to = absoluteTo;
409 419
410 unsigned totalNumCharacters = 0; 420 unsigned totalNumCharacters = 0;
411 for (unsigned j = 0; j < results.size(); j++) { 421 for (unsigned j = 0; j < results.size(); j++) {
412 RefPtr<ShapeResult> result = results[j]; 422 RefPtr<ShapeResult> result = results[j];
423 if (direction == RTL) {
424 // Convert logical offsets to visual offsets, because results are in
wkorman 2015/11/02 04:29:20 Is visual the same as physical? Which name is pref
kojii 2015/11/02 05:19:44 IIUC Unicode bidi reordering uses logical/visual w
425 // logical order while runs are in visual order.
426 if (!foundFromX && from >= 0 && static_cast<unsigned>(from) < result ->numCharacters())
427 from = result->numCharacters() - from - 1;
428 if (!foundToX && to >= 0 && static_cast<unsigned>(to) < result->numC haracters())
429 to = result->numCharacters() - to - 1;
430 currentX -= result->width();
431 }
413 for (unsigned i = 0; i < result->m_runs.size(); i++) { 432 for (unsigned i = 0; i < result->m_runs.size(); i++) {
414 if (!result->m_runs[i]) 433 if (!result->m_runs[i])
415 continue; 434 continue;
416 if (direction == RTL) 435 ASSERT((direction == RTL) == result->m_runs[i]->rtl());
417 currentX -= result->m_runs[i]->m_width;
418 int numCharacters = result->m_runs[i]->m_numCharacters; 436 int numCharacters = result->m_runs[i]->m_numCharacters;
419 if (!foundFromX && from >= 0 && from < numCharacters) { 437 if (!foundFromX && from >= 0 && from < numCharacters) {
420 fromX = result->m_runs[i]->xPositionForOffset(from) + currentX; 438 fromX = result->m_runs[i]->xPositionForVisualOffset(from) + curr entX;
421 foundFromX = true; 439 foundFromX = true;
422 } else { 440 } else {
423 from -= numCharacters; 441 from -= numCharacters;
424 } 442 }
425 443
426 if (!foundToX && to >= 0 && to < numCharacters) { 444 if (!foundToX && to >= 0 && to < numCharacters) {
427 toX = result->m_runs[i]->xPositionForOffset(to) + currentX; 445 toX = result->m_runs[i]->xPositionForVisualOffset(to) + currentX ;
428 foundToX = true; 446 foundToX = true;
429 } else { 447 } else {
430 to -= numCharacters; 448 to -= numCharacters;
431 } 449 }
432 450
433 if (foundFromX && foundToX) 451 if (foundFromX && foundToX)
434 break; 452 break;
435 if (direction != RTL) 453 currentX += result->m_runs[i]->m_width;
436 currentX += result->m_runs[i]->m_width;
437 } 454 }
455 if (direction == RTL)
456 currentX -= result->width();
438 totalNumCharacters += result->numCharacters(); 457 totalNumCharacters += result->numCharacters();
439 } 458 }
440 459
441 // The position in question might be just after the text. 460 // The position in question might be just after the text.
442 if (!foundFromX && absoluteFrom == totalNumCharacters) { 461 if (!foundFromX && absoluteFrom == totalNumCharacters) {
443 fromX = direction == RTL ? 0 : totalWidth; 462 fromX = direction == RTL ? 0 : totalWidth;
444 foundFromX = true; 463 foundFromX = true;
445 } 464 }
446 if (!foundToX && absoluteTo == totalNumCharacters) { 465 if (!foundToX && absoluteTo == totalNumCharacters) {
447 toX = direction == RTL ? 0 : totalWidth; 466 toX = direction == RTL ? 0 : totalWidth;
(...skipping 868 matching lines...) Expand 10 before | Expand all | Expand 10 after
1316 } 1335 }
1317 1336
1318 // Don't need to check m_textRun.allowsTrailingExpansion() since it's covere d by !m_expansionOpportunityCount above 1337 // Don't need to check m_textRun.allowsTrailingExpansion() since it's covere d by !m_expansionOpportunityCount above
1319 spacing += nextExpansionPerOpportunity(); 1338 spacing += nextExpansionPerOpportunity();
1320 m_isAfterExpansion = true; 1339 m_isAfterExpansion = true;
1321 return spacing; 1340 return spacing;
1322 } 1341 }
1323 1342
1324 1343
1325 } // namespace blink 1344 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/LayoutTests/fast/text/international/rtl-selection-rect-with-fallback.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698