| 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 |