1 /*
2  * Copyright (c) 2021-2022 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_CORE_COMPONENTS_BASE_PROPERTIES_SHADOW_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_BASE_PROPERTIES_SHADOW_H
18 
19 #include "base/geometry/offset.h"
20 #include "core/components/common/properties/color.h"
21 
22 namespace OHOS::Ace {
23 
24 constexpr float LIGHT_HEIGHT = 600.0f; // System recommended value.
25 constexpr float LIGHT_RADIUS = 800.0f; // System recommended value.
26 constexpr float LIGHT_POSITION_X = 540.0f; // System recommended value.
27 constexpr float LIGHT_POSITION_Y = 0.0f; // System recommended value.
28 
29 enum class ShadowStyle {
30     OuterDefaultXS,
31     OuterDefaultSM,
32     OuterDefaultMD,
33     OuterDefaultLG,
34     OuterFloatingSM,
35     OuterFloatingMD,
36     None,
37 };
38 
39 enum class ShadowType {
40     COLOR,
41     BLUR,
42 };
43 
44 enum class ShadowColorStrategy : char {
45     NONE,
46     AVERAGE,
47     PRIMARY,
48 };
49 // A style class indicates the way to render shadow effect
50 class Shadow final {
51 public:
52     static Shadow Blend(const Shadow& to, const Shadow& from, float progress);
53 
54     Shadow() = default;
55     ~Shadow() = default;
56 
57     // create shadow for hardware rending.
Shadow(float elevation,Offset offset,Color spotColor,ShadowStyle style)58     Shadow(float elevation, Offset offset, Color spotColor, ShadowStyle style)
59         : offset_(offset), color_(spotColor), style_(style)
60     {
61         SetElevation(elevation);
62     };
63 
64      // create shadow for hardware rending.
Shadow(double radius,Offset offset,Color spotColor,ShadowStyle style)65     Shadow(double radius, Offset offset, Color spotColor, ShadowStyle style)
66         : offset_(offset), color_(spotColor), style_(style)
67     {
68         SetBlurRadius(radius);
69     };
70 
71     // create shadow for software rending.
Shadow(double blurRadius,double spreadRadius,Offset offset,Color spotColor)72     Shadow(double blurRadius, double spreadRadius, Offset offset, Color spotColor)
73         : spreadRadius_(spreadRadius), offset_(offset), color_(spotColor)
74     {
75         SetBlurRadius(blurRadius);
76     };
77 
78     static Shadow CreateShadow(ShadowStyle style);
79 
80     bool operator==(const Shadow& rhs) const
81     {
82         return color_ == rhs.color_ && NearEqual(blurRadius_, rhs.blurRadius_) && offset_ == rhs.offset_ &&
83                NearEqual(spreadRadius_, rhs.spreadRadius_) && NearEqual(elevation_, rhs.elevation_) &&
84                isFilled_ == rhs.isFilled_ && colorStrategy_ == rhs.colorStrategy_ && type_ == rhs.type_;
85     }
86 
87     bool operator!=(const Shadow& rhs) const
88     {
89         return !(rhs == *this);
90     }
91 
SetColor(const Color & newColor)92     void SetColor(const Color& newColor)
93     {
94         color_ = newColor;
95     }
96 
GetColor()97     const Color& GetColor() const
98     {
99         return color_;
100     }
101 
SetBlurRadius(double blurRadius)102     void SetBlurRadius(double blurRadius)
103     {
104         if (blurRadius >= 0.0) {
105             blurRadius_ = blurRadius;
106             isHardwareAcceleration_ = false;
107             return;
108         }
109         blurRadius_ = 0.0;
110     }
111 
GetBlurRadius()112     double GetBlurRadius() const
113     {
114         return blurRadius_;
115     }
116 
SetOffset(const Offset & offset)117     void SetOffset(const Offset& offset)
118     {
119         offset_ = offset;
120     }
121 
GetOffset()122     const Offset& GetOffset() const
123     {
124         return offset_;
125     }
126 
SetOffsetX(double x)127     void SetOffsetX(double x)
128     {
129         offset_.SetX(x);
130     }
131 
SetOffsetY(double y)132     void SetOffsetY(double y)
133     {
134         offset_.SetY(y);
135     }
136 
SetSpreadRadius(double spreadRadius)137     void SetSpreadRadius(double spreadRadius)
138     {
139         spreadRadius_ = spreadRadius;
140         isHardwareAcceleration_ = false;
141     }
142 
GetSpreadRadius()143     double GetSpreadRadius() const
144     {
145         return spreadRadius_;
146     }
147 
SetElevation(float elevation)148     void SetElevation(float elevation)
149     {
150         if (elevation >= 0.0f && elevation < LIGHT_HEIGHT) {
151             elevation_ = elevation;
152             isHardwareAcceleration_ = true;
153             return;
154         }
155         elevation_ = 0.0f;
156     }
157 
GetElevation()158     float GetElevation() const
159     {
160         return elevation_;
161     }
162 
SetHardwareAcceleration(bool acceleration)163     void SetHardwareAcceleration(bool acceleration)
164     {
165         isHardwareAcceleration_ = acceleration;
166     }
167 
SetIsFilled(bool isFilled)168     void SetIsFilled(bool isFilled)
169     {
170         isFilled_ = isFilled;
171     }
172 
GetHardwareAcceleration()173     bool GetHardwareAcceleration() const
174     {
175         return isHardwareAcceleration_;
176     }
177 
SetLightHeight(float lightHeight)178     void SetLightHeight(float lightHeight)
179     {
180         if (lightHeight > 0.0f) {
181             lightHeight_ = lightHeight;
182         }
183     }
184 
GetLightHeight()185     float GetLightHeight() const
186     {
187         return lightHeight_;
188     }
189 
SetLightRadius(float lightRadius)190     void SetLightRadius(float lightRadius)
191     {
192         if (lightRadius > 0.0f) {
193             lightRadius_ = lightRadius;
194         }
195     }
196 
GetLightRadius()197     float GetLightRadius() const
198     {
199         return lightRadius_;
200     }
201 
GetStyle()202     ShadowStyle GetStyle() const
203     {
204         return style_;
205     }
206 
SetShadowType(ShadowType type)207     void SetShadowType(ShadowType type)
208     {
209         type_ = type;
210     }
211 
GetShadowType()212     ShadowType GetShadowType() const
213     {
214         return type_;
215     }
216 
SetShadowColorStrategy(ShadowColorStrategy colorStrategy)217     void SetShadowColorStrategy(ShadowColorStrategy colorStrategy)
218     {
219         colorStrategy_ = colorStrategy;
220     }
221 
GetShadowColorStrategy()222     ShadowColorStrategy GetShadowColorStrategy() const
223     {
224         return colorStrategy_;
225     }
226 
GetIsFilled()227     bool GetIsFilled() const
228     {
229         return isFilled_;
230     }
231 
IsValid()232     bool IsValid() const
233     {
234         if (isHardwareAcceleration_) {
235             return elevation_ > 0.0f && elevation_ < LIGHT_HEIGHT;
236         }
237         return blurRadius_ > 0.0 || spreadRadius_ > 0.0 || offset_ != Offset::Zero();
238     }
239 
UpdateColorByResourceId()240     void UpdateColorByResourceId()
241     {
242         color_.UpdateColorByResourceId();
243     }
244 
245 private:
246     float lightHeight_ = LIGHT_HEIGHT;
247     float lightRadius_ = LIGHT_RADIUS;
248     float elevation_ = 0.0f; // Rosen always needs a non-zero elevation.
249     double blurRadius_ = 0.0;
250     double spreadRadius_ = 0.0;
251     Offset offset_;
252     Color color_ = Color::BLACK;
253     bool isHardwareAcceleration_ = false;
254     bool isFilled_ = false;
255     ShadowStyle style_ = ShadowStyle::None;
256     ShadowType type_ = ShadowType::COLOR;
257     ShadowColorStrategy colorStrategy_ = ShadowColorStrategy::NONE;
258 };
259 
260 } // namespace OHOS::Ace
261 
262 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_BASE_PROPERTIES_SHADOW_H
263