Changeset 126763 in webkit
- Timestamp:
- Aug 27, 2012, 8:31:56 AM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r126762 r126763 1 2012-08-27 Ned Holbrook <nholbrook@apple.com> 2 3 Improve line breaking performance for complex text 4 https://bugs.webkit.org/show_bug.cgi?id=83045 5 6 Reviewed by Darin Adler. 7 8 Currently RenderBlock::LineBreaker::nextLineBreak assumes that measuring individual words is as cheap 9 as free. This is not the case when dealing with complex text, which benefits from laying out as much 10 text as possible and by reusing that layout when feasible: by doing so this patch improves line 11 breaking by 25% as measured with a simple test app. 12 13 The bulk of this change is modifying ComplexTextController::advance, which previously required the 14 text offset to be strictly increasing and assumed unidirectional text; now it supports random seeking 15 in a naive fashion (by restarting to the beginning) and traverses glyphs in logical order. In the 16 latter case, the presence of any non-LTR runs triggers the population of a mapping from logical to 17 visual run indices. Finally, a new flag has been added which inhibits glyph advances from being split 18 across ligatures (thus causing spurious line breaks). 19 20 A ComplexTextController and its associated TextRun and Font are encapsulated in a TextLayout object, 21 which is instantiated as an opaque object via functions that are no-ops unless building for Mac. A 22 static member function (isNeeded) checks to see whether a TextRun is complex, in order to avoid 23 needless instantiation. It also bails if tabs would be enabled since positional effects are not yet 24 handled in this mode. 25 26 No behavioral changes are expected due to this change, so no new tests. 27 28 * platform/graphics/Font.cpp: 29 (WTF): Define deleteOwnedPtr for TextLayout as calling through destroyLayout; relying on operator delete is not workable as the class does not exist on all platforms. 30 (WTF::WebCore::TextLayout): 31 (WebCore): Implement no-op TextLayout wrappers for non-Mac platforms. 32 (WebCore::Font::createLayout): 33 (WebCore::Font::deleteLayout): 34 (WebCore::Font::width): 35 * platform/graphics/Font.h: 36 (WebCore): Add forward declarations for RenderText and TextLayout. 37 (Font): Add functions for dealing with pointer to TextLayout implementation. 38 (WTF): Declare deleteOwnedPtr for TextLayout. 39 * platform/graphics/mac/ComplexTextController.cpp: 40 (TextLayout): An instance of this class corresponds to a ComplexTextController for a particular TextRun. 41 (WebCore::TextLayout::isNeeded): Used by wrapper to avoid instantiation when complex layout is not required. 42 (WebCore::TextLayout::TextLayout): 43 (WebCore::TextLayout::width): 44 (WebCore::TextLayout::fontWithNoWordSpacing): Helper function to allow initialization of member variable. 45 (WebCore::TextLayout::constructTextRun): Ditto. 46 (WebCore): Implement real TextLayout wrappers for Mac. 47 (WebCore::Font::createLayout): 48 (WebCore::Font::deleteLayout): 49 (WebCore::Font::width): 50 (WebCore::ComplexTextController::ComplexTextController): Initialize m_ltrOnly and reserve initial capacity for m_runIndices. 51 (WebCore::ComplexTextController::indexOfCurrentRun): Return (visual) m_complexTextRuns index corresponding to (logical) m_currentRun, lazily constructing m_runIndices if needed. 52 (WebCore::ComplexTextController::incrementCurrentRun): Return next m_complexTextRuns index in logical order. 53 (WebCore::ComplexTextController::advance): Allow restarting, support for bidi reordering, and option to measure only whole glyphs rather than dividing advances. 54 (WebCore::ComplexTextController::adjustGlyphsAndAdvances): Clear m_ltrOnly on detecting a RTL run. 55 * platform/graphics/mac/ComplexTextController.h: 56 (ComplexTextController): Add m_ltrOnly indicating no bidi reordering, and m_runIndices mapping from runs (logical order) to m_complexTextRuns (visual order). 57 (WebCore::ComplexTextController::ComplexTextRun::indexBegin): 58 (WebCore::ComplexTextController::ComplexTextRun::isLTR): 59 (ComplexTextRun): Add helper functions returning values pertinent to individual runs as opposed to the entire containing line. 60 (WebCore::ComplexTextController::stringBegin): Return first string index. 61 (WebCore::ComplexTextController::stringEnd): Return one past last string index. 62 * platform/graphics/mac/ComplexTextControllerCoreText.mm: Initialize m_indexBegin and m_ltr. 63 (WebCore::ComplexTextController::ComplexTextRun::ComplexTextRun): Initialize m_indexBegin and m_ltr. 64 * rendering/RenderBlock.h: 65 (RenderTextInfo): Add single mapping from RenderText to LazyLineBreakIterator and (possibly null) TextLayout since they are recreated under the same circumstances. 66 * rendering/RenderBlockLineLayout.cpp: 67 (WebCore::RenderBlock::RenderTextInfo::RenderTextInfo): Make non-inline to avoid compilation errors. 68 (WebCore::RenderBlock::RenderTextInfo::~RenderTextInfo): Ditto. 69 (WebCore::RenderBlock::layoutRunsAndFloatsInRange): Allow RenderTextInfo to be reused across calls to nextLineBreak. 70 (WebCore::textWidth): Use TextLayout when supplied for measuring. 71 (WebCore::RenderBlock::LineBreaker::nextLineBreak): 72 1 73 2012-08-27 Nico Weber <thakis@chromium.org> 2 74 -
trunk/Source/WebCore/platform/graphics/Font.cpp
r125766 r126763 40 40 using namespace Unicode; 41 41 42 namespace WTF { 43 44 // allow compilation of OwnPtr<TextLayout> in source files that don't have access to the TextLayout class definition 45 template <> void deleteOwnedPtr<WebCore::TextLayout>(WebCore::TextLayout* ptr) 46 { 47 WebCore::Font::deleteLayout(ptr); 48 } 49 50 } 51 42 52 namespace WebCore { 43 53 … … 198 208 } 199 209 210 #if !PLATFORM(MAC) 211 212 PassOwnPtr<TextLayout> Font::createLayout(RenderText*, float, bool) const 213 { 214 return nullptr; 215 } 216 217 void Font::deleteLayout(TextLayout*) 218 { 219 } 220 221 float Font::width(TextLayout&, unsigned, unsigned) 222 { 223 ASSERT_NOT_REACHED(); 224 return 0; 225 } 226 227 #endif 228 200 229 FloatRect Font::selectionRectForText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const 201 230 { -
trunk/Source/WebCore/platform/graphics/Font.h
r125766 r126763 54 54 class GlyphPageTreeNode; 55 55 class GraphicsContext; 56 class RenderText; 57 class TextLayout; 56 58 class TextRun; 57 59 … … 102 104 float width(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; 103 105 float width(const TextRun&, int& charsConsumed, String& glyphName) const; 106 107 PassOwnPtr<TextLayout> createLayout(RenderText*, float xPos, bool collapseWhiteSpace) const; 108 static void deleteLayout(TextLayout*); 109 static float width(TextLayout&, unsigned from, unsigned len); 104 110 105 111 int offsetForPosition(const TextRun&, float position, bool includePartialGlyphs) const; … … 311 317 } 312 318 313 #endif 319 namespace WTF { 320 321 template <> void deleteOwnedPtr<WebCore::TextLayout>(WebCore::TextLayout*); 322 323 } 324 325 #endif -
trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp
r125437 r126763 28 28 #include "FloatSize.h" 29 29 #include "Font.h" 30 #include "RenderBlock.h" 31 #include "RenderText.h" 30 32 #include "TextBreakIterator.h" 31 33 #include "TextRun.h" … … 38 40 namespace WebCore { 39 41 42 class TextLayout { 43 public: 44 static bool isNeeded(RenderText* text, const Font& font) 45 { 46 TextRun run = RenderBlock::constructTextRun(text, font, text->characters(), text->textLength(), text->style()); 47 return font.codePath(run) == Font::Complex; 48 } 49 50 TextLayout(RenderText* text, const Font& font, float xPos) 51 : m_font(fontWithNoWordSpacing(font)) 52 , m_run(constructTextRun(text, font, xPos)) 53 , m_controller(adoptPtr(new ComplexTextController(&m_font, m_run, true))) 54 { 55 } 56 57 float width(unsigned from, unsigned len) 58 { 59 m_controller->advance(from, 0, ByWholeGlyphs); 60 float beforeWidth = m_controller->runWidthSoFar(); 61 m_controller->advance(from + len, 0, ByWholeGlyphs); 62 float afterWidth = m_controller->runWidthSoFar(); 63 return afterWidth - beforeWidth; 64 } 65 66 private: 67 static Font fontWithNoWordSpacing(const Font& originalFont) 68 { 69 Font font(originalFont); 70 font.setWordSpacing(0); 71 return font; 72 } 73 74 static TextRun constructTextRun(RenderText* text, const Font& font, float xPos) 75 { 76 TextRun run = RenderBlock::constructTextRun(text, font, text->characters(), text->textLength(), text->style()); 77 run.setCharactersLength(text->textLength()); 78 ASSERT(run.charactersLength() >= run.length()); 79 80 run.setXPos(xPos); 81 return run; 82 } 83 84 // ComplexTextController has only references to its Font and TextRun so they must be kept alive here. 85 Font m_font; 86 TextRun m_run; 87 OwnPtr<ComplexTextController> m_controller; 88 }; 89 90 PassOwnPtr<TextLayout> Font::createLayout(RenderText* text, float xPos, bool collapseWhiteSpace) const 91 { 92 if (!collapseWhiteSpace || !TextLayout::isNeeded(text, *this)) 93 return nullptr; 94 return adoptPtr(new TextLayout(text, *this, xPos)); 95 } 96 97 void Font::deleteLayout(TextLayout* layout) 98 { 99 delete layout; 100 } 101 102 float Font::width(TextLayout& layout, unsigned from, unsigned len) 103 { 104 return layout.width(from, len); 105 } 106 40 107 static inline CGFloat roundCGFloat(CGFloat f) 41 108 { … … 55 122 : m_font(*font) 56 123 , m_run(run) 124 , m_isLTROnly(true) 57 125 , m_mayUseNaturalWritingDirection(mayUseNaturalWritingDirection) 58 126 , m_forTextEmphasis(forTextEmphasis) … … 92 160 collectComplexTextRuns(); 93 161 adjustGlyphsAndAdvances(); 162 163 if (!m_isLTROnly) 164 m_runIndices.reserveInitialCapacity(m_complexTextRuns.size()); 94 165 95 166 m_runWidthSoFar = m_leadingExpansion; … … 341 412 } 342 413 343 void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer) 414 unsigned ComplexTextController::indexOfCurrentRun(unsigned& leftmostGlyph) 415 { 416 leftmostGlyph = 0; 417 418 size_t runCount = m_complexTextRuns.size(); 419 if (m_currentRun >= runCount) 420 return runCount; 421 422 if (m_isLTROnly) { 423 for (unsigned i = 0; i < m_currentRun; ++i) 424 leftmostGlyph += m_complexTextRuns[i]->glyphCount(); 425 return m_currentRun; 426 } 427 428 while (m_runIndices.size() <= m_currentRun) { 429 unsigned offset = m_runIndices.isEmpty() ? 0 : stringEnd(*m_complexTextRuns[m_runIndices.last()]); 430 431 for (unsigned i = 0; i < runCount; ++i) { 432 if (offset == stringBegin(*m_complexTextRuns[i])) { 433 m_runIndices.uncheckedAppend(i); 434 break; 435 } 436 } 437 } 438 439 unsigned currentRunIndex = m_runIndices[m_currentRun]; 440 for (unsigned i = 0; i < currentRunIndex; ++i) 441 leftmostGlyph += m_complexTextRuns[i]->glyphCount(); 442 return currentRunIndex; 443 } 444 445 unsigned ComplexTextController::incrementCurrentRun(unsigned& leftmostGlyph) 446 { 447 if (m_isLTROnly) { 448 leftmostGlyph += m_complexTextRuns[m_currentRun++]->glyphCount(); 449 return m_currentRun; 450 } 451 452 m_currentRun++; 453 leftmostGlyph = 0; 454 return indexOfCurrentRun(leftmostGlyph); 455 } 456 457 void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer, GlyphIterationStyle iterationStyle) 344 458 { 345 459 if (static_cast<int>(offset) > m_end) 346 460 offset = m_end; 347 461 348 if (offset <= m_currentCharacter) 349 return; 462 if (offset <= m_currentCharacter) { 463 m_runWidthSoFar = m_leadingExpansion; 464 m_numGlyphsSoFar = 0; 465 m_currentRun = 0; 466 m_glyphInCurrentRun = 0; 467 m_characterInCurrentGlyph = 0; 468 } 350 469 351 470 m_currentCharacter = offset; … … 353 472 size_t runCount = m_complexTextRuns.size(); 354 473 355 bool ltr = m_run.ltr(); 356 357 unsigned k = ltr ? m_numGlyphsSoFar : m_adjustedGlyphs.size() - 1 - m_numGlyphsSoFar; 474 unsigned leftmostGlyph = 0; 475 unsigned currentRunIndex = indexOfCurrentRun(leftmostGlyph); 358 476 while (m_currentRun < runCount) { 359 const ComplexTextRun& complexTextRun = *m_complexTextRuns[ltr ? m_currentRun : runCount - 1 - m_currentRun]; 477 const ComplexTextRun& complexTextRun = *m_complexTextRuns[currentRunIndex]; 478 bool ltr = complexTextRun.isLTR(); 360 479 size_t glyphCount = complexTextRun.glyphCount(); 361 480 unsigned g = ltr ? m_glyphInCurrentRun : glyphCount - 1 - m_glyphInCurrentRun; 481 unsigned k = leftmostGlyph + g; 482 362 483 while (m_glyphInCurrentRun < glyphCount) { 363 484 unsigned glyphStartOffset = complexTextRun.indexAt(g); … … 388 509 ASSERT(m_characterInCurrentGlyph == oldCharacterInCurrentGlyph); 389 510 m_runWidthSoFar += adjustedAdvance.width; 511 } else if (iterationStyle == ByWholeGlyphs) { 512 if (!oldCharacterInCurrentGlyph) 513 m_runWidthSoFar += adjustedAdvance.width; 390 514 } else 391 515 m_runWidthSoFar += adjustedAdvance.width * (m_characterInCurrentGlyph - oldCharacterInCurrentGlyph) / (glyphEndOffset - glyphStartOffset); … … 405 529 } 406 530 } 407 m_currentRun++;531 currentRunIndex = incrementCurrentRun(leftmostGlyph); 408 532 m_glyphInCurrentRun = 0; 409 533 } 410 if (! ltr&& m_numGlyphsSoFar == m_adjustedAdvances.size())534 if (!m_run.ltr() && m_numGlyphsSoFar == m_adjustedAdvances.size()) 411 535 m_runWidthSoFar += m_finalRoundingWidth; 412 536 } … … 421 545 unsigned glyphCount = complexTextRun.glyphCount(); 422 546 const SimpleFontData* fontData = complexTextRun.fontData(); 547 548 if (!complexTextRun.isLTR()) 549 m_isLTROnly = false; 423 550 424 551 const CGGlyph* glyphs = complexTextRun.glyphs(); -
trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.h
r123181 r126763 45 45 class TextRun; 46 46 47 enum GlyphIterationStyle { IncludePartialGlyphs, ByWholeGlyphs }; 48 47 49 // ComplexTextController is responsible for rendering and measuring glyphs for 48 50 // complex scripts on OS X. … … 52 54 53 55 // Advance and emit glyphs up to the specified character. 54 void advance(unsigned to, GlyphBuffer* = 0 );56 void advance(unsigned to, GlyphBuffer* = 0, GlyphIterationStyle = IncludePartialGlyphs); 55 57 56 58 // Compute the character offset for a given x coordinate. … … 90 92 size_t stringLength() const { return m_stringLength; } 91 93 ALWAYS_INLINE CFIndex indexAt(size_t i) const; 94 CFIndex indexBegin() const { return m_indexBegin; } 92 95 CFIndex indexEnd() const { return m_indexEnd; } 93 96 CFIndex endOffsetAt(size_t i) const { ASSERT(!m_isMonotonic); return m_glyphEndOffsets[i]; } 94 97 const CGGlyph* glyphs() const { return m_glyphs; } 95 98 const CGSize* advances() const { return m_advances; } 99 bool isLTR() const { return m_isLTR; } 96 100 bool isMonotonic() const { return m_isMonotonic; } 97 101 void setIsNonMonotonic(); … … 108 112 Vector<CFIndex, 64> m_coreTextIndicesVector; 109 113 const CFIndex* m_coreTextIndices; 114 CFIndex m_indexBegin; 110 115 CFIndex m_indexEnd; 111 116 Vector<CFIndex, 64> m_glyphEndOffsets; … … 114 119 Vector<CGSize, 64> m_advancesVector; 115 120 const CGSize* m_advances; 121 bool m_isLTR; 116 122 bool m_isMonotonic; 117 123 }; 124 125 static unsigned stringBegin(const ComplexTextRun& run) { return run.stringLocation() + run.indexBegin(); } 126 static unsigned stringEnd(const ComplexTextRun& run) { return run.stringLocation() + run.indexEnd(); } 118 127 119 128 void collectComplexTextRuns(); … … 122 131 void adjustGlyphsAndAdvances(); 123 132 133 unsigned indexOfCurrentRun(unsigned& leftmostGlyph); 134 unsigned incrementCurrentRun(unsigned& leftmostGlyph); 135 136 // The default size of this vector was selected as being the smallest power of two greater than 137 // the average (3.5) plus one standard deviation (7.5) of nonzero sizes used on Arabic Wikipedia. 138 Vector<unsigned, 16> m_runIndices; 139 124 140 const Font& m_font; 125 141 const TextRun& m_run; 142 bool m_isLTROnly; 126 143 bool m_mayUseNaturalWritingDirection; 127 144 bool m_forTextEmphasis; -
trunk/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm
r123181 r126763 106 106 , m_stringLocation(stringLocation) 107 107 , m_stringLength(stringLength) 108 , m_indexBegin(runRange.location) 108 109 , m_indexEnd(runRange.location + runRange.length) 110 , m_isLTR(!(CTRunGetStatus(ctRun) & kCTRunStatusRightToLeft)) 109 111 , m_isMonotonic(true) 110 112 { … … 139 141 , m_stringLocation(stringLocation) 140 142 , m_stringLength(stringLength) 143 , m_indexBegin(0) 141 144 , m_indexEnd(stringLength) 145 , m_isLTR(ltr) 142 146 , m_isMonotonic(true) 143 147 { -
trunk/Source/WebCore/rendering/RenderBlock.h
r126605 r126763 30 30 #include "RenderLineBoxList.h" 31 31 #include "RootInlineBox.h" 32 #include "TextBreakIterator.h" 32 33 #include "TextRun.h" 33 34 #include <wtf/OwnPtr.h> … … 43 44 class InlineIterator; 44 45 class LayoutStateMaintainer; 45 class LazyLineBreakIterator;46 46 class LineLayoutState; 47 47 class LineWidth; … … 53 53 class LineInfo; 54 54 class RenderRubyRun; 55 class TextLayout; 55 56 56 57 template <class Iterator, class Run> class BidiResolver; … … 707 708 708 709 // The following functions' implementations are in RenderBlockLineLayout.cpp. 709 typedef std::pair<RenderText*, LazyLineBreakIterator> LineBreakIteratorInfo; 710 struct RenderTextInfo { 711 // Destruction of m_layout requires TextLayout to be a complete type, so the constructor and destructor are made non-inline to avoid compilation errors. 712 RenderTextInfo(); 713 ~RenderTextInfo(); 714 715 RenderText* m_text; 716 OwnPtr<TextLayout> m_layout; 717 LazyLineBreakIterator m_lineBreakIterator; 718 }; 719 710 720 class LineBreaker { 711 721 public: … … 716 726 } 717 727 718 InlineIterator nextLineBreak(InlineBidiResolver&, LineInfo&, LineBreakIteratorInfo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines);728 InlineIterator nextLineBreak(InlineBidiResolver&, LineInfo&, RenderTextInfo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines); 719 729 720 730 bool lineWasHyphenated() { return m_hyphenated; } -
trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp
r126605 r126763 37 37 #include "RenderView.h" 38 38 #include "Settings.h" 39 #include "TextBreakIterator.h"40 39 #include "TrailingFloatsRootInlineBox.h" 41 40 #include "VerticalPositionCache.h" … … 1275 1274 } 1276 1275 1276 RenderBlock::RenderTextInfo::RenderTextInfo() 1277 : m_text(0) 1278 { 1279 } 1280 1281 RenderBlock::RenderTextInfo::~RenderTextInfo() 1282 { 1283 } 1284 1277 1285 void RenderBlock::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, InlineBidiResolver& resolver, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines) 1278 1286 { … … 1282 1290 InlineIterator end = resolver.position(); 1283 1291 bool checkForEndLineMatch = layoutState.endLine(); 1284 LineBreakIteratorInfo lineBreakIteratorInfo;1292 RenderTextInfo renderTextInfo; 1285 1293 VerticalPositionCache verticalPositionCache; 1286 1294 … … 1318 1326 wrapShapeInfo->computeSegmentsForLine(logicalHeight()); 1319 1327 #endif 1320 end = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(), lineBreakIteratorInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines);1328 end = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(), renderTextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines); 1321 1329 if (resolver.position().atEnd()) { 1322 1330 // FIXME: We shouldn't be creating any runs in nextLineBreak to begin with! … … 2018 2026 } 2019 2027 2020 static inline float textWidth(RenderText* text, unsigned from, unsigned len, const Font& font, float xPos, bool isFixedPitch, bool collapseWhiteSpace )2028 static inline float textWidth(RenderText* text, unsigned from, unsigned len, const Font& font, float xPos, bool isFixedPitch, bool collapseWhiteSpace, TextLayout* layout = 0) 2021 2029 { 2022 2030 if (isFixedPitch || (!from && len == text->textLength()) || text->style()->hasTextCombine()) 2023 2031 return text->width(from, len, font, xPos); 2032 2033 if (layout) 2034 return Font::width(*layout, from, len); 2024 2035 2025 2036 TextRun run = RenderBlock::constructTextRun(text, font, text->characters() + from, len, text->style()); … … 2184 2195 } 2185 2196 2186 InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resolver, LineInfo& lineInfo, 2187 LineBreakIteratorInfo& lineBreakIteratorInfo, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines) 2197 InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resolver, LineInfo& lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines) 2188 2198 { 2189 2199 reset(); … … 2424 2434 } 2425 2435 2436 if (renderTextInfo.m_text != t || renderTextInfo.m_lineBreakIterator.string() != t->characters()) { 2437 renderTextInfo.m_text = t; 2438 renderTextInfo.m_layout = f.createLayout(t, width.currentWidth(), collapseWhiteSpace); 2439 renderTextInfo.m_lineBreakIterator.reset(t->characters(), t->textLength(), style->locale()); 2440 } 2441 TextLayout* textLayout = renderTextInfo.m_layout.get(); 2442 2426 2443 for (; current.m_pos < t->textLength(); current.fastIncrementInTextNode()) { 2427 2444 bool previousCharacterIsSpace = currentCharacterIsSpace; … … 2445 2462 wrapW += charWidth; 2446 2463 bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && current.m_pos + 1 < t->textLength() && U16_IS_TRAIL(t->characters()[current.m_pos + 1]); 2447 charWidth = textWidth(t, current.m_pos, midWordBreakIsBeforeSurrogatePair ? 2 : 1, f, width.committedWidth() + wrapW, isFixedPitch, collapseWhiteSpace );2464 charWidth = textWidth(t, current.m_pos, midWordBreakIsBeforeSurrogatePair ? 2 : 1, f, width.committedWidth() + wrapW, isFixedPitch, collapseWhiteSpace, textLayout); 2448 2465 midWordBreak = width.committedWidth() + wrapW + charWidth > width.availableWidth(); 2449 2466 } 2450 2467 2451 if ((lineBreakIteratorInfo.first != t) || (lineBreakIteratorInfo.second.string() != t->characters())) { 2452 lineBreakIteratorInfo.first = t; 2453 lineBreakIteratorInfo.second.reset(t->characters(), t->textLength(), style->locale()); 2454 } 2455 2456 bool betweenWords = c == '\n' || (currWS != PRE && !atStart && isBreakable(lineBreakIteratorInfo.second, current.m_pos, current.m_nextBreakablePosition, breakNBSP) 2468 bool betweenWords = c == '\n' || (currWS != PRE && !atStart && isBreakable(renderTextInfo.m_lineBreakIterator, current.m_pos, current.m_nextBreakablePosition, breakNBSP) 2457 2469 && (style->hyphens() != HyphensNone || (current.previousInSameNode() != softHyphen))); 2458 2470 … … 2476 2488 float additionalTmpW; 2477 2489 if (wordTrailingSpaceWidth && currentCharacterIsSpace) 2478 additionalTmpW = textWidth(t, lastSpace, current.m_pos + 1 - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace ) - wordTrailingSpaceWidth + lastSpaceWordSpacing;2490 additionalTmpW = textWidth(t, lastSpace, current.m_pos + 1 - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, textLayout) - wordTrailingSpaceWidth + lastSpaceWordSpacing; 2479 2491 else 2480 additionalTmpW = textWidth(t, lastSpace, current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace ) + lastSpaceWordSpacing;2492 additionalTmpW = textWidth(t, lastSpace, current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, textLayout) + lastSpaceWordSpacing; 2481 2493 width.addUncommittedWidth(additionalTmpW); 2482 2494 if (!appliedStartWidth) { … … 2495 2507 bool lineWasTooWide = false; 2496 2508 if (width.fitsOnLine() && currentCharacterIsWS && currentStyle->breakOnlyAfterWhiteSpace() && !midWordBreak) { 2497 float charWidth = textWidth(t, current.m_pos, 1, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace ) + (applyWordSpacing ? wordSpacing : 0);2509 float charWidth = textWidth(t, current.m_pos, 1, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, textLayout) + (applyWordSpacing ? wordSpacing : 0); 2498 2510 // Check if line is too big even without the extra space 2499 2511 // at the end of the line. If it is not, do nothing. … … 2621 2633 2622 2634 // IMPORTANT: current.m_pos is > length here! 2623 float additionalTmpW = ignoringSpaces ? 0 : textWidth(t, lastSpace, current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace ) + lastSpaceWordSpacing;2635 float additionalTmpW = ignoringSpaces ? 0 : textWidth(t, lastSpace, current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, textLayout) + lastSpaceWordSpacing; 2624 2636 width.addUncommittedWidth(additionalTmpW + inlineLogicalWidth(current.m_obj, !appliedStartWidth, includeEndWidth)); 2625 2637 includeEndWidth = false;
Note:
See TracChangeset
for help on using the changeset viewer.