Commit 5fb0af8e authored by allan.jensen@digia.com's avatar allan.jensen@digia.com
Browse files

Font's fast code path doesn't handle partial runs correctly when kerning or ligatures are enabled

https://bugs.webkit.org/show_bug.cgi?id=100050

Reviewed by Darin Adler.

Renamed m_characterIndex to m_characterIndexOfGlyph and gave it an inline size of 10,
which covers around 66% of all cases. The rest of the cases are now preallocated to the
upper limit which is length of the original TextRun.

* platform/graphics/FontFastPath.cpp:
(WebCore::Font::getGlyphsAndAdvancesForSimpleText):
(WebCore::Font::selectionRectForSimpleText):
(WebCore::Font::offsetForPositionForSimpleText):
* platform/graphics/WidthIterator.cpp:
(WebCore::WidthIterator::WidthIterator):
(WebCore::WidthIterator::advanceInternal):
* platform/graphics/WidthIterator.h:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@154674 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 181483e1
2013-08-27 Allan Sandfeld Jensen <allan.jensen@digia.com>
Font's fast code path doesn't handle partial runs correctly when kerning or ligatures are enabled
https://bugs.webkit.org/show_bug.cgi?id=100050
Reviewed by Darin Adler.
Renamed m_characterIndex to m_characterIndexOfGlyph and gave it an inline size of 10,
which covers around 66% of all cases. The rest of the cases are now preallocated to the
upper limit which is length of the original TextRun.
* platform/graphics/FontFastPath.cpp:
(WebCore::Font::getGlyphsAndAdvancesForSimpleText):
(WebCore::Font::selectionRectForSimpleText):
(WebCore::Font::offsetForPositionForSimpleText):
* platform/graphics/WidthIterator.cpp:
(WebCore::WidthIterator::WidthIterator):
(WebCore::WidthIterator::advanceInternal):
* platform/graphics/WidthIterator.h:
2013-08-27 Christophe Dumez <ch.dumez@sisa.samsung.com>
 
Implement DOM3 wheel event
......@@ -139,13 +139,13 @@ float Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int
float totalWidth = it.m_runWidthSoFar;
float beforeWidth = 0;
int glyphPos = 0;
for (; glyphPos < localGlyphBuffer.size() && it.m_characterIndex[glyphPos] < from; ++glyphPos)
for (; glyphPos < localGlyphBuffer.size() && it.m_characterIndexOfGlyph[glyphPos] < from; ++glyphPos)
beforeWidth += localGlyphBuffer.advanceAt(glyphPos).width();
int glyphFrom = glyphPos;
float afterWidth = totalWidth;
glyphPos = localGlyphBuffer.size() - 1;
for (; glyphPos >= glyphFrom && it.m_characterIndex[glyphPos] >= to; --glyphPos)
for (; glyphPos >= glyphFrom && it.m_characterIndexOfGlyph[glyphPos] >= to; --glyphPos)
afterWidth -= localGlyphBuffer.advanceAt(glyphPos).width();
int glyphTo = glyphPos + 1;
......@@ -303,13 +303,13 @@ FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint&
float totalWidth = it.m_runWidthSoFar;
float beforeWidth = 0;
int glyphPos = 0;
for (; glyphPos < glyphBuffer.size() && it.m_characterIndex[glyphPos] < from; ++glyphPos)
for (; glyphPos < glyphBuffer.size() && it.m_characterIndexOfGlyph[glyphPos] < from; ++glyphPos)
beforeWidth += glyphBuffer.advanceAt(glyphPos).width();
int glyphFrom = glyphPos;
float afterWidth = totalWidth;
glyphPos = glyphBuffer.size() - 1;
for (; glyphPos >= glyphFrom && it.m_characterIndex[glyphPos] >= to; --glyphPos)
for (; glyphPos >= glyphFrom && it.m_characterIndexOfGlyph[glyphPos] >= to; --glyphPos)
afterWidth -= glyphBuffer.advanceAt(glyphPos).width();
// Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning.
......@@ -334,7 +334,7 @@ int Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool inclu
characterOffset = run.length();
break;
}
characterOffset = it.m_characterIndex[glyphPosition];
characterOffset = it.m_characterIndexOfGlyph[glyphPosition];
float glyphWidth = glyphBuffer.advanceAt(glyphPosition).width();
if (includePartialGlyphs) {
if (currentX - glyphWidth / 2.0f <= x)
......@@ -352,7 +352,7 @@ int Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool inclu
characterOffset = run.length();
break;
}
characterOffset = it.m_characterIndex[glyphPosition];
characterOffset = it.m_characterIndexOfGlyph[glyphPosition];
float glyphWidth = glyphBuffer.advanceAt(glyphPosition).width();
if (includePartialGlyphs) {
if (currentX + glyphWidth / 2.0f >= x)
......
......@@ -67,6 +67,8 @@ WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const
else
m_expansionPerOpportunity = m_expansion / expansionOpportunityCount;
}
// Character-index will end up the same or slightly shorter than m_run, so if we reserve that much it will never need to resize.
m_characterIndexOfGlyph.reserveInitialCapacity(m_run.length());
}
GlyphData WidthIterator::glyphDataForCharacter(UChar32 character, bool mirror, int currentCharacter, unsigned& advanceLength)
......@@ -231,7 +233,7 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph
glyphBuffer->add(fontData->zeroWidthSpaceGlyph(), fontData, m_expansionPerOpportunity);
else
glyphBuffer->add(fontData->spaceGlyph(), fontData, expansionAtThisOpportunity);
m_characterIndex.append(currentCharacterIndex);
m_characterIndexOfGlyph.append(currentCharacterIndex);
} else
glyphBuffer->expandLastAdvance(expansionAtThisOpportunity);
}
......@@ -300,7 +302,7 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph
if (glyphBuffer) {
glyphBuffer->add(glyph, fontData, (rtl ? oldWidth + lastRoundingWidth : width));
m_characterIndex.append(currentCharacterIndex);
m_characterIndexOfGlyph.append(currentCharacterIndex);
}
lastRoundingWidth = width - oldWidth;
......
......@@ -82,7 +82,8 @@ public:
float m_expansionPerOpportunity;
bool m_isAfterExpansion;
float m_finalRoundingWidth;
Vector<int> m_characterIndex;
// An inline capacity of 10 catches around 2/3 of the cases. To catch 90% we would need 32.
Vector<int, 10> m_characterIndexOfGlyph;
#if ENABLE(SVG_FONTS)
String m_lastGlyphName;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment