Changeset 129108 in webkit


Ignore:
Timestamp:
Sep 20, 2012 1:44:43 AM (12 years ago)
Author:
allan.jensen@nokia.com
Message:

[TouchAdjustment] Simplify and improve hybrid distance function.
https://bugs.webkit.org/show_bug.cgi?id=96519

Reviewed by Antonio Gomes.

The current distance function is a combination of two functions. One measuring the distance from
the hot-spot in the touch-area to the centerline of the target, and one measuring how much of the
target is covered.

The distance to the center-line was used instead of just the distance to the target, to make it
easier to hit small targets near big targets. The very same feature is however also the reason
measuring how much the target is covered is added. Using the distance to center-line is therefore
redundant now, and can be replaced with the simpler 'distance the hot-spot needs to be adjusted'.

Tested by existing touchadjustment tests.

  • page/TouchAdjustment.cpp:

(TouchAdjustment):
(WebCore::TouchAdjustment::hybridDistanceFunction):

  • platform/graphics/IntRect.cpp:
  • platform/graphics/IntRect.h:

(IntRect):

Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r129107 r129108  
     12012-09-20  Allan Sandfeld Jensen  <allan.jensen@nokia.com>
     2
     3        [TouchAdjustment] Simplify and improve hybrid distance function.
     4        https://bugs.webkit.org/show_bug.cgi?id=96519
     5
     6        Reviewed by Antonio Gomes.
     7
     8        The current distance function is a combination of two functions. One measuring the distance from
     9        the hot-spot in the touch-area to the centerline of the target, and one measuring how much of the
     10        target is covered.
     11
     12        The distance to the center-line was used instead of just the distance to the target, to make it
     13        easier to hit small targets near big targets. The very same feature is however also the reason
     14        measuring how much the target is covered is added. Using the distance to center-line is therefore
     15        redundant now, and can be replaced with the simpler 'distance the hot-spot needs to be adjusted'.
     16
     17        Tested by existing touchadjustment tests.
     18
     19        * page/TouchAdjustment.cpp:
     20        (TouchAdjustment):
     21        (WebCore::TouchAdjustment::hybridDistanceFunction):
     22        * platform/graphics/IntRect.cpp:
     23        * platform/graphics/IntRect.h:
     24        (IntRect):
     25
    1262012-09-20  Yoshifumi Inoue  <yosin@chromium.org>
    227
  • trunk/Source/WebCore/page/TouchAdjustment.cpp

    r128757 r129108  
    286286}
    287287
    288 
    289 float distanceSquaredToTargetCenterLine(const IntPoint& touchHotspot, const IntRect& touchArea, const SubtargetGeometry& subtarget)
    290 {
    291     UNUSED_PARAM(touchArea);
    292     // For a better center of a line-box we use the center-line instead of the center-point.
    293     // We use the center-line of the bounding box of the quad though, since it is much faster
    294     // and gives the same result in all untransformed cases, and in transformed cases still
    295     // gives a better distance-function than the distance to the center-point.
    296     IntRect rect = subtarget.boundingBox();
    297     ASSERT(subtarget.node()->document());
    298     ASSERT(subtarget.node()->document()->view());
    299     // Convert from frame coordinates to window coordinates.
    300     rect = subtarget.node()->document()->view()->contentsToWindow(rect);
    301 
    302     return rect.distanceSquaredFromCenterLineToPoint(touchHotspot);
    303 }
    304 
    305288// This returns quotient of the target area and its intersection with the touch area.
    306289// This will prioritize largest intersection and smallest area, while balancing the two against each other.
     
    322305}
    323306
    324 // Uses a hybrid of distance to center and intersect ratio, normalizing each
    325 // score between 0 and 1 and choosing the better score. The distance to
    326 // centerline works best for disambiguating clicks on targets such as links,
    327 // where the width may be significantly larger than the touch width. Using
    328 // area of overlap in such cases can lead to a bias towards shorter links.
    329 // Conversely, percentage of overlap can provide strong confidence in tapping
    330 // on a small target, where the overlap is often quite high, and works well
    331 // for tightly packed controls.
    332 float hybridDistanceFunction(const IntPoint& touchHotspot, const IntRect& touchArea, const SubtargetGeometry& subtarget)
     307// Uses a hybrid of distance to adjust and intersect ratio, normalizing each score between 0 and 1
     308// and combining them. The distance to adjust works best for disambiguating clicks on targets such
     309// as links, where the width may be significantly larger than the touch width. Using area of overlap
     310// in such cases can lead to a bias towards shorter links. Conversely, percentage of overlap can
     311// provide strong confidence in tapping on a small target, where the overlap is often quite high,
     312// and works well for tightly packed controls.
     313float hybridDistanceFunction(const IntPoint& touchHotspot, const IntRect& touchRect, const SubtargetGeometry& subtarget)
    333314{
    334315    IntRect rect = subtarget.boundingBox();
     
    337318    rect = subtarget.node()->document()->view()->contentsToWindow(rect);
    338319   
    339     float touchWidth = touchArea.width();
    340     float touchHeight = touchArea.height();
    341     float distanceScale =  touchWidth * touchWidth + touchHeight * touchHeight;
    342     float distanceToCenterScore = rect.distanceSquaredFromCenterLineToPoint(touchHotspot) / distanceScale;
     320    float radiusSquared = 0.25f * (touchRect.size().diagonalLengthSquared());
     321    float distanceToAdjustScore = rect.distanceSquaredToPoint(touchHotspot) / radiusSquared;
    343322
    344323    float targetArea = rect.size().area();
    345     rect.intersect(touchArea);
     324    rect.intersect(touchRect);
    346325    float intersectArea = rect.size().area();
    347326    float intersectionScore = 1 - intersectArea / targetArea;
    348327
    349     return intersectionScore < distanceToCenterScore ? intersectionScore : distanceToCenterScore;
     328    float hybridScore = intersectionScore + distanceToAdjustScore;
     329
     330    return hybridScore;
    350331}
    351332
     
    447428                    targetNode = node;
    448429                    targetArea = it->boundingBox();
    449                 } else {
    450                     // Minimize adjustment distance.
    451                     float dx = targetPoint.x() - touchHotspot.x();
    452                     float dy = targetPoint.y() - touchHotspot.y();
    453                     float bestDistance = dx * dx + dy * dy;
    454                     dx = adjustedPoint.x() - touchHotspot.x();
    455                     dy = adjustedPoint.y() - touchHotspot.y();
    456                     float distance = dx * dx + dy * dy;
    457                     if (distance < bestDistance) {
    458                         targetPoint = adjustedPoint;
    459                         targetNode = node;
    460                         targetArea = it->boundingBox();
    461                     }
    462430                }
    463431            }
  • trunk/Source/WebCore/platform/graphics/IntRect.cpp

    r125167 r129108  
    149149}
    150150
    151 IntSize IntRect::differenceFromCenterLineToPoint(const IntPoint& point) const
    152 {
    153     // The center-line is the natural center of a rectangle. It has an equal distance to all sides of the rectangle.
    154     IntPoint centerPoint = center();
    155     int xdistance = centerPoint.x() - point.x();
    156     int ydistance = centerPoint.y() - point.y();
    157     if (width() > height())
    158         xdistance = distanceToInterval(point.x(), x() + (height() / 2), maxX() - (height() / 2));
    159     else
    160         ydistance = distanceToInterval(point.y(), y() + (width() / 2), maxY() - (width() / 2));
    161     return IntSize(xdistance, ydistance);
    162 }
    163 
    164151IntRect unionRect(const Vector<IntRect>& rects)
    165152{
  • trunk/Source/WebCore/platform/graphics/IntRect.h

    r128572 r129108  
    191191
    192192    IntSize differenceToPoint(const IntPoint&) const;
    193     IntSize differenceFromCenterLineToPoint(const IntPoint&) const;
    194193    int distanceSquaredToPoint(const IntPoint& p) const { return differenceToPoint(p).diagonalLengthSquared(); }
    195     int distanceSquaredFromCenterLineToPoint(const IntPoint& p) const { return differenceFromCenterLineToPoint(p).diagonalLengthSquared(); }
    196194
    197195    IntRect transposedRect() const { return IntRect(m_location.transposedPoint(), m_size.transposedSize()); }
Note: See TracChangeset for help on using the changeset viewer.