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

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

Issue 1813493002: COMPLETED PREVIEW Migrate to Display Placement (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@gfxmove
Patch Set: Created 4 years, 9 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
« no previous file with comments | « ui/gfx/win/scaling_util.h ('k') | ui/gfx/win/scaling_util_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/scaling_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 // Returns the relative position of |test| with respect to |ref|.
25 // If |test| is below |ref|, then the return value is RelativePosition::BOTTOM.
26 // The precedence of relative position in order of highest to lowest is
27 // BOTTOM, LEFT, TOP, and finally RIGHT.
28 // In other words, if |test| is both below and to the left of |ref|, then the
29 // RelativePosition is BOTTOM.
30 RelativePosition RectRelativePosition(const gfx::Rect& ref,
31 const gfx::Rect& test) {
32 if (ref.bottom() <= test.y())
33 return RelativePosition::BOTTOM;
34 if (test.right() <= ref.x())
35 return RelativePosition::LEFT;
36 if (test.bottom() <= ref.y())
37 return RelativePosition::TOP;
38
39 return RelativePosition::RIGHT;
40 }
41
42 gfx::Rect CoordinateRotateRectangle90(const gfx::Rect& rect) {
43 return gfx::Rect(rect.y(), -rect.x() - rect.width(),
44 rect.height(), rect.width());
45 }
46
47 gfx::Rect CoordinateRotateRectangle180(const gfx::Rect& rect) {
48 return gfx::Rect(-rect.x() - rect.width(), -rect.y() -rect.height(),
49 rect.width(), rect.height());
50 }
51
52 gfx::Rect CoordinateRotateRectangle270(const gfx::Rect& rect) {
53 return gfx::Rect(-rect.y() - rect.height(), rect.x(),
54 rect.height(), rect.width());
55 }
56
57 gfx::Rect CoordinateReflectRectangleYAxis(const gfx::Rect& rect) {
58 return gfx::Rect(-rect.x() - rect.width(), rect.y(),
59 rect.width(), rect.height());
60 }
61
62 gfx::Rect CanonicalizeRelativePosition(const gfx::Rect& rect,
63 RelativePosition relative_position) {
64 switch (relative_position) {
65 case RelativePosition::LEFT:
66 return CoordinateRotateRectangle90(rect);
67 case RelativePosition::TOP:
68 return CoordinateRotateRectangle180(rect);
69 case RelativePosition::RIGHT:
70 return CoordinateRotateRectangle270(rect);
71 }
72 return rect;
73 }
74
75 bool InRange(int target, int lower_bound, int upper_bound) {
76 return lower_bound <= target && target <= upper_bound;
77 }
78
79 // Scales |val| within |old_min| and |old_max| to |new_min| and |new_max|.
80 int ScaleValue(int new_min, int new_max, int old_min, int old_max, int val) {
81 int old_delta = old_max - old_min;
82 if (old_delta == 0) {
83 DCHECK_EQ(new_min, new_max);
84 return new_min;
85 }
86 float percent =
87 static_cast<float>(val - old_min) / static_cast<float>(old_delta);
88 return new_min + gfx::ToFlooredInt(percent * (float)(new_max - new_min));
89 }
90
91 // Scaled |unscaled_offset| to the same relative position on |unscaled_length|
92 // based off of |unscaled_length|'s |scale_factor|.
93 int ScaleOffset(int unscaled_length, float scale_factor, int unscaled_offset) {
94 float scaled_length = static_cast<float>(unscaled_length) / scale_factor;
95 float percent =
96 static_cast<float>(unscaled_offset) / static_cast<float>(unscaled_length);
97 return gfx::ToFlooredInt(scaled_length * percent);
98 }
99
100 } // namespace
101
102 namespace gfx {
103 namespace win {
104
105 bool DisplayInfosTouch(const gfx::win::DisplayInfo& a,
106 const gfx::win::DisplayInfo& b) {
107 const gfx::Rect& a_rect = a.screen_rect();
108 const gfx::Rect& b_rect = b.screen_rect();
109 int max_left = std::max(a_rect.x(), b_rect.x());
110 int max_top = std::max(a_rect.y(), b_rect.y());
111 int min_right = std::min(a_rect.right(), b_rect.right());
112 int min_bottom = std::min(a_rect.bottom(), b_rect.bottom());
113 return max_left == min_right || max_top == min_bottom;
114 }
115
116 gfx::DisplayPlacement::Position CalculateDisplayPosition(
117 const gfx::win::DisplayInfo& parent,
118 const gfx::win::DisplayInfo& current) {
119 const gfx::Rect& parent_rect = parent.screen_rect();
120 const gfx::Rect& current_rect = current.screen_rect();
121 int max_left = std::max(parent_rect.x(), current_rect.x());
122 int max_top = std::max(parent_rect.y(), current_rect.y());
123 int min_right = std::min(parent_rect.right(), current_rect.right());
124 int min_bottom = std::min(parent_rect.bottom(), current_rect.bottom());
125 if (max_left == min_right && max_top == min_bottom) {
126 // Corner touching.
127 if (parent_rect.bottom() == max_top)
128 return gfx::DisplayPlacement::Position::BOTTOM;
129 if (parent_rect.x() == max_left)
130 return gfx::DisplayPlacement::Position::LEFT;
131
132 return gfx::DisplayPlacement::Position::TOP;
133 }
134 if (max_left == min_right) {
135 // Vertical edge touching.
136 return parent_rect.x() == max_left
137 ? gfx::DisplayPlacement::Position::LEFT
138 : gfx::DisplayPlacement::Position::RIGHT;
139 }
140 if (max_top == min_bottom) {
141 // Horizontal edge touching.
142 return parent_rect.y() == max_top
143 ? gfx::DisplayPlacement::Position::TOP
144 : gfx::DisplayPlacement::Position::BOTTOM;
145 }
146 NOTREACHED();
147 return gfx::DisplayPlacement::Position::RIGHT;
148 }
149
150 gfx::DisplayPlacement CalculateDisplayPlacement(
151 const gfx::win::DisplayInfo& parent,
152 const gfx::win::DisplayInfo& current) {
153 DCHECK(DisplayInfosTouch(parent, current)) << "DisplayInfos must touch.";
154
155 gfx::DisplayPlacement placement;
156 placement.parent_display_id = parent.id();
157 placement.display_id = current.id();
158 placement.position = CalculateDisplayPosition(parent, current);
159
160 int parent_begin = 0;
161 int parent_end = 0;
162 int current_begin = 0;
163 int current_end = 0;
164
165 switch (placement.position) {
166 case gfx::DisplayPlacement::Position::TOP:
167 case gfx::DisplayPlacement::Position::BOTTOM:
168 parent_begin = parent.screen_rect().x();
169 parent_end = parent.screen_rect().right();
170 current_begin = current.screen_rect().x();
171 current_end = current.screen_rect().right();
172 break;
173 case gfx::DisplayPlacement::Position::LEFT:
174 case gfx::DisplayPlacement::Position::RIGHT:
175 parent_begin = parent.screen_rect().y();
176 parent_end = parent.screen_rect().bottom();
177 current_begin = current.screen_rect().y();
178 current_end = current.screen_rect().bottom();
179 break;
180 }
181
182 // Since we're talking offsets, make everything relative to parent_begin.
183 parent_end -= parent_begin;
184 current_begin -= parent_begin;
185 current_end -= parent_begin;
186 parent_begin = 0;
187
188 // There are a few ways lines can intersect:
189 // End Aligned
190 // CURRENT's offset is relative to the end (in our world, BOTTOM_RIGHT).
191 // +-PARENT----------------+
192 // +-CURRENT------------+
193 //
194 // Positioning based off of |current_begin|.
195 // CURRENT's offset is simply a percentage of its position on PARENT.
196 // +-PARENT----------------+
197 // +-CURRENT------------+
198 //
199 // Positioning based off of |current_end|.
200 // CURRENT's offset is dependent on the percentage of its end position on
201 // PARENT.
202 // +-PARENT----------------+
203 // +-CURRENT------------+
204 //
205 // Positioning based off of |parent_begin| on current.
206 // CURRENT's offset is dependent on the percentage of its end position on
207 // PARENT.
208 // +-PARENT----------------+
209 // +-CURRENT--------------------------+
210 if (parent_end == current_end) {
211 // End aligned.
212 placement.offset_reference =
213 gfx::DisplayPlacement::OffsetReference::BOTTOM_RIGHT;
214 placement.offset = 0;
215 } else if (InRange(current_begin, parent_begin, parent_end)) {
216 placement.offset = ScaleOffset(parent_end,
217 parent.device_scale_factor(),
218 current_begin);
219 } else if (InRange(current_end, parent_begin, parent_end)) {
220 placement.offset_reference =
221 gfx::DisplayPlacement::OffsetReference::BOTTOM_RIGHT;
222 placement.offset = ScaleOffset(parent_end,
223 parent.device_scale_factor(),
224 parent_end - current_end);
225 } else {
226 DCHECK(InRange(parent_begin, current_begin, current_end));
227 placement.offset = ScaleOffset(current_end - current_begin,
228 current.device_scale_factor(),
229 current_begin);
230 }
231
232 return placement;
233 }
234
235 // This function takes the same approach as ScaleAndPositionRect, transforming
236 // the two input rects so that the relative positions are always the same.
237 int64_t SquaredDistanceBetweenRects(const gfx::Rect& ref,
238 const gfx::Rect& rect) {
239 if (ref.Intersects(rect))
240 return 0;
241
242 RelativePosition relative_position = RectRelativePosition(ref, rect);
243 gfx::Rect ref_work(CanonicalizeRelativePosition(ref, relative_position));
244 gfx::Rect rect_work(CanonicalizeRelativePosition(rect, relative_position));
245 // Now that the ref is on top, we can concentrate ref bottom
246 // and rect top calculations.
247 if (rect_work.right() < ref_work.x())
248 return (rect_work.top_right() - ref_work.bottom_left()).LengthSquared();
249 else if (ref_work.right() < rect_work.x())
250 return (rect_work.origin() - ref_work.bottom_right()).LengthSquared();
251
252 int distance = rect_work.y() - ref_work.bottom();
253 return distance * distance;
254 }
255
256 } // namespace win
257 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/win/scaling_util.h ('k') | ui/gfx/win/scaling_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698