Changeset 182325 in webkit
- Timestamp:
- Apr 3, 2015, 11:27:55 AM (10 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r182321 r182325 1 2015-04-03 Zalan Bujtas <zalan@apple.com> 2 3 Simple line layout: Use pre-computed simple line runs to produce innerText content. 4 https://bugs.webkit.org/show_bug.cgi?id=143351 5 6 Reviewed by Antti Koivisto. 7 8 This is in preparation to cover <br> with simple line layout. 9 Runs provide line layout information that can be used to cover hard line break cases. 10 (similar to TextIterator::handleTextBox()) 11 12 Covered by existing tests. 13 14 * editing/TextIterator.cpp: 15 (WebCore::TextIterator::handleTextNode): 16 (WebCore::TextIterator::emitCharacter): 17 (WebCore::TextIterator::emitText): 18 * editing/TextIterator.h: 19 * rendering/SimpleLineLayoutResolver.h: 20 (WebCore::SimpleLineLayout::RunResolver::Run::isEndOfLine): 21 1 22 2015-04-03 Antti Koivisto <antti@apple.com> 2 23 -
trunk/Source/WebCore/editing/TextIterator.cpp
r179143 r182325 45 45 #include "RenderTextFragment.h" 46 46 #include "ShadowRoot.h" 47 #include "SimpleLineLayout.h" 48 #include "SimpleLineLayoutResolver.h" 47 49 #include "TextBoundaries.h" 48 50 #include "TextBreakIterator.h" … … 508 510 509 511 auto& renderer = *textNode.renderer(); 510 512 const auto* previousTextNode = m_lastTextNode; 511 513 m_lastTextNode = &textNode; 512 514 String rendererText = renderer.text(); … … 542 544 } 543 545 544 if ( renderer.simpleLineLayout()) {546 if (const auto* layout = renderer.simpleLineLayout()) { 545 547 if (renderer.style().visibility() != VISIBLE && !(m_behavior & TextIteratorIgnoresStyleVisibility)) 546 548 return true; 547 // This code aims to produce same results as handleTextBox() below so test results don't change. It does not make much logical sense. 548 unsigned end = (m_node == m_endContainer) ? static_cast<unsigned>(m_endOffset) : rendererText.length(); 549 unsigned runEnd = m_offset; 550 unsigned runStart = m_offset; 551 while (runEnd < end && (renderer.style().isCollapsibleWhiteSpace(rendererText[runEnd]) || rendererText[runEnd] == '\t')) 552 ++runEnd; 553 bool addSpaceForPrevious = m_lastTextNodeEndedWithCollapsedSpace && m_lastCharacter && !renderer.style().isCollapsibleWhiteSpace(m_lastCharacter); 554 if (runEnd > runStart || addSpaceForPrevious) { 555 if (runEnd == rendererText.length()) { 556 m_lastTextNodeEndedWithCollapsedSpace = true; 557 return true; 558 } 559 bool addSpaceForCurrent = runStart || (m_lastCharacter && !renderer.style().isCollapsibleWhiteSpace(m_lastCharacter)); 560 if (addSpaceForCurrent || addSpaceForPrevious) { 561 emitCharacter(' ', textNode, nullptr, runStart, runEnd); 562 m_offset = runEnd; 549 // Use the simple layout runs to iterate over the text content. 550 ASSERT(renderer.parent() && is<RenderBlockFlow>(renderer.parent())); 551 const auto& blockFlow = downcast<RenderBlockFlow>(*renderer.parent()); 552 SimpleLineLayout::RunResolver runResolver(blockFlow, *layout); 553 auto range = runResolver.rangeForRenderer(renderer); 554 unsigned endPosition = (m_node == m_endContainer) ? static_cast<unsigned>(m_endOffset) : rendererText.length(); 555 // Simple line layout run positions are all absolute to the parent flow. 556 // Offsetting is required when multiple renderers are present. 557 if (previousTextNode && previousTextNode != &textNode) { 558 const RenderObject& previousRenderer = *previousTextNode->renderer(); 559 if (previousRenderer.parent() != &blockFlow) 560 m_previousTextLengthInFlow = 0; 561 else 562 m_previousTextLengthInFlow += previousTextNode->renderer()->text()->length(); 563 } 564 // Skip to m_offset position. 565 auto it = range.begin(); 566 auto end = range.end(); 567 while (it != end && (*it).end() <= (static_cast<unsigned>(m_offset) + m_previousTextLengthInFlow)) 568 ++it; 569 if (it == end) { 570 // Collapsed trailing whitespace. 571 m_offset = endPosition; 572 m_lastTextNodeEndedWithCollapsedSpace = true; 573 return true; 574 } 575 if (m_nextRunNeedsWhitespace) { 576 emitCharacter(' ', textNode, nullptr, m_offset, m_offset + 1); 577 return false; 578 } 579 const auto run = *it; 580 ASSERT(run.end() - run.start() <= rendererText.length()); 581 // contentStart skips leading whitespace. 582 unsigned contentStart = std::max<unsigned>(m_offset, run.start() - m_previousTextLengthInFlow); 583 unsigned contentEnd = std::min(endPosition, run.end() - m_previousTextLengthInFlow); 584 // Check if whitespace adjustment is needed when crossing renderer boundary. 585 if (previousTextNode && previousTextNode != &textNode) { 586 bool lastCharacterIsNotWhitespace = m_lastCharacter && !renderer.style().isCollapsibleWhiteSpace(m_lastCharacter); 587 bool addTrailingWhitespaceForPrevious = m_lastTextNodeEndedWithCollapsedSpace && lastCharacterIsNotWhitespace; 588 bool leadingWhitespaceIsNeededForCurrent = contentStart > static_cast<unsigned>(m_offset) && lastCharacterIsNotWhitespace; 589 if (addTrailingWhitespaceForPrevious || leadingWhitespaceIsNeededForCurrent) { 590 emitCharacter(' ', textNode, nullptr, m_offset, m_offset + 1); 563 591 return false; 564 592 } 565 runStart = runEnd; 566 } 567 while (runEnd < end && !renderer.style().isCollapsibleWhiteSpace(rendererText[runEnd])) 568 ++runEnd; 569 if (runStart < end) 570 emitText(textNode, renderer, runStart, runEnd); 571 m_offset = runEnd; 572 return runEnd == end; 593 } 594 // \n \t single whitespace characters need replacing so that the new line/tab character won't show up. 595 unsigned stopPosition = contentStart; 596 while (stopPosition < contentEnd) { 597 if (rendererText[stopPosition] == '\n' || rendererText[stopPosition] == '\t') { 598 emitText(textNode, renderer, contentStart, stopPosition); 599 m_offset = stopPosition + 1; 600 m_nextRunNeedsWhitespace = true; 601 return false; 602 } 603 ++stopPosition; 604 } 605 emitText(textNode, renderer, contentStart, contentEnd); 606 // When line ending with collapsed whitespace is present, we need to carry over one whitespace: foo\nbar -> foo bar (otherwise we would end up with foobar). 607 m_nextRunNeedsWhitespace = run.isEndOfLine() && contentEnd < endPosition && renderer.style().isCollapsibleWhiteSpace(rendererText[contentEnd]); 608 m_offset = contentEnd; 609 return static_cast<unsigned>(m_offset) == endPosition; 573 610 } 574 611 … … 1066 1103 m_lastCharacter = character; 1067 1104 m_lastTextNodeEndedWithCollapsedSpace = false; 1105 m_nextRunNeedsWhitespace = false; 1068 1106 } 1069 1107 … … 1090 1128 1091 1129 m_lastTextNodeEndedWithCollapsedSpace = false; 1130 m_nextRunNeedsWhitespace = false; 1092 1131 m_hasEmitted = true; 1093 1132 } -
trunk/Source/WebCore/editing/TextIterator.h
r177588 r182325 164 164 UChar m_lastCharacter; 165 165 166 // Used to do simple line layout run logic. 167 bool m_nextRunNeedsWhitespace { false }; 168 unsigned m_previousTextLengthInFlow { 0 }; 166 169 // Used when text boxes are out of order (Hebrew/Arabic with embedded LTR text) 167 170 Vector<InlineTextBox*> m_sortedTextBoxes; -
trunk/Source/WebCore/rendering/SimpleLineLayoutResolver.h
r181290 r182325 64 64 FloatPoint baseline() const; 65 65 StringView text() const; 66 bool isEndOfLine() const; 66 67 67 68 unsigned lineIndex() const; … … 159 160 } 160 161 162 inline bool RunResolver::Run::isEndOfLine() const 163 { 164 return m_iterator.simpleRun().isEndOfLine; 165 } 166 161 167 inline unsigned RunResolver::Run::lineIndex() const 162 168 {
Note:
See TracChangeset
for help on using the changeset viewer.