Changeset 154384 in webkit
- Timestamp:
- Aug 21, 2013 6:43:00 AM (11 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r154383 r154384 1 2013-08-21 Allan Sandfeld Jensen <allan.jensen@digia.com> 2 3 Font’s fast code path doesn’t handle partial runs correctly when kerning or ligatures are enabled 4 https://bugs.webkit.org/show_bug.cgi?id=100050 5 6 Reviewed by Antti Koivisto. 7 8 * fast/text/resources/PTS55F-webfont.ttf: Added. 9 * fast/text/partial-textruns-expected.html: Added. 10 * fast/text/partial-textruns.html: Added. 11 1 12 2013-08-20 Antonio Gomes <a1.gomes@sisa.samsung.com> 2 13 -
trunk/Source/WebCore/ChangeLog
r154383 r154384 1 2013-08-21 Allan Sandfeld Jensen <allan.jensen@digia.com> 2 3 Font’s fast code path doesn’t handle partial runs correctly when kerning or ligatures are enabled 4 https://bugs.webkit.org/show_bug.cgi?id=100050 5 6 Reviewed by Antti Koivisto. 7 8 Always let WidthIterator iterate over an entire TextRun to avoid problems 9 with pixel rounding or shaping on partial runs. 10 11 This fix is necessary for Qt because the complex font-path can not disable 12 shaping, leading to the complex path painting slighly different from the 13 fast path, which messes up selection painting. 14 15 No change in functionality, no new tests. 16 17 * platform/graphics/Font.cpp: 18 (WebCore::Font::drawText): 19 (WebCore::Font::drawEmphasisMarks): 20 (WebCore::Font::selectionRectForText): 21 (WebCore::Font::offsetForPosition): 22 * platform/graphics/FontFastPath.cpp: 23 (WebCore::Font::getGlyphsAndAdvancesForSimpleText): 24 (WebCore::Font::selectionRectForSimpleText): 25 (WebCore::Font::offsetForPositionForSimpleText): 26 * platform/graphics/GlyphBuffer.h: 27 (WebCore::GlyphBuffer::add): 28 (GlyphBuffer): 29 * platform/graphics/WidthIterator.cpp: 30 (WebCore::WidthIterator::advanceInternal): 31 * platform/graphics/WidthIterator.h: 32 (WidthIterator): Removed now unused advanceOneCharacter method. 33 1 34 2013-08-20 Antonio Gomes <a1.gomes@sisa.samsung.com> 2 35 -
trunk/Source/WebCore/platform/graphics/Font.cpp
r152653 r154384 265 265 to = (to == -1 ? run.length() : to); 266 266 267 CodePath codePathToUse = codePath(run); 268 // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050 269 if (codePathToUse != Complex && typesettingFeatures() && (from || to != run.length()) && !run.renderingContext()) 270 codePathToUse = Complex; 271 272 if (codePathToUse != Complex) 267 if (codePath(run) != Complex) 273 268 return drawSimpleText(context, run, point, from, to); 274 269 … … 284 279 to = run.length(); 285 280 286 CodePath codePathToUse = codePath(run); 287 // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050 288 if (codePathToUse != Complex && typesettingFeatures() && (from || to != run.length()) && !run.renderingContext()) 289 codePathToUse = Complex; 290 291 if (codePathToUse != Complex) 281 if (codePath(run) != Complex) 292 282 drawEmphasisMarksForSimpleText(context, run, mark, point, from, to); 293 283 else … … 361 351 to = (to == -1 ? run.length() : to); 362 352 363 CodePath codePathToUse = codePath(run); 364 // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050 365 if (codePathToUse != Complex && typesettingFeatures() && (from || to != run.length()) && !run.renderingContext()) 366 codePathToUse = Complex; 367 368 if (codePathToUse != Complex) 353 if (codePath(run) != Complex) 369 354 return selectionRectForSimpleText(run, point, h, from, to); 370 355 … … 374 359 int Font::offsetForPosition(const TextRun& run, float x, bool includePartialGlyphs) const 375 360 { 376 // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050 377 if (codePath(run) != Complex && !typesettingFeatures()) 361 if (codePath(run) != Complex) 378 362 return offsetForPositionForSimpleText(run, x, includePartialGlyphs); 379 363 -
trunk/Source/WebCore/platform/graphics/FontFastPath.cpp
r150956 r154384 130 130 float Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int to, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const 131 131 { 132 float initialAdvance;133 134 132 WidthIterator it(this, run, 0, false, forTextEmphasis); 135 // FIXME: Using separate glyph buffers for the prefix and the suffix is incorrect when kerning or136 // ligatures are enabled.137 133 GlyphBuffer localGlyphBuffer; 138 it.advance(from, &localGlyphBuffer); 139 float beforeWidth = it.m_runWidthSoFar; 140 it.advance(to, &glyphBuffer); 141 142 if (glyphBuffer.isEmpty()) 143 return 0; 144 145 float afterWidth = it.m_runWidthSoFar; 134 it.advance(run.length(), &localGlyphBuffer); 135 136 if (localGlyphBuffer.isEmpty()) 137 return 0; 138 139 float totalWidth = it.m_runWidthSoFar; 140 float beforeWidth = 0; 141 int glyphPos = 0; 142 for (; glyphPos < localGlyphBuffer.size() && it.m_characterIndex[glyphPos] < from; ++glyphPos) 143 beforeWidth += localGlyphBuffer.advanceAt(glyphPos).width(); 144 int glyphFrom = glyphPos; 145 146 float afterWidth = totalWidth; 147 glyphPos = localGlyphBuffer.size() - 1; 148 for (; glyphPos >= glyphFrom && it.m_characterIndex[glyphPos] >= to; --glyphPos) 149 afterWidth -= localGlyphBuffer.advanceAt(glyphPos).width(); 150 int glyphTo = glyphPos + 1; 151 152 glyphBuffer.add(&localGlyphBuffer, glyphFrom, glyphTo - glyphFrom); 146 153 147 154 if (run.rtl()) { 148 float finalRoundingWidth = it.m_finalRoundingWidth;149 it.advance(run.length(), &localGlyphBuffer);150 initialAdvance = finalRoundingWidth + it.m_runWidthSoFar - afterWidth;151 } else152 initialAdvance = beforeWidth;153 154 if (run.rtl())155 155 glyphBuffer.reverse(0, glyphBuffer.size()); 156 157 return initialAdvance; 156 return totalWidth - afterWidth; 157 } 158 159 return beforeWidth; 158 160 } 159 161 … … 297 299 GlyphBuffer glyphBuffer; 298 300 WidthIterator it(this, run); 299 it.advance(from, &glyphBuffer); 300 float beforeWidth = it.m_runWidthSoFar; 301 it.advance(to, &glyphBuffer); 302 float afterWidth = it.m_runWidthSoFar; 301 it.advance(run.length(), &glyphBuffer); 302 303 float totalWidth = it.m_runWidthSoFar; 304 float beforeWidth = 0; 305 int glyphPos = 0; 306 for (; glyphPos < glyphBuffer.size() && it.m_characterIndex[glyphPos] < from; ++glyphPos) 307 beforeWidth += glyphBuffer.advanceAt(glyphPos).width(); 308 int glyphFrom = glyphPos; 309 310 float afterWidth = totalWidth; 311 glyphPos = glyphBuffer.size() - 1; 312 for (; glyphPos >= glyphFrom && it.m_characterIndex[glyphPos] >= to; --glyphPos) 313 afterWidth -= glyphBuffer.advanceAt(glyphPos).width(); 303 314 304 315 // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning. 305 316 if (run.rtl()) { 306 it.advance(run.length(), &glyphBuffer);307 float totalWidth = it.m_runWidthSoFar;308 317 return FloatRect(floorf(point.x() + totalWidth - afterWidth), point.y(), roundf(point.x() + totalWidth - beforeWidth) - floorf(point.x() + totalWidth - afterWidth), h); 309 318 } … … 314 323 int Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool includePartialGlyphs) const 315 324 { 316 float delta = x; 317 325 GlyphBuffer glyphBuffer; 318 326 WidthIterator it(this, run); 319 GlyphBuffer localGlyphBuffer; 320 unsigned offset; 327 it.advance(run.length(), &glyphBuffer); 328 329 int characterOffset = 0; 321 330 if (run.rtl()) { 322 delta -= floatWidthForSimpleText(run); 323 while (1) { 324 offset = it.m_currentCharacter; 325 float w; 326 if (!it.advanceOneCharacter(w, localGlyphBuffer)) 331 float currentX = it.m_runWidthSoFar; 332 for (int glyphPosition = 0; glyphPosition <= glyphBuffer.size(); ++glyphPosition) { 333 if (glyphPosition == glyphBuffer.size()) { 334 characterOffset = run.length(); 327 335 break; 328 delta += w; 336 } 337 characterOffset = it.m_characterIndex[glyphPosition]; 338 float glyphWidth = glyphBuffer.advanceAt(glyphPosition).width(); 329 339 if (includePartialGlyphs) { 330 if ( delta - w / 2 >= 0)340 if (currentX - glyphWidth / 2.0f <= x) 331 341 break; 332 342 } else { 333 if ( delta >= 0)343 if (currentX - glyphWidth <= x) 334 344 break; 335 345 } 346 currentX -= glyphWidth; 336 347 } 337 348 } else { 338 while (1) {339 offset = it.m_currentCharacter;340 float w;341 if (!it.advanceOneCharacter(w, localGlyphBuffer))349 float currentX = 0; 350 for (int glyphPosition = 0; glyphPosition <= glyphBuffer.size(); ++glyphPosition) { 351 if (glyphPosition == glyphBuffer.size()) { 352 characterOffset = run.length(); 342 353 break; 343 delta -= w; 354 } 355 characterOffset = it.m_characterIndex[glyphPosition]; 356 float glyphWidth = glyphBuffer.advanceAt(glyphPosition).width(); 344 357 if (includePartialGlyphs) { 345 if ( delta + w / 2 <= 0)358 if (currentX + glyphWidth / 2.0f >= x) 346 359 break; 347 360 } else { 348 if ( delta <= 0)361 if (currentX + glyphWidth >= x) 349 362 break; 350 363 } 364 currentX += glyphWidth; 351 365 } 352 366 } 353 367 354 return offset;355 } 356 357 } 368 return characterOffset; 369 } 370 371 } // namespace WebCore -
trunk/Source/WebCore/platform/graphics/GlyphBuffer.h
r151610 r154384 140 140 } 141 141 142 void add(const GlyphBuffer* glyphBuffer, int from, int len) 143 { 144 m_glyphs.append(glyphBuffer->glyphs(from), len); 145 m_advances.append(glyphBuffer->advances(from), len); 146 m_fontData.append(glyphBuffer->m_fontData.data() + from, len); 147 #if PLATFORM(WIN) 148 m_offsets.append(glyphBuffer->m_offsets.data() + from, len); 149 #endif 150 } 151 142 152 void add(Glyph glyph, const SimpleFontData* font, float width, const FloatSize* offset = 0) 143 153 { -
trunk/Source/WebCore/platform/graphics/WidthIterator.cpp
r148956 r154384 163 163 while (textIterator.consume(character, clusterLength)) { 164 164 unsigned advanceLength = clusterLength; 165 const GlyphData& glyphData = glyphDataForCharacter(character, rtl, textIterator.currentCharacter(), advanceLength); 165 int currentCharacterIndex = textIterator.currentCharacter(); 166 const GlyphData& glyphData = glyphDataForCharacter(character, rtl, currentCharacterIndex, advanceLength); 166 167 Glyph glyph = glyphData.glyph; 167 168 const SimpleFontData* fontData = glyphData.fontData; … … 231 232 else 232 233 glyphBuffer->add(fontData->spaceGlyph(), fontData, expansionAtThisOpportunity); 234 m_characterIndex.append(currentCharacterIndex); 233 235 } else 234 236 glyphBuffer->expandLastAdvance(expansionAtThisOpportunity); … … 297 299 } 298 300 299 if (glyphBuffer) 301 if (glyphBuffer) { 300 302 glyphBuffer->add(glyph, fontData, (rtl ? oldWidth + lastRoundingWidth : width)); 303 m_characterIndex.append(currentCharacterIndex); 304 } 301 305 302 306 lastRoundingWidth = width - oldWidth; … … 338 342 } 339 343 340 bool WidthIterator::advanceOneCharacter(float& width, GlyphBuffer& glyphBuffer) 341 { 342 int oldSize = glyphBuffer.size(); 343 advance(m_currentCharacter + 1, &glyphBuffer); 344 float w = 0; 345 for (int i = oldSize; i < glyphBuffer.size(); ++i) 346 w += glyphBuffer.advanceAt(i).width(); 347 width = w; 348 return glyphBuffer.size() > oldSize; 349 } 350 351 } 344 } -
trunk/Source/WebCore/platform/graphics/WidthIterator.h
r154186 r154384 44 44 45 45 unsigned advance(int to, GlyphBuffer*); 46 bool advanceOneCharacter(float& width, GlyphBuffer&);47 46 48 47 float maxGlyphBoundingBoxY() const { ASSERT(m_accountForGlyphBounds); return m_maxGlyphBoundingBoxY; } … … 84 83 bool m_isAfterExpansion; 85 84 float m_finalRoundingWidth; 85 Vector<int> m_characterIndex; 86 86 87 87 #if ENABLE(SVG_FONTS)
Note: See TracChangeset
for help on using the changeset viewer.