Index: Source/core/rendering/RenderText.cpp |
diff --git a/Source/core/rendering/RenderText.cpp b/Source/core/rendering/RenderText.cpp |
index b89ddc756ba895becf08f1e0450384710bd4f2af..1a16f14775f7b3bcc927cb574b8792281f09677c 100644 |
--- a/Source/core/rendering/RenderText.cpp |
+++ b/Source/core/rendering/RenderText.cpp |
@@ -40,7 +40,9 @@ |
#include "core/rendering/RenderView.h" |
#include "core/rendering/break_lines.h" |
#include "platform/geometry/FloatQuad.h" |
+#include "platform/text/BidiResolver.h" |
#include "platform/text/TextBreakIterator.h" |
+#include "platform/text/TextRunIterator.h" |
#include "wtf/text/StringBuffer.h" |
#include "wtf/text/StringBuilder.h" |
#include "wtf/unicode/CharacterNames.h" |
@@ -720,7 +722,7 @@ LayoutRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, Lay |
return style()->isHorizontalWritingMode() ? IntRect(left, top, caretWidth, height) : IntRect(top, left, height, caretWidth); |
} |
-ALWAYS_INLINE float RenderText::widthFromCache(const Font& f, int start, int len, float xPos, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const |
+ALWAYS_INLINE float RenderText::widthFromCache(const Font& f, int start, int len, float xPos, TextDirection textDirection, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const |
{ |
if (style()->hasTextCombine() && isCombineText()) { |
const RenderCombineText* combineText = toRenderCombineText(this); |
@@ -760,7 +762,7 @@ ALWAYS_INLINE float RenderText::widthFromCache(const Font& f, int start, int len |
return w; |
} |
- TextRun run = RenderBlockFlow::constructTextRun(const_cast<RenderText*>(this), f, this, start, len, style()); |
+ TextRun run = RenderBlockFlow::constructTextRun(const_cast<RenderText*>(this), f, this, start, len, style(), textDirection); |
run.setCharactersLength(textLength() - start); |
ASSERT(run.charactersLength() >= run.length()); |
@@ -839,7 +841,7 @@ void RenderText::trimmedPrefWidths(float leadWidth, |
linelen++; |
if (linelen) { |
- lastLineMaxWidth = widthFromCache(f, i, linelen, leadWidth + lastLineMaxWidth, 0, 0); |
+ lastLineMaxWidth = widthFromCache(f, i, linelen, leadWidth + lastLineMaxWidth, LTR, 0, 0); |
if (firstLine) { |
firstLine = false; |
leadWidth = 0; |
@@ -937,11 +939,27 @@ void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si |
bool breakAll = (styleToUse->wordBreak() == BreakAllWordBreak || styleToUse->wordBreak() == BreakWordBreak) && styleToUse->autoWrap(); |
+ TextRun textRun(text()); |
+ BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver; |
+ bidiResolver.setStatus(BidiStatus(textRun.direction(), textRun.directionalOverride())); |
+ bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&textRun, 0)); |
+ bool hardLineBreak = false; |
+ bool reorderRuns = false; |
+ bidiResolver.createBidiRunsForLine(TextRunIterator(&textRun, textRun.length()), NoVisualOverride, hardLineBreak, reorderRuns); |
+ |
+ BidiRunList<BidiCharacterRun>& bidiRuns = bidiResolver.runs(); |
+ BidiCharacterRun* run = bidiRuns.firstRun(); |
for (int i = 0; i < len; i++) { |
UChar c = uncheckedCharacterAt(i); |
- bool previousCharacterIsSpace = isSpace; |
+ while (i > run->stop()) |
+ run = run->next(); |
+ ASSERT(run); |
+ ASSERT(i >= run->start() && i <= run->stop()); |
+ TextDirection textDirection = run->direction(); |
+ |
+ bool previousCharacterIsSpace = isSpace; |
bool isNewline = false; |
if (c == '\n') { |
if (styleToUse->preserveNewline()) { |
@@ -979,7 +997,7 @@ void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si |
lastWordBoundary++; |
continue; |
} else if (c == softHyphen) { |
- currMaxWidth += widthFromCache(f, lastWordBoundary, i - lastWordBoundary, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow); |
+ currMaxWidth += widthFromCache(f, lastWordBoundary, i - lastWordBoundary, leadWidth + currMaxWidth, textDirection, &fallbackFonts, &glyphOverflow); |
if (firstGlyphLeftOverflow < 0) |
firstGlyphLeftOverflow = glyphOverflow.left; |
lastWordBoundary = i + 1; |
@@ -1007,9 +1025,9 @@ void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si |
bool isSpace = (j < len) && c == ' '; |
float w; |
if (wordTrailingSpaceWidth && isSpace) |
- w = widthFromCache(f, i, wordLen + 1, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow) - wordTrailingSpaceWidth; |
+ w = widthFromCache(f, i, wordLen + 1, leadWidth + currMaxWidth, textDirection, &fallbackFonts, &glyphOverflow) - wordTrailingSpaceWidth; |
else { |
- w = widthFromCache(f, i, wordLen, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow); |
+ w = widthFromCache(f, i, wordLen, leadWidth + currMaxWidth, textDirection, &fallbackFonts, &glyphOverflow); |
if (c == softHyphen) |
currMinWidth += hyphenWidth(this, f); |
} |
@@ -1023,7 +1041,7 @@ void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si |
if (lastWordBoundary == i) |
currMaxWidth += w; |
else |
- currMaxWidth += widthFromCache(f, lastWordBoundary, j - lastWordBoundary, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow); |
+ currMaxWidth += widthFromCache(f, lastWordBoundary, j - lastWordBoundary, leadWidth + currMaxWidth, textDirection, &fallbackFonts, &glyphOverflow); |
lastWordBoundary = j; |
} |
@@ -1445,7 +1463,7 @@ void RenderText::positionLineBox(InlineBox* box) |
m_containsReversedText |= !s->isLeftToRightDirection(); |
} |
-float RenderText::width(unsigned from, unsigned len, float xPos, bool firstLine, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const |
+float RenderText::width(unsigned from, unsigned len, float xPos, TextDirection textDirection, bool firstLine, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const |
{ |
if (from >= textLength()) |
return 0; |
@@ -1453,10 +1471,10 @@ float RenderText::width(unsigned from, unsigned len, float xPos, bool firstLine, |
if (from + len > textLength()) |
len = textLength() - from; |
- return width(from, len, style(firstLine)->font(), xPos, fallbackFonts, glyphOverflow); |
+ return width(from, len, style(firstLine)->font(), xPos, textDirection, fallbackFonts, glyphOverflow); |
} |
-float RenderText::width(unsigned from, unsigned len, const Font& f, float xPos, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const |
+float RenderText::width(unsigned from, unsigned len, const Font& f, float xPos, TextDirection textDirection, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const |
{ |
ASSERT(from + len <= textLength()); |
if (!textLength()) |
@@ -1475,10 +1493,11 @@ float RenderText::width(unsigned from, unsigned len, const Font& f, float xPos, |
w = m_maxWidth; |
} else |
w = maxLogicalWidth(); |
- } else |
- w = widthFromCache(f, from, len, xPos, fallbackFonts, glyphOverflow); |
+ } else { |
+ w = widthFromCache(f, from, len, xPos, textDirection, fallbackFonts, glyphOverflow); |
+ } |
} else { |
- TextRun run = RenderBlockFlow::constructTextRun(const_cast<RenderText*>(this), f, this, from, len, style()); |
+ TextRun run = RenderBlockFlow::constructTextRun(const_cast<RenderText*>(this), f, this, from, len, style(), textDirection); |
run.setCharactersLength(textLength() - from); |
ASSERT(run.charactersLength() >= run.length()); |