1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_RRECT_H
17 #define FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_RRECT_H
18 
19 #include <algorithm>
20 #include <cstdint>
21 #include <cstring>
22 
23 #include "base/geometry/rect.h"
24 #include "core/components/common/properties/radius.h"
25 
26 namespace OHOS::Ace {
27 
28 struct Corner {
29     Radius topLeftRadius;
30     Radius topRightRadius;
31     Radius bottomRightRadius;
32     Radius bottomLeftRadius;
33 };
34 
35 class RRect final {
36 public:
37     RRect() = default;
38     ~RRect() = default;
39 
RRect(const Rect & rect)40     explicit RRect(const Rect& rect) : rect_(rect) {}
RRect(double x,double y,double width,double height)41     RRect(double x, double y, double width, double height)
42     {
43         rect_.SetRect(x, y, width, height);
44     }
45 
MakeRect(const Rect & rect)46     static RRect MakeRect(const Rect& rect)
47     {
48         RRect rrect;
49         rrect.SetRect(rect);
50         return rrect;
51     }
52 
MakeRRect(const Rect & rect,const Radius & radius)53     static RRect MakeRRect(const Rect& rect, const Radius& radius)
54     {
55         RRect rrect;
56         rrect.SetRectWithSimpleRadius(rect, radius.GetX().Value(), radius.GetY().Value());
57         return rrect;
58     }
59 
MakeRRect(const Rect & rect,double x,double y)60     static RRect MakeRRect(const Rect& rect, double x, double y)
61     {
62         RRect rrect;
63         rrect.SetRectWithSimpleRadius(rect, x, y);
64         return rrect;
65     }
66 
MakeOval(const Rect & rect)67     static RRect MakeOval(const Rect& rect)
68     {
69         RRect rrect;
70         rrect.SetOval(rect);
71         return rrect;
72     }
73 
GetRect()74     const Rect& GetRect() const
75     {
76         return rect_;
77     }
78 
GetCorner()79     const Corner& GetCorner() const
80     {
81         return corner_;
82     }
83 
SetRect(const Rect & rect)84     void SetRect(const Rect& rect)
85     {
86         rect_ = rect;
87     }
88 
SetCorner(const Corner & corner)89     void SetCorner(const Corner& corner)
90     {
91         corner_ = corner;
92     }
93 
SetRectWithSimpleRadius(const Rect & rect,double xRadius,double yRadius)94     void SetRectWithSimpleRadius(const Rect& rect, double xRadius, double yRadius)
95     {
96         rect_ = rect;
97         if (xRadius <= 0 || yRadius <= 0) {
98             return;
99         }
100         if (rect_.Width() < (xRadius + xRadius) || rect.Height() < (yRadius + yRadius)) {
101             double scale = std::min(rect.Width() / (xRadius + xRadius), rect.Height() / (yRadius + yRadius));
102             xRadius *= scale;
103             yRadius *= scale;
104         }
105         auto radius = Radius(xRadius, yRadius);
106         corner_ = { radius, radius, radius, radius };
107     }
108 
ApplyScaleAndRound(float scale)109     void ApplyScaleAndRound(float scale)
110     {
111         rect_.ApplyScaleAndRound(Size(scale, scale));
112         corner_.topLeftRadius.ApplyScaleAndRound(scale);
113         corner_.topRightRadius.ApplyScaleAndRound(scale);
114         corner_.bottomRightRadius.ApplyScaleAndRound(scale);
115         corner_.bottomLeftRadius.ApplyScaleAndRound(scale);
116     }
117 
SetOval(const Rect & rect)118     void SetOval(const Rect& rect)
119     {
120         rect_ = rect;
121         double xRadius = rect.Width() / 2;
122         double yRadius = rect.Height() / 2;
123         auto radius = Radius(xRadius, yRadius);
124         corner_ = { radius, radius, radius, radius };
125     }
126 
Width()127     double Width() const
128     {
129         return rect_.Width();
130     }
131 
Height()132     double Height() const
133     {
134         return rect_.Height();
135     }
136 
137     bool operator==(const RRect& rrect) const
138     {
139         return rrect.GetCorner().bottomLeftRadius == corner_.bottomLeftRadius &&
140                rrect.GetCorner().bottomRightRadius == corner_.bottomRightRadius &&
141                rrect.GetCorner().topLeftRadius == corner_.topLeftRadius &&
142                rrect.GetCorner().topRightRadius == corner_.topRightRadius && rrect.GetRect() == rect_;
143     }
144 
145     RRect& operator+=(const Offset& offset)
146     {
147         rect_ += offset;
148         return *this;
149     }
150 
151 private:
152     Corner corner_ { { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 } };
153     Rect rect_;
154 };
155 
156 } // namespace OHOS::Ace
157 
158 #endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_RRECT_H
159