• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 #include "core/components_ng/render/adapter/gradient_style_modifier.h"
17 
18 #include "core/components_ng/render/adapter/rosen_render_context.h"
19 #ifndef USE_ROSEN_DRAWING
20 #include "core/components_ng/render/adapter/skia_decoration_painter.h"
21 #else
22 #include "core/components_ng/render/adapter/drawing_decoration_painter.h"
23 #endif
24 
25 namespace OHOS::Ace::NG {
26 namespace {
27 constexpr double MAX_COLOR_STOP = 100.0;
28 } // namespace
Draw(RSDrawingContext & context) const29 void GradientStyleModifier::Draw(RSDrawingContext& context) const
30 {
31     CHECK_NULL_VOID(colors_);
32     CHECK_NULL_VOID(colorStops_);
33     CHECK_NULL_VOID(sizeF_);
34 #ifndef USE_ROSEN_DRAWING
35     std::shared_ptr<SkCanvas> skCanvas { context.canvas, [](SkCanvas* /* unused */) {} };
36     SizeF contentSize(sizeF_->Get()[0], sizeF_->Get()[1]);
37     PaintGradient(*skCanvas, contentSize);
38 #else
39     CHECK_NULL_VOID(context.canvas);
40     SizeF contentSize(sizeF_->Get()[0], sizeF_->Get()[1]);
41     PaintGradient(*context.canvas, contentSize);
42 #endif
43 }
44 
45 #ifndef USE_ROSEN_DRAWING
PaintGradient(SkCanvas & canvas,const SizeF & frameSize) const46 void GradientStyleModifier::PaintGradient(SkCanvas& canvas, const SizeF& frameSize) const
47 {
48     if (Negative(frameSize.Height()) || Negative(frameSize.Width())) {
49         return;
50     }
51     auto shader = SkiaDecorationPainter::CreateGradientShader(GetGradient(), frameSize);
52     auto renderContext = renderContext_.Upgrade();
53     CHECK_NULL_VOID(renderContext);
54     if (!shader) {
55         renderContext->SetBackgroundShader(nullptr);
56         return;
57     }
58     renderContext->SetBackgroundShader(Rosen::RSShader::CreateRSShader(shader));
59 }
60 #else
PaintGradient(RSCanvas & canvas,const SizeF & frameSize) const61 void GradientStyleModifier::PaintGradient(RSCanvas& canvas, const SizeF& frameSize) const
62 {
63     if (Negative(frameSize.Height()) || Negative(frameSize.Width())) {
64         return;
65     }
66     auto shader = DrawingDecorationPainter::CreateGradientShader(GetGradient(), frameSize);
67     auto renderContext = renderContext_.Upgrade();
68     CHECK_NULL_VOID(renderContext);
69     if (!shader) {
70         renderContext->SetBackgroundShader(nullptr);
71         return;
72     }
73     renderContext->SetBackgroundShader(Rosen::RSShader::CreateRSShader(shader));
74 }
75 #endif
76 
GetGradient() const77 Gradient GradientStyleModifier::GetGradient() const
78 {
79     Gradient gradient;
80     std::vector<Color> colors = colors_->Get().GetColors();
81     std::vector<Dimension> stops = colorStops_->Get().GetColorStops();
82     if (gradient_) {
83         gradient = gradient_->Get();
84     }
85     auto size = colors.size();
86     gradient.ClearColors();
87     if (size > stops.size()) {
88         return gradient;
89     }
90     GradientColor color;
91     for (size_t index = 0; index < size; index++) {
92         colors[index].SetColorSpace(colorSpace_);
93         color.SetColor(colors[index]);
94         auto colorStop =
95             stops[index].Value() > MAX_COLOR_STOP ? Dimension(MAX_COLOR_STOP, DimensionUnit::PERCENT) : stops[index];
96         color.SetDimension(colorStop);
97         gradient.AddColor(color);
98     }
99     return gradient;
100 }
101 
SetGradient(const Gradient & gradient)102 void GradientStyleModifier::SetGradient(const Gradient& gradient)
103 {
104     if (!colors_) {
105         colors_ = std::make_shared<Rosen::RSAnimatableProperty<ColorAnimatableArithmetic>>(
106             ColorAnimatableArithmetic(gradient));
107         AttachProperty(colors_);
108     } else {
109         auto colors = ColorAnimatableArithmetic(gradient);
110         PaddingColors(colors, gradient.GetRepeat());
111         colors_->Set(colors);
112     }
113     if (!colorStops_) {
114         colorStops_ = std::make_shared<Rosen::RSAnimatableProperty<ColorStopAnimatableArithmetic>>(
115             ColorStopAnimatableArithmetic(gradient));
116         AttachProperty(colorStops_);
117     } else {
118         auto colorStops = ColorStopAnimatableArithmetic(gradient);
119         PaddingColorStops(colorStops, gradient.GetRepeat());
120         colorStops_->Set(colorStops);
121     }
122     if (!gradient_) {
123         gradient_ = std::make_shared<Rosen::RSProperty<Gradient>>(gradient);
124         AttachProperty(gradient_);
125     } else {
126         gradient_->Set(gradient);
127     }
128     if (gradient.GetColors().empty()) {
129         colorSpace_ = ColorSpace::SRGB;
130     } else {
131         colorSpace_ = gradient.GetColors().back().GetColor().GetColorSpace();
132     }
133 }
134 
PaddingColors(ColorAnimatableArithmetic & colors,bool repeat)135 void GradientStyleModifier::PaddingColors(ColorAnimatableArithmetic& colors, bool repeat)
136 {
137     if (repeat) {
138         return;
139     }
140     if (colors_->Get().GetColors().size() <= colors.GetColors().size()) {
141         return;
142     }
143     size_t paddingSize = colors_->Get().GetColors().size() - colors.GetColors().size();
144     colors.PaddingColors(paddingSize, Color::TRANSPARENT);
145 }
146 
PaddingColorStops(ColorStopAnimatableArithmetic & colorStops,bool repeat)147 void GradientStyleModifier::PaddingColorStops(ColorStopAnimatableArithmetic& colorStops, bool repeat)
148 {
149     if (repeat) {
150         return;
151     }
152     if (colorStops_->Get().GetColorStops().size() <= colorStops.GetColorStops().size()) {
153         return;
154     }
155     size_t paddingSize = colorStops_->Get().GetColorStops().size() - colorStops.GetColorStops().size();
156     colorStops.PaddingColorStops(paddingSize, Dimension(MAX_COLOR_STOP, DimensionUnit::PERCENT));
157 }
158 
SetSizeF(const SizeF & size)159 void GradientStyleModifier::SetSizeF(const SizeF& size)
160 {
161     if (!sizeF_) {
162         sizeF_ = std::make_shared<Rosen::RSAnimatableProperty<Rosen::Vector2f>>(
163             Rosen::Vector2f(size.Width(), size.Height()));
164         AttachProperty(sizeF_);
165     } else {
166         sizeF_->Set(Rosen::Vector2f(size.Width(), size.Height()));
167     }
168 }
169 
ColorAnimatableArithmetic(const Gradient & gradient)170 ColorAnimatableArithmetic::ColorAnimatableArithmetic(const Gradient& gradient)
171 {
172     for (const auto& color : gradient.GetColors()) {
173         colors_.push_back(color.GetColor());
174     }
175 }
176 
Add(const ColorAnimatableArithmetic & value) const177 ColorAnimatableArithmetic ColorAnimatableArithmetic::Add(const ColorAnimatableArithmetic& value) const
178 {
179     auto srcColorSize = colors_.size();
180     auto dstColorSize = value.colors_.size();
181     auto idealSize = std::min(srcColorSize, dstColorSize);
182 
183     ColorAnimatableArithmetic result;
184     size_t index = 0;
185     for (; index < idealSize; index++) {
186         Color color = Color::FromARGB(colors_[index].GetAlpha() + value.colors_[index].GetAlpha(),
187             colors_[index].GetRed() + value.colors_[index].GetRed(),
188             colors_[index].GetGreen() + value.colors_[index].GetGreen(),
189             colors_[index].GetBlue() + value.colors_[index].GetBlue());
190         result.colors_.push_back(color);
191     }
192     if (srcColorSize > dstColorSize) {
193         for (; index < srcColorSize; index++) {
194             result.colors_.push_back(colors_[index]);
195         }
196     } else {
197         for (; index < dstColorSize; index++) {
198             result.colors_.push_back(value.colors_[index]);
199         }
200     }
201     return result;
202 }
203 
Minus(const ColorAnimatableArithmetic & value) const204 ColorAnimatableArithmetic ColorAnimatableArithmetic::Minus(const ColorAnimatableArithmetic& value) const
205 {
206     auto srcColorSize = colors_.size();
207     auto dstColorSize = value.colors_.size();
208     auto idealSize = std::min(srcColorSize, dstColorSize);
209 
210     ColorAnimatableArithmetic result;
211     size_t index = 0;
212     for (; index < idealSize; index++) {
213         Color color = Color::FromARGB(colors_[index].GetAlpha() - value.colors_[index].GetAlpha(),
214             colors_[index].GetRed() - value.colors_[index].GetRed(),
215             colors_[index].GetGreen() - value.colors_[index].GetGreen(),
216             colors_[index].GetBlue() - value.colors_[index].GetBlue());
217         result.colors_.push_back(color);
218     }
219     if (srcColorSize > dstColorSize) {
220         for (; index < srcColorSize; index++) {
221             result.colors_.push_back(colors_[index]);
222         }
223     } else {
224         for (; index < dstColorSize; index++) {
225             result.colors_.push_back(value.colors_[index]);
226         }
227     }
228     return result;
229 }
230 
Multiply(const float scale) const231 ColorAnimatableArithmetic ColorAnimatableArithmetic::Multiply(const float scale) const
232 {
233     auto srcColorSize = colors_.size();
234     ColorAnimatableArithmetic result;
235     size_t index = 0;
236     for (; index < srcColorSize; index++) {
237         Color color = Color::FromARGB(colors_[index].GetAlpha() * scale, colors_[index].GetRed() * scale,
238             colors_[index].GetGreen() * scale, colors_[index].GetBlue() * scale);
239         result.colors_.push_back(color);
240     }
241     return result;
242 }
243 
IsEqual(const ColorAnimatableArithmetic & value) const244 bool ColorAnimatableArithmetic::IsEqual(const ColorAnimatableArithmetic& value) const
245 {
246     auto srcColorSize = colors_.size();
247     auto dstColorSize = value.colors_.size();
248     if (srcColorSize != dstColorSize) {
249         return false;
250     }
251     for (size_t index = 0; index < srcColorSize; index++) {
252         if (colors_[index] != value.colors_[index]) {
253             return false;
254         }
255     }
256     return true;
257 }
258 
ColorStopAnimatableArithmetic(const Gradient & gradient)259 ColorStopAnimatableArithmetic::ColorStopAnimatableArithmetic(const Gradient& gradient)
260 {
261     for (const auto& colorStop : gradient.GetColors()) {
262         colorStops_.push_back(colorStop.GetDimension());
263     }
264 }
265 
Add(const ColorStopAnimatableArithmetic & value) const266 ColorStopAnimatableArithmetic ColorStopAnimatableArithmetic::Add(const ColorStopAnimatableArithmetic& value) const
267 {
268     auto srcColorStopSize = colorStops_.size();
269     auto dstColorStopSize = value.colorStops_.size();
270     auto idealSize = std::min(srcColorStopSize, dstColorStopSize);
271 
272     ColorStopAnimatableArithmetic result;
273     size_t index = 0;
274     for (; index < idealSize; index++) {
275         auto colorStop = colorStops_[index].Value() + value.colorStops_[index].Value();
276         result.colorStops_.push_back(Dimension(colorStop, DimensionUnit::PERCENT));
277     }
278     if (srcColorStopSize > dstColorStopSize) {
279         for (; index < srcColorStopSize; index++) {
280             result.colorStops_.push_back(colorStops_[index]);
281         }
282     } else {
283         for (; index < dstColorStopSize; index++) {
284             result.colorStops_.push_back(value.colorStops_[index]);
285         }
286     }
287     return result;
288 }
289 
Minus(const ColorStopAnimatableArithmetic & value) const290 ColorStopAnimatableArithmetic ColorStopAnimatableArithmetic::Minus(const ColorStopAnimatableArithmetic& value) const
291 {
292     auto srcColorStopSize = colorStops_.size();
293     auto dstColorStopSize = value.colorStops_.size();
294     auto idealSize = std::min(srcColorStopSize, dstColorStopSize);
295 
296     ColorStopAnimatableArithmetic result;
297     size_t index = 0;
298     for (; index < idealSize; index++) {
299         auto colorStop = colorStops_[index].Value() - value.colorStops_[index].Value();
300         result.colorStops_.push_back(Dimension(colorStop, DimensionUnit::PERCENT));
301     }
302     if (srcColorStopSize > dstColorStopSize) {
303         for (; index < srcColorStopSize; index++) {
304             result.colorStops_.push_back(colorStops_[index]);
305         }
306     } else {
307         for (; index < dstColorStopSize; index++) {
308             result.colorStops_.push_back(value.colorStops_[index]);
309         }
310     }
311     return result;
312 }
313 
Multiply(const float scale) const314 ColorStopAnimatableArithmetic ColorStopAnimatableArithmetic::Multiply(const float scale) const
315 {
316     auto srcColorStopSize = colorStops_.size();
317 
318     ColorStopAnimatableArithmetic result;
319     for (size_t index = 0; index < srcColorStopSize; index++) {
320         auto colorStop = colorStops_[index].Value() * scale;
321         result.colorStops_.push_back(Dimension(colorStop, DimensionUnit::PERCENT));
322     }
323     return result;
324 }
325 
IsEqual(const ColorStopAnimatableArithmetic & value) const326 bool ColorStopAnimatableArithmetic::IsEqual(const ColorStopAnimatableArithmetic& value) const
327 {
328     auto srcColorStopSize = colorStops_.size();
329     auto dstColorStopSize = value.colorStops_.size();
330     if (srcColorStopSize != dstColorStopSize) {
331         return false;
332     }
333     for (size_t index = 0; index < srcColorStopSize; index++) {
334         if (!NearEqual(colorStops_[index].Value(), value.colorStops_[index].Value())) {
335             return false;
336         }
337     }
338     return true;
339 }
340 } // namespace OHOS::Ace::NG
341