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 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 | 197 |
198 TextIterator::~TextIterator() | 198 TextIterator::~TextIterator() |
199 { | 199 { |
200 } | 200 } |
201 | 201 |
202 bool TextIterator::isInsideReplacedElement() const | 202 bool TextIterator::isInsideReplacedElement() const |
203 { | 203 { |
204 if (atEnd() || length() != 1 || !m_node) | 204 if (atEnd() || length() != 1 || !m_node) |
205 return false; | 205 return false; |
206 | 206 |
207 RenderObject* renderer = m_node->renderer(); | 207 LayoutObject* renderer = m_node->renderer(); |
208 return renderer && renderer->isReplaced(); | 208 return renderer && renderer->isReplaced(); |
209 } | 209 } |
210 | 210 |
211 void TextIterator::advance() | 211 void TextIterator::advance() |
212 { | 212 { |
213 if (m_shouldStop) | 213 if (m_shouldStop) |
214 return; | 214 return; |
215 | 215 |
216 ASSERT(!m_node || !m_node->document().needsRenderTreeUpdate()); | 216 ASSERT(!m_node || !m_node->document().needsRenderTreeUpdate()); |
217 | 217 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 // if the range ends at offset 0 of an element, represent the | 253 // if the range ends at offset 0 of an element, represent the |
254 // position, but not the content, of that element e.g. if the | 254 // position, but not the content, of that element e.g. if the |
255 // node is a blockflow element, emit a newline that | 255 // node is a blockflow element, emit a newline that |
256 // precedes the element | 256 // precedes the element |
257 if (m_node == m_endContainer && !m_endOffset) { | 257 if (m_node == m_endContainer && !m_endOffset) { |
258 representNodeOffsetZero(); | 258 representNodeOffsetZero(); |
259 m_node = nullptr; | 259 m_node = nullptr; |
260 return; | 260 return; |
261 } | 261 } |
262 | 262 |
263 RenderObject* renderer = m_node->renderer(); | 263 LayoutObject* renderer = m_node->renderer(); |
264 if (!renderer) { | 264 if (!renderer) { |
265 if (m_node->isShadowRoot()) { | 265 if (m_node->isShadowRoot()) { |
266 // A shadow root doesn't have a renderer, but we want to visit c
hildren anyway. | 266 // A shadow root doesn't have a renderer, but we want to visit c
hildren anyway. |
267 m_iterationProgress = m_iterationProgress < HandledNode ? Handle
dNode : m_iterationProgress; | 267 m_iterationProgress = m_iterationProgress < HandledNode ? Handle
dNode : m_iterationProgress; |
268 } else { | 268 } else { |
269 m_iterationProgress = HandledChildren; | 269 m_iterationProgress = HandledChildren; |
270 } | 270 } |
271 } else { | 271 } else { |
272 // Enter author shadow roots, from youngest, if any and if necessary
. | 272 // Enter author shadow roots, from youngest, if any and if necessary
. |
273 if (m_iterationProgress < HandledAuthorShadowRoots) { | 273 if (m_iterationProgress < HandledAuthorShadowRoots) { |
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
617 { | 617 { |
618 m_handledFirstLetter = true; | 618 m_handledFirstLetter = true; |
619 | 619 |
620 if (!renderer->isRemainingTextRenderer()) | 620 if (!renderer->isRemainingTextRenderer()) |
621 return; | 621 return; |
622 | 622 |
623 FirstLetterPseudoElement* firstLetterElement = renderer->firstLetterPseudoEl
ement(); | 623 FirstLetterPseudoElement* firstLetterElement = renderer->firstLetterPseudoEl
ement(); |
624 if (!firstLetterElement) | 624 if (!firstLetterElement) |
625 return; | 625 return; |
626 | 626 |
627 RenderObject* pseudoRenderer = firstLetterElement->renderer(); | 627 LayoutObject* pseudoRenderer = firstLetterElement->renderer(); |
628 if (pseudoRenderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisib
ility) | 628 if (pseudoRenderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisib
ility) |
629 return; | 629 return; |
630 | 630 |
631 RenderObject* firstLetter = pseudoRenderer->slowFirstChild(); | 631 LayoutObject* firstLetter = pseudoRenderer->slowFirstChild(); |
632 ASSERT(firstLetter); | 632 ASSERT(firstLetter); |
633 | 633 |
634 m_remainingTextBox = m_textBox; | 634 m_remainingTextBox = m_textBox; |
635 m_textBox = toRenderText(firstLetter)->firstTextBox(); | 635 m_textBox = toRenderText(firstLetter)->firstTextBox(); |
636 m_sortedTextBoxes.clear(); | 636 m_sortedTextBoxes.clear(); |
637 m_firstLetterText = toRenderText(firstLetter); | 637 m_firstLetterText = toRenderText(firstLetter); |
638 } | 638 } |
639 | 639 |
640 bool TextIterator::supportsAltText(Node* m_node) | 640 bool TextIterator::supportsAltText(Node* m_node) |
641 { | 641 { |
642 if (!m_node->isHTMLElement()) | 642 if (!m_node->isHTMLElement()) |
643 return false; | 643 return false; |
644 HTMLElement& element = toHTMLElement(*m_node); | 644 HTMLElement& element = toHTMLElement(*m_node); |
645 | 645 |
646 // FIXME: Add isSVGImageElement. | 646 // FIXME: Add isSVGImageElement. |
647 if (isHTMLImageElement(element)) | 647 if (isHTMLImageElement(element)) |
648 return true; | 648 return true; |
649 if (isHTMLInputElement(toHTMLElement(*m_node)) && toHTMLInputElement(*m_node
).isImage()) | 649 if (isHTMLInputElement(toHTMLElement(*m_node)) && toHTMLInputElement(*m_node
).isImage()) |
650 return true; | 650 return true; |
651 return false; | 651 return false; |
652 } | 652 } |
653 | 653 |
654 bool TextIterator::handleReplacedElement() | 654 bool TextIterator::handleReplacedElement() |
655 { | 655 { |
656 if (m_fullyClippedStack.top()) | 656 if (m_fullyClippedStack.top()) |
657 return false; | 657 return false; |
658 | 658 |
659 RenderObject* renderer = m_node->renderer(); | 659 LayoutObject* renderer = m_node->renderer(); |
660 if (renderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility) | 660 if (renderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility) |
661 return false; | 661 return false; |
662 | 662 |
663 if (m_emitsObjectReplacementCharacter) { | 663 if (m_emitsObjectReplacementCharacter) { |
664 emitCharacter(objectReplacementCharacter, m_node->parentNode(), m_node,
0, 1); | 664 emitCharacter(objectReplacementCharacter, m_node->parentNode(), m_node,
0, 1); |
665 return true; | 665 return true; |
666 } | 666 } |
667 | 667 |
668 if (m_lastTextNodeEndedWithCollapsedSpace) { | 668 if (m_lastTextNodeEndedWithCollapsedSpace) { |
669 emitCharacter(space, m_lastTextNode->parentNode(), m_lastTextNode, 1, 1)
; | 669 emitCharacter(space, m_lastTextNode->parentNode(), m_lastTextNode, 1, 1)
; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
712 return true; | 712 return true; |
713 | 713 |
714 if (!renderer->isTextFragment()) | 714 if (!renderer->isTextFragment()) |
715 return false; | 715 return false; |
716 | 716 |
717 RenderTextFragment* fragment = toRenderTextFragment(renderer); | 717 RenderTextFragment* fragment = toRenderTextFragment(renderer); |
718 if (!fragment->isRemainingTextRenderer()) | 718 if (!fragment->isRemainingTextRenderer()) |
719 return false; | 719 return false; |
720 | 720 |
721 ASSERT(fragment->firstLetterPseudoElement()); | 721 ASSERT(fragment->firstLetterPseudoElement()); |
722 RenderObject* pseudoElementRenderer = fragment->firstLetterPseudoElement()->
renderer(); | 722 LayoutObject* pseudoElementRenderer = fragment->firstLetterPseudoElement()->
renderer(); |
723 return pseudoElementRenderer && pseudoElementRenderer->style()->visibility()
== VISIBLE; | 723 return pseudoElementRenderer && pseudoElementRenderer->style()->visibility()
== VISIBLE; |
724 } | 724 } |
725 | 725 |
726 bool TextIterator::shouldEmitTabBeforeNode(Node* node) | 726 bool TextIterator::shouldEmitTabBeforeNode(Node* node) |
727 { | 727 { |
728 RenderObject* r = node->renderer(); | 728 LayoutObject* r = node->renderer(); |
729 | 729 |
730 // Table cells are delimited by tabs. | 730 // Table cells are delimited by tabs. |
731 if (!r || !isTableCell(node)) | 731 if (!r || !isTableCell(node)) |
732 return false; | 732 return false; |
733 | 733 |
734 // Want a tab before every cell other than the first one | 734 // Want a tab before every cell other than the first one |
735 LayoutTableCell* rc = toLayoutTableCell(r); | 735 LayoutTableCell* rc = toLayoutTableCell(r); |
736 LayoutTable* t = rc->table(); | 736 LayoutTable* t = rc->table(); |
737 return t && (t->cellBefore(rc) || t->cellAbove(rc)); | 737 return t && (t->cellBefore(rc) || t->cellAbove(rc)); |
738 } | 738 } |
739 | 739 |
740 bool TextIterator::shouldEmitNewlineForNode(Node* node, bool emitsOriginalText) | 740 bool TextIterator::shouldEmitNewlineForNode(Node* node, bool emitsOriginalText) |
741 { | 741 { |
742 RenderObject* renderer = node->renderer(); | 742 LayoutObject* renderer = node->renderer(); |
743 | 743 |
744 if (renderer ? !renderer->isBR() : !isHTMLBRElement(node)) | 744 if (renderer ? !renderer->isBR() : !isHTMLBRElement(node)) |
745 return false; | 745 return false; |
746 return emitsOriginalText || !(node->isInShadowTree() && isHTMLInputElement(*
node->shadowHost())); | 746 return emitsOriginalText || !(node->isInShadowTree() && isHTMLInputElement(*
node->shadowHost())); |
747 } | 747 } |
748 | 748 |
749 static bool shouldEmitNewlinesBeforeAndAfterNode(Node& node) | 749 static bool shouldEmitNewlinesBeforeAndAfterNode(Node& node) |
750 { | 750 { |
751 // Block flow (versus inline flow) is represented by having | 751 // Block flow (versus inline flow) is represented by having |
752 // a newline both before and after the element. | 752 // a newline both before and after the element. |
753 RenderObject* r = node.renderer(); | 753 LayoutObject* r = node.renderer(); |
754 if (!r) { | 754 if (!r) { |
755 return (node.hasTagName(blockquoteTag) | 755 return (node.hasTagName(blockquoteTag) |
756 || node.hasTagName(ddTag) | 756 || node.hasTagName(ddTag) |
757 || node.hasTagName(divTag) | 757 || node.hasTagName(divTag) |
758 || node.hasTagName(dlTag) | 758 || node.hasTagName(dlTag) |
759 || node.hasTagName(dtTag) | 759 || node.hasTagName(dtTag) |
760 || node.hasTagName(h1Tag) | 760 || node.hasTagName(h1Tag) |
761 || node.hasTagName(h2Tag) | 761 || node.hasTagName(h2Tag) |
762 || node.hasTagName(h3Tag) | 762 || node.hasTagName(h3Tag) |
763 || node.hasTagName(h4Tag) | 763 || node.hasTagName(h4Tag) |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
815 { | 815 { |
816 return shouldEmitNewlinesBeforeAndAfterNode(node); | 816 return shouldEmitNewlinesBeforeAndAfterNode(node); |
817 } | 817 } |
818 | 818 |
819 static bool shouldEmitExtraNewlineForNode(Node* node) | 819 static bool shouldEmitExtraNewlineForNode(Node* node) |
820 { | 820 { |
821 // When there is a significant collapsed bottom margin, emit an extra | 821 // When there is a significant collapsed bottom margin, emit an extra |
822 // newline for a more realistic result. We end up getting the right | 822 // newline for a more realistic result. We end up getting the right |
823 // result even without margin collapsing. For example: <div><p>text</p></div
> | 823 // result even without margin collapsing. For example: <div><p>text</p></div
> |
824 // will work right even if both the <div> and the <p> have bottom margins. | 824 // will work right even if both the <div> and the <p> have bottom margins. |
825 RenderObject* r = node->renderer(); | 825 LayoutObject* r = node->renderer(); |
826 if (!r || !r->isBox()) | 826 if (!r || !r->isBox()) |
827 return false; | 827 return false; |
828 | 828 |
829 // NOTE: We only do this for a select set of nodes, and fwiw WinIE appears | 829 // NOTE: We only do this for a select set of nodes, and fwiw WinIE appears |
830 // not to do this at all | 830 // not to do this at all |
831 if (node->hasTagName(h1Tag) | 831 if (node->hasTagName(h1Tag) |
832 || node->hasTagName(h2Tag) | 832 || node->hasTagName(h2Tag) |
833 || node->hasTagName(h3Tag) | 833 || node->hasTagName(h3Tag) |
834 || node->hasTagName(h4Tag) | 834 || node->hasTagName(h4Tag) |
835 || node->hasTagName(h5Tag) | 835 || node->hasTagName(h5Tag) |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1178 return createPlainText(it); | 1178 return createPlainText(it); |
1179 } | 1179 } |
1180 | 1180 |
1181 String plainText(const Position& start, const Position& end, TextIteratorBehavio
rFlags behavior) | 1181 String plainText(const Position& start, const Position& end, TextIteratorBehavio
rFlags behavior) |
1182 { | 1182 { |
1183 TextIterator it(start, end, behavior); | 1183 TextIterator it(start, end, behavior); |
1184 return createPlainText(it); | 1184 return createPlainText(it); |
1185 } | 1185 } |
1186 | 1186 |
1187 } | 1187 } |
OLD | NEW |