1 /*
2 * Copyright (c) 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 #include "modifier/rs_render_modifier.h"
17 #ifndef USE_ROSEN_DRAWING
18 #else
19 #include "draw/color.h"
20 #include "image/bitmap.h"
21 #endif
22 #include <memory>
23 #include <unordered_map>
24
25 #include "include/effects/SkColorMatrix.h"
26 #include "pixel_map.h"
27
28 #include "common/rs_obj_abs_geometry.h"
29 #include "modifier/rs_modifier_type.h"
30 #include "pipeline/rs_draw_cmd_list.h"
31 #include "pipeline/rs_paint_filter_canvas.h"
32 #include "property/rs_properties.h"
33 #include "property/rs_properties_def.h"
34 #include "property/rs_properties_painter.h"
35
36 namespace OHOS {
37 namespace Rosen {
38 namespace {
39 using ModifierUnmarshallingFunc = RSRenderModifier* (*)(Parcel& parcel);
40
41 #define DECLARE_ANIMATABLE_MODIFIER(MODIFIER_NAME, TYPE, MODIFIER_TYPE, DELTA_OP, MODIFIER_TIER) \
42 { RSModifierType::MODIFIER_TYPE, [](Parcel& parcel) -> RSRenderModifier* { \
43 std::shared_ptr<RSRenderAnimatableProperty<TYPE>> prop; \
44 if (!RSMarshallingHelper::Unmarshalling(parcel, prop)) { \
45 return nullptr; \
46 } \
47 auto modifier = new RS##MODIFIER_NAME##RenderModifier(prop); \
48 return ((!modifier) ? nullptr : modifier); \
49 }, \
50 },
51
52 #define DECLARE_NOANIMATABLE_MODIFIER(MODIFIER_NAME, TYPE, MODIFIER_TYPE, MODIFIER_TIER) \
53 { RSModifierType::MODIFIER_TYPE, [](Parcel& parcel) -> RSRenderModifier* { \
54 std::shared_ptr<RSRenderProperty<TYPE>> prop; \
55 if (!RSMarshallingHelper::Unmarshalling(parcel, prop)) { \
56 return nullptr; \
57 } \
58 auto modifier = new RS##MODIFIER_NAME##RenderModifier(prop); \
59 return ((!modifier) ? nullptr : modifier); \
60 }, \
61 },
62
63 static std::unordered_map<RSModifierType, ModifierUnmarshallingFunc> funcLUT = {
64 #include "modifier/rs_modifiers_def.in"
__anon71b58cac0202() 65 { RSModifierType::EXTENDED, [](Parcel& parcel) -> RSRenderModifier* {
66 #ifndef USE_ROSEN_DRAWING
67 std::shared_ptr<RSRenderProperty<std::shared_ptr<DrawCmdList>>> prop;
68 #else
69 std::shared_ptr<RSRenderProperty<std::shared_ptr<Drawing::DrawCmdList>>> prop;
70 #endif
71 int16_t type;
72 if (!RSMarshallingHelper::Unmarshalling(parcel, prop) || !parcel.ReadInt16(type)) {
73 return nullptr;
74 }
75 RSDrawCmdListRenderModifier* modifier = new RSDrawCmdListRenderModifier(prop);
76 modifier->SetType(static_cast<RSModifierType>(type));
77 return modifier;
78 },
79 },
__anon71b58cac0302() 80 { RSModifierType::ENV_FOREGROUND_COLOR, [](Parcel& parcel) -> RSRenderModifier* {
81 std::shared_ptr<RSRenderAnimatableProperty<Color>> prop;
82 if (!RSMarshallingHelper::Unmarshalling(parcel, prop)) {
83 return nullptr;
84 }
85 auto modifier = new RSEnvForegroundColorRenderModifier(prop);
86 if (!modifier) {
87 return nullptr;
88 }
89 return modifier;
90 },
91 },
__anon71b58cac0402() 92 { RSModifierType::ENV_FOREGROUND_COLOR_STRATEGY, [](Parcel& parcel) -> RSRenderModifier* {
93 std::shared_ptr<RSRenderProperty<ForegroundColorStrategyType>> prop;
94 if (!RSMarshallingHelper::Unmarshalling(parcel, prop)) {
95 return nullptr;
96 }
97 auto modifier = new RSEnvForegroundColorStrategyRenderModifier(prop);
98 if (!modifier) {
99 return nullptr;
100 }
101 return modifier;
102 },
103 },
104
__anon71b58cac0502() 105 { RSModifierType::GEOMETRYTRANS, [](Parcel& parcel) -> RSRenderModifier* {
106 #ifndef USE_ROSEN_DRAWING
107 std::shared_ptr<RSRenderProperty<SkMatrix>> prop;
108 #else
109 std::shared_ptr<RSRenderProperty<Drawing::Matrix>> prop;
110 #endif
111 int16_t type;
112 if (!RSMarshallingHelper::Unmarshalling(parcel, prop) || !parcel.ReadInt16(type)) {
113 return nullptr;
114 }
115 auto modifier = new RSGeometryTransRenderModifier(prop);
116 modifier->SetType(static_cast<RSModifierType>(type));
117 return modifier;
118 },
119 },
120 };
121
122 #undef DECLARE_ANIMATABLE_MODIFIER
123 #undef DECLARE_NOANIMATABLE_MODIFIER
124 }
125
Apply(RSModifierContext & context) const126 void RSDrawCmdListRenderModifier::Apply(RSModifierContext& context) const
127 {
128 if (context.canvas_) {
129 auto cmds = property_->Get();
130 RSPropertiesPainter::DrawFrame(context.property_, *context.canvas_, cmds);
131 }
132 }
133
Update(const std::shared_ptr<RSRenderPropertyBase> & prop,bool isDelta)134 void RSDrawCmdListRenderModifier::Update(const std::shared_ptr<RSRenderPropertyBase>& prop, bool isDelta)
135 {
136 #ifndef USE_ROSEN_DRAWING
137 if (auto property = std::static_pointer_cast<RSRenderProperty<DrawCmdListPtr>>(prop)) {
138 property_->Set(property->Get());
139 }
140 #else
141 if (auto property = std::static_pointer_cast<RSRenderProperty<Drawing::DrawCmdListPtr>>(prop)) {
142 property_->Set(property->Get());
143 }
144 #endif
145 }
146
Marshalling(Parcel & parcel)147 bool RSDrawCmdListRenderModifier::Marshalling(Parcel& parcel)
148 {
149 return parcel.WriteInt16(static_cast<int16_t>(RSModifierType::EXTENDED)) &&
150 RSMarshallingHelper::Marshalling(parcel, property_) && parcel.WriteInt16(static_cast<int16_t>(GetType()));
151 }
152
GetCmdsClipRect() const153 RectF RSDrawCmdListRenderModifier::GetCmdsClipRect() const
154 {
155 #if defined(RS_ENABLE_DRIVEN_RENDER) && defined(RS_ENABLE_GL)
156 auto cmds = property_->Get();
157 return RSPropertiesPainter::GetCmdsClipRect(cmds);
158 #else
159 return RectF { 0.0f, 0.0f, 0.0f, 0.0f };
160 #endif
161 }
162
ApplyForDrivenContent(RSModifierContext & context) const163 void RSDrawCmdListRenderModifier::ApplyForDrivenContent(RSModifierContext& context) const
164 {
165 #if defined(RS_ENABLE_DRIVEN_RENDER) && defined(RS_ENABLE_GL)
166 if (context.canvas_) {
167 auto cmds = property_->Get();
168 RSPropertiesPainter::DrawFrameForDriven(context.property_, *context.canvas_, cmds);
169 }
170 #endif
171 }
172
Apply(RSModifierContext & context) const173 void RSParticleRenderModifier::Apply(RSModifierContext& context) const
174 {
175 auto renderProperty = std::static_pointer_cast<RSRenderProperty<RSRenderParticleVector>>(property_);
176 context.property_.SetParticles(renderProperty->Get());
177 }
178
Update(const std::shared_ptr<RSRenderPropertyBase> & prop,bool isDelta)179 void RSParticleRenderModifier::Update(const std::shared_ptr<RSRenderPropertyBase>& prop, bool isDelta)
180 {
181 if (auto property = std::static_pointer_cast<RSRenderProperty<RSRenderParticleVector>>(prop)) {
182 property_->Set(property->Get());
183 }
184 }
185
Marshalling(Parcel & parcel)186 bool RSParticleRenderModifier::Marshalling(Parcel& parcel)
187 {
188 return true;
189 }
190
Marshalling(Parcel & parcel)191 bool RSEnvForegroundColorRenderModifier::Marshalling(Parcel& parcel)
192 {
193 auto renderProperty = std::static_pointer_cast<RSRenderAnimatableProperty<Color>>(property_);
194 return parcel.WriteInt16(static_cast<int16_t>(RSModifierType::ENV_FOREGROUND_COLOR)) &&
195 RSMarshallingHelper::Marshalling(parcel, renderProperty);
196 }
197
Apply(RSModifierContext & context) const198 void RSEnvForegroundColorRenderModifier::Apply(RSModifierContext& context) const
199 {
200 auto renderProperty = std::static_pointer_cast<RSRenderAnimatableProperty<Color>>(property_);
201 context.canvas_->SetEnvForegroundColor(renderProperty->Get());
202 }
203
Update(const std::shared_ptr<RSRenderPropertyBase> & prop,bool isDelta)204 void RSEnvForegroundColorRenderModifier::Update(const std::shared_ptr<RSRenderPropertyBase>& prop, bool isDelta)
205 {
206 if (auto property = std::static_pointer_cast<RSRenderAnimatableProperty<Color>>(prop)) {
207 auto renderProperty = std::static_pointer_cast<RSRenderAnimatableProperty<Color>>(property_);
208 renderProperty->Set(isDelta ? (renderProperty->Get() + property->Get()) : property->Get());
209 }
210 }
211
Marshalling(Parcel & parcel)212 bool RSEnvForegroundColorStrategyRenderModifier::Marshalling(Parcel& parcel)
213 {
214 auto renderProperty = std::static_pointer_cast<RSRenderProperty<ForegroundColorStrategyType>>(property_);
215 return parcel.WriteInt16(static_cast<short>(RSModifierType::ENV_FOREGROUND_COLOR_STRATEGY)) &&
216 RSMarshallingHelper::Marshalling(parcel, renderProperty);
217 }
218
219
Apply(RSModifierContext & context) const220 void RSEnvForegroundColorStrategyRenderModifier::Apply(RSModifierContext& context) const
221 {
222 auto renderProperty = std::static_pointer_cast<RSRenderProperty<ForegroundColorStrategyType>>(property_);
223 switch (renderProperty->Get()) {
224 case ForegroundColorStrategyType::INVERT_BACKGROUNDCOLOR: {
225 // calculate the color by screebshot
226 Color color = GetInvertBackgroundColor(context);
227 context.canvas_->SetEnvForegroundColor(color);
228 break;
229 }
230 default: {
231 break;
232 }
233 }
234 }
235
CalculateInvertColor(Color backgroundColor) const236 Color RSEnvForegroundColorStrategyRenderModifier::CalculateInvertColor(Color backgroundColor) const
237 {
238 uint32_t a = backgroundColor.GetAlpha();
239 uint32_t r = 255 - backgroundColor.GetRed();
240 uint32_t g = 255 - backgroundColor.GetGreen();
241 uint32_t b = 255 - backgroundColor.GetBlue();
242 return Color(r, g, b, a);
243 }
244
GetInvertBackgroundColor(RSModifierContext & context) const245 Color RSEnvForegroundColorStrategyRenderModifier::GetInvertBackgroundColor(RSModifierContext& context) const
246 {
247 #ifdef ROSEN_OHOS
248 #ifndef USE_ROSEN_DRAWING
249 SkAutoCanvasRestore acr(context.canvas_, true);
250 #else
251 Drawing::AutoCanvasRestore acr(*context.canvas_, true);
252 #endif
253 if (!context.property_.GetClipToBounds()) {
254 RS_LOGI("RSRenderModifier::GetInvertBackgroundColor not GetClipToBounds");
255 Vector4f clipRegion = context.property_.GetBounds();
256 #ifndef USE_ROSEN_DRAWING
257 SkRect rect = SkRect::MakeXYWH(0, 0, clipRegion.z_, clipRegion.w_);
258 context.canvas_->clipRect(rect);
259 #else
260 Drawing::Rect rect = Drawing::Rect(0, 0, clipRegion.z_, clipRegion.w_);
261 context.canvas_->ClipRect(rect, Drawing::ClipOp::INTERSECT, false);
262 #endif
263 }
264 Color backgroundColor = context.property_.GetBackgroundColor();
265 if (backgroundColor.GetAlpha() == 0xff) {
266 RS_LOGI("RSRenderModifier::GetInvertBackgroundColor not alpha");
267 return CalculateInvertColor(backgroundColor);
268 }
269 #ifndef USE_ROSEN_DRAWING
270 auto imageSnapshot = context.canvas_->GetSurface()->makeImageSnapshot(context.canvas_->getDeviceClipBounds());
271 #else
272 auto imageSnapshot = context.canvas_->GetSurface()->GetImageSnapshot(context.canvas_->GetDeviceClipBounds());
273 #endif
274 if (imageSnapshot == nullptr) {
275 RS_LOGI("RSRenderModifier::GetInvertBackgroundColor imageSnapshot null");
276 return Color(0);
277 }
278 Media::InitializationOptions opts;
279 opts.size.width = context.property_.GetBoundsWidth();
280 opts.size.height = context.property_.GetBoundsHeight();
281 if (opts.size.width == 0 || opts.size.height == 0) {
282 RS_LOGI("RSRenderModifier::GetInvertBackgroundColor opts.size.width/height == 0");
283 return Color(0);
284 }
285 std::unique_ptr<Media::PixelMap> pixelmap = Media::PixelMap::Create(opts);
286 uint8_t* data = static_cast<uint8_t*>(malloc(pixelmap->GetRowBytes() * pixelmap->GetHeight()));
287 if (data == nullptr) {
288 RS_LOGE("RSRenderModifier::GetInvertBackgroundColor: data is nullptr");
289 return Color(0);
290 }
291 #ifndef USE_ROSEN_DRAWING
292 SkImageInfo info = SkImageInfo::Make(pixelmap->GetWidth(), pixelmap->GetHeight(),
293 kRGBA_8888_SkColorType, kPremul_SkAlphaType);
294 if (!imageSnapshot->readPixels(info, data, pixelmap->GetRowBytes(), 0, 0)) {
295 #else
296 Drawing::BitmapFormat format = { Drawing::ColorType::COLORTYPE_RGBA_8888, Drawing::AlphaType::ALPHATYPE_PREMUL };
297 Drawing::Bitmap bitmap;
298 bitmap.Build(pixelmap->GetWidth(), pixelmap->GetHeight(), format);
299 bitmap.SetPixels(data);
300 if (!imageSnapshot->ReadPixels(bitmap, 0, 0)) {
301 #endif
302 RS_LOGE("RSRenderModifier::Run: readPixels failed");
303 free(data);
304 data = nullptr;
305 return Color(0);
306 }
307 pixelmap->SetPixelsAddr(data, nullptr, pixelmap->GetRowBytes() * pixelmap->GetHeight(),
308 Media::AllocatorType::HEAP_ALLOC, nullptr);
309 OHOS::Media::InitializationOptions options;
310 options.alphaType = pixelmap->GetAlphaType();
311 options.pixelFormat = pixelmap->GetPixelFormat();
312 options.scaleMode = OHOS::Media::ScaleMode::FIT_TARGET_SIZE;
313 options.size.width = 1;
314 options.size.height = 1;
315 options.editable = true;
316 std::unique_ptr<Media::PixelMap> newPixelMap = Media::PixelMap::Create(*pixelmap.get(), options);
317 uint32_t colorVal = 0;
318 newPixelMap->GetARGB32Color(0, 0, colorVal);
319 return CalculateInvertColor(Color(colorVal));
320 #else
321 return Color(0);
322 #endif
323 }
324
325 void RSEnvForegroundColorStrategyRenderModifier::Update(const std::shared_ptr<RSRenderPropertyBase>& prop, bool isDelta)
326 {
327 if (auto property = std::static_pointer_cast<RSRenderProperty<ForegroundColorStrategyType >>(prop)) {
328 auto renderProperty = std::static_pointer_cast<RSRenderProperty<ForegroundColorStrategyType >>(property_);
329 renderProperty->Set(property->Get());
330 }
331 }
332
333 void RSGeometryTransRenderModifier::Apply(RSModifierContext& context) const
334 {
335 auto geoPtr = (context.property_.GetBoundsGeometry());
336 auto property = property_->Get();
337 geoPtr->ConcatMatrix(property);
338 }
339
340 void RSGeometryTransRenderModifier::Update(const std::shared_ptr<RSRenderPropertyBase>& prop, bool isDelta)
341 {
342 #ifndef USE_ROSEN_DRAWING
343 if (auto property = std::static_pointer_cast<RSRenderProperty<SkMatrix>>(prop)) {
344 #else
345 if (auto property = std::static_pointer_cast<RSRenderProperty<Drawing::Matrix>>(prop)) {
346 #endif
347 property_->Set(property->Get());
348 }
349 }
350
351 bool RSGeometryTransRenderModifier::Marshalling(Parcel& parcel)
352 {
353 return parcel.WriteInt16(static_cast<int16_t>(RSModifierType::GEOMETRYTRANS)) &&
354 RSMarshallingHelper::Marshalling(parcel, property_) && parcel.WriteInt16(static_cast<int16_t>(GetType()));
355 }
356
357 RSRenderModifier* RSRenderModifier::Unmarshalling(Parcel& parcel)
358 {
359 int16_t type = 0;
360 if (!parcel.ReadInt16(type)) {
361 return nullptr;
362 }
363 auto it = funcLUT.find(static_cast<RSModifierType>(type));
364 if (it == funcLUT.end()) {
365 ROSEN_LOGE("RSRenderModifier Unmarshalling cannot find func in lut %d", type);
366 return nullptr;
367 }
368 return it->second(parcel);
369 }
370
371 namespace {
372 template<typename T>
373 T Add(T a, T b)
374 {
375 return a + b;
376 }
377 template<typename T>
378 T Add(const std::optional<T>& a, T b)
379 {
380 return a.has_value() ? *a + b : b;
381 }
382
383 template<typename T>
384 T Multiply(T a, T b)
385 {
386 return a * b;
387 }
388 template<typename T>
389 T Multiply(const std::optional<T>& a, T b)
390 {
391 return a.has_value() ? *a * b : b;
392 }
393
394 template<typename T>
395 T Replace(T a, T b)
396 {
397 return b;
398 }
399 template<typename T>
400 T Replace(const std::optional<T>& a, T b)
401 {
402 return b;
403 }
404 } // namespace
405
406 #define DECLARE_ANIMATABLE_MODIFIER(MODIFIER_NAME, TYPE, MODIFIER_TYPE, DELTA_OP, MODIFIER_TIER) \
407 bool RS##MODIFIER_NAME##RenderModifier::Marshalling(Parcel& parcel) \
408 { \
409 auto renderProperty = std::static_pointer_cast<RSRenderAnimatableProperty<TYPE>>(property_); \
410 return parcel.WriteInt16(static_cast<int16_t>(RSModifierType::MODIFIER_TYPE)) && \
411 RSMarshallingHelper::Marshalling(parcel, renderProperty); \
412 } \
413 void RS##MODIFIER_NAME##RenderModifier::Apply(RSModifierContext& context) const \
414 { \
415 auto renderProperty = std::static_pointer_cast<RSRenderAnimatableProperty<TYPE>>(property_); \
416 context.property_.Set##MODIFIER_NAME(DELTA_OP(context.property_.Get##MODIFIER_NAME(), renderProperty->Get())); \
417 } \
418 void RS##MODIFIER_NAME##RenderModifier::Update(const std::shared_ptr<RSRenderPropertyBase>& prop, bool isDelta) \
419 { \
420 if (auto property = std::static_pointer_cast<RSRenderAnimatableProperty<TYPE>>(prop)) { \
421 auto renderProperty = std::static_pointer_cast<RSRenderAnimatableProperty<TYPE>>(property_); \
422 renderProperty->Set(isDelta ? (renderProperty->Get() + property->Get()) : property->Get()); \
423 } \
424 }
425
426 #define DECLARE_NOANIMATABLE_MODIFIER(MODIFIER_NAME, TYPE, MODIFIER_TYPE, MODIFIER_TIER) \
427 bool RS##MODIFIER_NAME##RenderModifier::Marshalling(Parcel& parcel) \
428 { \
429 auto renderProperty = std::static_pointer_cast<RSRenderProperty<TYPE>>(property_); \
430 return parcel.WriteInt16(static_cast<short>(RSModifierType::MODIFIER_TYPE)) && \
431 RSMarshallingHelper::Marshalling(parcel, renderProperty); \
432 } \
433 void RS##MODIFIER_NAME##RenderModifier::Apply(RSModifierContext& context) const \
434 { \
435 auto renderProperty = std::static_pointer_cast<RSRenderProperty<TYPE>>(property_); \
436 context.property_.Set##MODIFIER_NAME(renderProperty->Get()); \
437 } \
438 void RS##MODIFIER_NAME##RenderModifier::Update(const std::shared_ptr<RSRenderPropertyBase>& prop, bool isDelta) \
439 { \
440 if (auto property = std::static_pointer_cast<RSRenderProperty<TYPE>>(prop)) { \
441 auto renderProperty = std::static_pointer_cast<RSRenderProperty<TYPE>>(property_); \
442 renderProperty->Set(property->Get()); \
443 } \
444 }
445
446 #include "modifier/rs_modifiers_def.in"
447
448 #undef DECLARE_ANIMATABLE_MODIFIER
449 #undef DECLARE_NOANIMATABLE_MODIFIER
450 } // namespace Rosen
451 } // namespace OHOS
452