Modified: trunk/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp (129073 => 129074)
--- trunk/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp 2012-09-19 23:59:01 UTC (rev 129073)
+++ trunk/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp 2012-09-20 00:00:45 UTC (rev 129074)
@@ -85,12 +85,13 @@
m_numGlyphs = hb_buffer_get_length(harfbuzzBuffer);
m_glyphs.resize(m_numGlyphs);
m_advances.resize(m_numGlyphs);
- m_glyphToCharacterIndex.resize(m_numGlyphs);
+ m_glyphToCharacterIndexes.resize(m_numGlyphs);
m_logClusters.resize(m_numCharacters);
+ m_offsets.resize(m_numGlyphs);
hb_glyph_info_t* infos = hb_buffer_get_glyph_infos(harfbuzzBuffer, 0);
for (unsigned i = 0; i < m_numGlyphs; ++i)
- m_glyphToCharacterIndex[i] = infos[i].cluster;
+ m_glyphToCharacterIndexes[i] = infos[i].cluster;
// Fill logical clusters
unsigned index = 0;
@@ -111,10 +112,11 @@
}
}
-void HarfBuzzShaper::HarfBuzzRun::setGlyphAndAdvance(unsigned index, uint16_t glyphId, float advance)
+void HarfBuzzShaper::HarfBuzzRun::setGlyphAndPositions(unsigned index, uint16_t glyphId, float advance, float offsetX, float offsetY)
{
m_glyphs[index] = glyphId;
m_advances[index] = advance;
+ m_offsets[index] = FloatPoint(offsetX, offsetY);
}
int HarfBuzzShaper::HarfBuzzRun::characterIndexForXPosition(float targetX)
@@ -126,7 +128,7 @@
float currentAdvance = m_advances[i] / 2.0;
float nextX = currentX + prevAdvance + currentAdvance;
if (currentX <= targetX && targetX <= nextX)
- return m_glyphToCharacterIndex[i] + (rtl() ? 1 : 0);
+ return m_glyphToCharacterIndexes[i] + (rtl() ? 1 : 0);
currentX = nextX;
prevAdvance = currentAdvance;
}
@@ -190,11 +192,6 @@
m_toIndex = to;
}
-bool HarfBuzzShaper::shouldDrawCharacterAt(int index)
-{
- return m_fromIndex <= index && index < m_toIndex;
-}
-
void HarfBuzzShaper::setFontFeatures()
{
FontFeatureSettings* settings = m_font->fontDescription().featureSettings();
@@ -218,9 +215,13 @@
return false;
m_totalWidth = 0;
- if (!shapeHarfBuzzRuns(glyphBuffer))
+ if (!shapeHarfBuzzRuns())
return false;
m_totalWidth = roundf(m_totalWidth);
+
+ if (glyphBuffer)
+ fillGlyphBuffer(glyphBuffer);
+
return true;
}
@@ -304,14 +305,12 @@
return !m_harfbuzzRuns.isEmpty();
}
-bool HarfBuzzShaper::shapeHarfBuzzRuns(GlyphBuffer* glyphBuffer)
+bool HarfBuzzShaper::shapeHarfBuzzRuns()
{
HarfBuzzScopedPtr<hb_buffer_t> harfbuzzBuffer(hb_buffer_create(), hb_buffer_destroy);
- float pendingGlyphAdvanceX = 0;
- float pendingGlyphAdvanceY = 0;
hb_buffer_set_unicode_funcs(harfbuzzBuffer.get(), hb_icu_get_unicode_funcs());
- if (m_run.directionalOverride())
+ if (m_run.rtl() || m_run.directionalOverride())
hb_buffer_set_direction(harfbuzzBuffer.get(), m_run.rtl() ? HB_DIRECTION_RTL : HB_DIRECTION_LTR);
for (unsigned i = 0; i < m_harfbuzzRuns.size(); ++i) {
@@ -335,16 +334,17 @@
hb_shape(harfbuzzFont.get(), harfbuzzBuffer.get(), m_features.isEmpty() ? 0 : m_features.data(), m_features.size());
currentRun->applyShapeResult(harfbuzzBuffer.get());
- setGlyphPositionsForHarfBuzzRun(currentRun, i, harfbuzzBuffer.get(), glyphBuffer, pendingGlyphAdvanceX, pendingGlyphAdvanceY);
+ setGlyphPositionsForHarfBuzzRun(currentRun, harfbuzzBuffer.get());
hb_buffer_reset(harfbuzzBuffer.get());
- if (m_run.directionalOverride())
+ if (m_run.rtl() || m_run.directionalOverride())
hb_buffer_set_direction(harfbuzzBuffer.get(), m_run.rtl() ? HB_DIRECTION_RTL : HB_DIRECTION_LTR);
}
+
return true;
}
-void HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun(HarfBuzzRun* currentRun, unsigned runIndexInVisualOrder, hb_buffer_t* harfbuzzBuffer, GlyphBuffer* glyphBuffer, float& pendingGlyphAdvanceX, float& pendingGlyphAdvanceY)
+void HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun(HarfBuzzRun* currentRun, hb_buffer_t* harfbuzzBuffer)
{
const SimpleFontData* currentFontData = currentRun->fontData();
hb_glyph_info_t* glyphInfos = hb_buffer_get_glyph_infos(harfbuzzBuffer, 0);
@@ -352,58 +352,93 @@
unsigned numGlyphs = currentRun->numGlyphs();
float totalAdvance = 0;
- float nextOffsetX = harfbuzzPositionToFloat(glyphPositions[0].x_offset);
- float nextOffsetY = -harfbuzzPositionToFloat(glyphPositions[0].y_offset);
- // HarfBuzz returns the shaping result in visual order. We need not to flip them for RTL.
+
+ // HarfBuzz returns the shaping result in visual order. We need not to flip for RTL.
for (size_t i = 0; i < numGlyphs; ++i) {
bool runEnd = i + 1 == numGlyphs;
uint16_t glyph = glyphInfos[i].codepoint;
- float offsetX = nextOffsetX;
- float offsetY = nextOffsetY;
+ float offsetX = harfbuzzPositionToFloat(glyphPositions[i].x_offset);
+ float offsetY = -harfbuzzPositionToFloat(glyphPositions[i].y_offset);
float advance = harfbuzzPositionToFloat(glyphPositions[i].x_advance);
- nextOffsetX = runEnd ? 0 : harfbuzzPositionToFloat(glyphPositions[i + 1].x_offset);
- nextOffsetY = runEnd ? 0 : -harfbuzzPositionToFloat(glyphPositions[i + 1].y_offset);
unsigned currentCharacterIndex = currentRun->startIndex() + glyphInfos[i].cluster;
bool isClusterEnd = runEnd || glyphInfos[i].cluster != glyphInfos[i + 1].cluster;
- float spacing = isClusterEnd ? m_letterSpacing : 0;
+ float spacing = 0;
+ if (isClusterEnd && !Font::treatAsZeroWidthSpace(m_normalizedBuffer[currentCharacterIndex]))
+ spacing += m_letterSpacing;
if (isClusterEnd && isWordEnd(currentCharacterIndex))
spacing += determineWordBreakSpacing();
if (currentFontData->isZeroWidthSpaceGlyph(glyph)) {
- currentRun->setGlyphAndAdvance(i, glyph, 0);
- if (glyphBuffer && shouldDrawCharacterAt(currentCharacterIndex))
- glyphBuffer->add(glyph, currentFontData, createGlyphBufferAdvance(0, 0));
+ currentRun->setGlyphAndPositions(i, glyph, 0, 0, 0);
continue;
}
advance += spacing;
-
- currentRun->setGlyphAndAdvance(i, glyph, advance);
- if (glyphBuffer) {
- if (!i && !runIndexInVisualOrder)
- m_startOffset.set(offsetX, offsetY);
- float glyphAdvanceX = advance + nextOffsetX - offsetX;
- float glyphAdvanceY = nextOffsetY - offsetY;
- if (shouldDrawCharacterAt(currentCharacterIndex)) {
- glyphAdvanceX += pendingGlyphAdvanceX;
- glyphAdvanceY += pendingGlyphAdvanceY;
- pendingGlyphAdvanceX = 0;
- pendingGlyphAdvanceY = 0;
- glyphBuffer->add(glyph, currentFontData, createGlyphBufferAdvance(glyphAdvanceX, glyphAdvanceY));
- } else {
- pendingGlyphAdvanceX += glyphAdvanceX;
- pendingGlyphAdvanceY += glyphAdvanceY;
- }
+ if (m_run.rtl()) {
+ // In RTL, spacing should be added to left side of glyphs.
+ offsetX += spacing;
+ if (!isClusterEnd)
+ offsetX += m_letterSpacing;
}
+ currentRun->setGlyphAndPositions(i, glyph, advance, offsetX, offsetY);
+
totalAdvance += advance;
}
currentRun->setWidth(totalAdvance > 0.0 ? totalAdvance : 0.0);
m_totalWidth += currentRun->width();
}
+void HarfBuzzShaper::fillGlyphBufferFromHarfBuzzRun(GlyphBuffer* glyphBuffer, HarfBuzzRun* currentRun, FloatPoint& firstOffsetOfNextRun)
+{
+ FloatPoint* offsets = currentRun->offsets();
+ uint16_t* glyphs = currentRun->glyphs();
+ float* advances = currentRun->advances();
+ unsigned numGlyphs = currentRun->numGlyphs();
+ uint16_t* glyphToCharacterIndexes = currentRun->glyphToCharacterIndexes();
+
+ for (unsigned i = 0; i < numGlyphs; ++i) {
+ uint16_t currentCharacterIndex = currentRun->startIndex() + glyphToCharacterIndexes[i];
+ FloatPoint& currentOffset = offsets[i];
+ FloatPoint& nextOffset = (i == numGlyphs - 1) ? firstOffsetOfNextRun : offsets[i + 1];
+ float glyphAdvanceX = advances[i] + nextOffset.x() - currentOffset.x();
+ float glyphAdvanceY = nextOffset.y() - currentOffset.y();
+ if (m_run.rtl()) {
+ if (currentCharacterIndex > m_toIndex)
+ m_startOffset.move(glyphAdvanceX, glyphAdvanceY);
+ else if (currentCharacterIndex >= m_fromIndex)
+ glyphBuffer->add(glyphs[i], currentRun->fontData(), createGlyphBufferAdvance(glyphAdvanceX, glyphAdvanceY));
+ } else {
+ if (currentCharacterIndex < m_fromIndex)
+ m_startOffset.move(glyphAdvanceX, glyphAdvanceY);
+ else if (currentCharacterIndex < m_toIndex)
+ glyphBuffer->add(glyphs[i], currentRun->fontData(), createGlyphBufferAdvance(glyphAdvanceX, glyphAdvanceY));
+ }
+ }
+}
+
+void HarfBuzzShaper::fillGlyphBuffer(GlyphBuffer* glyphBuffer)
+{
+ unsigned numRuns = m_harfbuzzRuns.size();
+ if (m_run.rtl()) {
+ m_startOffset = m_harfbuzzRuns.last()->offsets()[0];
+ for (int runIndex = numRuns - 1; runIndex >= 0; --runIndex) {
+ HarfBuzzRun* currentRun = m_harfbuzzRuns[runIndex].get();
+ FloatPoint firstOffsetOfNextRun = !runIndex ? FloatPoint() : m_harfbuzzRuns[runIndex - 1]->offsets()[0];
+ fillGlyphBufferFromHarfBuzzRun(glyphBuffer, currentRun, firstOffsetOfNextRun);
+ }
+ } else {
+ m_startOffset = m_harfbuzzRuns.first()->offsets()[0];
+ for (unsigned runIndex = 0; runIndex < numRuns; ++runIndex) {
+ HarfBuzzRun* currentRun = m_harfbuzzRuns[runIndex].get();
+ FloatPoint firstOffsetOfNextRun = runIndex == numRuns - 1 ? FloatPoint() : m_harfbuzzRuns[runIndex + 1]->offsets()[0];
+ fillGlyphBufferFromHarfBuzzRun(glyphBuffer, currentRun, firstOffsetOfNextRun);
+ }
+ }
+}
+
int HarfBuzzShaper::offsetForPosition(float targetX)
{
int charactersSoFar = 0;
Modified: trunk/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.h (129073 => 129074)
--- trunk/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.h 2012-09-19 23:59:01 UTC (rev 129073)
+++ trunk/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.h 2012-09-20 00:00:45 UTC (rev 129074)
@@ -67,7 +67,7 @@
}
void applyShapeResult(hb_buffer_t*);
- void setGlyphAndAdvance(unsigned index, uint16_t glyphId, float advance);
+ void setGlyphAndPositions(unsigned index, uint16_t glyphId, float advance, float offsetX, float offsetY);
void setWidth(float width) { m_width = width; }
int characterIndexForXPosition(float targetX);
@@ -79,6 +79,8 @@
unsigned numGlyphs() const { return m_numGlyphs; }
uint16_t* glyphs() { return &m_glyphs[0]; }
float* advances() { return &m_advances[0]; }
+ FloatPoint* offsets() { return &m_offsets[0]; }
+ uint16_t* glyphToCharacterIndexes() { return &m_glyphToCharacterIndexes[0]; }
float width() { return m_width; }
private:
@@ -93,16 +95,18 @@
Vector<uint16_t, 256> m_glyphs;
Vector<float, 256> m_advances;
Vector<uint16_t, 256> m_logClusters;
- Vector<uint16_t, 256> m_glyphToCharacterIndex;
+ Vector<uint16_t, 256> m_glyphToCharacterIndexes;
+ Vector<FloatPoint, 256> m_offsets;
float m_width;
};
- bool shouldDrawCharacterAt(int index);
void setFontFeatures();
bool collectHarfBuzzRuns();
- bool shapeHarfBuzzRuns(GlyphBuffer*);
- void setGlyphPositionsForHarfBuzzRun(HarfBuzzRun*, unsigned runIndexInVisualOrder, hb_buffer_t*, GlyphBuffer*, float& pendingGlyphAdvanceX, float& pendingGlyphAdvanceY);
+ bool shapeHarfBuzzRuns();
+ void fillGlyphBuffer(GlyphBuffer*);
+ void fillGlyphBufferFromHarfBuzzRun(GlyphBuffer*, HarfBuzzRun*, FloatPoint& firstOffsetOfNextRun);
+ void setGlyphPositionsForHarfBuzzRun(HarfBuzzRun*, hb_buffer_t*);
GlyphBufferAdvance createGlyphBufferAdvance(float, float);