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 "ppapi/cpp/rect.h"
6
7 #include <algorithm>
8
9 namespace {
10
11 template<typename T>
AdjustAlongAxis(T dst_origin,T dst_size,T * origin,T * size)12 void AdjustAlongAxis(T dst_origin, T dst_size,
13 T* origin, T* size) {
14 if (*origin < dst_origin) {
15 *origin = dst_origin;
16 *size = std::min(dst_size, *size);
17 } else {
18 *size = std::min(dst_size, *size);
19 *origin = std::min(dst_origin + dst_size, *origin + *size) - *size;
20 }
21 }
22
23 } // namespace
24
25 namespace pp {
26
Inset(int32_t left,int32_t top,int32_t right,int32_t bottom)27 void Rect::Inset(int32_t left, int32_t top, int32_t right, int32_t bottom) {
28 Offset(left, top);
29 set_width(std::max<int32_t>(width() - left - right, 0));
30 set_height(std::max<int32_t>(height() - top - bottom, 0));
31 }
32
Offset(int32_t horizontal,int32_t vertical)33 void Rect::Offset(int32_t horizontal, int32_t vertical) {
34 rect_.point.x += horizontal;
35 rect_.point.y += vertical;
36 }
37
Contains(int32_t point_x,int32_t point_y) const38 bool Rect::Contains(int32_t point_x, int32_t point_y) const {
39 return (point_x >= x()) && (point_x < right()) &&
40 (point_y >= y()) && (point_y < bottom());
41 }
42
Contains(const Rect & rect) const43 bool Rect::Contains(const Rect& rect) const {
44 return (rect.x() >= x() && rect.right() <= right() &&
45 rect.y() >= y() && rect.bottom() <= bottom());
46 }
47
Intersects(const Rect & rect) const48 bool Rect::Intersects(const Rect& rect) const {
49 return !(rect.x() >= right() || rect.right() <= x() ||
50 rect.y() >= bottom() || rect.bottom() <= y());
51 }
52
Intersect(const Rect & rect) const53 Rect Rect::Intersect(const Rect& rect) const {
54 int32_t rx = std::max(x(), rect.x());
55 int32_t ry = std::max(y(), rect.y());
56 int32_t rr = std::min(right(), rect.right());
57 int32_t rb = std::min(bottom(), rect.bottom());
58
59 if (rx >= rr || ry >= rb)
60 rx = ry = rr = rb = 0; // non-intersecting
61
62 return Rect(rx, ry, rr - rx, rb - ry);
63 }
64
Union(const Rect & rect) const65 Rect Rect::Union(const Rect& rect) const {
66 // special case empty rects...
67 if (IsEmpty())
68 return rect;
69 if (rect.IsEmpty())
70 return *this;
71
72 int32_t rx = std::min(x(), rect.x());
73 int32_t ry = std::min(y(), rect.y());
74 int32_t rr = std::max(right(), rect.right());
75 int32_t rb = std::max(bottom(), rect.bottom());
76
77 return Rect(rx, ry, rr - rx, rb - ry);
78 }
79
Subtract(const Rect & rect) const80 Rect Rect::Subtract(const Rect& rect) const {
81 // boundary cases:
82 if (!Intersects(rect))
83 return *this;
84 if (rect.Contains(*this))
85 return Rect();
86
87 int32_t rx = x();
88 int32_t ry = y();
89 int32_t rr = right();
90 int32_t rb = bottom();
91
92 if (rect.y() <= y() && rect.bottom() >= bottom()) {
93 // complete intersection in the y-direction
94 if (rect.x() <= x()) {
95 rx = rect.right();
96 } else {
97 rr = rect.x();
98 }
99 } else if (rect.x() <= x() && rect.right() >= right()) {
100 // complete intersection in the x-direction
101 if (rect.y() <= y()) {
102 ry = rect.bottom();
103 } else {
104 rb = rect.y();
105 }
106 }
107 return Rect(rx, ry, rr - rx, rb - ry);
108 }
109
AdjustToFit(const Rect & rect) const110 Rect Rect::AdjustToFit(const Rect& rect) const {
111 int32_t new_x = x();
112 int32_t new_y = y();
113 int32_t new_width = width();
114 int32_t new_height = height();
115 AdjustAlongAxis(rect.x(), rect.width(), &new_x, &new_width);
116 AdjustAlongAxis(rect.y(), rect.height(), &new_y, &new_height);
117 return Rect(new_x, new_y, new_width, new_height);
118 }
119
CenterPoint() const120 Point Rect::CenterPoint() const {
121 return Point(x() + (width() + 1) / 2, y() + (height() + 1) / 2);
122 }
123
SharesEdgeWith(const Rect & rect) const124 bool Rect::SharesEdgeWith(const Rect& rect) const {
125 return (y() == rect.y() && height() == rect.height() &&
126 (x() == rect.right() || right() == rect.x())) ||
127 (x() == rect.x() && width() == rect.width() &&
128 (y() == rect.bottom() || bottom() == rect.y()));
129 }
130
Inset(float left,float top,float right,float bottom)131 void FloatRect::Inset(float left, float top, float right, float bottom) {
132 Offset(left, top);
133 set_width(std::max<float>(width() - left - right, 0.0f));
134 set_height(std::max<float>(height() - top - bottom, 0.0f));
135 }
136
Offset(float horizontal,float vertical)137 void FloatRect::Offset(float horizontal, float vertical) {
138 rect_.point.x += horizontal;
139 rect_.point.y += vertical;
140 }
141
Contains(float point_x,float point_y) const142 bool FloatRect::Contains(float point_x, float point_y) const {
143 return (point_x >= x()) && (point_x < right()) &&
144 (point_y >= y()) && (point_y < bottom());
145 }
146
Contains(const FloatRect & rect) const147 bool FloatRect::Contains(const FloatRect& rect) const {
148 return (rect.x() >= x() && rect.right() <= right() &&
149 rect.y() >= y() && rect.bottom() <= bottom());
150 }
151
Intersects(const FloatRect & rect) const152 bool FloatRect::Intersects(const FloatRect& rect) const {
153 return !(rect.x() >= right() || rect.right() <= x() ||
154 rect.y() >= bottom() || rect.bottom() <= y());
155 }
156
Intersect(const FloatRect & rect) const157 FloatRect FloatRect::Intersect(const FloatRect& rect) const {
158 float rx = std::max(x(), rect.x());
159 float ry = std::max(y(), rect.y());
160 float rr = std::min(right(), rect.right());
161 float rb = std::min(bottom(), rect.bottom());
162
163 if (rx >= rr || ry >= rb)
164 rx = ry = rr = rb = 0; // non-intersecting
165
166 return FloatRect(rx, ry, rr - rx, rb - ry);
167 }
168
Union(const FloatRect & rect) const169 FloatRect FloatRect::Union(const FloatRect& rect) const {
170 // special case empty rects...
171 if (IsEmpty())
172 return rect;
173 if (rect.IsEmpty())
174 return *this;
175
176 float rx = std::min(x(), rect.x());
177 float ry = std::min(y(), rect.y());
178 float rr = std::max(right(), rect.right());
179 float rb = std::max(bottom(), rect.bottom());
180
181 return FloatRect(rx, ry, rr - rx, rb - ry);
182 }
183
Subtract(const FloatRect & rect) const184 FloatRect FloatRect::Subtract(const FloatRect& rect) const {
185 // boundary cases:
186 if (!Intersects(rect))
187 return *this;
188 if (rect.Contains(*this))
189 return FloatRect();
190
191 float rx = x();
192 float ry = y();
193 float rr = right();
194 float rb = bottom();
195
196 if (rect.y() <= y() && rect.bottom() >= bottom()) {
197 // complete intersection in the y-direction
198 if (rect.x() <= x()) {
199 rx = rect.right();
200 } else {
201 rr = rect.x();
202 }
203 } else if (rect.x() <= x() && rect.right() >= right()) {
204 // complete intersection in the x-direction
205 if (rect.y() <= y()) {
206 ry = rect.bottom();
207 } else {
208 rb = rect.y();
209 }
210 }
211 return FloatRect(rx, ry, rr - rx, rb - ry);
212 }
213
AdjustToFit(const FloatRect & rect) const214 FloatRect FloatRect::AdjustToFit(const FloatRect& rect) const {
215 float new_x = x();
216 float new_y = y();
217 float new_width = width();
218 float new_height = height();
219 AdjustAlongAxis(rect.x(), rect.width(), &new_x, &new_width);
220 AdjustAlongAxis(rect.y(), rect.height(), &new_y, &new_height);
221 return FloatRect(new_x, new_y, new_width, new_height);
222 }
223
CenterPoint() const224 FloatPoint FloatRect::CenterPoint() const {
225 return FloatPoint(x() + (width() + 1.0f) / 2.0f,
226 y() + (height() + 1.0f) / 2.0f);
227 }
228
SharesEdgeWith(const FloatRect & rect) const229 bool FloatRect::SharesEdgeWith(const FloatRect& rect) const {
230 return (y() == rect.y() && height() == rect.height() &&
231 (x() == rect.right() || right() == rect.x())) ||
232 (x() == rect.x() && width() == rect.width() &&
233 (y() == rect.bottom() || bottom() == rect.y()));
234 }
235 } // namespace pp
236