forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathresize_utils.cc
112 lines (100 loc) · 3.83 KB
/
resize_utils.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/gfx/geometry/resize_utils.h"
#include "base/check_op.h"
#include "base/numerics/ranges.h"
#include "base/numerics/safe_conversions.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
namespace gfx {
namespace {
// This function decides whether SizeRectToAspectRatio() will adjust the height
// to match the specified width (resizing horizontally) or vice versa (resizing
// vertically).
bool IsResizingHorizontally(ResizeEdge resize_edge) {
switch (resize_edge) {
case ResizeEdge::kLeft:
case ResizeEdge::kRight:
case ResizeEdge::kTopLeft:
case ResizeEdge::kBottomLeft:
return true;
default:
return false;
}
}
} // namespace
void SizeRectToAspectRatio(ResizeEdge resize_edge,
float aspect_ratio,
const Size& min_window_size,
const Size& max_window_size,
Rect* rect) {
DCHECK_GT(aspect_ratio, 0.0f);
DCHECK_GE(max_window_size.width(), min_window_size.width());
DCHECK_GE(max_window_size.height(), min_window_size.height());
DCHECK(rect->Contains(Rect(rect->origin(), min_window_size)))
<< rect->ToString() << " is smaller than the minimum size "
<< min_window_size.ToString();
DCHECK(Rect(rect->origin(), max_window_size).Contains(*rect))
<< rect->ToString() << " is larger than the maximum size "
<< max_window_size.ToString();
Size new_size = rect->size();
if (IsResizingHorizontally(resize_edge)) {
new_size.set_height(base::ClampRound(new_size.width() / aspect_ratio));
if (min_window_size.height() > new_size.height() ||
new_size.height() > max_window_size.height()) {
new_size.set_height(base::ClampToRange(new_size.height(),
min_window_size.height(),
max_window_size.height()));
new_size.set_width(base::ClampRound(new_size.height() * aspect_ratio));
}
} else {
new_size.set_width(base::ClampRound(new_size.height() * aspect_ratio));
if (min_window_size.width() > new_size.width() ||
new_size.width() > max_window_size.width()) {
new_size.set_width(base::ClampToRange(
new_size.width(), min_window_size.width(), max_window_size.width()));
new_size.set_height(base::ClampRound(new_size.width() / aspect_ratio));
}
}
// The dimensions might still be outside of the allowed ranges at this point.
// This happens when the aspect ratio makes it impossible to fit |rect|
// within the size limits without letter-/pillarboxing.
new_size.SetToMin(max_window_size);
new_size.SetToMax(min_window_size);
// |rect| bounds before sizing to aspect ratio.
int left = rect->x();
int top = rect->y();
int right = rect->right();
int bottom = rect->bottom();
switch (resize_edge) {
case ResizeEdge::kRight:
case ResizeEdge::kBottom:
right = new_size.width() + left;
bottom = top + new_size.height();
break;
case ResizeEdge::kTop:
right = new_size.width() + left;
top = bottom - new_size.height();
break;
case ResizeEdge::kLeft:
case ResizeEdge::kTopLeft:
left = right - new_size.width();
top = bottom - new_size.height();
break;
case ResizeEdge::kTopRight:
right = left + new_size.width();
top = bottom - new_size.height();
break;
case ResizeEdge::kBottomLeft:
left = right - new_size.width();
bottom = top + new_size.height();
break;
case ResizeEdge::kBottomRight:
right = left + new_size.width();
bottom = top + new_size.height();
break;
}
rect->SetByBounds(left, top, right, bottom);
}
} // namespace gfx