Index: Source/platform/fonts/shaping/CachingWordShapeIterator.h |
diff --git a/Source/platform/fonts/shaping/CachingWordShapeIterator.h b/Source/platform/fonts/shaping/CachingWordShapeIterator.h |
index 2321d81c85b47ea976ea3c5a79578111c3cab5fe..d66080e3c5a3246a7e73dd65d23663ef6bb26a12 100644 |
--- a/Source/platform/fonts/shaping/CachingWordShapeIterator.h |
+++ b/Source/platform/fonts/shaping/CachingWordShapeIterator.h |
@@ -38,7 +38,8 @@ class CachingWordShapeIterator { |
public: |
CachingWordShapeIterator(ShapeCache* cache, const TextRun& run, |
const Font* font) |
- : m_shapeCache(cache), m_textRun(run), m_font(font), m_startIndex(0) |
+ : m_shapeCache(cache), m_textRun(run), m_font(font) |
+ , m_widthSoFar(0), m_startIndex(0) |
{ |
ASSERT(font); |
const FontDescription& fontDescription = font->fontDescription(); |
@@ -48,7 +49,7 @@ public: |
// If expansion is used (for justified text) the spacing between words |
// change and thus we need to shape the entire run. |
m_wordResultCachable = !fontDescription.wordSpacing() |
- && !fontDescription.letterSpacing() && !run.allowTabs() |
+ && !fontDescription.letterSpacing() |
&& m_textRun.expansion() == 0.0f; |
// Shaping word by word is faster as each word is cached. If we cannot |
@@ -59,6 +60,9 @@ public: |
bool next(RefPtr<ShapeResult>* wordResult) |
{ |
+ if (UNLIKELY(m_textRun.allowTabs())) |
+ return nextForAllowTabs(wordResult); |
+ |
if (!m_shapeByWord) { |
if (m_startIndex) |
return false; |
@@ -67,26 +71,7 @@ public: |
return *wordResult; |
} |
- unsigned length = m_textRun.length(); |
- if (m_startIndex < length) { |
- if (m_textRun[m_startIndex] == spaceCharacter) { |
- TextRun wordRun = m_textRun.subRun(m_startIndex, 1); |
- *wordResult = shapeWord(wordRun, m_font); |
- m_startIndex++; |
- return true; |
- } |
- |
- for (unsigned i = m_startIndex; ; i++) { |
- if (i == length || m_textRun[i] == spaceCharacter) { |
- TextRun wordRun = m_textRun.subRun(m_startIndex, |
- i - m_startIndex); |
- *wordResult = shapeWord(wordRun, m_font); |
- m_startIndex = i; |
- return true; |
- } |
- } |
- } |
- return false; |
+ return nextWord(wordResult); |
} |
private: |
@@ -109,9 +94,71 @@ private: |
return shapeResult.release(); |
} |
+ bool nextWord(RefPtr<ShapeResult>* wordResult) |
+ { |
+ unsigned length = m_textRun.length(); |
+ if (m_startIndex < length) { |
+ if (m_textRun[m_startIndex] == spaceCharacter |
+ || m_textRun[m_startIndex] == tabulationCharacter) { |
+ TextRun wordRun = m_textRun.subRun(m_startIndex, 1); |
+ *wordResult = shapeWord(wordRun, m_font); |
+ m_startIndex++; |
+ return *wordResult; |
+ } |
+ |
+ return nextUntilCharacterOrTab(wordResult, spaceCharacter); |
+ } |
+ return false; |
+ } |
+ |
+ bool nextUntilCharacterOrTab(RefPtr<ShapeResult>* wordResult, UChar delimiter) |
+ { |
+ unsigned length = m_textRun.length(); |
+ ASSERT(m_startIndex < length); |
+ for (unsigned i = m_startIndex + 1; ; i++) { |
+ if (i == length || m_textRun[i] == delimiter |
+ || m_textRun[i] == tabulationCharacter) { |
+ TextRun wordRun = m_textRun.subRun(m_startIndex, |
+ i - m_startIndex); |
+ m_startIndex = i; |
+ *wordResult = shapeWord(wordRun, m_font); |
+ return *wordResult; |
+ } |
+ } |
+ } |
+ |
+ bool nextForAllowTabs(RefPtr<ShapeResult>* wordResult) |
+ { |
+ unsigned length = m_textRun.length(); |
+ if (m_startIndex >= length) |
+ return false; |
+ |
+ if (UNLIKELY(m_textRun[m_startIndex] == tabulationCharacter)) { |
+ for (unsigned i = m_startIndex + 1; ; i++) { |
+ if (i == length || m_textRun[i] != tabulationCharacter) { |
+ *wordResult = ShapeResult::createForTabulationCharacters( |
+ m_font, m_textRun, m_widthSoFar, i - m_startIndex); |
+ m_startIndex = i; |
+ break; |
+ } |
+ } |
+ } else if (!m_shapeByWord) { |
+ if (!nextUntilCharacterOrTab(wordResult, 0)) |
+ return false; |
+ } else { |
+ if (!nextWord(wordResult)) |
+ return false; |
+ } |
+ if (!*wordResult) |
+ return false; |
+ m_widthSoFar += (*wordResult)->width(); |
+ return true; |
+ } |
+ |
ShapeCache* m_shapeCache; |
const TextRun& m_textRun; |
const Font* m_font; |
+ float m_widthSoFar; // Used only when allowTabs() |
unsigned m_startIndex : 30; |
unsigned m_wordResultCachable : 1; |
unsigned m_shapeByWord : 1; |