summaryrefslogtreecommitdiffstats
path: root/ui/gfx/rect_base.h
blob: 8ae2a64e5580d16c0fd389e20877b7ed4335a574 (plain)
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// Copyright (c) 2012 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.

// A template for a simple rectangle class.  The containment semantics
// are array-like; that is, the coordinate (x, y) is considered to be
// contained by the rectangle, but the coordinate (x + width, y) is not.
// The class will happily let you create malformed rectangles (that is,
// rectangles with negative width and/or height), but there will be assertions
// in the operations (such as Contains()) to complain in this case.

#ifndef UI_GFX_RECT_BASE_H_
#define UI_GFX_RECT_BASE_H_

#include <string>

#include "base/compiler_specific.h"

namespace gfx {

template<typename Class,
         typename PointClass,
         typename SizeClass,
         typename InsetsClass,
         typename VectorClass,
         typename Type>
class UI_EXPORT RectBase {
 public:
  Type x() const { return origin_.x(); }
  void set_x(Type x) { origin_.set_x(x); }

  Type y() const { return origin_.y(); }
  void set_y(Type y) { origin_.set_y(y); }

  Type width() const { return size_.width(); }
  void set_width(Type width) { size_.set_width(width); }

  Type height() const { return size_.height(); }
  void set_height(Type height) { size_.set_height(height); }

  const PointClass& origin() const { return origin_; }
  void set_origin(const PointClass& origin) { origin_ = origin; }

  const SizeClass& size() const { return size_; }
  void set_size(const SizeClass& size) { size_ = size; }

  Type right() const { return x() + width(); }
  Type bottom() const { return y() + height(); }

  PointClass top_right() const { return PointClass(right(), y()); }
  PointClass bottom_left() const { return PointClass(x(), bottom()); }
  PointClass bottom_right() const { return PointClass(right(), bottom()); }

  VectorClass OffsetFromOrigin() const {
    return VectorClass(x(), y());
  }

  void SetRect(Type x, Type y, Type width, Type height);

  // Shrink the rectangle by a horizontal and vertical distance on all sides.
  void Inset(Type horizontal, Type vertical) {
    Inset(horizontal, vertical, horizontal, vertical);
  }

  // Shrink the rectangle by the given insets.
  void Inset(const InsetsClass& insets);

  // Shrink the rectangle by the specified amount on each side.
  void Inset(Type left, Type top, Type right, Type bottom);

  // Move the rectangle by a horizontal and vertical distance.
  void Offset(Type horizontal, Type vertical);
  void Offset(const VectorClass& distance) {
    Offset(distance.x(), distance.y());
  }
  void operator+=(const VectorClass& offset);
  void operator-=(const VectorClass& offset);

  InsetsClass InsetsFrom(const Class& inner) const {
    return InsetsClass(inner.y() - y(),
                       inner.x() - x(),
                       bottom() - inner.bottom(),
                       right() - inner.right());
  }

  // Returns true if the area of the rectangle is zero.
  bool IsEmpty() const { return size_.IsEmpty(); }

  // A rect is less than another rect if its origin is less than
  // the other rect's origin. If the origins are equal, then the
  // shortest rect is less than the other. If the origin and the
  // height are equal, then the narrowest rect is less than.
  // This comparison is required to use Rects in sets, or sorted
  // vectors.
  bool operator<(const Class& other) const;

  // Returns true if the point identified by point_x and point_y falls inside
  // this rectangle.  The point (x, y) is inside the rectangle, but the
  // point (x + width, y + height) is not.
  bool Contains(Type point_x, Type point_y) const;

  // Returns true if the specified point is contained by this rectangle.
  bool Contains(const PointClass& point) const {
    return Contains(point.x(), point.y());
  }

  // Returns true if this rectangle contains the specified rectangle.
  bool Contains(const Class& rect) const;

  // Returns true if this rectangle intersects the specified rectangle.
  bool Intersects(const Class& rect) const;

  // Computes the intersection of this rectangle with the given rectangle.
  void Intersect(const Class& rect);

  // Computes the union of this rectangle with the given rectangle.  The union
  // is the smallest rectangle containing both rectangles.
  void Union(const Class& rect);

  // Computes the rectangle resulting from subtracting |rect| from |this|.  If
  // |rect| does not intersect completely in either the x- or y-direction, then
  // |*this| does not change.  If |rect| contains |this|, then an empty Rect is
  // the result.
  void Subtract(const Class& rect);

  // Fits as much of the receiving rectangle into the supplied rectangle as
  // possible, becoming the result. For example, if the receiver had
  // a x-location of 2 and a width of 4, and the supplied rectangle had
  // an x-location of 0 with a width of 5, the returned rectangle would have
  // an x-location of 1 with a width of 4.
  void AdjustToFit(const Class& rect);

  // Returns the center of this rectangle.
  PointClass CenterPoint() const;

  // Becomes a rectangle that has the same center point but with a size capped
  // at given |size|.
  void ClampToCenteredSize(const SizeClass& size);

  // Splits |this| in two halves, |left_half| and |right_half|.
  void SplitVertically(Class* left_half, Class* right_half) const;

  // Returns true if this rectangle shares an entire edge (i.e., same width or
  // same height) with the given rectangle, and the rectangles do not overlap.
  bool SharesEdgeWith(const Class& rect) const;

 protected:
  RectBase(const PointClass& origin, const SizeClass& size)
      : origin_(origin), size_(size) {}
  explicit RectBase(const SizeClass& size)
      : size_(size) {}
  explicit RectBase(const PointClass& origin)
      : origin_(origin) {}
  // Destructor is intentionally made non virtual and protected.
  // Do not make this public.
  ~RectBase() {}

 private:
  PointClass origin_;
  SizeClass size_;
};

}  // namespace gfx

#endif  // UI_GFX_RECT_BASE_H_