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 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 return m_size; | 156 return m_size; |
157 } | 157 } |
158 | 158 |
159 // -------- | 159 // -------- |
160 | 160 |
161 #if ENABLE(ASSERT) | 161 #if ENABLE(ASSERT) |
162 | 162 |
163 static unsigned depthCrossingShadowBoundaries(Node* node) | 163 static unsigned depthCrossingShadowBoundaries(Node* node) |
164 { | 164 { |
165 unsigned depth = 0; | 165 unsigned depth = 0; |
166 for (Node* parent = node->parentOrShadowHostNode(); parent; parent = parent-
>parentOrShadowHostNode()) | 166 for (ContainerNode* parent = node->parentOrShadowHostNode(); parent; parent
= parent->parentOrShadowHostNode()) |
167 ++depth; | 167 ++depth; |
168 return depth; | 168 return depth; |
169 } | 169 } |
170 | 170 |
171 #endif | 171 #endif |
172 | 172 |
173 // This function is like Range::pastLastNode, except for the fact that it can cl
imb up out of shadow trees. | 173 // This function is like Range::pastLastNode, except for the fact that it can cl
imb up out of shadow trees. |
174 static Node* nextInPreOrderCrossingShadowBoundaries(Node* rangeEndContainer, int
rangeEndOffset) | 174 static Node* nextInPreOrderCrossingShadowBoundaries(Node* rangeEndContainer, int
rangeEndOffset) |
175 { | 175 { |
176 if (!rangeEndContainer) | 176 if (!rangeEndContainer) |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 // primitives, not with DOM primitives. | 218 // primitives, not with DOM primitives. |
219 | 219 |
220 // Push true if this node full clips its contents, or if a parent already ha
s fully | 220 // Push true if this node full clips its contents, or if a parent already ha
s fully |
221 // clipped and this is not a node that ignores its container's clip. | 221 // clipped and this is not a node that ignores its container's clip. |
222 stack.push(fullyClipsContents(node) || (stack.top() && !ignoresContainerClip
(node))); | 222 stack.push(fullyClipsContents(node) || (stack.top() && !ignoresContainerClip
(node))); |
223 } | 223 } |
224 | 224 |
225 static void setUpFullyClippedStack(BitStack& stack, Node* node) | 225 static void setUpFullyClippedStack(BitStack& stack, Node* node) |
226 { | 226 { |
227 // Put the nodes in a vector so we can iterate in reverse order. | 227 // Put the nodes in a vector so we can iterate in reverse order. |
228 WillBeHeapVector<RawPtrWillBeMember<Node>, 100> ancestry; | 228 WillBeHeapVector<RawPtrWillBeMember<ContainerNode>, 100> ancestry; |
229 for (Node* parent = node->parentOrShadowHostNode(); parent; parent = parent-
>parentOrShadowHostNode()) | 229 for (ContainerNode* parent = node->parentOrShadowHostNode(); parent; parent
= parent->parentOrShadowHostNode()) |
230 ancestry.append(parent); | 230 ancestry.append(parent); |
231 | 231 |
232 // Call pushFullyClippedState on each node starting with the earliest ancest
or. | 232 // Call pushFullyClippedState on each node starting with the earliest ancest
or. |
233 size_t size = ancestry.size(); | 233 size_t size = ancestry.size(); |
234 for (size_t i = 0; i < size; ++i) | 234 for (size_t i = 0; i < size; ++i) |
235 pushFullyClippedState(stack, ancestry[size - i - 1]); | 235 pushFullyClippedState(stack, ancestry[size - i - 1]); |
236 pushFullyClippedState(stack, node); | 236 pushFullyClippedState(stack, node); |
237 | 237 |
238 ASSERT(stack.size() == 1 + depthCrossingShadowBoundaries(node)); | 238 ASSERT(stack.size() == 1 + depthCrossingShadowBoundaries(node)); |
239 } | 239 } |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 } | 457 } |
458 m_iterationProgress = HandledUserAgentShadowRoot; | 458 m_iterationProgress = HandledUserAgentShadowRoot; |
459 } | 459 } |
460 | 460 |
461 // Handle the current node according to its type. | 461 // Handle the current node according to its type. |
462 if (m_iterationProgress < HandledNode) { | 462 if (m_iterationProgress < HandledNode) { |
463 bool handledNode = false; | 463 bool handledNode = false; |
464 if (renderer->isText() && m_node->nodeType() == Node::TEXT_NODE)
{ // FIXME: What about CDATA_SECTION_NODE? | 464 if (renderer->isText() && m_node->nodeType() == Node::TEXT_NODE)
{ // FIXME: What about CDATA_SECTION_NODE? |
465 handledNode = handleTextNode(); | 465 handledNode = handleTextNode(); |
466 } else if (renderer && (renderer->isImage() || renderer->isWidge
t() | 466 } else if (renderer && (renderer->isImage() || renderer->isWidge
t() |
467 || (m_node && m_node->isElementNode() | 467 || (m_node && m_node->isHTMLElement() |
468 && (toElement(m_node)->isFormControlElement() | 468 && (isHTMLFormControlElement(toHTMLElement(*m_node)) |
469 || isHTMLLegendElement(toElement(*m_node)) | 469 || isHTMLLegendElement(toHTMLElement(*m_node)) |
470 || isHTMLMeterElement(toElement(*m_node)) | 470 || isHTMLMeterElement(toHTMLElement(*m_node)) |
471 || isHTMLProgressElement(toElement(*m_node)))))) { | 471 || isHTMLProgressElement(toHTMLElement(*m_node)))))) { |
472 handledNode = handleReplacedElement(); | 472 handledNode = handleReplacedElement(); |
473 } else { | 473 } else { |
474 handledNode = handleNonTextNode(); | 474 handledNode = handleNonTextNode(); |
475 } | 475 } |
476 if (handledNode) | 476 if (handledNode) |
477 m_iterationProgress = HandledNode; | 477 m_iterationProgress = HandledNode; |
478 if (m_positionNode) | 478 if (m_positionNode) |
479 return; | 479 return; |
480 } | 480 } |
481 } | 481 } |
482 | 482 |
483 // Find a new current node to handle in depth-first manner, | 483 // Find a new current node to handle in depth-first manner, |
484 // calling exitNode() as we come back thru a parent node. | 484 // calling exitNode() as we come back thru a parent node. |
485 // | 485 // |
486 // 1. Iterate over child nodes, if we haven't done yet. | 486 // 1. Iterate over child nodes, if we haven't done yet. |
487 Node* next = m_iterationProgress < HandledChildren ? m_node->firstChild(
) : 0; | 487 Node* next = m_iterationProgress < HandledChildren ? m_node->firstChild(
) : 0; |
488 m_offset = 0; | 488 m_offset = 0; |
489 if (!next) { | 489 if (!next) { |
490 // 2. If we've already iterated children or they are not available,
go to the next sibling node. | 490 // 2. If we've already iterated children or they are not available,
go to the next sibling node. |
491 next = m_node->nextSibling(); | 491 next = m_node->nextSibling(); |
492 if (!next) { | 492 if (!next) { |
493 // 3. If we are at the last child, go up the node tree until we
find a next sibling. | 493 // 3. If we are at the last child, go up the node tree until we
find a next sibling. |
494 bool pastEnd = NodeTraversal::next(*m_node) == m_pastEndNode; | 494 bool pastEnd = NodeTraversal::next(*m_node) == m_pastEndNode; |
495 Node* parentNode = m_node->parentNode(); | 495 ContainerNode* parentNode = m_node->parentNode(); |
496 while (!next && parentNode) { | 496 while (!next && parentNode) { |
497 if ((pastEnd && parentNode == m_endContainer) || m_endContai
ner->isDescendantOf(parentNode)) | 497 if ((pastEnd && parentNode == m_endContainer) || m_endContai
ner->isDescendantOf(parentNode)) |
498 return; | 498 return; |
499 bool haveRenderer = m_node->renderer(); | 499 bool haveRenderer = m_node->renderer(); |
500 m_node = parentNode; | 500 m_node = parentNode; |
501 m_fullyClippedStack.pop(); | 501 m_fullyClippedStack.pop(); |
502 parentNode = m_node->parentNode(); | 502 parentNode = m_node->parentNode(); |
503 if (haveRenderer) | 503 if (haveRenderer) |
504 exitNode(); | 504 exitNode(); |
505 if (m_positionNode) { | 505 if (m_positionNode) { |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
598 } else { | 598 } else { |
599 builder.append(string(), startOffset() + position, lengthToAppend); | 599 builder.append(string(), startOffset() + position, lengthToAppend); |
600 } | 600 } |
601 } | 601 } |
602 | 602 |
603 bool TextIterator::handleTextNode() | 603 bool TextIterator::handleTextNode() |
604 { | 604 { |
605 if (m_fullyClippedStack.top() && !m_ignoresStyleVisibility) | 605 if (m_fullyClippedStack.top() && !m_ignoresStyleVisibility) |
606 return false; | 606 return false; |
607 | 607 |
608 RenderText* renderer = toRenderText(m_node->renderer()); | 608 Text* textNode = toText(m_node); |
| 609 RenderText* renderer = textNode->renderer(); |
609 | 610 |
610 m_lastTextNode = m_node; | 611 m_lastTextNode = textNode; |
611 String str = renderer->text(); | 612 String str = renderer->text(); |
612 | 613 |
613 // handle pre-formatted text | 614 // handle pre-formatted text |
614 if (!renderer->style()->collapseWhiteSpace()) { | 615 if (!renderer->style()->collapseWhiteSpace()) { |
615 int runStart = m_offset; | 616 int runStart = m_offset; |
616 if (m_lastTextNodeEndedWithCollapsedSpace && hasVisibleTextNode(renderer
)) { | 617 if (m_lastTextNodeEndedWithCollapsedSpace && hasVisibleTextNode(renderer
)) { |
617 emitCharacter(' ', m_node, 0, runStart, runStart); | 618 emitCharacter(' ', textNode, 0, runStart, runStart); |
618 return false; | 619 return false; |
619 } | 620 } |
620 if (!m_handledFirstLetter && renderer->isTextFragment() && !m_offset) { | 621 if (!m_handledFirstLetter && renderer->isTextFragment() && !m_offset) { |
621 handleTextNodeFirstLetter(toRenderTextFragment(renderer)); | 622 handleTextNodeFirstLetter(toRenderTextFragment(renderer)); |
622 if (m_firstLetterText) { | 623 if (m_firstLetterText) { |
623 String firstLetter = m_firstLetterText->text(); | 624 String firstLetter = m_firstLetterText->text(); |
624 emitText(m_node, m_firstLetterText, m_offset, m_offset + firstLe
tter.length()); | 625 emitText(textNode, m_firstLetterText, m_offset, m_offset + first
Letter.length()); |
625 m_firstLetterText = 0; | 626 m_firstLetterText = 0; |
626 m_textBox = 0; | 627 m_textBox = 0; |
627 return false; | 628 return false; |
628 } | 629 } |
629 } | 630 } |
630 if (renderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibil
ity) | 631 if (renderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibil
ity) |
631 return false; | 632 return false; |
632 int strLength = str.length(); | 633 int strLength = str.length(); |
633 int end = (m_node == m_endContainer) ? m_endOffset : INT_MAX; | 634 int end = (textNode == m_endContainer) ? m_endOffset : INT_MAX; |
634 int runEnd = std::min(strLength, end); | 635 int runEnd = std::min(strLength, end); |
635 | 636 |
636 if (runStart >= runEnd) | 637 if (runStart >= runEnd) |
637 return true; | 638 return true; |
638 | 639 |
639 emitText(m_node, runStart, runEnd); | 640 emitText(textNode, textNode->renderer(), runStart, runEnd); |
640 return true; | 641 return true; |
641 } | 642 } |
642 | 643 |
643 if (renderer->firstTextBox()) | 644 if (renderer->firstTextBox()) |
644 m_textBox = renderer->firstTextBox(); | 645 m_textBox = renderer->firstTextBox(); |
645 | 646 |
646 bool shouldHandleFirstLetter = !m_handledFirstLetter && renderer->isTextFrag
ment() && !m_offset; | 647 bool shouldHandleFirstLetter = !m_handledFirstLetter && renderer->isTextFrag
ment() && !m_offset; |
647 if (shouldHandleFirstLetter) | 648 if (shouldHandleFirstLetter) |
648 handleTextNodeFirstLetter(toRenderTextFragment(renderer)); | 649 handleTextNodeFirstLetter(toRenderTextFragment(renderer)); |
649 | 650 |
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1149 // remember information with which to construct the TextIterator::characters
() and length() | 1150 // remember information with which to construct the TextIterator::characters
() and length() |
1150 m_singleCharacterBuffer = c; | 1151 m_singleCharacterBuffer = c; |
1151 ASSERT(m_singleCharacterBuffer); | 1152 ASSERT(m_singleCharacterBuffer); |
1152 m_textLength = 1; | 1153 m_textLength = 1; |
1153 | 1154 |
1154 // remember some iteration state | 1155 // remember some iteration state |
1155 m_lastTextNodeEndedWithCollapsedSpace = false; | 1156 m_lastTextNodeEndedWithCollapsedSpace = false; |
1156 m_lastCharacter = c; | 1157 m_lastCharacter = c; |
1157 } | 1158 } |
1158 | 1159 |
1159 void TextIterator::emitText(Node* textNode, RenderObject* renderObject, int text
StartOffset, int textEndOffset) | 1160 void TextIterator::emitText(Node* textNode, RenderText* renderer, int textStartO
ffset, int textEndOffset) |
1160 { | 1161 { |
1161 RenderText* renderer = toRenderText(renderObject); | |
1162 m_text = m_emitsOriginalText ? renderer->originalText() : renderer->text(); | 1162 m_text = m_emitsOriginalText ? renderer->originalText() : renderer->text(); |
1163 ASSERT(!m_text.isEmpty()); | 1163 ASSERT(!m_text.isEmpty()); |
1164 ASSERT(0 <= textStartOffset && textStartOffset < static_cast<int>(m_text.len
gth())); | 1164 ASSERT(0 <= textStartOffset && textStartOffset < static_cast<int>(m_text.len
gth())); |
1165 ASSERT(0 <= textEndOffset && textEndOffset <= static_cast<int>(m_text.length
())); | 1165 ASSERT(0 <= textEndOffset && textEndOffset <= static_cast<int>(m_text.length
())); |
1166 ASSERT(textStartOffset <= textEndOffset); | 1166 ASSERT(textStartOffset <= textEndOffset); |
1167 | 1167 |
1168 m_positionNode = textNode; | 1168 m_positionNode = textNode; |
1169 m_positionOffsetBaseNode = nullptr; | 1169 m_positionOffsetBaseNode = nullptr; |
1170 m_positionStartOffset = textStartOffset; | 1170 m_positionStartOffset = textStartOffset; |
1171 m_positionEndOffset = textEndOffset; | 1171 m_positionEndOffset = textEndOffset; |
1172 m_singleCharacterBuffer = 0; | 1172 m_singleCharacterBuffer = 0; |
1173 m_textLength = textEndOffset - textStartOffset; | 1173 m_textLength = textEndOffset - textStartOffset; |
1174 m_lastCharacter = m_text[textEndOffset - 1]; | 1174 m_lastCharacter = m_text[textEndOffset - 1]; |
1175 | 1175 |
1176 m_lastTextNodeEndedWithCollapsedSpace = false; | 1176 m_lastTextNodeEndedWithCollapsedSpace = false; |
1177 m_hasEmitted = true; | 1177 m_hasEmitted = true; |
1178 } | 1178 } |
1179 | 1179 |
1180 void TextIterator::emitText(Node* textNode, int textStartOffset, int textEndOffs
et) | |
1181 { | |
1182 emitText(textNode, m_node->renderer(), textStartOffset, textEndOffset); | |
1183 } | |
1184 | |
1185 PassRefPtrWillBeRawPtr<Range> TextIterator::range() const | 1180 PassRefPtrWillBeRawPtr<Range> TextIterator::range() const |
1186 { | 1181 { |
1187 // use the current run information, if we have it | 1182 // use the current run information, if we have it |
1188 if (m_positionNode) { | 1183 if (m_positionNode) { |
1189 if (m_positionOffsetBaseNode) { | 1184 if (m_positionOffsetBaseNode) { |
1190 int index = m_positionOffsetBaseNode->nodeIndex(); | 1185 int index = m_positionOffsetBaseNode->nodeIndex(); |
1191 m_positionStartOffset += index; | 1186 m_positionStartOffset += index; |
1192 m_positionEndOffset += index; | 1187 m_positionEndOffset += index; |
1193 m_positionOffsetBaseNode = nullptr; | 1188 m_positionOffsetBaseNode = nullptr; |
1194 } | 1189 } |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1372 m_handledNode = false; | 1367 m_handledNode = false; |
1373 m_handledChildren = false; | 1368 m_handledChildren = false; |
1374 | 1369 |
1375 if (m_positionNode) | 1370 if (m_positionNode) |
1376 return; | 1371 return; |
1377 } | 1372 } |
1378 } | 1373 } |
1379 | 1374 |
1380 bool SimplifiedBackwardsTextIterator::handleTextNode() | 1375 bool SimplifiedBackwardsTextIterator::handleTextNode() |
1381 { | 1376 { |
1382 m_lastTextNode = m_node; | 1377 m_lastTextNode = toText(m_node); |
1383 | 1378 |
1384 int startOffset; | 1379 int startOffset; |
1385 int offsetInNode; | 1380 int offsetInNode; |
1386 RenderText* renderer = handleFirstLetter(startOffset, offsetInNode); | 1381 RenderText* renderer = handleFirstLetter(startOffset, offsetInNode); |
1387 if (!renderer) | 1382 if (!renderer) |
1388 return true; | 1383 return true; |
1389 | 1384 |
1390 String text = renderer->text(); | 1385 String text = renderer->text(); |
1391 if (!renderer->firstTextBox() && text.length() > 0) | 1386 if (!renderer->firstTextBox() && text.length() > 0) |
1392 return true; | 1387 return true; |
(...skipping 827 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2220 resultEnd = collapseTo; | 2215 resultEnd = collapseTo; |
2221 return; | 2216 return; |
2222 } | 2217 } |
2223 } | 2218 } |
2224 | 2219 |
2225 CharacterIterator computeRangeIterator(inputStart, inputEnd, iteratorFlagsFo
rFindPlainText); | 2220 CharacterIterator computeRangeIterator(inputStart, inputEnd, iteratorFlagsFo
rFindPlainText); |
2226 calculateCharacterSubrange(computeRangeIterator, matchStart, matchLength, re
sultStart, resultEnd); | 2221 calculateCharacterSubrange(computeRangeIterator, matchStart, matchLength, re
sultStart, resultEnd); |
2227 } | 2222 } |
2228 | 2223 |
2229 } | 2224 } |
OLD | NEW |