rrect_f.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // Copyright 2018 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. #ifndef UI_GFX_GEOMETRY_RRECT_F_H_
  5. #define UI_GFX_GEOMETRY_RRECT_F_H_
  6. #include <memory>
  7. #include <string>
  8. #include "third_party/skia/include/core/SkRRect.h"
  9. #include "ui/gfx/geometry/rect_f.h"
  10. #include "ui/gfx/geometry/rounded_corners_f.h"
  11. #include "ui/gfx/geometry/skia_conversions.h"
  12. namespace gfx {
  13. class GEOMETRY_SKIA_EXPORT RRectF {
  14. public:
  15. RRectF() = default;
  16. ~RRectF() = default;
  17. RRectF(const RRectF& rect) = default;
  18. RRectF& operator=(const RRectF& rect) = default;
  19. explicit RRectF(const SkRRect& rect) : skrrect_(rect) {}
  20. explicit RRectF(const gfx::RectF& rect) : RRectF(rect, 0.f) {}
  21. RRectF(const gfx::RectF& rect, float radius) : RRectF(rect, radius, radius) {}
  22. RRectF(const gfx::RectF& rect, float x_rad, float y_rad)
  23. : RRectF(rect.x(), rect.y(), rect.width(), rect.height(), x_rad, y_rad) {}
  24. // Sets all x and y radii to radius.
  25. RRectF(float x, float y, float width, float height, float radius)
  26. : RRectF(x, y, width, height, radius, radius) {}
  27. // Sets all x radii to x_rad, and all y radii to y_rad. If one of x_rad or
  28. // y_rad are zero, sets ALL radii to zero.
  29. RRectF(float x, float y, float width, float height, float x_rad, float y_rad);
  30. // Directly sets all four corners.
  31. RRectF(float x,
  32. float y,
  33. float width,
  34. float height,
  35. float upper_left_x,
  36. float upper_left_y,
  37. float upper_right_x,
  38. float upper_right_y,
  39. float lower_right_x,
  40. float lower_right_y,
  41. float lower_left_x,
  42. float lower_left_y);
  43. RRectF(const gfx::RectF& rect,
  44. float upper_left_x,
  45. float upper_left_y,
  46. float upper_right_x,
  47. float upper_right_y,
  48. float lower_right_x,
  49. float lower_right_y,
  50. float lower_left_x,
  51. float lower_left_y)
  52. : RRectF(rect.x(),
  53. rect.y(),
  54. rect.width(),
  55. rect.height(),
  56. upper_left_x,
  57. upper_left_y,
  58. upper_right_x,
  59. upper_right_y,
  60. lower_right_x,
  61. lower_right_y,
  62. lower_left_x,
  63. lower_left_y) {}
  64. RRectF(const gfx::RectF& rect, const gfx::RoundedCornersF& corners)
  65. : RRectF(rect.x(),
  66. rect.y(),
  67. rect.width(),
  68. rect.height(),
  69. corners.upper_left(),
  70. corners.upper_left(),
  71. corners.upper_right(),
  72. corners.upper_right(),
  73. corners.lower_right(),
  74. corners.lower_right(),
  75. corners.lower_left(),
  76. corners.lower_left()) {}
  77. // The rectangular portion of the RRectF, without the corner radii.
  78. gfx::RectF rect() const { return gfx::SkRectToRectF(skrrect_.rect()); }
  79. // Returns the radii of the all corners. DCHECKs that all corners
  80. // have the same radii (the type is <= kOval).
  81. gfx::Vector2dF GetSimpleRadii() const;
  82. // Returns the radius of all corners. DCHECKs that all corners have the same
  83. // radii, and that x_rad == y_rad (the type is <= kSingle).
  84. float GetSimpleRadius() const;
  85. // Make the RRectF empty.
  86. void Clear() { skrrect_.setEmpty(); }
  87. bool Equals(const RRectF& other) const { return skrrect_ == other.skrrect_; }
  88. // These are all mutually exclusive, and ordered in increasing complexity. The
  89. // order is assumed in several functions.
  90. enum class Type {
  91. kEmpty, // Zero width or height.
  92. kRect, // Non-zero width and height, and zeroed radii - a pure rectangle.
  93. kSingle, // Non-zero width and height, and a single, non-zero value for all
  94. // X and Y radii.
  95. kSimple, // Non-zero width and height, X radii all equal and non-zero, Y
  96. // radii all equal and non-zero, and x_rad != y_rad.
  97. kOval, // Non-zero width and height, X radii all equal to width/2, and Y
  98. // radii all equal to height/2, and x_rad != y_rad.
  99. kComplex, // Non-zero width and height, and arbitrary (non-equal) radii.
  100. };
  101. Type GetType() const;
  102. bool IsEmpty() const { return GetType() == Type::kEmpty; }
  103. // Enumeration of the corners of a rectangle in clockwise order. Values match
  104. // SkRRect::Corner.
  105. enum class Corner {
  106. kUpperLeft = SkRRect::kUpperLeft_Corner,
  107. kUpperRight = SkRRect::kUpperRight_Corner,
  108. kLowerRight = SkRRect::kLowerRight_Corner,
  109. kLowerLeft = SkRRect::kLowerLeft_Corner,
  110. };
  111. // GetCornerRadii may be called for any type of RRect (kRect, kOval, etc.),
  112. // and it will return "correct" values. If GetType() is kOval or less, all
  113. // corner values will be identical to each other. SetCornerRadii can similarly
  114. // be called on any type of RRect, but GetType() may change as a result of the
  115. // call.
  116. gfx::Vector2dF GetCornerRadii(Corner corner) const;
  117. void SetCornerRadii(Corner corner, float x_rad, float y_rad);
  118. void SetCornerRadii(Corner corner, const gfx::Vector2dF& radii) {
  119. SetCornerRadii(corner, radii.x(), radii.y());
  120. }
  121. // Returns true if |rect| is inside the bounds and corner radii of this
  122. // RRectF, and if both this RRectF and rect are not empty.
  123. bool Contains(const RectF& rect) const {
  124. return skrrect_.contains(gfx::RectFToSkRect(rect));
  125. }
  126. // Scales the rectangle by |scale|.
  127. void Scale(float scale) { Scale(scale, scale); }
  128. // Scales the rectangle by |x_scale| and |y_scale|.
  129. void Scale(float x_scale, float y_scale);
  130. // Move the rectangle by a horizontal and vertical distance.
  131. void Offset(float horizontal, float vertical);
  132. void Offset(const Vector2dF& distance) { Offset(distance.x(), distance.y()); }
  133. const RRectF& operator+=(const gfx::Vector2dF& offset);
  134. const RRectF& operator-=(const gfx::Vector2dF& offset);
  135. std::string ToString() const;
  136. bool ApproximatelyEqual(const RRectF& rect, float tolerance) const;
  137. // Insets bounds by dx and dy, and adjusts radii by dx and dy. dx and dy may
  138. // be positive, negative, or zero. If either corner radius is zero, the corner
  139. // has no curvature and is unchanged. Otherwise, if adjusted radius becomes
  140. // negative, the radius is pinned to zero.
  141. void Inset(float val) { skrrect_.inset(val, val); }
  142. void Inset(float dx, float dy) { skrrect_.inset(dx, dy); }
  143. // Outsets bounds by dx and dy, and adjusts radii by dx and dy. dx and dy may
  144. // be positive, negative, or zero. If either corner radius is zero, the corner
  145. // has no curvature and is unchanged. Otherwise, if adjusted radius becomes
  146. // negative, the radius is pinned to zero.
  147. void Outset(float val) { skrrect_.outset(val, val); }
  148. void Outset(float dx, float dy) { skrrect_.outset(dx, dy); }
  149. explicit operator SkRRect() const { return skrrect_; }
  150. private:
  151. void GetAllRadii(SkVector radii[4]) const;
  152. SkRRect skrrect_;
  153. };
  154. inline std::ostream& operator<<(std::ostream& os, const RRectF& rect) {
  155. return os << rect.ToString();
  156. }
  157. inline bool operator==(const RRectF& a, const RRectF& b) {
  158. return a.Equals(b);
  159. }
  160. inline bool operator!=(const RRectF& a, const RRectF& b) {
  161. return !(a == b);
  162. }
  163. inline RRectF operator+(const RRectF& a, const gfx::Vector2dF& b) {
  164. RRectF result = a;
  165. result += b;
  166. return result;
  167. }
  168. inline RRectF operator-(const RRectF& a, const Vector2dF& b) {
  169. RRectF result = a;
  170. result -= b;
  171. return result;
  172. }
  173. } // namespace gfx
  174. #endif // UI_GFX_GEOMETRY_RRECT_F_H_