summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.cpp')
-rw-r--r--Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.cpp141
1 files changed, 53 insertions, 88 deletions
diff --git a/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.cpp b/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.cpp
index b5eda93..99159e6 100644
--- a/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.cpp
+++ b/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.cpp
@@ -50,7 +50,6 @@ ComplexTextController::ComplexTextController(const TextRun& run, unsigned starti
, m_startingX(startingX)
, m_offsetX(m_startingX)
, m_run(getNormalizedTextRun(run, m_normalizedRun, m_normalizedBuffer))
- , m_iterateBackwards(m_run.rtl())
, m_wordSpacingAdjustment(0)
, m_padding(0)
, m_padPerWordBreak(0)
@@ -140,54 +139,33 @@ void ComplexTextController::setPadding(int padding)
void ComplexTextController::reset()
{
- if (m_iterateBackwards)
- m_indexOfNextScriptRun = m_run.length() - 1;
- else
- m_indexOfNextScriptRun = 0;
+ m_indexOfNextScriptRun = 0;
m_offsetX = m_startingX;
}
-void ComplexTextController::setBackwardsIteration(bool isBackwards)
-{
- m_iterateBackwards = isBackwards;
- reset();
-}
-
// Advance to the next script run, returning false when the end of the
// TextRun has been reached.
bool ComplexTextController::nextScriptRun()
{
- if (m_iterateBackwards) {
- // In right-to-left mode we need to render the shaped glyph backwards and
- // also render the script runs themselves backwards. So given a TextRun:
- // AAAAAAACTTTTTTT (A = Arabic, C = Common, T = Thai)
- // we render:
- // TTTTTTCAAAAAAA
- // (and the glyphs in each A, C and T section are backwards too)
- if (!hb_utf16_script_run_prev(&m_numCodePoints, &m_item.item, m_run.characters(), m_run.length(), &m_indexOfNextScriptRun))
- return false;
- m_currentFontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false).fontData;
- } else {
- if (!hb_utf16_script_run_next(&m_numCodePoints, &m_item.item, m_run.characters(), m_run.length(), &m_indexOfNextScriptRun))
- return false;
-
- // It is actually wrong to consider script runs at all in this code.
- // Other WebKit code (e.g. Mac) segments complex text just by finding
- // the longest span of text covered by a single font.
- // But we currently need to call hb_utf16_script_run_next anyway to fill
- // in the harfbuzz data structures to e.g. pick the correct script's shaper.
- // So we allow that to run first, then do a second pass over the range it
- // found and take the largest subregion that stays within a single font.
- m_currentFontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false).fontData;
- unsigned endOfRun;
- for (endOfRun = 1; endOfRun < m_item.item.length; ++endOfRun) {
- const SimpleFontData* nextFontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos + endOfRun], false).fontData;
- if (nextFontData != m_currentFontData)
- break;
- }
- m_item.item.length = endOfRun;
- m_indexOfNextScriptRun = m_item.item.pos + endOfRun;
+ if (!hb_utf16_script_run_next(&m_numCodePoints, &m_item.item, m_run.characters(), m_run.length(), &m_indexOfNextScriptRun))
+ return false;
+
+ // It is actually wrong to consider script runs at all in this code.
+ // Other WebKit code (e.g. Mac) segments complex text just by finding
+ // the longest span of text covered by a single font.
+ // But we currently need to call hb_utf16_script_run_next anyway to fill
+ // in the harfbuzz data structures to e.g. pick the correct script's shaper.
+ // So we allow that to run first, then do a second pass over the range it
+ // found and take the largest subregion that stays within a single font.
+ m_currentFontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false).fontData;
+ unsigned endOfRun;
+ for (endOfRun = 1; endOfRun < m_item.item.length; ++endOfRun) {
+ const SimpleFontData* nextFontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos + endOfRun], false).fontData;
+ if (nextFontData != m_currentFontData)
+ break;
}
+ m_item.item.length = endOfRun;
+ m_indexOfNextScriptRun = m_item.item.pos + endOfRun;
setupFontForScriptRun();
shapeGlyphs();
@@ -273,7 +251,7 @@ void ComplexTextController::shapeGlyphs()
{
// HB_ShapeItem() resets m_item.num_glyphs. If the previous call to
// HB_ShapeItem() used less space than was available, the capacity of
- // the array may be larger than the current value of m_item.num_glyphs.
+ // the array may be larger than the current value of m_item.num_glyphs.
// So, we need to reset the num_glyphs to the capacity of the array.
m_item.num_glyphs = m_glyphsArrayCapacity;
resetGlyphArrays();
@@ -291,62 +269,49 @@ void ComplexTextController::shapeGlyphs()
void ComplexTextController::setGlyphXPositions(bool isRTL)
{
+ const double rtlFlip = isRTL ? -1 : 1;
double position = 0;
- // logClustersIndex indexes logClusters for the first (or last when
- // RTL) codepoint of the current glyph. Each time we advance a glyph,
- // we skip over all the codepoints that contributed to the current
- // glyph.
+
+ // logClustersIndex indexes logClusters for the first codepoint of the current glyph.
+ // Each time we advance a glyph, we skip over all the codepoints that contributed to the current glyph.
int logClustersIndex = 0;
- if (isRTL) {
- logClustersIndex = m_item.num_glyphs - 1;
-
- // Glyphs are stored in logical order, but for layout purposes we
- // always go left to right.
- for (int i = m_item.num_glyphs - 1; i >= 0; --i) {
- if (!m_currentFontData->isZeroWidthSpaceGlyph(m_glyphs16[i])) {
- // Whitespace must be laid out in logical order, so when inserting
- // spaces in RTL (but iterating in LTR order) we must insert spaces
- // _before_ the next glyph.
- if (static_cast<unsigned>(i + 1) >= m_item.num_glyphs || m_item.attributes[i + 1].clusterStart)
- position += m_letterSpacing;
-
- position += determineWordBreakSpacing(logClustersIndex);
- }
-
- m_glyphs16[i] = m_item.glyphs[i];
- double offsetX = truncateFixedPointToInteger(m_item.offsets[i].x);
- m_xPositions[i] = m_offsetX + position + offsetX;
-
- while (logClustersIndex > 0 && logClusters()[logClustersIndex] == i)
- logClustersIndex--;
-
- if (!m_currentFontData->isZeroWidthSpaceGlyph(m_glyphs16[i]))
- position += truncateFixedPointToInteger(m_item.advances[i]);
- }
- } else {
- for (size_t i = 0; i < m_item.num_glyphs; ++i) {
- m_glyphs16[i] = m_item.glyphs[i];
- double offsetX = truncateFixedPointToInteger(m_item.offsets[i].x);
- m_xPositions[i] = m_offsetX + position + offsetX;
+ // Iterate through the glyphs in logical order, flipping for RTL where necessary.
+ // In RTL mode all variables are positive except m_xPositions, which starts from m_offsetX and runs negative.
+ // It is fixed up in a second pass below.
+ for (size_t i = 0; i < m_item.num_glyphs; ++i) {
+ while (static_cast<unsigned>(logClustersIndex) < m_item.item.length && logClusters()[logClustersIndex] < i)
+ logClustersIndex++;
- if (m_currentFontData->isZeroWidthSpaceGlyph(m_glyphs16[i]))
- continue;
+ // If the current glyph is just after a space, add in the word spacing.
+ position += determineWordBreakSpacing(logClustersIndex);
- double advance = truncateFixedPointToInteger(m_item.advances[i]);
+ m_glyphs16[i] = m_item.glyphs[i];
+ double offsetX = truncateFixedPointToInteger(m_item.offsets[i].x);
+ double advance = truncateFixedPointToInteger(m_item.advances[i]);
+ if (isRTL)
+ offsetX -= advance;
- advance += determineWordBreakSpacing(logClustersIndex);
+ m_xPositions[i] = m_offsetX + (position * rtlFlip) + offsetX;
- if (m_item.attributes[i].clusterStart)
- advance += m_letterSpacing;
+ if (m_currentFontData->isZeroWidthSpaceGlyph(m_glyphs16[i]))
+ continue;
- while (static_cast<unsigned>(logClustersIndex) < m_item.item.length && logClusters()[logClustersIndex] == i)
- logClustersIndex++;
+ // At the end of each cluster, add in the letter spacing.
+ if (i + 1 == m_item.num_glyphs || m_item.attributes[i + 1].clusterStart)
+ position += m_letterSpacing;
- position += advance;
- }
+ position += advance;
}
- m_pixelWidth = std::max(position, 0.0);
+ const double width = position;
+
+ // Now that we've computed the total width, do another pass to fix positioning for RTL.
+ if (isRTL) {
+ for (size_t i = 0; i < m_item.num_glyphs; ++i)
+ m_xPositions[i] += width;
+ }
+
+ m_pixelWidth = std::max(width, 0.0);
m_offsetX += m_pixelWidth;
}