Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org> | 2 * Copyright (C) 2004, 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org> |
| 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Rob Buis <buis@kde.org> | 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Rob Buis <buis@kde.org> |
| 4 * Copyright (C) 2007 Apple Inc. All rights reserved. | 4 * Copyright (C) 2007 Apple Inc. All rights reserved. |
| 5 * | 5 * |
| 6 * This library is free software; you can redistribute it and/or | 6 * This library is free software; you can redistribute it and/or |
| 7 * modify it under the terms of the GNU Library General Public | 7 * modify it under the terms of the GNU Library General Public |
| 8 * License as published by the Free Software Foundation; either | 8 * License as published by the Free Software Foundation; either |
| 9 * version 2 of the License, or (at your option) any later version. | 9 * version 2 of the License, or (at your option) any later version. |
| 10 * | 10 * |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 322 if (updateRelativeLengthsOrViewBox | 322 if (updateRelativeLengthsOrViewBox |
| 323 || SVGZoomAndPan::isKnownAttribute(attrName)) { | 323 || SVGZoomAndPan::isKnownAttribute(attrName)) { |
| 324 if (renderer()) | 324 if (renderer()) |
| 325 RenderSVGResource::markForLayoutAndParentResourceInvalidation(render er()); | 325 RenderSVGResource::markForLayoutAndParentResourceInvalidation(render er()); |
| 326 return; | 326 return; |
| 327 } | 327 } |
| 328 | 328 |
| 329 SVGGraphicsElement::svgAttributeChanged(attrName); | 329 SVGGraphicsElement::svgAttributeChanged(attrName); |
| 330 } | 330 } |
| 331 | 331 |
| 332 PassRefPtr<NodeList> SVGSVGElement::collectIntersectionOrEnclosureList(const Flo atRect& rect, SVGElement* referenceElement, CollectIntersectionOrEnclosure colle ct) const | 332 // FloatRect::intersects does not consider horizontal or vertical lines (because of isEmpty()). |
| 333 // So special-case handling of such lines. | |
| 334 static bool intersectsAllowingEmpty(const FloatRect& r, const FloatRect& other) | |
|
Stephen Chennney
2014/03/03 13:00:22
Either this is much simpler to implement, or I'm n
f(malita)
2014/03/03 14:12:18
TBH I haven't looked beyond the comments when movi
| |
| 335 { | |
| 336 if (r.isEmpty() && other.isEmpty()) | |
|
fs
2014/03/03 10:44:32
This function had me wondering...
Since isEmpty()
| |
| 337 return false; | |
| 338 if (r.isEmpty() && !other.isEmpty()) { | |
| 339 return (other.contains(r.x(), r.y()) && !other.contains(r.maxX(), r.maxY ())) | |
| 340 || (!other.contains(r.x(), r.y()) && other.contains(r.maxX(), r.maxY ())); | |
| 341 } | |
| 342 if (other.isEmpty() && !r.isEmpty()) | |
| 343 return intersectsAllowingEmpty(other, r); | |
|
fs
2014/03/03 10:44:32
Might make sense to just make the code in the abov
| |
| 344 return r.intersects(other); | |
| 345 } | |
| 346 | |
| 347 // One of the element types that can cause graphics to be drawn onto the target canvas. | |
| 348 // Specifically: circle, ellipse, image, line, path, polygon, polyline, rect, te xt and use. | |
| 349 static bool isIntersectionOrEnclosureTarget(RenderObject* renderer) | |
| 350 { | |
| 351 return renderer->isSVGShape() | |
| 352 || renderer->isSVGText() | |
| 353 || renderer->isSVGImage() | |
| 354 || renderer->node()->hasTagName(SVGNames::useTag); | |
| 355 } | |
| 356 | |
| 357 bool SVGSVGElement::checkIntersectionOrEnclosure(const SVGElement& element, cons t FloatRect& rect, | |
| 358 CheckIntersectionOrEnclosure mode) const | |
| 359 { | |
| 360 RenderObject* renderer = element.renderer(); | |
| 361 ASSERT(!renderer || renderer->style()); | |
| 362 if (!renderer || renderer->style()->pointerEvents() == PE_NONE) | |
| 363 return false; | |
| 364 | |
| 365 if (!isIntersectionOrEnclosureTarget(renderer)) | |
| 366 return false; | |
| 367 | |
| 368 ASSERT(WebCore::isSVGGraphicsElement(element)); | |
| 369 AffineTransform ctm = toSVGGraphicsElement(element).computeCTM(AncestorScope , DisallowStyleUpdate, this); | |
| 370 FloatRect mappedRepaintRect = ctm.mapRect(renderer->repaintRectInLocalCoordi nates()); | |
| 371 | |
| 372 bool result = false; | |
| 373 switch (mode) { | |
| 374 case CheckIntersection: | |
| 375 result = intersectsAllowingEmpty(rect, mappedRepaintRect); | |
| 376 break; | |
| 377 case CheckEnclosure: | |
| 378 result = rect.contains(mappedRepaintRect); | |
| 379 break; | |
| 380 default: | |
| 381 ASSERT_NOT_REACHED(); | |
| 382 break; | |
| 383 } | |
| 384 | |
| 385 return result; | |
| 386 } | |
| 387 | |
| 388 PassRefPtr<NodeList> SVGSVGElement::collectIntersectionOrEnclosureList(const Flo atRect& rect, | |
| 389 SVGElement* referenceElement, CheckIntersectionOrEnclosure mode) const | |
| 333 { | 390 { |
| 334 Vector<RefPtr<Node> > nodes; | 391 Vector<RefPtr<Node> > nodes; |
| 335 Element* element = ElementTraversal::next(*(referenceElement ? referenceElem ent : this)); | 392 |
| 336 while (element) { | 393 const SVGElement* root = this; |
| 337 if (element->isSVGElement()) { | 394 if (referenceElement) { |
|
fs
2014/03/03 10:44:32
Some test(s) for this case would be nice - but I'm
f(malita)
2014/03/03 14:12:18
I'll add some willingly :)
| |
| 338 SVGElement* svgElement = toSVGElement(element); | 395 // Only the common subtree needs to be traversed. |
| 339 if (collect == CollectIntersectionList) { | 396 if (contains(referenceElement)) { |
| 340 if (RenderSVGModelObject::checkIntersection(svgElement->renderer (), rect)) | 397 root = referenceElement; |
| 341 nodes.append(element); | 398 } else if (!isDescendantOf(referenceElement)) { |
| 342 } else { | 399 // No common subtree: the spec is not clear about this case - should we bend over backwards |
|
fs
2014/03/03 10:44:32
I think this is in line with the spec wording, so
f(malita)
2014/03/03 14:12:18
Awesome, I'll remove the comment then.
| |
| 343 if (RenderSVGModelObject::checkEnclosure(svgElement->renderer(), rect)) | 400 // to find a common ancestor and map everything in its space? |
| 344 nodes.append(element); | 401 return StaticNodeList::adopt(nodes); |
| 345 } | |
| 346 } | 402 } |
| 403 } | |
| 347 | 404 |
| 348 element = ElementTraversal::next(*element, referenceElement ? referenceE lement : this); | 405 for (Element* element = ElementTraversal::firstWithin(*root); element; |
| 406 element = ElementTraversal::next(*element, root)) { | |
| 407 | |
| 408 if (!WebCore::isSVGGraphicsElement(*element)) | |
| 409 continue; | |
| 410 | |
| 411 SVGElement* svgElement = toSVGElement(element); | |
| 412 if (checkIntersectionOrEnclosure(*svgElement, rect, mode)) | |
| 413 nodes.append(element); | |
| 349 } | 414 } |
| 415 | |
| 350 return StaticNodeList::adopt(nodes); | 416 return StaticNodeList::adopt(nodes); |
| 351 } | 417 } |
| 352 | 418 |
| 353 PassRefPtr<NodeList> SVGSVGElement::getIntersectionList(PassRefPtr<SVGRectTearOf f> passRect, SVGElement* referenceElement) const | 419 PassRefPtr<NodeList> SVGSVGElement::getIntersectionList(PassRefPtr<SVGRectTearOf f> rect, SVGElement* referenceElement) const |
| 354 { | 420 { |
| 355 RefPtr<SVGRectTearOff> rect = passRect; | 421 document().updateLayoutIgnorePendingStylesheets(); |
| 356 return collectIntersectionOrEnclosureList(rect->target()->value(), reference Element, CollectIntersectionList); | 422 |
| 423 return collectIntersectionOrEnclosureList(rect->target()->value(), reference Element, CheckIntersection); | |
| 357 } | 424 } |
| 358 | 425 |
| 359 PassRefPtr<NodeList> SVGSVGElement::getEnclosureList(PassRefPtr<SVGRectTearOff> passRect, SVGElement* referenceElement) const | 426 PassRefPtr<NodeList> SVGSVGElement::getEnclosureList(PassRefPtr<SVGRectTearOff> rect, SVGElement* referenceElement) const |
| 360 { | 427 { |
| 361 RefPtr<SVGRectTearOff> rect = passRect; | 428 document().updateLayoutIgnorePendingStylesheets(); |
| 362 return collectIntersectionOrEnclosureList(rect->target()->value(), reference Element, CollectEnclosureList); | 429 |
| 430 return collectIntersectionOrEnclosureList(rect->target()->value(), reference Element, CheckEnclosure); | |
| 363 } | 431 } |
| 364 | 432 |
| 365 bool SVGSVGElement::checkIntersection(SVGElement* element, PassRefPtr<SVGRectTea rOff> passRect) const | 433 bool SVGSVGElement::checkIntersection(SVGElement* element, PassRefPtr<SVGRectTea rOff> rect) const |
| 366 { | 434 { |
| 367 RefPtr<SVGRectTearOff> rect = passRect; | 435 ASSERT(element); |
| 368 return RenderSVGModelObject::checkIntersection(element->renderer(), rect->ta rget()->value()); | 436 document().updateLayoutIgnorePendingStylesheets(); |
| 437 | |
| 438 return checkIntersectionOrEnclosure(*element, rect->target()->value(), Check Intersection); | |
| 369 } | 439 } |
| 370 | 440 |
| 371 bool SVGSVGElement::checkEnclosure(SVGElement* element, PassRefPtr<SVGRectTearOf f> passRect) const | 441 bool SVGSVGElement::checkEnclosure(SVGElement* element, PassRefPtr<SVGRectTearOf f> rect) const |
| 372 { | 442 { |
| 373 RefPtr<SVGRectTearOff> rect = passRect; | 443 ASSERT(element); |
| 374 return RenderSVGModelObject::checkEnclosure(element->renderer(), rect->targe t()->value()); | 444 document().updateLayoutIgnorePendingStylesheets(); |
| 445 | |
| 446 return checkIntersectionOrEnclosure(*element, rect->target()->value(), Check Enclosure); | |
| 375 } | 447 } |
| 376 | 448 |
| 377 void SVGSVGElement::deselectAll() | 449 void SVGSVGElement::deselectAll() |
| 378 { | 450 { |
| 379 if (LocalFrame* frame = document().frame()) | 451 if (LocalFrame* frame = document().frame()) |
| 380 frame->selection().clear(); | 452 frame->selection().clear(); |
| 381 } | 453 } |
| 382 | 454 |
| 383 PassRefPtr<SVGNumberTearOff> SVGSVGElement::createSVGNumber() | 455 PassRefPtr<SVGNumberTearOff> SVGSVGElement::createSVGNumber() |
| 384 { | 456 { |
| (...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 780 Vector<Element*>::const_iterator end = elements.end(); | 852 Vector<Element*>::const_iterator end = elements.end(); |
| 781 for (Vector<Element*>::const_iterator it = elements.begin(); it != end; ++it ) { | 853 for (Vector<Element*>::const_iterator it = elements.begin(); it != end; ++it ) { |
| 782 if ((*it)->isDescendantOf(this)) | 854 if ((*it)->isDescendantOf(this)) |
| 783 return *it; | 855 return *it; |
| 784 } | 856 } |
| 785 | 857 |
| 786 return 0; | 858 return 0; |
| 787 } | 859 } |
| 788 | 860 |
| 789 } | 861 } |
| OLD | NEW |