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 ROUND_RECT_H
17 #define ROUND_RECT_H
18 
19 #include <vector>
20 
21 #include "utils/drawing_macros.h"
22 #include "utils/point.h"
23 #include "utils/rect.h"
24 
25 namespace OHOS {
26 namespace Rosen {
27 namespace Drawing {
28 class DRAWING_API RoundRect {
29 public:
30     enum CornerPos : int {
31         TOP_LEFT_POS,
32         TOP_RIGHT_POS,
33         BOTTOM_RIGHT_POS,
34         BOTTOM_LEFT_POS,
35         CORNER_NUMBER
36     };
37 
38     inline RoundRect() noexcept;
~RoundRect()39     inline ~RoundRect() {}
40 
41     inline RoundRect(const RoundRect& roundRect) noexcept;
42     inline RoundRect(const Rect& r, scalar xRad, scalar yRad) noexcept;
43     inline RoundRect(const Rect& r, const std::vector<Point>& radiusXY) noexcept;
44 
45     inline void SetCornerRadius(CornerPos pos, scalar radiusX, scalar radiusY);
46     inline const Point& GetCornerRadius(CornerPos pos) const;
47 
48     inline void SetRect(const Rect& rect);
49     inline const Rect& GetRect() const;
50 
51     /**
52      * @brief Translates RoundRect by (dx, dy).
53      * @param dx  offset added to rect left and rect right
54      * @param dy  offset added to rect top and rect bottom
55      */
56     inline void Offset(scalar dx, scalar dy);
57     inline bool IsSimpleRoundRect() const;
58     inline scalar GetSimpleX() const;
59     inline scalar GetSimpleY() const;
60 
61     void AdjustRadiiX(double limit, double scale, CornerPos cornerPosA, CornerPos cornerPosB);
62     void AdjustRadiiY(double limit, double scale, CornerPos cornerPosA, CornerPos cornerPosB);
63     bool ClampToZero();
64 
65     /**
66      * @brief Returns true if the radii had to be scaled to fit rect.
67      */
68     bool ScaleRadii();
69 
70 private:
71     Rect rect_;
72     // Four radii are stored: top-left/top-right/bottom-left/bottom-right corner radii.
73     Point radiusXY_[CORNER_NUMBER] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
74     bool isSimple_ = false;
75 };
76 
RoundRect()77 inline RoundRect::RoundRect() noexcept : rect_(), isSimple_(true) {}
78 
RoundRect(const RoundRect & roundRect)79 inline RoundRect::RoundRect(const RoundRect& roundRect) noexcept : RoundRect()
80 {
81     rect_ = roundRect.rect_;
82     for (int i = 0; i < CORNER_NUMBER; ++i) {
83         radiusXY_[i] = roundRect.radiusXY_[i];
84     }
85     isSimple_ = roundRect.isSimple_;
86 }
87 
RoundRect(const Rect & r,scalar xRad,scalar yRad)88 inline RoundRect::RoundRect(const Rect& r, scalar xRad, scalar yRad) noexcept : RoundRect()
89 {
90     rect_ = r;
91     for (int i = 0; i < CORNER_NUMBER; ++i) {
92         radiusXY_[i].SetX(xRad);
93         radiusXY_[i].SetY(yRad);
94     }
95     isSimple_ = true;
96 }
97 
RoundRect(const Rect & r,const std::vector<Point> & radiusXY)98 inline RoundRect::RoundRect(const Rect& r, const std::vector<Point>& radiusXY) noexcept : RoundRect()
99 {
100     rect_ = r;
101     for (int i = 0; i < CORNER_NUMBER && i < static_cast<int>(radiusXY.size()); ++i) {
102         radiusXY_[i] = radiusXY[i];
103     }
104     isSimple_ = false;
105     ScaleRadii();
106 }
107 
SetCornerRadius(CornerPos pos,scalar radiusX,scalar radiusY)108 inline void RoundRect::SetCornerRadius(CornerPos pos, scalar radiusX, scalar radiusY)
109 {
110     radiusXY_[pos].SetX(radiusX);
111     radiusXY_[pos].SetY(radiusY);
112     isSimple_ = false;
113 }
114 
GetCornerRadius(CornerPos pos)115 inline const Point& RoundRect::GetCornerRadius(CornerPos pos) const
116 {
117     return radiusXY_[pos];
118 }
119 
SetRect(const Rect & rect)120 inline void RoundRect::SetRect(const Rect& rect)
121 {
122     rect_ = rect;
123 }
124 
GetRect()125 inline const Rect& RoundRect::GetRect() const
126 {
127     return rect_;
128 }
129 
Offset(scalar dx,scalar dy)130 inline void RoundRect::Offset(scalar dx, scalar dy)
131 {
132     rect_.Offset(dx, dy);
133 }
134 
IsSimpleRoundRect()135 inline bool RoundRect::IsSimpleRoundRect() const
136 {
137     return isSimple_;
138 }
139 
GetSimpleX()140 inline scalar RoundRect::GetSimpleX() const
141 {
142     return radiusXY_[RoundRect::TOP_LEFT_POS].GetX();
143 }
144 
GetSimpleY()145 inline scalar RoundRect::GetSimpleY() const
146 {
147     return radiusXY_[RoundRect::TOP_LEFT_POS].GetY();
148 }
149 } // namespace Drawing
150 } // namespace Rosen
151 } // namespace OHOS
152 #endif