bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction) { IntPoint pointInContainer(_x, _y); IntSize containerToParentOffset(_tx, _ty); IntPoint pointInParent = pointInContainer - containerToParentOffset; IntPoint pointInBorderBox = pointInParent - parentOriginToBorderBox(); // Note: For now, we're ignoring hits to border and padding for <svg> IntPoint pointInContentBox = pointInBorderBox - borderOriginToContentBox(); if (!contentBoxRect().contains(pointInContentBox)) return false; IntPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent); for (RenderObject* child = lastChild(); child; child = child->previousSibling()) { if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) { // FIXME: CSS/HTML assumes the local point is relative to the border box, right? updateHitTestResult(result, pointInBorderBox); return true; } } // Spec: Only graphical elements can be targeted by the mouse, so we don't check self here. // 16.4: "If there are no graphics elements whose relevant graphics content is under the pointer (i.e., there is no target element), the event is not dispatched." return false; }
bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const IntPoint& pointInContainer, const IntPoint& accumulatedOffset, HitTestAction hitTestAction) { IntPoint pointInParent = pointInContainer - toSize(accumulatedOffset); IntPoint pointInBorderBox = pointInParent - parentOriginToBorderBox(); // Note: For now, we're ignoring hits to border and padding for <svg> IntPoint pointInContentBox = pointInBorderBox - borderOriginToContentBox(); if (!contentBoxRect().contains(pointInContentBox)) return false; IntPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent); for (RenderObject* child = lastChild(); child; child = child->previousSibling()) { if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) { // FIXME: CSS/HTML assumes the local point is relative to the border box, right? updateHitTestResult(result, pointInBorderBox); // FIXME: nodeAtFloatPoint() doesn't handle rect-based hit tests yet. result.addNodeToRectBasedTestResult(child->node(), pointInContainer); return true; } } // If we didn't early exit above, we've just hit the container <svg> element. Unlike SVG 1.1, 2nd Edition allows container elements to be hit. if (hitTestAction == HitTestBlockBackground && style()->pointerEvents() != PE_NONE) { // Only return true here, if the last hit testing phase 'BlockBackground' is executed. If we'd return true in the 'Foreground' phase, // hit testing would stop immediately. For SVG only trees this doesn't matter. Though when we have a <foreignObject> subtree we need // to be able to detect hits on the background of a <div> element. If we'd return true here in the 'Foreground' phase, we are not able // to detect these hits anymore. updateHitTestResult(result, roundedIntPoint(localPoint)); return true; } return false; }
// RenderBox methods will expect coordinates w/o any transforms in coordinates // relative to our borderBox origin. This method gives us exactly that. AffineTransform RenderSVGRoot::localToBorderBoxTransform() const { IntSize borderAndPadding = borderOriginToContentBox(); SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); float scale = svg->currentScale(); AffineTransform ctm(scale, 0, 0, scale, borderAndPadding.width(), borderAndPadding.height()); ctm.translate(svg->currentTranslate().x(), svg->currentTranslate().y()); return svg->viewBoxToViewTransform(width(), height()) * ctm; }
// RenderBox methods will expect coordinates w/o any transforms in coordinates // relative to our borderBox origin. This method gives us exactly that. AffineTransform RenderSVGRoot::localToBorderBoxTransform() const { IntSize borderAndPadding = borderOriginToContentBox(); SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); float scale = style()->effectiveZoom(); FloatPoint translate = svg->currentTranslate(); AffineTransform ctm(scale, 0, 0, scale, borderAndPadding.width() + translate.x(), borderAndPadding.height() + translate.y()); return ctm * svg->viewBoxToViewTransform(width() / scale, height() / scale); }