123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- // Copyright 2018 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.
- #ifndef UI_GFX_GEOMETRY_RRECT_F_H_
- #define UI_GFX_GEOMETRY_RRECT_F_H_
- #include <memory>
- #include <string>
- #include "third_party/skia/include/core/SkRRect.h"
- #include "ui/gfx/geometry/rect_f.h"
- #include "ui/gfx/geometry/rounded_corners_f.h"
- #include "ui/gfx/geometry/skia_conversions.h"
- namespace gfx {
- class GEOMETRY_SKIA_EXPORT RRectF {
- public:
- RRectF() = default;
- ~RRectF() = default;
- RRectF(const RRectF& rect) = default;
- RRectF& operator=(const RRectF& rect) = default;
- explicit RRectF(const SkRRect& rect) : skrrect_(rect) {}
- explicit RRectF(const gfx::RectF& rect) : RRectF(rect, 0.f) {}
- RRectF(const gfx::RectF& rect, float radius) : RRectF(rect, radius, radius) {}
- RRectF(const gfx::RectF& rect, float x_rad, float y_rad)
- : RRectF(rect.x(), rect.y(), rect.width(), rect.height(), x_rad, y_rad) {}
- // Sets all x and y radii to radius.
- RRectF(float x, float y, float width, float height, float radius)
- : RRectF(x, y, width, height, radius, radius) {}
- // Sets all x radii to x_rad, and all y radii to y_rad. If one of x_rad or
- // y_rad are zero, sets ALL radii to zero.
- RRectF(float x, float y, float width, float height, float x_rad, float y_rad);
- // Directly sets all four corners.
- RRectF(float x,
- float y,
- float width,
- float height,
- float upper_left_x,
- float upper_left_y,
- float upper_right_x,
- float upper_right_y,
- float lower_right_x,
- float lower_right_y,
- float lower_left_x,
- float lower_left_y);
- RRectF(const gfx::RectF& rect,
- float upper_left_x,
- float upper_left_y,
- float upper_right_x,
- float upper_right_y,
- float lower_right_x,
- float lower_right_y,
- float lower_left_x,
- float lower_left_y)
- : RRectF(rect.x(),
- rect.y(),
- rect.width(),
- rect.height(),
- upper_left_x,
- upper_left_y,
- upper_right_x,
- upper_right_y,
- lower_right_x,
- lower_right_y,
- lower_left_x,
- lower_left_y) {}
- RRectF(const gfx::RectF& rect, const gfx::RoundedCornersF& corners)
- : RRectF(rect.x(),
- rect.y(),
- rect.width(),
- rect.height(),
- corners.upper_left(),
- corners.upper_left(),
- corners.upper_right(),
- corners.upper_right(),
- corners.lower_right(),
- corners.lower_right(),
- corners.lower_left(),
- corners.lower_left()) {}
- // The rectangular portion of the RRectF, without the corner radii.
- gfx::RectF rect() const { return gfx::SkRectToRectF(skrrect_.rect()); }
- // Returns the radii of the all corners. DCHECKs that all corners
- // have the same radii (the type is <= kOval).
- gfx::Vector2dF GetSimpleRadii() const;
- // Returns the radius of all corners. DCHECKs that all corners have the same
- // radii, and that x_rad == y_rad (the type is <= kSingle).
- float GetSimpleRadius() const;
- // Make the RRectF empty.
- void Clear() { skrrect_.setEmpty(); }
- bool Equals(const RRectF& other) const { return skrrect_ == other.skrrect_; }
- // These are all mutually exclusive, and ordered in increasing complexity. The
- // order is assumed in several functions.
- enum class Type {
- kEmpty, // Zero width or height.
- kRect, // Non-zero width and height, and zeroed radii - a pure rectangle.
- kSingle, // Non-zero width and height, and a single, non-zero value for all
- // X and Y radii.
- kSimple, // Non-zero width and height, X radii all equal and non-zero, Y
- // radii all equal and non-zero, and x_rad != y_rad.
- kOval, // Non-zero width and height, X radii all equal to width/2, and Y
- // radii all equal to height/2, and x_rad != y_rad.
- kComplex, // Non-zero width and height, and arbitrary (non-equal) radii.
- };
- Type GetType() const;
- bool IsEmpty() const { return GetType() == Type::kEmpty; }
- // Enumeration of the corners of a rectangle in clockwise order. Values match
- // SkRRect::Corner.
- enum class Corner {
- kUpperLeft = SkRRect::kUpperLeft_Corner,
- kUpperRight = SkRRect::kUpperRight_Corner,
- kLowerRight = SkRRect::kLowerRight_Corner,
- kLowerLeft = SkRRect::kLowerLeft_Corner,
- };
- // GetCornerRadii may be called for any type of RRect (kRect, kOval, etc.),
- // and it will return "correct" values. If GetType() is kOval or less, all
- // corner values will be identical to each other. SetCornerRadii can similarly
- // be called on any type of RRect, but GetType() may change as a result of the
- // call.
- gfx::Vector2dF GetCornerRadii(Corner corner) const;
- void SetCornerRadii(Corner corner, float x_rad, float y_rad);
- void SetCornerRadii(Corner corner, const gfx::Vector2dF& radii) {
- SetCornerRadii(corner, radii.x(), radii.y());
- }
- // Returns true if |rect| is inside the bounds and corner radii of this
- // RRectF, and if both this RRectF and rect are not empty.
- bool Contains(const RectF& rect) const {
- return skrrect_.contains(gfx::RectFToSkRect(rect));
- }
- // Scales the rectangle by |scale|.
- void Scale(float scale) { Scale(scale, scale); }
- // Scales the rectangle by |x_scale| and |y_scale|.
- void Scale(float x_scale, float y_scale);
- // Move the rectangle by a horizontal and vertical distance.
- void Offset(float horizontal, float vertical);
- void Offset(const Vector2dF& distance) { Offset(distance.x(), distance.y()); }
- const RRectF& operator+=(const gfx::Vector2dF& offset);
- const RRectF& operator-=(const gfx::Vector2dF& offset);
- std::string ToString() const;
- bool ApproximatelyEqual(const RRectF& rect, float tolerance) const;
- // Insets bounds by dx and dy, and adjusts radii by dx and dy. dx and dy may
- // be positive, negative, or zero. If either corner radius is zero, the corner
- // has no curvature and is unchanged. Otherwise, if adjusted radius becomes
- // negative, the radius is pinned to zero.
- void Inset(float val) { skrrect_.inset(val, val); }
- void Inset(float dx, float dy) { skrrect_.inset(dx, dy); }
- // Outsets bounds by dx and dy, and adjusts radii by dx and dy. dx and dy may
- // be positive, negative, or zero. If either corner radius is zero, the corner
- // has no curvature and is unchanged. Otherwise, if adjusted radius becomes
- // negative, the radius is pinned to zero.
- void Outset(float val) { skrrect_.outset(val, val); }
- void Outset(float dx, float dy) { skrrect_.outset(dx, dy); }
- explicit operator SkRRect() const { return skrrect_; }
- private:
- void GetAllRadii(SkVector radii[4]) const;
- SkRRect skrrect_;
- };
- inline std::ostream& operator<<(std::ostream& os, const RRectF& rect) {
- return os << rect.ToString();
- }
- inline bool operator==(const RRectF& a, const RRectF& b) {
- return a.Equals(b);
- }
- inline bool operator!=(const RRectF& a, const RRectF& b) {
- return !(a == b);
- }
- inline RRectF operator+(const RRectF& a, const gfx::Vector2dF& b) {
- RRectF result = a;
- result += b;
- return result;
- }
- inline RRectF operator-(const RRectF& a, const Vector2dF& b) {
- RRectF result = a;
- result -= b;
- return result;
- }
- } // namespace gfx
- #endif // UI_GFX_GEOMETRY_RRECT_F_H_
|