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