// Uses a hybrid of distance to adjust and intersect ratio, normalizing each score between 0 and 1 // and combining them. The distance to adjust works best for disambiguating clicks on targets such // as links, where the width may be significantly larger than the touch width. Using area of overlap // in such cases can lead to a bias towards shorter links. Conversely, percentage of overlap can // provide strong confidence in tapping on a small target, where the overlap is often quite high, // and works well for tightly packed controls. float hybridDistanceFunction(const IntPoint& touchHotspot, const IntRect& touchRect, const SubtargetGeometry& subtarget) { IntRect rect = subtarget.boundingBox(); // Convert from frame coordinates to window coordinates. rect = subtarget.node()->document()->view()->contentsToWindow(rect); float radiusSquared = 0.25f * (touchRect.size().diagonalLengthSquared()); float distanceToAdjustScore = rect.distanceSquaredToPoint(touchHotspot) / radiusSquared; int maxOverlapWidth = std::min(touchRect.width(), rect.width()); int maxOverlapHeight = std::min(touchRect.height(), rect.height()); float maxOverlapArea = std::max(maxOverlapWidth * maxOverlapHeight, 1); rect.intersect(touchRect); float intersectArea = rect.size().area(); float intersectionScore = 1 - intersectArea / maxOverlapArea; float hybridScore = intersectionScore + distanceToAdjustScore; return hybridScore; }