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// A template for a simple rectangle class.  The containment semantics
6// are array-like; that is, the coordinate (x, y) is considered to be
7// contained by the rectangle, but the coordinate (x + width, y) is not.
8// The class will happily let you create malformed rectangles (that is,
9// rectangles with negative width and/or height), but there will be assertions
10// in the operations (such as Contains()) to complain in this case.
11
12#ifndef UI_GFX_GEOMETRY_RECT_BASE_H_
13#define UI_GFX_GEOMETRY_RECT_BASE_H_
14
15#include <string>
16
17#include "base/compiler_specific.h"
18
19namespace gfx {
20
21template<typename Class,
22         typename PointClass,
23         typename SizeClass,
24         typename InsetsClass,
25         typename VectorClass,
26         typename Type>
27class GFX_EXPORT RectBase {
28 public:
29  Type x() const { return origin_.x(); }
30  void set_x(Type x) { origin_.set_x(x); }
31
32  Type y() const { return origin_.y(); }
33  void set_y(Type y) { origin_.set_y(y); }
34
35  Type width() const { return size_.width(); }
36  void set_width(Type width) { size_.set_width(width); }
37
38  Type height() const { return size_.height(); }
39  void set_height(Type height) { size_.set_height(height); }
40
41  const PointClass& origin() const { return origin_; }
42  void set_origin(const PointClass& origin) { origin_ = origin; }
43
44  const SizeClass& size() const { return size_; }
45  void set_size(const SizeClass& size) { size_ = size; }
46
47  Type right() const { return x() + width(); }
48  Type bottom() const { return y() + height(); }
49
50  PointClass top_right() const { return PointClass(right(), y()); }
51  PointClass bottom_left() const { return PointClass(x(), bottom()); }
52  PointClass bottom_right() const { return PointClass(right(), bottom()); }
53
54  VectorClass OffsetFromOrigin() const {
55    return VectorClass(x(), y());
56  }
57
58  void SetRect(Type x, Type y, Type width, Type height);
59
60  // Shrink the rectangle by a horizontal and vertical distance on all sides.
61  void Inset(Type horizontal, Type vertical) {
62    Inset(horizontal, vertical, horizontal, vertical);
63  }
64
65  // Shrink the rectangle by the given insets.
66  void Inset(const InsetsClass& insets);
67
68  // Shrink the rectangle by the specified amount on each side.
69  void Inset(Type left, Type top, Type right, Type bottom);
70
71  // Move the rectangle by a horizontal and vertical distance.
72  void Offset(Type horizontal, Type vertical);
73  void Offset(const VectorClass& distance) {
74    Offset(distance.x(), distance.y());
75  }
76  void operator+=(const VectorClass& offset);
77  void operator-=(const VectorClass& offset);
78
79  InsetsClass InsetsFrom(const Class& inner) const {
80    return InsetsClass(inner.y() - y(),
81                       inner.x() - x(),
82                       bottom() - inner.bottom(),
83                       right() - inner.right());
84  }
85
86  // Returns true if the area of the rectangle is zero.
87  bool IsEmpty() const { return size_.IsEmpty(); }
88
89  // A rect is less than another rect if its origin is less than
90  // the other rect's origin. If the origins are equal, then the
91  // shortest rect is less than the other. If the origin and the
92  // height are equal, then the narrowest rect is less than.
93  // This comparison is required to use Rects in sets, or sorted
94  // vectors.
95  bool operator<(const Class& other) const;
96
97  // Returns true if the point identified by point_x and point_y falls inside
98  // this rectangle.  The point (x, y) is inside the rectangle, but the
99  // point (x + width, y + height) is not.
100  bool Contains(Type point_x, Type point_y) const;
101
102  // Returns true if the specified point is contained by this rectangle.
103  bool Contains(const PointClass& point) const {
104    return Contains(point.x(), point.y());
105  }
106
107  // Returns true if this rectangle contains the specified rectangle.
108  bool Contains(const Class& rect) const;
109
110  // Returns true if this rectangle intersects the specified rectangle.
111  // An empty rectangle doesn't intersect any rectangle.
112  bool Intersects(const Class& rect) const;
113
114  // Computes the intersection of this rectangle with the given rectangle.
115  void Intersect(const Class& rect);
116
117  // Computes the union of this rectangle with the given rectangle.  The union
118  // is the smallest rectangle containing both rectangles.
119  void Union(const Class& rect);
120
121  // Computes the rectangle resulting from subtracting |rect| from |*this|,
122  // i.e. the bounding rect of |Region(*this) - Region(rect)|.
123  void Subtract(const Class& rect);
124
125  // Fits as much of the receiving rectangle into the supplied rectangle as
126  // possible, becoming the result. For example, if the receiver had
127  // a x-location of 2 and a width of 4, and the supplied rectangle had
128  // an x-location of 0 with a width of 5, the returned rectangle would have
129  // an x-location of 1 with a width of 4.
130  void AdjustToFit(const Class& rect);
131
132  // Returns the center of this rectangle.
133  PointClass CenterPoint() const;
134
135  // Becomes a rectangle that has the same center point but with a size capped
136  // at given |size|.
137  void ClampToCenteredSize(const SizeClass& size);
138
139  // Splits |this| in two halves, |left_half| and |right_half|.
140  void SplitVertically(Class* left_half, Class* right_half) const;
141
142  // Returns true if this rectangle shares an entire edge (i.e., same width or
143  // same height) with the given rectangle, and the rectangles do not overlap.
144  bool SharesEdgeWith(const Class& rect) const;
145
146  // Returns the manhattan distance from the rect to the point. If the point is
147  // inside the rect, returns 0.
148  Type ManhattanDistanceToPoint(const PointClass& point) const;
149
150  // Returns the manhattan distance between the contents of this rect and the
151  // contents of the given rect. That is, if the intersection of the two rects
152  // is non-empty then the function returns 0. If the rects share a side, it
153  // returns the smallest non-zero value appropriate for Type.
154  Type ManhattanInternalDistance(const Class& rect) const;
155
156 protected:
157  RectBase(const PointClass& origin, const SizeClass& size)
158      : origin_(origin), size_(size) {}
159  explicit RectBase(const SizeClass& size)
160      : size_(size) {}
161  explicit RectBase(const PointClass& origin)
162      : origin_(origin) {}
163  // Destructor is intentionally made non virtual and protected.
164  // Do not make this public.
165  ~RectBase() {}
166
167 private:
168  PointClass origin_;
169  SizeClass size_;
170};
171
172}  // namespace gfx
173
174#endif  // UI_GFX_GEOMETRY_RECT_BASE_H_
175