2 * Copyright (c) 2009, Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include "RenderSVGModelObject.h"
36 #include "RenderSVGResource.h"
37 #include "SVGStyledElement.h"
41 RenderSVGModelObject::RenderSVGModelObject(SVGStyledElement* node)
46 LayoutRect RenderSVGModelObject::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const
48 return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer);
51 void RenderSVGModelObject::computeRectForRepaint(RenderBoxModelObject* repaintContainer, LayoutRect& repaintRect, bool fixed) const
53 SVGRenderSupport::computeRectForRepaint(this, repaintContainer, repaintRect, fixed);
56 void RenderSVGModelObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, bool* wasFixed) const
58 SVGRenderSupport::mapLocalToContainer(this, repaintContainer, fixed, useTransforms, transformState, wasFixed);
61 // Copied from RenderBox, this method likely requires further refactoring to work easily for both SVG and CSS Box Model content.
62 // FIXME: This may also need to move into SVGRenderSupport as the RenderBox version depends
63 // on borderBoundingBox() which SVG RenderBox subclases (like SVGRenderBlock) do not implement.
64 LayoutRect RenderSVGModelObject::outlineBoundsForRepaint(RenderBoxModelObject* repaintContainer, LayoutPoint*) const
66 LayoutRect box = enclosingLayoutRect(repaintRectInLocalCoordinates());
67 adjustRectForOutlineAndShadow(box);
69 FloatQuad containerRelativeQuad = localToContainerQuad(FloatRect(box), repaintContainer);
70 return containerRelativeQuad.enclosingBoundingBox();
73 void RenderSVGModelObject::absoluteRects(Vector<LayoutRect>&, const LayoutPoint&)
75 // This code path should never be taken for SVG, as we're assuming useTransforms=true everywhere, absoluteQuads should be used.
79 void RenderSVGModelObject::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed)
81 quads.append(localToAbsoluteQuad(strokeBoundingBox(), false, wasFixed));
84 void RenderSVGModelObject::willBeDestroyed()
86 SVGResourcesCache::clientDestroyed(this);
87 RenderObject::willBeDestroyed();
90 void RenderSVGModelObject::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
92 if (diff == StyleDifferenceLayout)
93 setNeedsBoundariesUpdate();
94 RenderObject::styleWillChange(diff, newStyle);
97 void RenderSVGModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
99 RenderObject::styleDidChange(diff, oldStyle);
100 SVGResourcesCache::clientStyleChanged(this, diff, style());
103 void RenderSVGModelObject::updateFromElement()
105 RenderObject::updateFromElement();
106 SVGResourcesCache::clientUpdatedFromElement(this, style());
109 bool RenderSVGModelObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, const LayoutPoint&, const LayoutPoint&, HitTestAction)
111 ASSERT_NOT_REACHED();
115 static void getElementCTM(SVGElement* element, AffineTransform& transform)
118 element->document()->updateLayoutIgnorePendingStylesheets();
120 SVGElement* stopAtElement = SVGLocatable::nearestViewportElement(element);
121 ASSERT(stopAtElement);
123 Node* current = element;
124 while (current && current->isSVGElement()) {
125 SVGElement* currentElement = static_cast<SVGElement*>(current);
126 if (currentElement->isStyled())
127 transform = const_cast<AffineTransform&>(currentElement->renderer()->localToParentTransform()).multiply(transform);
129 // For getCTM() computation, stop at the nearest viewport element
130 if (currentElement == stopAtElement)
133 current = current->parentOrHostNode();
137 // FloatRect::intersects does not consider horizontal or vertical lines (because of isEmpty()).
138 // So special-case handling of such lines.
139 static bool intersectsAllowingEmpty(const FloatRect& r, const FloatRect& other)
141 if (r.isEmpty() && other.isEmpty())
143 if (r.isEmpty() && !other.isEmpty()) {
144 return (other.contains(r.x(), r.y()) && !other.contains(r.maxX(), r.maxY()))
145 || (!other.contains(r.x(), r.y()) && other.contains(r.maxX(), r.maxY()));
147 if (other.isEmpty() && !r.isEmpty())
148 return intersectsAllowingEmpty(other, r);
149 return r.intersects(other);
152 // One of the element types that can cause graphics to be drawn onto the target canvas. Specifically: circle, ellipse,
153 // image, line, path, polygon, polyline, rect, text and use.
154 static bool isGraphicsElement(RenderObject* renderer)
156 return renderer->isSVGPath() || renderer->isSVGText() || renderer->isSVGImage() || renderer->isSVGShadowTreeRootContainer();
159 bool RenderSVGModelObject::checkIntersection(RenderObject* renderer, const FloatRect& rect)
161 if (!renderer || renderer->style()->pointerEvents() == PE_NONE)
163 if (!isGraphicsElement(renderer))
166 getElementCTM(static_cast<SVGElement*>(renderer->node()), ctm);
167 return intersectsAllowingEmpty(rect, ctm.mapRect(renderer->repaintRectInLocalCoordinates()));
170 bool RenderSVGModelObject::checkEnclosure(RenderObject* renderer, const FloatRect& rect)
172 if (!renderer || renderer->style()->pointerEvents() == PE_NONE)
174 if (!isGraphicsElement(renderer))
177 getElementCTM(static_cast<SVGElement*>(renderer->node()), ctm);
178 return rect.contains(ctm.mapRect(renderer->repaintRectInLocalCoordinates()));
181 } // namespace WebCore
183 #endif // ENABLE(SVG)