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 |