bool LayoutSVGImage::nodeAtFloatPoint(HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) { // We only draw in the forground phase, so we only hit-test then. if (hitTestAction != HitTestForeground) return false; PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_IMAGE_HITTESTING, result.hitTestRequest(), style()->pointerEvents()); bool isVisible = (style()->visibility() == VISIBLE); if (isVisible || !hitRules.requireVisible) { FloatPoint localPoint; if (!SVGLayoutSupport::transformToUserSpaceAndCheckClipping(this, localToSVGParentTransform(), pointInParent, localPoint)) return false; if (hitRules.canHitFill || hitRules.canHitBoundingBox) { if (m_objectBoundingBox.contains(localPoint)) { const LayoutPoint& localLayoutPoint = roundedLayoutPoint(localPoint); updateHitTestResult(result, localLayoutPoint); if (result.addNodeToListBasedTestResult(element(), localLayoutPoint) == StopHitTesting) return true; } } } return false; }
bool LayoutSVGShape::nodeAtFloatPoint(HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) { // We only draw in the foreground phase, so we only hit-test then. if (hitTestAction != HitTestForeground) return false; FloatPoint localPoint; if (!SVGLayoutSupport::transformToUserSpaceAndCheckClipping( *this, localToSVGParentTransform(), pointInParent, localPoint)) return false; PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_GEOMETRY_HITTESTING, result.hitTestRequest(), style()->pointerEvents()); if (nodeAtFloatPointInternal(result.hitTestRequest(), localPoint, hitRules)) { const LayoutPoint& localLayoutPoint = LayoutPoint(localPoint); updateHitTestResult(result, localLayoutPoint); if (result.addNodeToListBasedTestResult(element(), localLayoutPoint) == StopHitTesting) return true; } return false; }
FloatRect LayoutSVGResourceMarker::markerBoundaries(const AffineTransform& markerTransformation) const { FloatRect coordinates = LayoutSVGContainer::paintInvalidationRectInLocalSVGCoordinates(); // Map paint invalidation rect into parent coordinate space, in which the marker boundaries have to be evaluated coordinates = localToSVGParentTransform().mapRect(coordinates); return markerTransformation.mapRect(coordinates); }
bool LayoutSVGContainer::nodeAtFloatPoint(HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) { // Give LayoutSVGViewportContainer a chance to apply its viewport clip if (!pointIsInsideViewportClip(pointInParent)) return false; FloatPoint localPoint; if (!SVGLayoutSupport::transformToUserSpaceAndCheckClipping( *this, localToSVGParentTransform(), pointInParent, localPoint)) return false; for (LayoutObject* child = lastChild(); child; child = child->previousSibling()) { if (child->nodeAtFloatPoint(result, localPoint, hitTestAction)) { const LayoutPoint& localLayoutPoint = roundedLayoutPoint(localPoint); updateHitTestResult(result, localLayoutPoint); if (result.addNodeToListBasedTestResult( child->node(), localLayoutPoint) == StopHitTesting) return true; } } // pointer-events: bounding-box makes it possible for containers to be direct // targets. if (style()->pointerEvents() == PE_BOUNDINGBOX) { // Check for a valid bounding box because it will be invalid for empty // containers. if (isObjectBoundingBoxValid() && objectBoundingBox().contains(localPoint)) { const LayoutPoint& localLayoutPoint = roundedLayoutPoint(localPoint); updateHitTestResult(result, localLayoutPoint); if (result.addNodeToListBasedTestResult(element(), localLayoutPoint) == StopHitTesting) return true; } } // 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; }