| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All r
ights reserved. | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All r
ights reserved. |
| 3 * Copyright (C) 2005 Alexey Proskuryakov. | 3 * Copyright (C) 2005 Alexey Proskuryakov. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 | 196 |
| 197 TextIterator::~TextIterator() | 197 TextIterator::~TextIterator() |
| 198 { | 198 { |
| 199 } | 199 } |
| 200 | 200 |
| 201 bool TextIterator::isInsideReplacedElement() const | 201 bool TextIterator::isInsideReplacedElement() const |
| 202 { | 202 { |
| 203 if (atEnd() || length() != 1 || !m_node) | 203 if (atEnd() || length() != 1 || !m_node) |
| 204 return false; | 204 return false; |
| 205 | 205 |
| 206 LayoutObject* renderer = m_node->renderer(); | 206 LayoutObject* renderer = m_node->layoutObject(); |
| 207 return renderer && renderer->isReplaced(); | 207 return renderer && renderer->isReplaced(); |
| 208 } | 208 } |
| 209 | 209 |
| 210 void TextIterator::advance() | 210 void TextIterator::advance() |
| 211 { | 211 { |
| 212 if (m_shouldStop) | 212 if (m_shouldStop) |
| 213 return; | 213 return; |
| 214 | 214 |
| 215 ASSERT(!m_node || !m_node->document().needsRenderTreeUpdate()); | 215 ASSERT(!m_node || !m_node->document().needsRenderTreeUpdate()); |
| 216 | 216 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 // if the range ends at offset 0 of an element, represent the | 252 // if the range ends at offset 0 of an element, represent the |
| 253 // position, but not the content, of that element e.g. if the | 253 // position, but not the content, of that element e.g. if the |
| 254 // node is a blockflow element, emit a newline that | 254 // node is a blockflow element, emit a newline that |
| 255 // precedes the element | 255 // precedes the element |
| 256 if (m_node == m_endContainer && !m_endOffset) { | 256 if (m_node == m_endContainer && !m_endOffset) { |
| 257 representNodeOffsetZero(); | 257 representNodeOffsetZero(); |
| 258 m_node = nullptr; | 258 m_node = nullptr; |
| 259 return; | 259 return; |
| 260 } | 260 } |
| 261 | 261 |
| 262 LayoutObject* renderer = m_node->renderer(); | 262 LayoutObject* renderer = m_node->layoutObject(); |
| 263 if (!renderer) { | 263 if (!renderer) { |
| 264 if (m_node->isShadowRoot()) { | 264 if (m_node->isShadowRoot()) { |
| 265 // A shadow root doesn't have a renderer, but we want to visit c
hildren anyway. | 265 // A shadow root doesn't have a renderer, but we want to visit c
hildren anyway. |
| 266 m_iterationProgress = m_iterationProgress < HandledNode ? Handle
dNode : m_iterationProgress; | 266 m_iterationProgress = m_iterationProgress < HandledNode ? Handle
dNode : m_iterationProgress; |
| 267 } else { | 267 } else { |
| 268 m_iterationProgress = HandledChildren; | 268 m_iterationProgress = HandledChildren; |
| 269 } | 269 } |
| 270 } else { | 270 } else { |
| 271 // Enter author shadow roots, from youngest, if any and if necessary
. | 271 // Enter author shadow roots, from youngest, if any and if necessary
. |
| 272 if (m_iterationProgress < HandledOpenShadowRoots) { | 272 if (m_iterationProgress < HandledOpenShadowRoots) { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 if (!next) { | 329 if (!next) { |
| 330 // 2. If we've already iterated children or they are not available,
go to the next sibling node. | 330 // 2. If we've already iterated children or they are not available,
go to the next sibling node. |
| 331 next = m_node->nextSibling(); | 331 next = m_node->nextSibling(); |
| 332 if (!next) { | 332 if (!next) { |
| 333 // 3. If we are at the last child, go up the node tree until we
find a next sibling. | 333 // 3. If we are at the last child, go up the node tree until we
find a next sibling. |
| 334 bool pastEnd = NodeTraversal::next(*m_node) == m_pastEndNode; | 334 bool pastEnd = NodeTraversal::next(*m_node) == m_pastEndNode; |
| 335 ContainerNode* parentNode = m_node->parentNode(); | 335 ContainerNode* parentNode = m_node->parentNode(); |
| 336 while (!next && parentNode) { | 336 while (!next && parentNode) { |
| 337 if ((pastEnd && parentNode == m_endContainer) || m_endContai
ner->isDescendantOf(parentNode)) | 337 if ((pastEnd && parentNode == m_endContainer) || m_endContai
ner->isDescendantOf(parentNode)) |
| 338 return; | 338 return; |
| 339 bool haveRenderer = m_node->renderer(); | 339 bool haveRenderer = m_node->layoutObject(); |
| 340 m_node = parentNode; | 340 m_node = parentNode; |
| 341 m_fullyClippedStack.pop(); | 341 m_fullyClippedStack.pop(); |
| 342 parentNode = m_node->parentNode(); | 342 parentNode = m_node->parentNode(); |
| 343 if (haveRenderer) | 343 if (haveRenderer) |
| 344 exitNode(); | 344 exitNode(); |
| 345 if (m_positionNode) { | 345 if (m_positionNode) { |
| 346 m_iterationProgress = HandledChildren; | 346 m_iterationProgress = HandledChildren; |
| 347 return; | 347 return; |
| 348 } | 348 } |
| 349 next = m_node->nextSibling(); | 349 next = m_node->nextSibling(); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 439 builder.append(string(), positionStartOffset() + position, lengthToAppen
d); | 439 builder.append(string(), positionStartOffset() + position, lengthToAppen
d); |
| 440 } | 440 } |
| 441 } | 441 } |
| 442 | 442 |
| 443 bool TextIterator::handleTextNode() | 443 bool TextIterator::handleTextNode() |
| 444 { | 444 { |
| 445 if (m_fullyClippedStack.top() && !m_ignoresStyleVisibility) | 445 if (m_fullyClippedStack.top() && !m_ignoresStyleVisibility) |
| 446 return false; | 446 return false; |
| 447 | 447 |
| 448 Text* textNode = toText(m_node); | 448 Text* textNode = toText(m_node); |
| 449 LayoutText* renderer = textNode->renderer(); | 449 LayoutText* renderer = textNode->layoutObject(); |
| 450 | 450 |
| 451 m_lastTextNode = textNode; | 451 m_lastTextNode = textNode; |
| 452 String str = renderer->text(); | 452 String str = renderer->text(); |
| 453 | 453 |
| 454 // handle pre-formatted text | 454 // handle pre-formatted text |
| 455 if (!renderer->style()->collapseWhiteSpace()) { | 455 if (!renderer->style()->collapseWhiteSpace()) { |
| 456 int runStart = m_offset; | 456 int runStart = m_offset; |
| 457 if (m_lastTextNodeEndedWithCollapsedSpace && hasVisibleTextNode(renderer
)) { | 457 if (m_lastTextNodeEndedWithCollapsedSpace && hasVisibleTextNode(renderer
)) { |
| 458 emitCharacter(space, textNode, 0, runStart, runStart); | 458 emitCharacter(space, textNode, 0, runStart, runStart); |
| 459 return false; | 459 return false; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 470 } | 470 } |
| 471 if (renderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibil
ity) | 471 if (renderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibil
ity) |
| 472 return false; | 472 return false; |
| 473 int strLength = str.length(); | 473 int strLength = str.length(); |
| 474 int end = (textNode == m_endContainer) ? m_endOffset : INT_MAX; | 474 int end = (textNode == m_endContainer) ? m_endOffset : INT_MAX; |
| 475 int runEnd = std::min(strLength, end); | 475 int runEnd = std::min(strLength, end); |
| 476 | 476 |
| 477 if (runStart >= runEnd) | 477 if (runStart >= runEnd) |
| 478 return true; | 478 return true; |
| 479 | 479 |
| 480 emitText(textNode, textNode->renderer(), runStart, runEnd); | 480 emitText(textNode, textNode->layoutObject(), runStart, runEnd); |
| 481 return true; | 481 return true; |
| 482 } | 482 } |
| 483 | 483 |
| 484 if (renderer->firstTextBox()) | 484 if (renderer->firstTextBox()) |
| 485 m_textBox = renderer->firstTextBox(); | 485 m_textBox = renderer->firstTextBox(); |
| 486 | 486 |
| 487 bool shouldHandleFirstLetter = !m_handledFirstLetter && renderer->isTextFrag
ment() && !m_offset; | 487 bool shouldHandleFirstLetter = !m_handledFirstLetter && renderer->isTextFrag
ment() && !m_offset; |
| 488 if (shouldHandleFirstLetter) | 488 if (shouldHandleFirstLetter) |
| 489 handleTextNodeFirstLetter(toLayoutTextFragment(renderer)); | 489 handleTextNodeFirstLetter(toLayoutTextFragment(renderer)); |
| 490 | 490 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 508 m_sortedTextBoxesPosition = 0; | 508 m_sortedTextBoxesPosition = 0; |
| 509 m_textBox = m_sortedTextBoxes.isEmpty() ? 0 : m_sortedTextBoxes[0]; | 509 m_textBox = m_sortedTextBoxes.isEmpty() ? 0 : m_sortedTextBoxes[0]; |
| 510 } | 510 } |
| 511 | 511 |
| 512 handleTextBox(); | 512 handleTextBox(); |
| 513 return true; | 513 return true; |
| 514 } | 514 } |
| 515 | 515 |
| 516 void TextIterator::handleTextBox() | 516 void TextIterator::handleTextBox() |
| 517 { | 517 { |
| 518 LayoutText* renderer = m_firstLetterText ? m_firstLetterText.get() : toLayou
tText(m_node->renderer()); | 518 LayoutText* renderer = m_firstLetterText ? m_firstLetterText.get() : toLayou
tText(m_node->layoutObject()); |
| 519 | 519 |
| 520 if (renderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility)
{ | 520 if (renderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility)
{ |
| 521 m_textBox = 0; | 521 m_textBox = 0; |
| 522 } else { | 522 } else { |
| 523 String str = renderer->text(); | 523 String str = renderer->text(); |
| 524 unsigned start = m_offset; | 524 unsigned start = m_offset; |
| 525 unsigned end = (m_node == m_endContainer) ? static_cast<unsigned>(m_endO
ffset) : INT_MAX; | 525 unsigned end = (m_node == m_endContainer) ? static_cast<unsigned>(m_endO
ffset) : INT_MAX; |
| 526 while (m_textBox) { | 526 while (m_textBox) { |
| 527 unsigned textBoxStart = m_textBox->start(); | 527 unsigned textBoxStart = m_textBox->start(); |
| 528 unsigned runStart = std::max(textBoxStart, start); | 528 unsigned runStart = std::max(textBoxStart, start); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 552 nextTextBox = m_sortedTextBoxes[m_sortedTextBoxesPosition +
1]; | 552 nextTextBox = m_sortedTextBoxes[m_sortedTextBoxesPosition +
1]; |
| 553 } else { | 553 } else { |
| 554 nextTextBox = m_textBox->nextTextBox(); | 554 nextTextBox = m_textBox->nextTextBox(); |
| 555 } | 555 } |
| 556 | 556 |
| 557 // FIXME: Based on the outcome of crbug.com/446502 it's possible we
can | 557 // FIXME: Based on the outcome of crbug.com/446502 it's possible we
can |
| 558 // remove this block. The reason we new it now is because BIDI and | 558 // remove this block. The reason we new it now is because BIDI and |
| 559 // FirstLetter seem to have different ideas of where things can sp
lit. | 559 // FirstLetter seem to have different ideas of where things can sp
lit. |
| 560 // FirstLetter takes the punctuation + first letter, and BIDI will | 560 // FirstLetter takes the punctuation + first letter, and BIDI will |
| 561 // split out the punctuation and possibly reorder it. | 561 // split out the punctuation and possibly reorder it. |
| 562 if (nextTextBox && nextTextBox->renderer() != renderer) { | 562 if (nextTextBox && nextTextBox->layoutObject() != renderer) { |
| 563 m_textBox = 0; | 563 m_textBox = 0; |
| 564 return; | 564 return; |
| 565 } | 565 } |
| 566 ASSERT(!nextTextBox || nextTextBox->renderer() == renderer); | 566 ASSERT(!nextTextBox || nextTextBox->layoutObject() == renderer); |
| 567 | 567 |
| 568 if (runStart < runEnd) { | 568 if (runStart < runEnd) { |
| 569 // Handle either a single newline character (which becomes a spa
ce), | 569 // Handle either a single newline character (which becomes a spa
ce), |
| 570 // or a run of characters that does not include a newline. | 570 // or a run of characters that does not include a newline. |
| 571 // This effectively translates newlines to spaces without copyin
g the text. | 571 // This effectively translates newlines to spaces without copyin
g the text. |
| 572 if (str[runStart] == '\n') { | 572 if (str[runStart] == '\n') { |
| 573 emitCharacter(space, m_node, 0, runStart, runStart + 1); | 573 emitCharacter(space, m_node, 0, runStart, runStart + 1); |
| 574 m_offset = runStart + 1; | 574 m_offset = runStart + 1; |
| 575 } else { | 575 } else { |
| 576 size_t subrunEnd = str.find('\n', runStart); | 576 size_t subrunEnd = str.find('\n', runStart); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 616 { | 616 { |
| 617 m_handledFirstLetter = true; | 617 m_handledFirstLetter = true; |
| 618 | 618 |
| 619 if (!renderer->isRemainingTextRenderer()) | 619 if (!renderer->isRemainingTextRenderer()) |
| 620 return; | 620 return; |
| 621 | 621 |
| 622 FirstLetterPseudoElement* firstLetterElement = renderer->firstLetterPseudoEl
ement(); | 622 FirstLetterPseudoElement* firstLetterElement = renderer->firstLetterPseudoEl
ement(); |
| 623 if (!firstLetterElement) | 623 if (!firstLetterElement) |
| 624 return; | 624 return; |
| 625 | 625 |
| 626 LayoutObject* pseudoRenderer = firstLetterElement->renderer(); | 626 LayoutObject* pseudoRenderer = firstLetterElement->layoutObject(); |
| 627 if (pseudoRenderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisib
ility) | 627 if (pseudoRenderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisib
ility) |
| 628 return; | 628 return; |
| 629 | 629 |
| 630 LayoutObject* firstLetter = pseudoRenderer->slowFirstChild(); | 630 LayoutObject* firstLetter = pseudoRenderer->slowFirstChild(); |
| 631 ASSERT(firstLetter); | 631 ASSERT(firstLetter); |
| 632 | 632 |
| 633 m_remainingTextBox = m_textBox; | 633 m_remainingTextBox = m_textBox; |
| 634 m_textBox = toLayoutText(firstLetter)->firstTextBox(); | 634 m_textBox = toLayoutText(firstLetter)->firstTextBox(); |
| 635 m_sortedTextBoxes.clear(); | 635 m_sortedTextBoxes.clear(); |
| 636 m_firstLetterText = toLayoutText(firstLetter); | 636 m_firstLetterText = toLayoutText(firstLetter); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 648 if (isHTMLInputElement(toHTMLElement(*m_node)) && toHTMLInputElement(*m_node
).isImage()) | 648 if (isHTMLInputElement(toHTMLElement(*m_node)) && toHTMLInputElement(*m_node
).isImage()) |
| 649 return true; | 649 return true; |
| 650 return false; | 650 return false; |
| 651 } | 651 } |
| 652 | 652 |
| 653 bool TextIterator::handleReplacedElement() | 653 bool TextIterator::handleReplacedElement() |
| 654 { | 654 { |
| 655 if (m_fullyClippedStack.top()) | 655 if (m_fullyClippedStack.top()) |
| 656 return false; | 656 return false; |
| 657 | 657 |
| 658 LayoutObject* renderer = m_node->renderer(); | 658 LayoutObject* renderer = m_node->layoutObject(); |
| 659 if (renderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility) | 659 if (renderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility) |
| 660 return false; | 660 return false; |
| 661 | 661 |
| 662 if (m_emitsObjectReplacementCharacter) { | 662 if (m_emitsObjectReplacementCharacter) { |
| 663 emitCharacter(objectReplacementCharacter, m_node->parentNode(), m_node,
0, 1); | 663 emitCharacter(objectReplacementCharacter, m_node->parentNode(), m_node,
0, 1); |
| 664 return true; | 664 return true; |
| 665 } | 665 } |
| 666 | 666 |
| 667 if (m_lastTextNodeEndedWithCollapsedSpace) { | 667 if (m_lastTextNodeEndedWithCollapsedSpace) { |
| 668 emitCharacter(space, m_lastTextNode->parentNode(), m_lastTextNode, 1, 1)
; | 668 emitCharacter(space, m_lastTextNode->parentNode(), m_lastTextNode, 1, 1)
; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 711 return true; | 711 return true; |
| 712 | 712 |
| 713 if (!renderer->isTextFragment()) | 713 if (!renderer->isTextFragment()) |
| 714 return false; | 714 return false; |
| 715 | 715 |
| 716 LayoutTextFragment* fragment = toLayoutTextFragment(renderer); | 716 LayoutTextFragment* fragment = toLayoutTextFragment(renderer); |
| 717 if (!fragment->isRemainingTextRenderer()) | 717 if (!fragment->isRemainingTextRenderer()) |
| 718 return false; | 718 return false; |
| 719 | 719 |
| 720 ASSERT(fragment->firstLetterPseudoElement()); | 720 ASSERT(fragment->firstLetterPseudoElement()); |
| 721 LayoutObject* pseudoElementRenderer = fragment->firstLetterPseudoElement()->
renderer(); | 721 LayoutObject* pseudoElementRenderer = fragment->firstLetterPseudoElement()->
layoutObject(); |
| 722 return pseudoElementRenderer && pseudoElementRenderer->style()->visibility()
== VISIBLE; | 722 return pseudoElementRenderer && pseudoElementRenderer->style()->visibility()
== VISIBLE; |
| 723 } | 723 } |
| 724 | 724 |
| 725 bool TextIterator::shouldEmitTabBeforeNode(Node* node) | 725 bool TextIterator::shouldEmitTabBeforeNode(Node* node) |
| 726 { | 726 { |
| 727 LayoutObject* r = node->renderer(); | 727 LayoutObject* r = node->layoutObject(); |
| 728 | 728 |
| 729 // Table cells are delimited by tabs. | 729 // Table cells are delimited by tabs. |
| 730 if (!r || !isTableCell(node)) | 730 if (!r || !isTableCell(node)) |
| 731 return false; | 731 return false; |
| 732 | 732 |
| 733 // Want a tab before every cell other than the first one | 733 // Want a tab before every cell other than the first one |
| 734 LayoutTableCell* rc = toLayoutTableCell(r); | 734 LayoutTableCell* rc = toLayoutTableCell(r); |
| 735 LayoutTable* t = rc->table(); | 735 LayoutTable* t = rc->table(); |
| 736 return t && (t->cellBefore(rc) || t->cellAbove(rc)); | 736 return t && (t->cellBefore(rc) || t->cellAbove(rc)); |
| 737 } | 737 } |
| 738 | 738 |
| 739 bool TextIterator::shouldEmitNewlineForNode(Node* node, bool emitsOriginalText) | 739 bool TextIterator::shouldEmitNewlineForNode(Node* node, bool emitsOriginalText) |
| 740 { | 740 { |
| 741 LayoutObject* renderer = node->renderer(); | 741 LayoutObject* renderer = node->layoutObject(); |
| 742 | 742 |
| 743 if (renderer ? !renderer->isBR() : !isHTMLBRElement(node)) | 743 if (renderer ? !renderer->isBR() : !isHTMLBRElement(node)) |
| 744 return false; | 744 return false; |
| 745 return emitsOriginalText || !(node->isInShadowTree() && isHTMLInputElement(*
node->shadowHost())); | 745 return emitsOriginalText || !(node->isInShadowTree() && isHTMLInputElement(*
node->shadowHost())); |
| 746 } | 746 } |
| 747 | 747 |
| 748 static bool shouldEmitNewlinesBeforeAndAfterNode(Node& node) | 748 static bool shouldEmitNewlinesBeforeAndAfterNode(Node& node) |
| 749 { | 749 { |
| 750 // Block flow (versus inline flow) is represented by having | 750 // Block flow (versus inline flow) is represented by having |
| 751 // a newline both before and after the element. | 751 // a newline both before and after the element. |
| 752 LayoutObject* r = node.renderer(); | 752 LayoutObject* r = node.layoutObject(); |
| 753 if (!r) { | 753 if (!r) { |
| 754 return (node.hasTagName(blockquoteTag) | 754 return (node.hasTagName(blockquoteTag) |
| 755 || node.hasTagName(ddTag) | 755 || node.hasTagName(ddTag) |
| 756 || node.hasTagName(divTag) | 756 || node.hasTagName(divTag) |
| 757 || node.hasTagName(dlTag) | 757 || node.hasTagName(dlTag) |
| 758 || node.hasTagName(dtTag) | 758 || node.hasTagName(dtTag) |
| 759 || node.hasTagName(h1Tag) | 759 || node.hasTagName(h1Tag) |
| 760 || node.hasTagName(h2Tag) | 760 || node.hasTagName(h2Tag) |
| 761 || node.hasTagName(h3Tag) | 761 || node.hasTagName(h3Tag) |
| 762 || node.hasTagName(h4Tag) | 762 || node.hasTagName(h4Tag) |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 797 bool TextIterator::shouldEmitNewlineAfterNode(Node& node) | 797 bool TextIterator::shouldEmitNewlineAfterNode(Node& node) |
| 798 { | 798 { |
| 799 // FIXME: It should be better but slower to create a VisiblePosition here. | 799 // FIXME: It should be better but slower to create a VisiblePosition here. |
| 800 if (!shouldEmitNewlinesBeforeAndAfterNode(node)) | 800 if (!shouldEmitNewlinesBeforeAndAfterNode(node)) |
| 801 return false; | 801 return false; |
| 802 // Check if this is the very last renderer in the document. | 802 // Check if this is the very last renderer in the document. |
| 803 // If so, then we should not emit a newline. | 803 // If so, then we should not emit a newline. |
| 804 Node* next = &node; | 804 Node* next = &node; |
| 805 do { | 805 do { |
| 806 next = NodeTraversal::nextSkippingChildren(*next); | 806 next = NodeTraversal::nextSkippingChildren(*next); |
| 807 if (next && next->renderer()) | 807 if (next && next->layoutObject()) |
| 808 return true; | 808 return true; |
| 809 } while (next); | 809 } while (next); |
| 810 return false; | 810 return false; |
| 811 } | 811 } |
| 812 | 812 |
| 813 bool TextIterator::shouldEmitNewlineBeforeNode(Node& node) | 813 bool TextIterator::shouldEmitNewlineBeforeNode(Node& node) |
| 814 { | 814 { |
| 815 return shouldEmitNewlinesBeforeAndAfterNode(node); | 815 return shouldEmitNewlinesBeforeAndAfterNode(node); |
| 816 } | 816 } |
| 817 | 817 |
| 818 static bool shouldEmitExtraNewlineForNode(Node* node) | 818 static bool shouldEmitExtraNewlineForNode(Node* node) |
| 819 { | 819 { |
| 820 // When there is a significant collapsed bottom margin, emit an extra | 820 // When there is a significant collapsed bottom margin, emit an extra |
| 821 // newline for a more realistic result. We end up getting the right | 821 // newline for a more realistic result. We end up getting the right |
| 822 // result even without margin collapsing. For example: <div><p>text</p></div
> | 822 // result even without margin collapsing. For example: <div><p>text</p></div
> |
| 823 // will work right even if both the <div> and the <p> have bottom margins. | 823 // will work right even if both the <div> and the <p> have bottom margins. |
| 824 LayoutObject* r = node->renderer(); | 824 LayoutObject* r = node->layoutObject(); |
| 825 if (!r || !r->isBox()) | 825 if (!r || !r->isBox()) |
| 826 return false; | 826 return false; |
| 827 | 827 |
| 828 // NOTE: We only do this for a select set of nodes, and fwiw WinIE appears | 828 // NOTE: We only do this for a select set of nodes, and fwiw WinIE appears |
| 829 // not to do this at all | 829 // not to do this at all |
| 830 if (node->hasTagName(h1Tag) | 830 if (node->hasTagName(h1Tag) |
| 831 || node->hasTagName(h2Tag) | 831 || node->hasTagName(h2Tag) |
| 832 || node->hasTagName(h3Tag) | 832 || node->hasTagName(h3Tag) |
| 833 || node->hasTagName(h4Tag) | 833 || node->hasTagName(h4Tag) |
| 834 || node->hasTagName(h5Tag) | 834 || node->hasTagName(h5Tag) |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 883 // emit after a preceding block. We chose not to emit (m_hasEmitted is false
), | 883 // emit after a preceding block. We chose not to emit (m_hasEmitted is false
), |
| 884 // so don't second guess that now. | 884 // so don't second guess that now. |
| 885 // NOTE: Is this really correct when m_node is not a leftmost descendant? Pr
obably | 885 // NOTE: Is this really correct when m_node is not a leftmost descendant? Pr
obably |
| 886 // immaterial since we likely would have already emitted something by now. | 886 // immaterial since we likely would have already emitted something by now. |
| 887 if (!m_startOffset) | 887 if (!m_startOffset) |
| 888 return false; | 888 return false; |
| 889 | 889 |
| 890 // If this node is unrendered or invisible the VisiblePosition checks below
won't have much meaning. | 890 // If this node is unrendered or invisible the VisiblePosition checks below
won't have much meaning. |
| 891 // Additionally, if the range we are iterating over contains huge sections o
f unrendered content, | 891 // Additionally, if the range we are iterating over contains huge sections o
f unrendered content, |
| 892 // we would create VisiblePositions on every call to this function without t
his check. | 892 // we would create VisiblePositions on every call to this function without t
his check. |
| 893 if (!m_node->renderer() || m_node->renderer()->style()->visibility() != VISI
BLE | 893 if (!m_node->layoutObject() || m_node->layoutObject()->style()->visibility()
!= VISIBLE |
| 894 || (m_node->renderer()->isLayoutBlockFlow() && !toLayoutBlock(m_node->re
nderer())->size().height() && !isHTMLBodyElement(*m_node))) | 894 || (m_node->layoutObject()->isLayoutBlockFlow() && !toLayoutBlock(m_node
->layoutObject())->size().height() && !isHTMLBodyElement(*m_node))) |
| 895 return false; | 895 return false; |
| 896 | 896 |
| 897 // The startPos.isNotNull() check is needed because the start could be befor
e the body, | 897 // The startPos.isNotNull() check is needed because the start could be befor
e the body, |
| 898 // and in that case we'll get null. We don't want to put in newlines at the
start in that case. | 898 // and in that case we'll get null. We don't want to put in newlines at the
start in that case. |
| 899 // The currPos.isNotNull() check is needed because positions in non-HTML con
tent | 899 // The currPos.isNotNull() check is needed because positions in non-HTML con
tent |
| 900 // (like SVG) do not have visible positions, and we don't want to emit for t
hem either. | 900 // (like SVG) do not have visible positions, and we don't want to emit for t
hem either. |
| 901 VisiblePosition startPos = VisiblePosition(Position(m_startContainer, m_star
tOffset, Position::PositionIsOffsetInAnchor), DOWNSTREAM); | 901 VisiblePosition startPos = VisiblePosition(Position(m_startContainer, m_star
tOffset, Position::PositionIsOffsetInAnchor), DOWNSTREAM); |
| 902 VisiblePosition currPos = VisiblePosition(positionBeforeNode(m_node), DOWNST
REAM); | 902 VisiblePosition currPos = VisiblePosition(positionBeforeNode(m_node), DOWNST
REAM); |
| 903 return startPos.isNotNull() && currPos.isNotNull() && !inSameLine(startPos,
currPos); | 903 return startPos.isNotNull() && currPos.isNotNull() && !inSameLine(startPos,
currPos); |
| 904 } | 904 } |
| 905 | 905 |
| 906 bool TextIterator::shouldEmitSpaceBeforeAndAfterNode(Node* node) | 906 bool TextIterator::shouldEmitSpaceBeforeAndAfterNode(Node* node) |
| 907 { | 907 { |
| 908 return isRenderedTableElement(node) && (node->renderer()->isInline() || m_em
itsCharactersBetweenAllVisiblePositions); | 908 return isRenderedTableElement(node) && (node->layoutObject()->isInline() ||
m_emitsCharactersBetweenAllVisiblePositions); |
| 909 } | 909 } |
| 910 | 910 |
| 911 void TextIterator::representNodeOffsetZero() | 911 void TextIterator::representNodeOffsetZero() |
| 912 { | 912 { |
| 913 // Emit a character to show the positioning of m_node. | 913 // Emit a character to show the positioning of m_node. |
| 914 | 914 |
| 915 // When we haven't been emitting any characters, shouldRepresentNodeOffsetZe
ro() can | 915 // When we haven't been emitting any characters, shouldRepresentNodeOffsetZe
ro() can |
| 916 // create VisiblePositions, which is expensive. So, we perform the inexpensi
ve checks | 916 // create VisiblePositions, which is expensive. So, we perform the inexpensi
ve checks |
| 917 // on m_node to see if it necessitates emitting a character first and will e
arly return | 917 // on m_node to see if it necessitates emitting a character first and will e
arly return |
| 918 // before encountering shouldRepresentNodeOffsetZero()s worse case behavior. | 918 // before encountering shouldRepresentNodeOffsetZero()s worse case behavior. |
| 919 if (shouldEmitTabBeforeNode(m_node)) { | 919 if (shouldEmitTabBeforeNode(m_node)) { |
| 920 if (shouldRepresentNodeOffsetZero()) | 920 if (shouldRepresentNodeOffsetZero()) |
| 921 emitCharacter('\t', m_node->parentNode(), m_node, 0, 0); | 921 emitCharacter('\t', m_node->parentNode(), m_node, 0, 0); |
| 922 } else if (shouldEmitNewlineBeforeNode(*m_node)) { | 922 } else if (shouldEmitNewlineBeforeNode(*m_node)) { |
| 923 if (shouldRepresentNodeOffsetZero()) | 923 if (shouldRepresentNodeOffsetZero()) |
| 924 emitCharacter('\n', m_node->parentNode(), m_node, 0, 0); | 924 emitCharacter('\n', m_node->parentNode(), m_node, 0, 0); |
| 925 } else if (shouldEmitSpaceBeforeAndAfterNode(m_node)) { | 925 } else if (shouldEmitSpaceBeforeAndAfterNode(m_node)) { |
| 926 if (shouldRepresentNodeOffsetZero()) | 926 if (shouldRepresentNodeOffsetZero()) |
| 927 emitCharacter(space, m_node->parentNode(), m_node, 0, 0); | 927 emitCharacter(space, m_node->parentNode(), m_node, 0, 0); |
| 928 } | 928 } |
| 929 } | 929 } |
| 930 | 930 |
| 931 bool TextIterator::handleNonTextNode() | 931 bool TextIterator::handleNonTextNode() |
| 932 { | 932 { |
| 933 if (shouldEmitNewlineForNode(m_node, m_emitsOriginalText)) | 933 if (shouldEmitNewlineForNode(m_node, m_emitsOriginalText)) |
| 934 emitCharacter('\n', m_node->parentNode(), m_node, 0, 1); | 934 emitCharacter('\n', m_node->parentNode(), m_node, 0, 1); |
| 935 else if (m_emitsCharactersBetweenAllVisiblePositions && m_node->renderer() &
& m_node->renderer()->isHR()) | 935 else if (m_emitsCharactersBetweenAllVisiblePositions && m_node->layoutObject
() && m_node->layoutObject()->isHR()) |
| 936 emitCharacter(space, m_node->parentNode(), m_node, 0, 1); | 936 emitCharacter(space, m_node->parentNode(), m_node, 0, 1); |
| 937 else | 937 else |
| 938 representNodeOffsetZero(); | 938 representNodeOffsetZero(); |
| 939 | 939 |
| 940 return true; | 940 return true; |
| 941 } | 941 } |
| 942 | 942 |
| 943 void TextIterator::flushPositionOffsets() const | 943 void TextIterator::flushPositionOffsets() const |
| 944 { | 944 { |
| 945 if (!m_positionOffsetBaseNode) | 945 if (!m_positionOffsetBaseNode) |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1177 return createPlainText(it); | 1177 return createPlainText(it); |
| 1178 } | 1178 } |
| 1179 | 1179 |
| 1180 String plainText(const Position& start, const Position& end, TextIteratorBehavio
rFlags behavior) | 1180 String plainText(const Position& start, const Position& end, TextIteratorBehavio
rFlags behavior) |
| 1181 { | 1181 { |
| 1182 TextIterator it(start, end, behavior); | 1182 TextIterator it(start, end, behavior); |
| 1183 return createPlainText(it); | 1183 return createPlainText(it); |
| 1184 } | 1184 } |
| 1185 | 1185 |
| 1186 } | 1186 } |
| OLD | NEW |