OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) | 2 * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) |
3 * | 3 * |
4 * This library is free software; you can redistribute it and/or | 4 * This library is free software; you can redistribute it and/or |
5 * modify it under the terms of the GNU Library General Public | 5 * modify it under the terms of the GNU Library General Public |
6 * License as published by the Free Software Foundation; either | 6 * License as published by the Free Software Foundation; either |
7 * version 2 of the License, or (at your option) any later version. | 7 * version 2 of the License, or (at your option) any later version. |
8 * | 8 * |
9 * This library is distributed in the hope that it will be useful, | 9 * This library is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 } | 313 } |
314 } | 314 } |
315 | 315 |
316 // This returns quotient of the target area and its intersection with the touch
area. | 316 // This returns quotient of the target area and its intersection with the touch
area. |
317 // This will prioritize largest intersection and smallest area, while balancing
the two against each other. | 317 // This will prioritize largest intersection and smallest area, while balancing
the two against each other. |
318 float zoomableIntersectionQuotient(const IntPoint& touchHotspot, const IntRect&
touchArea, const SubtargetGeometry& subtarget) | 318 float zoomableIntersectionQuotient(const IntPoint& touchHotspot, const IntRect&
touchArea, const SubtargetGeometry& subtarget) |
319 { | 319 { |
320 IntRect rect = subtarget.boundingBox(); | 320 IntRect rect = subtarget.boundingBox(); |
321 | 321 |
322 // Convert from frame coordinates to window coordinates. | 322 // Convert from frame coordinates to window coordinates. |
323 rect = subtarget.node()->document()->view()->contentsToWindow(rect); | 323 rect = subtarget.node()->document().view()->contentsToWindow(rect); |
324 | 324 |
325 // Check the rectangle is meaningful zoom target. It should at least contain
the hotspot. | 325 // Check the rectangle is meaningful zoom target. It should at least contain
the hotspot. |
326 if (!rect.contains(touchHotspot)) | 326 if (!rect.contains(touchHotspot)) |
327 return std::numeric_limits<float>::infinity(); | 327 return std::numeric_limits<float>::infinity(); |
328 IntRect intersection = rect; | 328 IntRect intersection = rect; |
329 intersection.intersect(touchArea); | 329 intersection.intersect(touchArea); |
330 | 330 |
331 // Return the quotient of the intersection. | 331 // Return the quotient of the intersection. |
332 return rect.size().area() / (float)intersection.size().area(); | 332 return rect.size().area() / (float)intersection.size().area(); |
333 } | 333 } |
334 | 334 |
335 // Uses a hybrid of distance to adjust and intersect ratio, normalizing each sco
re between 0 and 1 | 335 // Uses a hybrid of distance to adjust and intersect ratio, normalizing each sco
re between 0 and 1 |
336 // and combining them. The distance to adjust works best for disambiguating clic
ks on targets such | 336 // and combining them. The distance to adjust works best for disambiguating clic
ks on targets such |
337 // as links, where the width may be significantly larger than the touch width. U
sing area of overlap | 337 // as links, where the width may be significantly larger than the touch width. U
sing area of overlap |
338 // in such cases can lead to a bias towards shorter links. Conversely, percentag
e of overlap can | 338 // in such cases can lead to a bias towards shorter links. Conversely, percentag
e of overlap can |
339 // provide strong confidence in tapping on a small target, where the overlap is
often quite high, | 339 // provide strong confidence in tapping on a small target, where the overlap is
often quite high, |
340 // and works well for tightly packed controls. | 340 // and works well for tightly packed controls. |
341 float hybridDistanceFunction(const IntPoint& touchHotspot, const IntRect& touchR
ect, const SubtargetGeometry& subtarget) | 341 float hybridDistanceFunction(const IntPoint& touchHotspot, const IntRect& touchR
ect, const SubtargetGeometry& subtarget) |
342 { | 342 { |
343 IntRect rect = subtarget.boundingBox(); | 343 IntRect rect = subtarget.boundingBox(); |
344 | 344 |
345 // Convert from frame coordinates to window coordinates. | 345 // Convert from frame coordinates to window coordinates. |
346 rect = subtarget.node()->document()->view()->contentsToWindow(rect); | 346 rect = subtarget.node()->document().view()->contentsToWindow(rect); |
347 | 347 |
348 float radiusSquared = 0.25f * (touchRect.size().diagonalLengthSquared()); | 348 float radiusSquared = 0.25f * (touchRect.size().diagonalLengthSquared()); |
349 float distanceToAdjustScore = rect.distanceSquaredToPoint(touchHotspot) / ra
diusSquared; | 349 float distanceToAdjustScore = rect.distanceSquaredToPoint(touchHotspot) / ra
diusSquared; |
350 | 350 |
351 int maxOverlapWidth = std::min(touchRect.width(), rect.width()); | 351 int maxOverlapWidth = std::min(touchRect.width(), rect.width()); |
352 int maxOverlapHeight = std::min(touchRect.height(), rect.height()); | 352 int maxOverlapHeight = std::min(touchRect.height(), rect.height()); |
353 float maxOverlapArea = std::max(maxOverlapWidth * maxOverlapHeight, 1); | 353 float maxOverlapArea = std::max(maxOverlapWidth * maxOverlapHeight, 1); |
354 rect.intersect(touchRect); | 354 rect.intersect(touchRect); |
355 float intersectArea = rect.size().area(); | 355 float intersectArea = rect.size().area(); |
356 float intersectionScore = 1 - intersectArea / maxOverlapArea; | 356 float intersectionScore = 1 - intersectArea / maxOverlapArea; |
(...skipping 20 matching lines...) Expand all Loading... |
377 point.setX(rect.maxX()); | 377 point.setX(rect.maxX()); |
378 | 378 |
379 if (point.y() < rect.y()) | 379 if (point.y() < rect.y()) |
380 point.setY(rect.y()); | 380 point.setY(rect.y()); |
381 else if (point.y() > rect.maxY()) | 381 else if (point.y() > rect.maxY()) |
382 point.setY(rect.maxY()); | 382 point.setY(rect.maxY()); |
383 } | 383 } |
384 | 384 |
385 bool snapTo(const SubtargetGeometry& geom, const IntPoint& touchPoint, const Int
Rect& touchArea, IntPoint& adjustedPoint) | 385 bool snapTo(const SubtargetGeometry& geom, const IntPoint& touchPoint, const Int
Rect& touchArea, IntPoint& adjustedPoint) |
386 { | 386 { |
387 FrameView* view = geom.node()->document()->view(); | 387 FrameView* view = geom.node()->document().view(); |
388 FloatQuad quad = geom.quad(); | 388 FloatQuad quad = geom.quad(); |
389 | 389 |
390 if (quad.isRectilinear()) { | 390 if (quad.isRectilinear()) { |
391 IntRect contentBounds = geom.boundingBox(); | 391 IntRect contentBounds = geom.boundingBox(); |
392 // Convert from frame coordinates to window coordinates. | 392 // Convert from frame coordinates to window coordinates. |
393 IntRect bounds = view->contentsToWindow(contentBounds); | 393 IntRect bounds = view->contentsToWindow(contentBounds); |
394 if (bounds.contains(touchPoint)) { | 394 if (bounds.contains(touchPoint)) { |
395 adjustedPoint = touchPoint; | 395 adjustedPoint = touchPoint; |
396 return true; | 396 return true; |
397 } | 397 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
455 if (node->isDescendantOf(targetNode)) { | 455 if (node->isDescendantOf(targetNode)) { |
456 // Try to always return the inner-most element. | 456 // Try to always return the inner-most element. |
457 targetPoint = adjustedPoint; | 457 targetPoint = adjustedPoint; |
458 targetNode = node; | 458 targetNode = node; |
459 targetArea = it->boundingBox(); | 459 targetArea = it->boundingBox(); |
460 } | 460 } |
461 } | 461 } |
462 } | 462 } |
463 } | 463 } |
464 if (targetNode) { | 464 if (targetNode) { |
465 targetArea = targetNode->document()->view()->contentsToWindow(targetArea
); | 465 targetArea = targetNode->document().view()->contentsToWindow(targetArea)
; |
466 } | 466 } |
467 return (targetNode); | 467 return (targetNode); |
468 } | 468 } |
469 | 469 |
470 } // namespace TouchAdjustment | 470 } // namespace TouchAdjustment |
471 | 471 |
472 bool findBestClickableCandidate(Node*& targetNode, IntPoint &targetPoint, const
IntPoint &touchHotspot, const IntRect &touchArea, const Vector<RefPtr<Node> >& n
odes) | 472 bool findBestClickableCandidate(Node*& targetNode, IntPoint &targetPoint, const
IntPoint &touchHotspot, const IntRect &touchArea, const Vector<RefPtr<Node> >& n
odes) |
473 { | 473 { |
474 IntRect targetArea; | 474 IntRect targetArea; |
475 TouchAdjustment::SubtargetGeometryList subtargets; | 475 TouchAdjustment::SubtargetGeometryList subtargets; |
(...skipping 11 matching lines...) Expand all Loading... |
487 | 487 |
488 bool findBestZoomableArea(Node*& targetNode, IntRect& targetArea, const IntPoint
& touchHotspot, const IntRect& touchArea, const Vector<RefPtr<Node> >& nodes) | 488 bool findBestZoomableArea(Node*& targetNode, IntRect& targetArea, const IntPoint
& touchHotspot, const IntRect& touchArea, const Vector<RefPtr<Node> >& nodes) |
489 { | 489 { |
490 IntPoint targetPoint; | 490 IntPoint targetPoint; |
491 TouchAdjustment::SubtargetGeometryList subtargets; | 491 TouchAdjustment::SubtargetGeometryList subtargets; |
492 TouchAdjustment::compileZoomableSubtargets(nodes, subtargets); | 492 TouchAdjustment::compileZoomableSubtargets(nodes, subtargets); |
493 return TouchAdjustment::findNodeWithLowestDistanceMetric(targetNode, targetP
oint, targetArea, touchHotspot, touchArea, subtargets, TouchAdjustment::zoomable
IntersectionQuotient); | 493 return TouchAdjustment::findNodeWithLowestDistanceMetric(targetNode, targetP
oint, targetArea, touchHotspot, touchArea, subtargets, TouchAdjustment::zoomable
IntersectionQuotient); |
494 } | 494 } |
495 | 495 |
496 } // namespace WebCore | 496 } // namespace WebCore |
OLD | NEW |