blob: 738fb6d0fb5040d61168a52086b52aba73ff6638 [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// 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
9namespace {
10
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +010011template<typename T>
12void AdjustAlongAxis(T dst_origin, T dst_size,
13 T* origin, T* size) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +000014 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
25namespace pp {
26
27void 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
33void Rect::Offset(int32_t horizontal, int32_t vertical) {
34 rect_.point.x += horizontal;
35 rect_.point.y += vertical;
36}
37
38bool 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
43bool Rect::Contains(const Rect& rect) const {
44 return (rect.x() >= x() && rect.right() <= right() &&
45 rect.y() >= y() && rect.bottom() <= bottom());
46}
47
48bool Rect::Intersects(const Rect& rect) const {
49 return !(rect.x() >= right() || rect.right() <= x() ||
50 rect.y() >= bottom() || rect.bottom() <= y());
51}
52
53Rect 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
65Rect 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
80Rect 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()) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010093 // complete intersection in the y-direction
Torne (Richard Coles)58218062012-11-14 11:43:16 +000094 if (rect.x() <= x()) {
95 rx = rect.right();
96 } else {
97 rr = rect.x();
98 }
99 } else if (rect.x() <= x() && rect.right() >= right()) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100100 // complete intersection in the x-direction
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000101 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
110Rect 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
120Point Rect::CenterPoint() const {
121 return Point(x() + (width() + 1) / 2, y() + (height() + 1) / 2);
122}
123
124bool 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
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100131void 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
137void FloatRect::Offset(float horizontal, float vertical) {
138 rect_.point.x += horizontal;
139 rect_.point.y += vertical;
140}
141
142bool 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
147bool FloatRect::Contains(const FloatRect& rect) const {
148 return (rect.x() >= x() && rect.right() <= right() &&
149 rect.y() >= y() && rect.bottom() <= bottom());
150}
151
152bool FloatRect::Intersects(const FloatRect& rect) const {
153 return !(rect.x() >= right() || rect.right() <= x() ||
154 rect.y() >= bottom() || rect.bottom() <= y());
155}
156
157FloatRect 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
169FloatRect 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
184FloatRect 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
214FloatRect 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
224FloatPoint FloatRect::CenterPoint() const {
225 return FloatPoint(x() + (width() + 1.0f) / 2.0f,
226 y() + (height() + 1.0f) / 2.0f);
227}
228
229bool 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}
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000235} // namespace pp