Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(321)

Side by Side Diff: ui/gfx/win/rect_util.cc

Issue 1679393002: Multiple DPI Tracking for ScreenWin (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: CR Feedback EXCEPT Filename Change Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 "ui/gfx/win/rect_util.h"
6
7 #include <algorithm>
8
9 #include "ui/gfx/geometry/rect.h"
10 #include "ui/gfx/geometry/safe_integer_conversions.h"
11 #include "ui/gfx/geometry/size.h"
12 #include "ui/gfx/geometry/vector2d.h"
13 #include "ui/gfx/range/range.h"
14
15 namespace {
16
17 enum class RelativePosition {
18 BOTTOM = 0,
19 LEFT = 1,
20 TOP = 2,
21 RIGHT = 3,
22 };
23
24 gfx::Rect CoordinateRotateRectangle90(const gfx::Rect& rect) {
25 return gfx::Rect(rect.y(), -rect.x() - rect.width(),
26 rect.height(), rect.width());
27 }
28
29 gfx::Rect CoordinateRotateRectangle180(const gfx::Rect& rect) {
30 return gfx::Rect(-rect.x() - rect.width(), -rect.y() -rect.height(),
31 rect.width(), rect.height());
32 }
33
34 gfx::Rect CoordinateRotateRectangle270(const gfx::Rect& rect) {
35 return gfx::Rect(-rect.y() - rect.height(), rect.x(),
36 rect.height(), rect.width());
37 }
38
39 gfx::Rect CoordinateReflectRectangleYAxis(const gfx::Rect& rect) {
40 return gfx::Rect(-rect.x() - rect.width(), rect.y(),
41 rect.width(), rect.height());
42 }
43
44 gfx::Rect CanonicalizeRelativePosition(const gfx::Rect& rect,
45 RelativePosition relative_position) {
46 switch (relative_position) {
47 case RelativePosition::LEFT:
48 return CoordinateRotateRectangle90(rect);
49 case RelativePosition::TOP:
50 return CoordinateRotateRectangle180(rect);
51 case RelativePosition::RIGHT:
52 return CoordinateRotateRectangle270(rect);
53 }
54 return rect;
55 }
56
57 gfx::Rect CanonicalizeTouchingEdge(const gfx::Rect& rect,
58 gfx::win::RectEdge edge) {
59 switch (edge) {
60 case gfx::win::RectEdge::LEFT:
61 return CoordinateRotateRectangle90(rect);
62 case gfx::win::RectEdge::TOP:
63 // Helps prefer left and top alignment.
64 return CoordinateReflectRectangleYAxis(
65 CoordinateRotateRectangle180(rect));
66 case gfx::win::RectEdge::RIGHT:
67 // Helps prefer left and top alignment.
68 return CoordinateReflectRectangleYAxis(
69 CoordinateRotateRectangle270(rect));
70 }
71 return rect;
72 }
73
74 // Inverse of CanonicalizeTouchingEdge.
75 gfx::Rect RevertToOriginalEdge(const gfx::Rect& rect, gfx::win::RectEdge edge) {
76 switch (edge) {
77 case gfx::win::RectEdge::LEFT:
78 return CoordinateRotateRectangle270(rect);
79 case gfx::win::RectEdge::TOP:
80 return CoordinateRotateRectangle180(
81 CoordinateReflectRectangleYAxis(rect));
82 case gfx::win::RectEdge::RIGHT:
83 return CoordinateRotateRectangle90(
84 CoordinateReflectRectangleYAxis(rect));
85 }
86 return rect;
87 }
88
89 bool InRange(int target, int lower_bound, int upper_bound) {
90 return lower_bound <= target && target <= upper_bound;
91 }
92
93 // Scales |val| within |old_min| and |old_max| to |new_min| and |new_max|.
94 int ScaleValue(int new_min, int new_max, int old_min, int old_max, int val) {
95 int old_delta = old_max - old_min;
96 if (old_delta == 0) {
97 DCHECK_EQ(new_min, new_max);
98 return new_min;
99 }
100 float percent =
101 static_cast<float>(val - old_min) / static_cast<float>(old_delta);
102 return new_min + gfx::ToFlooredInt(percent * (float)(new_max - new_min));
103 }
104
105 // Returns the relative position of |test| with respect to |ref|.
106 // If |test| is below |ref|, then the return value is RelativePosition::BOTTOM.
107 // The precedence of relative position in order of highest to lowest is
108 // BOTTOM, LEFT, TOP, and finally RIGHT.
109 // In other words, if |test| is both below and to the left of |ref|, then the
110 // RelativePosition is BOTTOM.
111 RelativePosition RectRelativePosition(const gfx::Rect& ref,
112 const gfx::Rect& test) {
113 if (ref.bottom() <= test.y())
114 return RelativePosition::BOTTOM;
115 if (test.right() <= ref.x())
116 return RelativePosition::LEFT;
117 if (test.bottom() <= ref.y())
118 return RelativePosition::TOP;
119
120 return RelativePosition::RIGHT;
121 }
122
123 } // namespace
124
125 namespace gfx {
126 namespace win {
127
128 RectEdge FindTouchingRectEdge(const gfx::Rect& ref, const gfx::Rect& test) {
129 int max_x = std::max(ref.x(), test.x());
sky 2016/02/18 17:02:58 I have a hard time reading this code because max_x
robliao 2016/02/19 00:26:29 sgtm. Done. As an aside, the original naming from
130 int max_y = std::max(ref.y(), test.y());
131 int min_right = std::min(ref.right(), test.right());
132 int min_bottom = std::min(ref.bottom(), test.bottom());
133 if (max_x == min_right && max_y == min_bottom) {
134 // Corner touching.
135 if (ref.bottom() == max_y)
136 return RectEdge::BOTTOM;
137 if (ref.x() == max_x)
138 return RectEdge::LEFT;
139
140 return RectEdge::TOP;
141 }
142 if (max_x == min_right) {
143 // Vertical edge touching.
144 return ref.x() == max_x ? RectEdge::LEFT : RectEdge::RIGHT;
145 }
146 if (max_y == min_bottom) {
147 // Horizontal edge touching.
148 return ref.y() == max_y ? RectEdge::TOP : RectEdge::BOTTOM;
149 }
150 return RectEdge::NONE;
151 }
152
153 // Writing code that specifically deals with scaling each rect is tedious and
154 // error prone. Instead, this function transforms the positions of the
155 // two rects so that |ref_scaled_rect| is always on top of |ref_unscaled_rect|,
156 // calculates the scaled and positioned target rect, and then reverses the
157 // transforms. As a result, the position logic can be written in terms of the
158 // bottom of the |ref_unscaled_rect| instead of the bottom, left, top, and
159 // right.
160 gfx::Rect ScaleAndPositionRect(const gfx::Rect& ref_scaled_rect,
161 const gfx::Rect& ref_unscaled_rect,
162 const gfx::Rect& unscaled_rect,
163 float unscaled_rect_scale_factor) {
164 RectEdge orig_edge = FindTouchingRectEdge(ref_unscaled_rect, unscaled_rect);
165
166 // Scale size only since the scaled origin location will be determined below.
167 gfx::Rect scaled_rect(
168 gfx::ScaleToEnclosingRect(unscaled_rect,
169 1.0f / unscaled_rect_scale_factor));
170 scaled_rect.set_origin(gfx::Point(0, 0));
171
172 if (orig_edge == RectEdge::NONE) {
173 // ScaleAndPositionRect depends on unscaled rectangles touching.
174 DCHECK(false);
175 scaled_rect.set_origin(unscaled_rect.origin());
176 }
177
178 // Transform rectangles so we can simply deal with bottom edge sharing.
179 gfx::Rect ref_scaled_rect_work(
180 CanonicalizeTouchingEdge(ref_scaled_rect, orig_edge));
181 gfx::Rect ref_unscaled_rect_work(
182 CanonicalizeTouchingEdge(ref_unscaled_rect, orig_edge));
183 gfx::Rect unscaled_rect_work(
184 CanonicalizeTouchingEdge(unscaled_rect,orig_edge));
185 scaled_rect = CanonicalizeTouchingEdge(scaled_rect, orig_edge);
186
187 // Position the rect.
188 scaled_rect.set_y(ref_scaled_rect_work.bottom());
189 int x;
190 if (unscaled_rect_work.right() == ref_unscaled_rect_work.right()) {
191 // Maintain right alignment. If the rectangle was left-aligned, the next
192 // case will catch that.
193 x = ref_scaled_rect_work.right() - scaled_rect.width();
194 } else if (InRange(unscaled_rect_work.x(),
195 ref_unscaled_rect_work.x(),
196 ref_unscaled_rect_work.right())) {
197 // Position using the left point relative to the reference rect.
198 x = ScaleValue(ref_scaled_rect_work.x(), ref_scaled_rect_work.right(),
199 ref_unscaled_rect_work.x(), ref_unscaled_rect_work.right(),
200 unscaled_rect_work.x());
201 } else if (InRange(unscaled_rect_work.right(),
202 ref_unscaled_rect_work.x(),
203 ref_unscaled_rect_work.right())) {
204 // Position using the right point relative to the reference rect.
205 x = ScaleValue(ref_scaled_rect_work.x(), ref_scaled_rect_work.right(),
206 ref_unscaled_rect_work.x(), ref_unscaled_rect_work.right(),
207 unscaled_rect_work.right()) - scaled_rect.width();
208 } else if (InRange(ref_scaled_rect_work.x(),
209 unscaled_rect_work.x(),
210 unscaled_rect_work.right())) {
211 // Position relative to the left point of the reference rect.
212 int offset = ScaleValue(0, scaled_rect.width(),
213 0, unscaled_rect_work.width(),
214 ref_unscaled_rect_work.x() -
215 unscaled_rect_work.x());
216 x = ref_scaled_rect_work.x() - offset;
217 } else {
218 // Position relative to the right point of the reference rect.
219 int offset = ScaleValue(0, scaled_rect.width(),
220 0, unscaled_rect_work.width(),
221 ref_unscaled_rect_work.right() -
222 unscaled_rect_work.x());
223 x = ref_scaled_rect_work.x() - offset - scaled_rect.width();
224 }
225 scaled_rect.set_x(x);
226 DCHECK(FindTouchingRectEdge(ref_scaled_rect_work, scaled_rect) ==
227 RectEdge::BOTTOM);
228
229 // Reverse the transformation.
230 return RevertToOriginalEdge(scaled_rect, orig_edge);
231 }
232
233 // This function takes the same approach as ScaleAndPositionRect, transforming
234 // the two input rects so that the relative positions are always the same.
235 int64_t SquaredDistanceBetweenRects(const gfx::Rect& ref,
236 const gfx::Rect& rect) {
237 if (ref.Intersects(rect))
238 return 0;
239
240 RelativePosition relative_position = RectRelativePosition(ref, rect);
241 gfx::Rect ref_work(CanonicalizeRelativePosition(ref, relative_position));
242 gfx::Rect rect_work(CanonicalizeRelativePosition(rect, relative_position));
243 // Now that the ref is on top, we can concentrate ref bottom
244 // and rect top calculations.
245 if (rect_work.right() < ref_work.x())
246 return (rect_work.top_right() - ref_work.bottom_left()).LengthSquared();
247 else if (ref_work.right() < rect_work.x())
248 return (rect_work.origin() - ref_work.bottom_right()).LengthSquared();
249
250 int distance = rect_work.y() - ref_work.bottom();
251 return distance * distance;
252 }
253
254 } // namespace win
255 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698