OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "content/renderer/disambiguation_popup_helper.h" |
| 6 |
| 7 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h" |
| 8 #include "ui/gfx/size_conversions.h" |
| 9 |
| 10 using WebKit::WebRect; |
| 11 using WebKit::WebVector; |
| 12 |
| 13 namespace { |
| 14 |
| 15 // The amount of padding to add to the disambiguation popup to show |
| 16 // content around the possible elements, adding some context. |
| 17 const int kDisambiguationPopupPadding = 8; |
| 18 |
| 19 // Constants used for fitting the disambiguation popup inside the bounds of |
| 20 // the view. Note that there are mirror constants in PopupZoomer.java. |
| 21 const int kDisambiguationPopupBoundsMargin = 25; |
| 22 |
| 23 // The smallest allowable touch target used for disambiguation popup. |
| 24 // This value is used to determine the minimum amount we need to scale to |
| 25 // make all targets touchable. |
| 26 const int kDisambiguationPopupMinimumTouchSize = 40; |
| 27 const float kDisambiguationPopupMaxScale = 5.0; |
| 28 const float kDisambiguationPopupMinScale = 2.0; |
| 29 |
| 30 // Compute the scaling factor to ensure the smallest touch candidate reaches |
| 31 // a certain clickable size after zooming |
| 32 float FindOptimalScaleFactor(const WebVector<WebRect>& target_rects) { |
| 33 using std::min; |
| 34 using std::max; |
| 35 if (!target_rects.size()) // shall never reach |
| 36 return kDisambiguationPopupMinScale; |
| 37 int smallest_target = min(target_rects[0].width, target_rects[0].height); |
| 38 for (size_t i = 1; i < target_rects.size(); i++) { |
| 39 smallest_target = min(smallest_target, target_rects[i].width); |
| 40 smallest_target = min(smallest_target, target_rects[i].height); |
| 41 } |
| 42 smallest_target = max(smallest_target, 1); |
| 43 return min(kDisambiguationPopupMaxScale, max(kDisambiguationPopupMinScale, |
| 44 static_cast<float>(kDisambiguationPopupMinimumTouchSize) |
| 45 / smallest_target)); |
| 46 } |
| 47 |
| 48 void TrimEdges(int *e1, int *e2, int max_combined) { |
| 49 if (*e1 + *e2 <= max_combined) |
| 50 return; |
| 51 |
| 52 if (std::min(*e1, *e2) * 2 >= max_combined) |
| 53 *e1 = *e2 = max_combined / 2; |
| 54 else if (*e1 > *e2) |
| 55 *e1 = max_combined - *e2; |
| 56 else |
| 57 *e2 = max_combined - *e1; |
| 58 } |
| 59 |
| 60 // Ensure the disambiguation popup fits inside the screen, |
| 61 // clip the edges farthest to the touch point if needed. |
| 62 gfx::Rect CropZoomArea(const gfx::Rect& zoom_rect, |
| 63 const gfx::Size& viewport_size, |
| 64 const gfx::Point& touch_point, |
| 65 float scale) { |
| 66 gfx::Size max_size = viewport_size; |
| 67 max_size.Enlarge(-2 * kDisambiguationPopupBoundsMargin, |
| 68 -2 * kDisambiguationPopupBoundsMargin); |
| 69 max_size = ToCeiledSize(max_size.Scale(1.0 / scale)); |
| 70 |
| 71 int left = touch_point.x() - zoom_rect.x(); |
| 72 int right = zoom_rect.right() - touch_point.x(); |
| 73 int top = touch_point.y() - zoom_rect.y(); |
| 74 int bottom = zoom_rect.bottom() - touch_point.y(); |
| 75 TrimEdges(&left, &right, max_size.width()); |
| 76 TrimEdges(&top, &bottom, max_size.height()); |
| 77 |
| 78 return gfx::Rect(touch_point.x() - left, |
| 79 touch_point.y() - top, |
| 80 left + right, |
| 81 top + bottom); |
| 82 } |
| 83 |
| 84 } // unnamed namespace |
| 85 |
| 86 namespace content { |
| 87 |
| 88 float DisambiguationPopupHelper::ComputeZoomAreaAndScaleFactor( |
| 89 const gfx::Rect& tap_rect, |
| 90 const WebVector<WebRect>& target_rects, |
| 91 const gfx::Size& viewport_size, |
| 92 gfx::Rect* zoom_rect) { |
| 93 *zoom_rect = tap_rect; |
| 94 for (size_t i = 0; i < target_rects.size(); i++) |
| 95 *zoom_rect = zoom_rect->Union(gfx::Rect(target_rects[i])); |
| 96 zoom_rect->Inset(-kDisambiguationPopupPadding, -kDisambiguationPopupPadding); |
| 97 *zoom_rect = zoom_rect->Intersect(gfx::Rect(viewport_size)); |
| 98 |
| 99 float scale = FindOptimalScaleFactor(target_rects); |
| 100 *zoom_rect = CropZoomArea( |
| 101 *zoom_rect, viewport_size, tap_rect.CenterPoint(), scale); |
| 102 |
| 103 return scale; |
| 104 } |
| 105 |
| 106 } // namespace content |
OLD | NEW |