// A generic function for finding the target node with the lowest distance metric. A distance metric here is the result // of a distance-like function, that computes how well the touch hits the node. // Distance functions could for instance be distance squared or area of intersection. bool findNodeWithLowestDistanceMetric(Node*& targetNode, IntPoint& targetPoint, IntRect& targetArea, const IntPoint& touchHotspot, const IntRect& touchArea, SubtargetGeometryList& subtargets, DistanceFunction distanceFunction) { targetNode = 0; float bestDistanceMetric = std::numeric_limits<float>::infinity(); SubtargetGeometryList::const_iterator it = subtargets.begin(); const SubtargetGeometryList::const_iterator end = subtargets.end(); IntPoint adjustedPoint; for (; it != end; ++it) { Node* node = it->node(); float distanceMetric = distanceFunction(touchHotspot, touchArea, *it); if (distanceMetric < bestDistanceMetric) { if (snapTo(*it, touchHotspot, touchArea, adjustedPoint)) { targetPoint = adjustedPoint; targetArea = it->boundingBox(); targetNode = node; bestDistanceMetric = distanceMetric; } } else if (distanceMetric - bestDistanceMetric < zeroTolerance) { if (snapTo(*it, touchHotspot, touchArea, adjustedPoint)) { if (node->isDescendantOf(targetNode)) { // Try to always return the inner-most element. targetPoint = adjustedPoint; targetNode = node; targetArea = it->boundingBox(); } } } } if (targetNode) { targetArea = targetNode->document()->view()->contentsToWindow(targetArea); } return (targetNode); }
static inline void appendQuadsToSubtargetList(Vector<FloatQuad>& quads, Node* node, SubtargetGeometryList& subtargets) { Vector<FloatQuad>::const_iterator it = quads.begin(); const Vector<FloatQuad>::const_iterator end = quads.end(); for (; it != end; ++it) subtargets.append(SubtargetGeometry(node, *it)); }
static inline void appendSubtargetsForNodeToList(Node* node, SubtargetGeometryList& subtargets) { // Since the node is a result of a hit test, we are already ensured it has a renderer. ASSERT(node->renderer()); Vector<FloatQuad> quads; node->renderer()->absoluteQuads(quads); Vector<FloatQuad>::const_iterator it = quads.begin(); const Vector<FloatQuad>::const_iterator end = quads.end(); for (; it != end; ++it) subtargets.append(SubtargetGeometry(node, *it)); }
// A generic function for finding the target node with the lowest distance metric. A distance metric here is the result // of a distance-like function, that computes how well the touch hits the node. // Distance functions could for instance be distance squared or area of intersection. bool findNodeWithLowestDistanceMetric(Node*& targetNode, IntPoint& targetPoint, const IntPoint& touchHotspot, const IntRect& touchArea, SubtargetGeometryList& subtargets, DistanceFunction distanceFunction) { targetNode = 0; float bestDistanceMetric = INFINITY; SubtargetGeometryList::const_iterator it = subtargets.begin(); const SubtargetGeometryList::const_iterator end = subtargets.end(); for (; it != end; ++it) { Node* node = it->node(); float distanceMetric = distanceFunction(touchHotspot, touchArea, *it); if (distanceMetric < bestDistanceMetric) { targetPoint = roundedIntPoint(it->quad().center()); targetNode = node; bestDistanceMetric = distanceMetric; } else if (distanceMetric == bestDistanceMetric) { // Try to always return the inner-most element. if (node->isDescendantOf(targetNode)) targetNode = node; } } return (targetNode); }
static inline void appendZoomableSubtargets(Node* node, SubtargetGeometryList& subtargets) { RenderBox* renderer = toRenderBox(node->renderer()); ASSERT(renderer); Vector<FloatQuad> quads; FloatRect borderBoxRect = renderer->borderBoxRect(); FloatRect contentBoxRect = renderer->contentBoxRect(); quads.append(renderer->localToAbsoluteQuad(borderBoxRect)); if (borderBoxRect != contentBoxRect) quads.append(renderer->localToAbsoluteQuad(contentBoxRect)); // FIXME: For RenderBlocks, add column boxes and content boxes cleared for floats. Vector<FloatQuad>::const_iterator it = quads.begin(); const Vector<FloatQuad>::const_iterator end = quads.end(); for (; it != end; ++it) subtargets.append(SubtargetGeometry(node, *it)); }