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/rosen/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 color.SetColor(colors[index]);
93 auto colorStop =
94 stops[index].Value() > MAX_COLOR_STOP ? Dimension(MAX_COLOR_STOP, DimensionUnit::PERCENT) : stops[index];
95 color.SetDimension(colorStop);
96 gradient.AddColor(color);
97 }
98 return gradient;
99 }
100
SetGradient(const Gradient & gradient)101 void GradientStyleModifier::SetGradient(const Gradient& gradient)
102 {
103 if (!colors_) {
104 colors_ = std::make_shared<Rosen::RSAnimatableProperty<ColorAnimatableArithmetic>>(
105 ColorAnimatableArithmetic(gradient));
106 AttachProperty(colors_);
107 } else {
108 auto colors = ColorAnimatableArithmetic(gradient);
109 PaddingColors(colors, gradient.GetRepeat());
110 colors_->Set(colors);
111 }
112 if (!colorStops_) {
113 colorStops_ = std::make_shared<Rosen::RSAnimatableProperty<ColorStopAnimatableArithmetic>>(
114 ColorStopAnimatableArithmetic(gradient));
115 AttachProperty(colorStops_);
116 } else {
117 auto colorStops = ColorStopAnimatableArithmetic(gradient);
118 PaddingColorStops(colorStops, gradient.GetRepeat());
119 colorStops_->Set(colorStops);
120 }
121 if (!gradient_) {
122 gradient_ = std::make_shared<Rosen::RSProperty<Gradient>>(gradient);
123 AttachProperty(gradient_);
124 } else {
125 gradient_->Set(gradient);
126 }
127 }
128
PaddingColors(ColorAnimatableArithmetic & colors,bool repeat)129 void GradientStyleModifier::PaddingColors(ColorAnimatableArithmetic& colors, bool repeat)
130 {
131 if (repeat) {
132 return;
133 }
134 if (colors_->Get().GetColors().size() <= colors.GetColors().size()) {
135 return;
136 }
137 size_t paddingSize = colors_->Get().GetColors().size() - colors.GetColors().size();
138 colors.PaddingColors(paddingSize, Color::TRANSPARENT);
139 }
140
PaddingColorStops(ColorStopAnimatableArithmetic & colorStops,bool repeat)141 void GradientStyleModifier::PaddingColorStops(ColorStopAnimatableArithmetic& colorStops, bool repeat)
142 {
143 if (repeat) {
144 return;
145 }
146 if (colorStops_->Get().GetColorStops().size() <= colorStops.GetColorStops().size()) {
147 return;
148 }
149 size_t paddingSize = colorStops_->Get().GetColorStops().size() - colorStops.GetColorStops().size();
150 colorStops.PaddingColorStops(paddingSize, Dimension(MAX_COLOR_STOP, DimensionUnit::PERCENT));
151 }
152
SetSizeF(const SizeF & size)153 void GradientStyleModifier::SetSizeF(const SizeF& size)
154 {
155 if (!sizeF_) {
156 sizeF_ = std::make_shared<Rosen::RSAnimatableProperty<Rosen::Vector2f>>(
157 Rosen::Vector2f(size.Width(), size.Height()));
158 AttachProperty(sizeF_);
159 } else {
160 sizeF_->Set(Rosen::Vector2f(size.Width(), size.Height()));
161 }
162 }
163
ColorAnimatableArithmetic(const Gradient & gradient)164 ColorAnimatableArithmetic::ColorAnimatableArithmetic(const Gradient& gradient)
165 {
166 for (const auto& color : gradient.GetColors()) {
167 colors_.push_back(color.GetColor());
168 }
169 }
170
Add(const ColorAnimatableArithmetic & value) const171 ColorAnimatableArithmetic ColorAnimatableArithmetic::Add(const ColorAnimatableArithmetic& value) const
172 {
173 auto srcColorSize = colors_.size();
174 auto dstColorSize = value.colors_.size();
175 auto idealSize = std::min(srcColorSize, dstColorSize);
176
177 ColorAnimatableArithmetic result;
178 size_t index = 0;
179 for (; index < idealSize; index++) {
180 Color color = Color::FromARGB(colors_[index].GetAlpha() + value.colors_[index].GetAlpha(),
181 colors_[index].GetRed() + value.colors_[index].GetRed(),
182 colors_[index].GetGreen() + value.colors_[index].GetGreen(),
183 colors_[index].GetBlue() + value.colors_[index].GetBlue());
184 result.colors_.push_back(color);
185 }
186 if (srcColorSize > dstColorSize) {
187 for (; index < srcColorSize; index++) {
188 result.colors_.push_back(colors_[index]);
189 }
190 } else {
191 for (; index < dstColorSize; index++) {
192 result.colors_.push_back(value.colors_[index]);
193 }
194 }
195 return result;
196 }
197
Minus(const ColorAnimatableArithmetic & value) const198 ColorAnimatableArithmetic ColorAnimatableArithmetic::Minus(const ColorAnimatableArithmetic& value) const
199 {
200 auto srcColorSize = colors_.size();
201 auto dstColorSize = value.colors_.size();
202 auto idealSize = std::min(srcColorSize, dstColorSize);
203
204 ColorAnimatableArithmetic result;
205 size_t index = 0;
206 for (; index < idealSize; index++) {
207 Color color = Color::FromARGB(colors_[index].GetAlpha() - value.colors_[index].GetAlpha(),
208 colors_[index].GetRed() - value.colors_[index].GetRed(),
209 colors_[index].GetGreen() - value.colors_[index].GetGreen(),
210 colors_[index].GetBlue() - value.colors_[index].GetBlue());
211 result.colors_.push_back(color);
212 }
213 if (srcColorSize > dstColorSize) {
214 for (; index < srcColorSize; index++) {
215 result.colors_.push_back(colors_[index]);
216 }
217 } else {
218 for (; index < dstColorSize; index++) {
219 result.colors_.push_back(value.colors_[index]);
220 }
221 }
222 return result;
223 }
224
Multiply(const float scale) const225 ColorAnimatableArithmetic ColorAnimatableArithmetic::Multiply(const float scale) const
226 {
227 auto srcColorSize = colors_.size();
228 ColorAnimatableArithmetic result;
229 size_t index = 0;
230 for (; index < srcColorSize; index++) {
231 Color color = Color::FromARGB(colors_[index].GetAlpha() * scale, colors_[index].GetRed() * scale,
232 colors_[index].GetGreen() * scale, colors_[index].GetBlue() * scale);
233 result.colors_.push_back(color);
234 }
235 return result;
236 }
237
IsEqual(const ColorAnimatableArithmetic & value) const238 bool ColorAnimatableArithmetic::IsEqual(const ColorAnimatableArithmetic& value) const
239 {
240 auto srcColorSize = colors_.size();
241 auto dstColorSize = value.colors_.size();
242 if (srcColorSize != dstColorSize) {
243 return false;
244 }
245 for (size_t index = 0; index < srcColorSize; index++) {
246 if (colors_[index] != value.colors_[index]) {
247 return false;
248 }
249 }
250 return true;
251 }
252
ColorStopAnimatableArithmetic(const Gradient & gradient)253 ColorStopAnimatableArithmetic::ColorStopAnimatableArithmetic(const Gradient& gradient)
254 {
255 for (const auto& colorStop : gradient.GetColors()) {
256 colorStops_.push_back(colorStop.GetDimension());
257 }
258 }
259
Add(const ColorStopAnimatableArithmetic & value) const260 ColorStopAnimatableArithmetic ColorStopAnimatableArithmetic::Add(const ColorStopAnimatableArithmetic& value) const
261 {
262 auto srcColorStopSize = colorStops_.size();
263 auto dstColorStopSize = value.colorStops_.size();
264 auto idealSize = std::min(srcColorStopSize, dstColorStopSize);
265
266 ColorStopAnimatableArithmetic result;
267 size_t index = 0;
268 for (; index < idealSize; index++) {
269 auto colorStop = colorStops_[index].Value() + value.colorStops_[index].Value();
270 result.colorStops_.push_back(Dimension(colorStop, DimensionUnit::PERCENT));
271 }
272 if (srcColorStopSize > dstColorStopSize) {
273 for (; index < srcColorStopSize; index++) {
274 result.colorStops_.push_back(colorStops_[index]);
275 }
276 } else {
277 for (; index < dstColorStopSize; index++) {
278 result.colorStops_.push_back(value.colorStops_[index]);
279 }
280 }
281 return result;
282 }
283
Minus(const ColorStopAnimatableArithmetic & value) const284 ColorStopAnimatableArithmetic ColorStopAnimatableArithmetic::Minus(const ColorStopAnimatableArithmetic& value) const
285 {
286 auto srcColorStopSize = colorStops_.size();
287 auto dstColorStopSize = value.colorStops_.size();
288 auto idealSize = std::min(srcColorStopSize, dstColorStopSize);
289
290 ColorStopAnimatableArithmetic result;
291 size_t index = 0;
292 for (; index < idealSize; index++) {
293 auto colorStop = colorStops_[index].Value() - value.colorStops_[index].Value();
294 result.colorStops_.push_back(Dimension(colorStop, DimensionUnit::PERCENT));
295 }
296 if (srcColorStopSize > dstColorStopSize) {
297 for (; index < srcColorStopSize; index++) {
298 result.colorStops_.push_back(colorStops_[index]);
299 }
300 } else {
301 for (; index < dstColorStopSize; index++) {
302 result.colorStops_.push_back(value.colorStops_[index]);
303 }
304 }
305 return result;
306 }
307
Multiply(const float scale) const308 ColorStopAnimatableArithmetic ColorStopAnimatableArithmetic::Multiply(const float scale) const
309 {
310 auto srcColorStopSize = colorStops_.size();
311
312 ColorStopAnimatableArithmetic result;
313 for (size_t index = 0; index < srcColorStopSize; index++) {
314 auto colorStop = colorStops_[index].Value() * scale;
315 result.colorStops_.push_back(Dimension(colorStop, DimensionUnit::PERCENT));
316 }
317 return result;
318 }
319
IsEqual(const ColorStopAnimatableArithmetic & value) const320 bool ColorStopAnimatableArithmetic::IsEqual(const ColorStopAnimatableArithmetic& value) const
321 {
322 auto srcColorStopSize = colorStops_.size();
323 auto dstColorStopSize = value.colorStops_.size();
324 if (srcColorStopSize != dstColorStopSize) {
325 return false;
326 }
327 for (size_t index = 0; index < srcColorStopSize; index++) {
328 if (!NearEqual(colorStops_[index].Value(), value.colorStops_[index].Value())) {
329 return false;
330 }
331 }
332 return true;
333 }
334 } // namespace OHOS::Ace::NG
335