| OLD | NEW |
| 1 /* | 1 /* |
| 2 * (C) 1999 Lars Knoll (knoll@kde.org) | 2 * (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 2000 Gunnstein Lye (gunnstein@netcom.no) | 3 * (C) 2000 Gunnstein Lye (gunnstein@netcom.no) |
| 4 * (C) 2000 Frederik Holljen (frederik.holljen@hig.no) | 4 * (C) 2000 Frederik Holljen (frederik.holljen@hig.no) |
| 5 * (C) 2001 Peter Kelly (pmk@post.com) | 5 * (C) 2001 Peter Kelly (pmk@post.com) |
| 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All | 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All |
| 7 * rights reserved. | 7 * rights reserved. |
| 8 * Copyright (C) 2011 Motorola Mobility. All rights reserved. | 8 * Copyright (C) 2011 Motorola Mobility. All rights reserved. |
| 9 * | 9 * |
| 10 * This library is free software; you can redistribute it and/or | 10 * This library is free software; you can redistribute it and/or |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 m_end(m_ownerDocument) { | 63 m_end(m_ownerDocument) { |
| 64 m_ownerDocument->attachRange(this); | 64 m_ownerDocument->attachRange(this); |
| 65 } | 65 } |
| 66 | 66 |
| 67 Range* Range::create(Document& ownerDocument) { | 67 Range* Range::create(Document& ownerDocument) { |
| 68 return new Range(ownerDocument); | 68 return new Range(ownerDocument); |
| 69 } | 69 } |
| 70 | 70 |
| 71 inline Range::Range(Document& ownerDocument, | 71 inline Range::Range(Document& ownerDocument, |
| 72 Node* startContainer, | 72 Node* startContainer, |
| 73 int startOffset, | 73 unsigned startOffset, |
| 74 Node* endContainer, | 74 Node* endContainer, |
| 75 int endOffset) | 75 unsigned endOffset) |
| 76 : m_ownerDocument(&ownerDocument), | 76 : m_ownerDocument(&ownerDocument), |
| 77 m_start(m_ownerDocument), | 77 m_start(m_ownerDocument), |
| 78 m_end(m_ownerDocument) { | 78 m_end(m_ownerDocument) { |
| 79 m_ownerDocument->attachRange(this); | 79 m_ownerDocument->attachRange(this); |
| 80 | 80 |
| 81 // Simply setting the containers and offsets directly would not do any of the | 81 // Simply setting the containers and offsets directly would not do any of the |
| 82 // checking that setStart and setEnd do, so we call those functions. | 82 // checking that setStart and setEnd do, so we call those functions. |
| 83 setStart(startContainer, startOffset); | 83 setStart(startContainer, startOffset); |
| 84 setEnd(endContainer, endOffset); | 84 setEnd(endContainer, endOffset); |
| 85 } | 85 } |
| 86 | 86 |
| 87 Range* Range::create(Document& ownerDocument, | 87 Range* Range::create(Document& ownerDocument, |
| 88 Node* startContainer, | 88 Node* startContainer, |
| 89 int startOffset, | 89 unsigned startOffset, |
| 90 Node* endContainer, | 90 Node* endContainer, |
| 91 int endOffset) { | 91 unsigned endOffset) { |
| 92 return new Range(ownerDocument, startContainer, startOffset, endContainer, | 92 return new Range(ownerDocument, startContainer, startOffset, endContainer, |
| 93 endOffset); | 93 endOffset); |
| 94 } | 94 } |
| 95 | 95 |
| 96 Range* Range::create(Document& ownerDocument, | 96 Range* Range::create(Document& ownerDocument, |
| 97 const Position& start, | 97 const Position& start, |
| 98 const Position& end) { | 98 const Position& end) { |
| 99 return new Range(ownerDocument, start.computeContainerNode(), | 99 return new Range(ownerDocument, start.computeContainerNode(), |
| 100 start.computeOffsetInContainerNode(), | 100 start.computeOffsetInContainerNode(), |
| 101 end.computeContainerNode(), | 101 end.computeContainerNode(), |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 endRootContainer = endRootContainer->parentNode(); | 156 endRootContainer = endRootContainer->parentNode(); |
| 157 Node* startRootContainer = start.container(); | 157 Node* startRootContainer = start.container(); |
| 158 while (startRootContainer->parentNode()) | 158 while (startRootContainer->parentNode()) |
| 159 startRootContainer = startRootContainer->parentNode(); | 159 startRootContainer = startRootContainer->parentNode(); |
| 160 | 160 |
| 161 return startRootContainer != endRootContainer || | 161 return startRootContainer != endRootContainer || |
| 162 (Range::compareBoundaryPoints(start, end, ASSERT_NO_EXCEPTION) > 0); | 162 (Range::compareBoundaryPoints(start, end, ASSERT_NO_EXCEPTION) > 0); |
| 163 } | 163 } |
| 164 | 164 |
| 165 void Range::setStart(Node* refNode, | 165 void Range::setStart(Node* refNode, |
| 166 int offset, | 166 unsigned offset, |
| 167 ExceptionState& exceptionState) { | 167 ExceptionState& exceptionState) { |
| 168 if (!refNode) { | 168 if (!refNode) { |
| 169 // FIXME: Generated bindings code never calls with null, and neither should | 169 // FIXME: Generated bindings code never calls with null, and neither should |
| 170 // other callers! | 170 // other callers! |
| 171 exceptionState.throwTypeError("The node provided is null."); | 171 exceptionState.throwTypeError("The node provided is null."); |
| 172 return; | 172 return; |
| 173 } | 173 } |
| 174 | 174 |
| 175 Document& oldDocument = ownerDocument(); | 175 Document& oldDocument = ownerDocument(); |
| 176 bool didMoveDocument = false; | 176 bool didMoveDocument = false; |
| 177 if (refNode->document() != m_ownerDocument) { | 177 if (refNode->document() != m_ownerDocument) { |
| 178 setDocument(refNode->document()); | 178 setDocument(refNode->document()); |
| 179 didMoveDocument = true; | 179 didMoveDocument = true; |
| 180 } | 180 } |
| 181 | 181 |
| 182 Node* childNode = checkNodeWOffset(refNode, offset, exceptionState); | 182 Node* childNode = checkNodeWOffset(refNode, offset, exceptionState); |
| 183 if (exceptionState.hadException()) | 183 if (exceptionState.hadException()) |
| 184 return; | 184 return; |
| 185 | 185 |
| 186 m_start.set(refNode, offset, childNode); | 186 m_start.set(refNode, offset, childNode); |
| 187 | 187 |
| 188 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) { | 188 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) { |
| 189 removeFromSelectionIfInDifferentRoot(oldDocument); | 189 removeFromSelectionIfInDifferentRoot(oldDocument); |
| 190 collapse(true); | 190 collapse(true); |
| 191 return; | 191 return; |
| 192 } | 192 } |
| 193 updateSelectionIfAddedToSelection(); | 193 updateSelectionIfAddedToSelection(); |
| 194 } | 194 } |
| 195 | 195 |
| 196 void Range::setEnd(Node* refNode, int offset, ExceptionState& exceptionState) { | 196 void Range::setEnd(Node* refNode, |
| 197 unsigned offset, |
| 198 ExceptionState& exceptionState) { |
| 197 if (!refNode) { | 199 if (!refNode) { |
| 198 // FIXME: Generated bindings code never calls with null, and neither should | 200 // FIXME: Generated bindings code never calls with null, and neither should |
| 199 // other callers! | 201 // other callers! |
| 200 exceptionState.throwTypeError("The node provided is null."); | 202 exceptionState.throwTypeError("The node provided is null."); |
| 201 return; | 203 return; |
| 202 } | 204 } |
| 203 | 205 |
| 204 bool didMoveDocument = false; | 206 bool didMoveDocument = false; |
| 205 Document& oldDocument = ownerDocument(); | 207 Document& oldDocument = ownerDocument(); |
| 206 if (refNode->document() != m_ownerDocument) { | 208 if (refNode->document() != m_ownerDocument) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 237 void Range::collapse(bool toStart) { | 239 void Range::collapse(bool toStart) { |
| 238 if (toStart) | 240 if (toStart) |
| 239 m_end = m_start; | 241 m_end = m_start; |
| 240 else | 242 else |
| 241 m_start = m_end; | 243 m_start = m_end; |
| 242 updateSelectionIfAddedToSelection(); | 244 updateSelectionIfAddedToSelection(); |
| 243 } | 245 } |
| 244 | 246 |
| 245 bool Range::isNodeFullyContained(Node& node) const { | 247 bool Range::isNodeFullyContained(Node& node) const { |
| 246 ContainerNode* parentNode = node.parentNode(); | 248 ContainerNode* parentNode = node.parentNode(); |
| 247 int nodeIndex = node.nodeIndex(); | 249 unsigned nodeIndex = node.nodeIndex(); |
| 248 return isPointInRange( | 250 return isPointInRange( |
| 249 parentNode, nodeIndex, | 251 parentNode, nodeIndex, |
| 250 IGNORE_EXCEPTION_FOR_TESTING) // starts in the middle of this | 252 IGNORE_EXCEPTION_FOR_TESTING) // starts in the middle of this |
| 251 // range, or on the boundary points. | 253 // range, or on the boundary points. |
| 252 && isPointInRange( | 254 && isPointInRange( |
| 253 parentNode, nodeIndex + 1, | 255 parentNode, nodeIndex + 1, |
| 254 IGNORE_EXCEPTION_FOR_TESTING); // ends in the middle of this | 256 IGNORE_EXCEPTION_FOR_TESTING); // ends in the middle of this |
| 255 // range, or on the boundary | 257 // range, or on the boundary |
| 256 // points. | 258 // points. |
| 257 } | 259 } |
| 258 | 260 |
| 259 bool Range::hasSameRoot(const Node& node) const { | 261 bool Range::hasSameRoot(const Node& node) const { |
| 260 if (node.document() != m_ownerDocument) | 262 if (node.document() != m_ownerDocument) |
| 261 return false; | 263 return false; |
| 262 // commonAncestorContainer() is O(depth). We should avoid to call it in common | 264 // commonAncestorContainer() is O(depth). We should avoid to call it in common |
| 263 // cases. | 265 // cases. |
| 264 if (node.isInTreeScope() && m_start.container()->isInTreeScope() && | 266 if (node.isInTreeScope() && m_start.container()->isInTreeScope() && |
| 265 &node.treeScope() == &m_start.container()->treeScope()) | 267 &node.treeScope() == &m_start.container()->treeScope()) |
| 266 return true; | 268 return true; |
| 267 return node.commonAncestor(*m_start.container(), NodeTraversal::parent); | 269 return node.commonAncestor(*m_start.container(), NodeTraversal::parent); |
| 268 } | 270 } |
| 269 | 271 |
| 270 bool Range::isPointInRange(Node* refNode, | 272 bool Range::isPointInRange(Node* refNode, |
| 271 int offset, | 273 unsigned offset, |
| 272 ExceptionState& exceptionState) const { | 274 ExceptionState& exceptionState) const { |
| 273 if (!refNode) { | 275 if (!refNode) { |
| 274 // FIXME: Generated bindings code never calls with null, and neither should | 276 // FIXME: Generated bindings code never calls with null, and neither should |
| 275 // other callers! | 277 // other callers! |
| 276 exceptionState.throwTypeError("The node provided is null."); | 278 exceptionState.throwTypeError("The node provided is null."); |
| 277 return false; | 279 return false; |
| 278 } | 280 } |
| 279 if (!hasSameRoot(*refNode)) | 281 if (!hasSameRoot(*refNode)) |
| 280 return false; | 282 return false; |
| 281 | 283 |
| 282 checkNodeWOffset(refNode, offset, exceptionState); | 284 checkNodeWOffset(refNode, offset, exceptionState); |
| 283 if (exceptionState.hadException()) | 285 if (exceptionState.hadException()) |
| 284 return false; | 286 return false; |
| 285 | 287 |
| 286 return compareBoundaryPoints(refNode, offset, m_start.container(), | 288 return compareBoundaryPoints(refNode, offset, m_start.container(), |
| 287 m_start.offset(), exceptionState) >= 0 && | 289 m_start.offset(), exceptionState) >= 0 && |
| 288 !exceptionState.hadException() && | 290 !exceptionState.hadException() && |
| 289 compareBoundaryPoints(refNode, offset, m_end.container(), | 291 compareBoundaryPoints(refNode, offset, m_end.container(), |
| 290 m_end.offset(), exceptionState) <= 0 && | 292 m_end.offset(), exceptionState) <= 0 && |
| 291 !exceptionState.hadException(); | 293 !exceptionState.hadException(); |
| 292 } | 294 } |
| 293 | 295 |
| 294 short Range::comparePoint(Node* refNode, | 296 short Range::comparePoint(Node* refNode, |
| 295 int offset, | 297 unsigned offset, |
| 296 ExceptionState& exceptionState) const { | 298 ExceptionState& exceptionState) const { |
| 297 // http://developer.mozilla.org/en/docs/DOM:range.comparePoint | 299 // http://developer.mozilla.org/en/docs/DOM:range.comparePoint |
| 298 // This method returns -1, 0 or 1 depending on if the point described by the | 300 // This method returns -1, 0 or 1 depending on if the point described by the |
| 299 // refNode node and an offset within the node is before, same as, or after the | 301 // refNode node and an offset within the node is before, same as, or after the |
| 300 // range respectively. | 302 // range respectively. |
| 301 | 303 |
| 302 if (!hasSameRoot(*refNode)) { | 304 if (!hasSameRoot(*refNode)) { |
| 303 exceptionState.throwDOMException( | 305 exceptionState.throwDOMException( |
| 304 WrongDocumentError, | 306 WrongDocumentError, |
| 305 "The node provided and the Range are not in the same tree."); | 307 "The node provided and the Range are not in the same tree."); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 return compareBoundaryPoints(m_end, sourceRange->m_end, exceptionState); | 374 return compareBoundaryPoints(m_end, sourceRange->m_end, exceptionState); |
| 373 case kEndToStart: | 375 case kEndToStart: |
| 374 return compareBoundaryPoints(m_start, sourceRange->m_end, exceptionState); | 376 return compareBoundaryPoints(m_start, sourceRange->m_end, exceptionState); |
| 375 } | 377 } |
| 376 | 378 |
| 377 NOTREACHED(); | 379 NOTREACHED(); |
| 378 return 0; | 380 return 0; |
| 379 } | 381 } |
| 380 | 382 |
| 381 short Range::compareBoundaryPoints(Node* containerA, | 383 short Range::compareBoundaryPoints(Node* containerA, |
| 382 int offsetA, | 384 unsigned offsetA, |
| 383 Node* containerB, | 385 Node* containerB, |
| 384 int offsetB, | 386 unsigned offsetB, |
| 385 ExceptionState& exceptionState) { | 387 ExceptionState& exceptionState) { |
| 386 bool disconnected = false; | 388 bool disconnected = false; |
| 387 short result = comparePositionsInDOMTree(containerA, offsetA, containerB, | 389 short result = comparePositionsInDOMTree(containerA, offsetA, containerB, |
| 388 offsetB, &disconnected); | 390 offsetB, &disconnected); |
| 389 if (disconnected) { | 391 if (disconnected) { |
| 390 exceptionState.throwDOMException( | 392 exceptionState.throwDOMException( |
| 391 WrongDocumentError, "The two ranges are in separate documents."); | 393 WrongDocumentError, "The two ranges are in separate documents."); |
| 392 return 0; | 394 return 0; |
| 393 } | 395 } |
| 394 return result; | 396 return result; |
| (...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 950 } | 952 } |
| 951 | 953 |
| 952 String Range::toString() const { | 954 String Range::toString() const { |
| 953 StringBuilder builder; | 955 StringBuilder builder; |
| 954 | 956 |
| 955 Node* pastLast = pastLastNode(); | 957 Node* pastLast = pastLastNode(); |
| 956 for (Node* n = firstNode(); n != pastLast; n = NodeTraversal::next(*n)) { | 958 for (Node* n = firstNode(); n != pastLast; n = NodeTraversal::next(*n)) { |
| 957 Node::NodeType type = n->getNodeType(); | 959 Node::NodeType type = n->getNodeType(); |
| 958 if (type == Node::kTextNode || type == Node::kCdataSectionNode) { | 960 if (type == Node::kTextNode || type == Node::kCdataSectionNode) { |
| 959 String data = toCharacterData(n)->data(); | 961 String data = toCharacterData(n)->data(); |
| 960 int length = data.length(); | 962 unsigned length = data.length(); |
| 961 int start = (n == m_start.container()) | 963 unsigned start = |
| 962 ? std::min(std::max(0, m_start.offset()), length) | 964 (n == m_start.container()) ? std::min(m_start.offset(), length) : 0; |
| 963 : 0; | 965 unsigned end = (n == m_end.container()) |
| 964 int end = (n == m_end.container()) | 966 ? std::min(std::max(start, m_end.offset()), length) |
| 965 ? std::min(std::max(start, m_end.offset()), length) | 967 : length; |
| 966 : length; | |
| 967 builder.append(data, start, end - start); | 968 builder.append(data, start, end - start); |
| 968 } | 969 } |
| 969 } | 970 } |
| 970 | 971 |
| 971 return builder.toString(); | 972 return builder.toString(); |
| 972 } | 973 } |
| 973 | 974 |
| 974 String Range::text() const { | 975 String Range::text() const { |
| 975 DCHECK(!m_ownerDocument->needsLayoutTreeUpdate()); | 976 DCHECK(!m_ownerDocument->needsLayoutTreeUpdate()); |
| 976 return plainText(EphemeralRange(this), | 977 return plainText(EphemeralRange(this), |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1018 return blink::createContextualFragment( | 1019 return blink::createContextualFragment( |
| 1019 markup, element, AllowScriptingContentAndDoNotMarkAlreadyStarted, | 1020 markup, element, AllowScriptingContentAndDoNotMarkAlreadyStarted, |
| 1020 exceptionState); | 1021 exceptionState); |
| 1021 } | 1022 } |
| 1022 | 1023 |
| 1023 void Range::detach() { | 1024 void Range::detach() { |
| 1024 // This is now a no-op as per the DOM specification. | 1025 // This is now a no-op as per the DOM specification. |
| 1025 } | 1026 } |
| 1026 | 1027 |
| 1027 Node* Range::checkNodeWOffset(Node* n, | 1028 Node* Range::checkNodeWOffset(Node* n, |
| 1028 int offset, | 1029 unsigned offset, |
| 1029 ExceptionState& exceptionState) { | 1030 ExceptionState& exceptionState) { |
| 1030 switch (n->getNodeType()) { | 1031 switch (n->getNodeType()) { |
| 1031 case Node::kDocumentTypeNode: | 1032 case Node::kDocumentTypeNode: |
| 1032 exceptionState.throwDOMException( | 1033 exceptionState.throwDOMException( |
| 1033 InvalidNodeTypeError, | 1034 InvalidNodeTypeError, |
| 1034 "The node provided is of type '" + n->nodeName() + "'."); | 1035 "The node provided is of type '" + n->nodeName() + "'."); |
| 1035 return nullptr; | 1036 return nullptr; |
| 1036 case Node::kCdataSectionNode: | 1037 case Node::kCdataSectionNode: |
| 1037 case Node::kCommentNode: | 1038 case Node::kCommentNode: |
| 1038 case Node::kTextNode: | 1039 case Node::kTextNode: |
| 1039 if (static_cast<unsigned>(offset) > toCharacterData(n)->length()) | 1040 if (offset > toCharacterData(n)->length()) { |
| 1041 exceptionState.throwDOMException( |
| 1042 IndexSizeError, "The offset " + String::number(offset) + |
| 1043 " is larger than the node's length (" + |
| 1044 String::number(toCharacterData(n)->length()) + |
| 1045 ")."); |
| 1046 } |
| 1047 return nullptr; |
| 1048 case Node::kProcessingInstructionNode: |
| 1049 if (offset > toProcessingInstruction(n)->data().length()) { |
| 1040 exceptionState.throwDOMException( | 1050 exceptionState.throwDOMException( |
| 1041 IndexSizeError, | 1051 IndexSizeError, |
| 1042 "The offset " + String::number(offset) + | 1052 "The offset " + String::number(offset) + |
| 1043 " is larger than or equal to the node's length (" + | 1053 " is larger than the node's length (" + |
| 1044 String::number(toCharacterData(n)->length()) + ")."); | |
| 1045 return nullptr; | |
| 1046 case Node::kProcessingInstructionNode: | |
| 1047 if (static_cast<unsigned>(offset) > | |
| 1048 toProcessingInstruction(n)->data().length()) | |
| 1049 exceptionState.throwDOMException( | |
| 1050 IndexSizeError, | |
| 1051 "The offset " + String::number(offset) + | |
| 1052 " is larger than or equal to than the node's length (" + | |
| 1053 String::number(toProcessingInstruction(n)->data().length()) + | 1054 String::number(toProcessingInstruction(n)->data().length()) + |
| 1054 ")."); | 1055 ")."); |
| 1056 } |
| 1055 return nullptr; | 1057 return nullptr; |
| 1056 case Node::kAttributeNode: | 1058 case Node::kAttributeNode: |
| 1057 case Node::kDocumentFragmentNode: | 1059 case Node::kDocumentFragmentNode: |
| 1058 case Node::kDocumentNode: | 1060 case Node::kDocumentNode: |
| 1059 case Node::kElementNode: { | 1061 case Node::kElementNode: { |
| 1060 if (!offset) | 1062 if (!offset) |
| 1061 return nullptr; | 1063 return nullptr; |
| 1062 Node* childBefore = NodeTraversal::childAt(*n, offset - 1); | 1064 Node* childBefore = NodeTraversal::childAt(*n, offset - 1); |
| 1063 if (!childBefore) | 1065 if (!childBefore) { |
| 1064 exceptionState.throwDOMException( | 1066 exceptionState.throwDOMException( |
| 1065 IndexSizeError, | 1067 IndexSizeError, |
| 1066 "There is no child at offset " + String::number(offset) + "."); | 1068 "There is no child at offset " + String::number(offset) + "."); |
| 1069 } |
| 1067 return childBefore; | 1070 return childBefore; |
| 1068 } | 1071 } |
| 1069 } | 1072 } |
| 1070 NOTREACHED(); | 1073 NOTREACHED(); |
| 1071 return nullptr; | 1074 return nullptr; |
| 1072 } | 1075 } |
| 1073 | 1076 |
| 1074 void Range::checkNodeBA(Node* n, ExceptionState& exceptionState) const { | 1077 void Range::checkNodeBA(Node* n, ExceptionState& exceptionState) const { |
| 1075 if (!n) { | 1078 if (!n) { |
| 1076 // FIXME: Generated bindings code never calls with null, and neither should | 1079 // FIXME: Generated bindings code never calls with null, and neither should |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1417 Node* endContainer = m_end.container(); | 1420 Node* endContainer = m_end.container(); |
| 1418 DCHECK(endContainer); | 1421 DCHECK(endContainer); |
| 1419 | 1422 |
| 1420 Node* stopNode = pastLastNode(); | 1423 Node* stopNode = pastLastNode(); |
| 1421 for (Node* node = firstNode(); node != stopNode; | 1424 for (Node* node = firstNode(); node != stopNode; |
| 1422 node = NodeTraversal::next(*node)) { | 1425 node = NodeTraversal::next(*node)) { |
| 1423 LayoutObject* r = node->layoutObject(); | 1426 LayoutObject* r = node->layoutObject(); |
| 1424 if (!r || !r->isText()) | 1427 if (!r || !r->isText()) |
| 1425 continue; | 1428 continue; |
| 1426 LayoutText* layoutText = toLayoutText(r); | 1429 LayoutText* layoutText = toLayoutText(r); |
| 1427 int startOffset = node == startContainer ? m_start.offset() : 0; | 1430 unsigned startOffset = node == startContainer ? m_start.offset() : 0; |
| 1428 int endOffset = | 1431 unsigned endOffset = node == endContainer |
| 1429 node == endContainer ? m_end.offset() : std::numeric_limits<int>::max(); | 1432 ? m_end.offset() |
| 1433 : std::numeric_limits<unsigned>::max(); |
| 1430 layoutText->absoluteRectsForRange(rects, startOffset, endOffset, | 1434 layoutText->absoluteRectsForRange(rects, startOffset, endOffset, |
| 1431 useSelectionHeight); | 1435 useSelectionHeight); |
| 1432 } | 1436 } |
| 1433 } | 1437 } |
| 1434 | 1438 |
| 1435 void Range::textQuads(Vector<FloatQuad>& quads, bool useSelectionHeight) const { | 1439 void Range::textQuads(Vector<FloatQuad>& quads, bool useSelectionHeight) const { |
| 1436 Node* startContainer = m_start.container(); | 1440 Node* startContainer = m_start.container(); |
| 1437 DCHECK(startContainer); | 1441 DCHECK(startContainer); |
| 1438 Node* endContainer = m_end.container(); | 1442 Node* endContainer = m_end.container(); |
| 1439 DCHECK(endContainer); | 1443 DCHECK(endContainer); |
| 1440 | 1444 |
| 1441 Node* stopNode = pastLastNode(); | 1445 Node* stopNode = pastLastNode(); |
| 1442 for (Node* node = firstNode(); node != stopNode; | 1446 for (Node* node = firstNode(); node != stopNode; |
| 1443 node = NodeTraversal::next(*node)) { | 1447 node = NodeTraversal::next(*node)) { |
| 1444 LayoutObject* r = node->layoutObject(); | 1448 LayoutObject* r = node->layoutObject(); |
| 1445 if (!r || !r->isText()) | 1449 if (!r || !r->isText()) |
| 1446 continue; | 1450 continue; |
| 1447 LayoutText* layoutText = toLayoutText(r); | 1451 LayoutText* layoutText = toLayoutText(r); |
| 1448 int startOffset = node == startContainer ? m_start.offset() : 0; | 1452 unsigned startOffset = node == startContainer ? m_start.offset() : 0; |
| 1449 int endOffset = | 1453 unsigned endOffset = node == endContainer |
| 1450 node == endContainer ? m_end.offset() : std::numeric_limits<int>::max(); | 1454 ? m_end.offset() |
| 1455 : std::numeric_limits<unsigned>::max(); |
| 1451 layoutText->absoluteQuadsForRange(quads, startOffset, endOffset, | 1456 layoutText->absoluteQuadsForRange(quads, startOffset, endOffset, |
| 1452 useSelectionHeight); | 1457 useSelectionHeight); |
| 1453 } | 1458 } |
| 1454 } | 1459 } |
| 1455 | 1460 |
| 1456 bool areRangesEqual(const Range* a, const Range* b) { | 1461 bool areRangesEqual(const Range* a, const Range* b) { |
| 1457 if (a == b) | 1462 if (a == b) |
| 1458 return true; | 1463 return true; |
| 1459 if (!a || !b) | 1464 if (!a || !b) |
| 1460 return false; | 1465 return false; |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1557 boundaryTextRemoved(m_end, text, offset, length); | 1562 boundaryTextRemoved(m_end, text, offset, length); |
| 1558 } | 1563 } |
| 1559 | 1564 |
| 1560 static inline void boundaryTextNodesMerged(RangeBoundaryPoint& boundary, | 1565 static inline void boundaryTextNodesMerged(RangeBoundaryPoint& boundary, |
| 1561 const NodeWithIndex& oldNode, | 1566 const NodeWithIndex& oldNode, |
| 1562 unsigned offset) { | 1567 unsigned offset) { |
| 1563 if (boundary.container() == oldNode.node()) | 1568 if (boundary.container() == oldNode.node()) |
| 1564 boundary.set(oldNode.node().previousSibling(), boundary.offset() + offset, | 1569 boundary.set(oldNode.node().previousSibling(), boundary.offset() + offset, |
| 1565 0); | 1570 0); |
| 1566 else if (boundary.container() == oldNode.node().parentNode() && | 1571 else if (boundary.container() == oldNode.node().parentNode() && |
| 1567 boundary.offset() == oldNode.index()) | 1572 boundary.offset() == static_cast<unsigned>(oldNode.index())) |
| 1568 boundary.set(oldNode.node().previousSibling(), offset, 0); | 1573 boundary.set(oldNode.node().previousSibling(), offset, 0); |
| 1569 } | 1574 } |
| 1570 | 1575 |
| 1571 void Range::didMergeTextNodes(const NodeWithIndex& oldNode, unsigned offset) { | 1576 void Range::didMergeTextNodes(const NodeWithIndex& oldNode, unsigned offset) { |
| 1572 DCHECK_EQ(oldNode.node().document(), m_ownerDocument); | 1577 DCHECK_EQ(oldNode.node().document(), m_ownerDocument); |
| 1573 DCHECK(oldNode.node().parentNode()); | 1578 DCHECK(oldNode.node().parentNode()); |
| 1574 DCHECK(oldNode.node().isTextNode()); | 1579 DCHECK(oldNode.node().isTextNode()); |
| 1575 DCHECK(oldNode.node().previousSibling()); | 1580 DCHECK(oldNode.node().previousSibling()); |
| 1576 DCHECK(oldNode.node().previousSibling()->isTextNode()); | 1581 DCHECK(oldNode.node().previousSibling()->isTextNode()); |
| 1577 boundaryTextNodesMerged(m_start, oldNode, offset); | 1582 boundaryTextNodesMerged(m_start, oldNode, offset); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1675 Vector<FloatQuad> elementQuads; | 1680 Vector<FloatQuad> elementQuads; |
| 1676 layoutObject->absoluteQuads(elementQuads); | 1681 layoutObject->absoluteQuads(elementQuads); |
| 1677 m_ownerDocument->adjustFloatQuadsForScrollAndAbsoluteZoom( | 1682 m_ownerDocument->adjustFloatQuadsForScrollAndAbsoluteZoom( |
| 1678 elementQuads, *layoutObject); | 1683 elementQuads, *layoutObject); |
| 1679 | 1684 |
| 1680 quads.appendVector(elementQuads); | 1685 quads.appendVector(elementQuads); |
| 1681 } | 1686 } |
| 1682 } | 1687 } |
| 1683 } else if (node->isTextNode()) { | 1688 } else if (node->isTextNode()) { |
| 1684 if (LayoutText* layoutText = toText(node)->layoutObject()) { | 1689 if (LayoutText* layoutText = toText(node)->layoutObject()) { |
| 1685 int startOffset = (node == startContainer) ? m_start.offset() : 0; | 1690 unsigned startOffset = (node == startContainer) ? m_start.offset() : 0; |
| 1686 int endOffset = (node == endContainer) ? m_end.offset() : INT_MAX; | 1691 unsigned endOffset = (node == endContainer) |
| 1692 ? m_end.offset() |
| 1693 : std::numeric_limits<unsigned>::max(); |
| 1687 | 1694 |
| 1688 Vector<FloatQuad> textQuads; | 1695 Vector<FloatQuad> textQuads; |
| 1689 layoutText->absoluteQuadsForRange(textQuads, startOffset, endOffset); | 1696 layoutText->absoluteQuadsForRange(textQuads, startOffset, endOffset); |
| 1690 m_ownerDocument->adjustFloatQuadsForScrollAndAbsoluteZoom(textQuads, | 1697 m_ownerDocument->adjustFloatQuadsForScrollAndAbsoluteZoom(textQuads, |
| 1691 *layoutText); | 1698 *layoutText); |
| 1692 | 1699 |
| 1693 quads.appendVector(textQuads); | 1700 quads.appendVector(textQuads); |
| 1694 } | 1701 } |
| 1695 } | 1702 } |
| 1696 } | 1703 } |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1760 .data() | 1767 .data() |
| 1761 << "start offset: " << range->startOffset() | 1768 << "start offset: " << range->startOffset() |
| 1762 << ", end offset: " << range->endOffset(); | 1769 << ", end offset: " << range->endOffset(); |
| 1763 } else { | 1770 } else { |
| 1764 LOG(INFO) << "Cannot show tree if range is null, or if boundary points are " | 1771 LOG(INFO) << "Cannot show tree if range is null, or if boundary points are " |
| 1765 "invalid."; | 1772 "invalid."; |
| 1766 } | 1773 } |
| 1767 } | 1774 } |
| 1768 | 1775 |
| 1769 #endif | 1776 #endif |
| OLD | NEW |