<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[129108] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/129108">129108</a></dd>
<dt>Author</dt> <dd>allan.jensen@nokia.com</dd>
<dt>Date</dt> <dd>2012-09-20 01:44:43 -0700 (Thu, 20 Sep 2012)</dd>
</dl>

<h3>Log Message</h3>
<pre>[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):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorepageTouchAdjustmentcpp">trunk/Source/WebCore/page/TouchAdjustment.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsIntRectcpp">trunk/Source/WebCore/platform/graphics/IntRect.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsIntRecth">trunk/Source/WebCore/platform/graphics/IntRect.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (129107 => 129108)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2012-09-20 08:41:27 UTC (rev 129107)
+++ trunk/Source/WebCore/ChangeLog        2012-09-20 08:44:43 UTC (rev 129108)
</span><span class="lines">@@ -1,3 +1,28 @@
</span><ins>+2012-09-20  Allan Sandfeld Jensen  &lt;allan.jensen@nokia.com&gt;
+
+        [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):
+
</ins><span class="cx"> 2012-09-20  Yoshifumi Inoue  &lt;yosin@chromium.org&gt;
</span><span class="cx"> 
</span><span class="cx">         [Forms] HTMLSelectElement should call formStateDidChange on both menulist and lisbox mode
</span></span></pre></div>
<a id="trunkSourceWebCorepageTouchAdjustmentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/TouchAdjustment.cpp (129107 => 129108)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/TouchAdjustment.cpp        2012-09-20 08:41:27 UTC (rev 129107)
+++ trunk/Source/WebCore/page/TouchAdjustment.cpp        2012-09-20 08:44:43 UTC (rev 129108)
</span><span class="lines">@@ -285,23 +285,6 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-
-float distanceSquaredToTargetCenterLine(const IntPoint&amp; touchHotspot, const IntRect&amp; touchArea, const SubtargetGeometry&amp; subtarget)
-{
-    UNUSED_PARAM(touchArea);
-    // For a better center of a line-box we use the center-line instead of the center-point.
-    // We use the center-line of the bounding box of the quad though, since it is much faster
-    // and gives the same result in all untransformed cases, and in transformed cases still
-    // gives a better distance-function than the distance to the center-point.
-    IntRect rect = subtarget.boundingBox();
-    ASSERT(subtarget.node()-&gt;document());
-    ASSERT(subtarget.node()-&gt;document()-&gt;view());
-    // Convert from frame coordinates to window coordinates.
-    rect = subtarget.node()-&gt;document()-&gt;view()-&gt;contentsToWindow(rect);
-
-    return rect.distanceSquaredFromCenterLineToPoint(touchHotspot);
-}
-
</del><span class="cx"> // This returns quotient of the target area and its intersection with the touch area.
</span><span class="cx"> // This will prioritize largest intersection and smallest area, while balancing the two against each other.
</span><span class="cx"> float zoomableIntersectionQuotient(const IntPoint&amp; touchHotspot, const IntRect&amp; touchArea, const SubtargetGeometry&amp; subtarget)
</span><span class="lines">@@ -321,32 +304,30 @@
</span><span class="cx">     return rect.size().area() / (float)intersection.size().area();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-// Uses a hybrid of distance to center and intersect ratio, normalizing each
-// score between 0 and 1 and choosing the better score. The distance to
-// centerline 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&amp; touchHotspot, const IntRect&amp; touchArea, const SubtargetGeometry&amp; subtarget)
</del><ins>+// 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&amp; touchHotspot, const IntRect&amp; touchRect, const SubtargetGeometry&amp; subtarget)
</ins><span class="cx"> {
</span><span class="cx">     IntRect rect = subtarget.boundingBox();
</span><span class="cx"> 
</span><span class="cx">     // Convert from frame coordinates to window coordinates.
</span><span class="cx">     rect = subtarget.node()-&gt;document()-&gt;view()-&gt;contentsToWindow(rect);
</span><span class="cx">    
</span><del>-    float touchWidth = touchArea.width();
-    float touchHeight = touchArea.height();
-    float distanceScale =  touchWidth * touchWidth + touchHeight * touchHeight;
-    float distanceToCenterScore = rect.distanceSquaredFromCenterLineToPoint(touchHotspot) / distanceScale;
</del><ins>+    float radiusSquared = 0.25f * (touchRect.size().diagonalLengthSquared());
+    float distanceToAdjustScore = rect.distanceSquaredToPoint(touchHotspot) / radiusSquared;
</ins><span class="cx"> 
</span><span class="cx">     float targetArea = rect.size().area();
</span><del>-    rect.intersect(touchArea);
</del><ins>+    rect.intersect(touchRect);
</ins><span class="cx">     float intersectArea = rect.size().area();
</span><span class="cx">     float intersectionScore = 1 - intersectArea / targetArea;
</span><span class="cx"> 
</span><del>-    return intersectionScore &lt; distanceToCenterScore ? intersectionScore : distanceToCenterScore;
</del><ins>+    float hybridScore = intersectionScore + distanceToAdjustScore;
+
+    return hybridScore;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> FloatPoint contentsToWindow(FrameView *view, FloatPoint pt)
</span><span class="lines">@@ -446,19 +427,6 @@
</span><span class="cx">                     targetPoint = adjustedPoint;
</span><span class="cx">                     targetNode = node;
</span><span class="cx">                     targetArea = it-&gt;boundingBox();
</span><del>-                } else {
-                    // Minimize adjustment distance.
-                    float dx = targetPoint.x() - touchHotspot.x();
-                    float dy = targetPoint.y() - touchHotspot.y();
-                    float bestDistance = dx * dx + dy * dy;
-                    dx = adjustedPoint.x() - touchHotspot.x();
-                    dy = adjustedPoint.y() - touchHotspot.y();
-                    float distance = dx * dx + dy * dy;
-                    if (distance &lt; bestDistance) {
-                        targetPoint = adjustedPoint;
-                        targetNode = node;
-                        targetArea = it-&gt;boundingBox();
-                    }
</del><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsIntRectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/IntRect.cpp (129107 => 129108)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/IntRect.cpp        2012-09-20 08:41:27 UTC (rev 129107)
+++ trunk/Source/WebCore/platform/graphics/IntRect.cpp        2012-09-20 08:44:43 UTC (rev 129108)
</span><span class="lines">@@ -148,19 +148,6 @@
</span><span class="cx">     return IntSize(xdistance, ydistance);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-IntSize IntRect::differenceFromCenterLineToPoint(const IntPoint&amp; point) const
-{
-    // The center-line is the natural center of a rectangle. It has an equal distance to all sides of the rectangle.
-    IntPoint centerPoint = center();
-    int xdistance = centerPoint.x() - point.x();
-    int ydistance = centerPoint.y() - point.y();
-    if (width() &gt; height())
-        xdistance = distanceToInterval(point.x(), x() + (height() / 2), maxX() - (height() / 2));
-    else
-        ydistance = distanceToInterval(point.y(), y() + (width() / 2), maxY() - (width() / 2));
-    return IntSize(xdistance, ydistance);
-}
-
</del><span class="cx"> IntRect unionRect(const Vector&lt;IntRect&gt;&amp; rects)
</span><span class="cx"> {
</span><span class="cx">     IntRect result;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsIntRecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/IntRect.h (129107 => 129108)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/IntRect.h        2012-09-20 08:41:27 UTC (rev 129107)
+++ trunk/Source/WebCore/platform/graphics/IntRect.h        2012-09-20 08:44:43 UTC (rev 129108)
</span><span class="lines">@@ -190,9 +190,7 @@
</span><span class="cx">     void scale(float s);
</span><span class="cx"> 
</span><span class="cx">     IntSize differenceToPoint(const IntPoint&amp;) const;
</span><del>-    IntSize differenceFromCenterLineToPoint(const IntPoint&amp;) const;
</del><span class="cx">     int distanceSquaredToPoint(const IntPoint&amp; p) const { return differenceToPoint(p).diagonalLengthSquared(); }
</span><del>-    int distanceSquaredFromCenterLineToPoint(const IntPoint&amp; p) const { return differenceFromCenterLineToPoint(p).diagonalLengthSquared(); }
</del><span class="cx"> 
</span><span class="cx">     IntRect transposedRect() const { return IntRect(m_location.transposedPoint(), m_size.transposedSize()); }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>