1 /*
2 * Copyright (c) 2024 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 "drawable/rs_misc_drawable.h"
17
18 #include "rs_profiler.h"
19
20 #include "common/rs_common_def.h"
21 #include "common/rs_optional_trace.h"
22 #include "drawable/rs_property_drawable_utils.h"
23 #include "drawable/rs_render_node_drawable_adapter.h"
24 #include "memory/rs_tag_tracker.h"
25 #include "modifier_ng/rs_render_modifier_ng.h"
26 #include "pipeline/rs_canvas_drawing_render_node.h"
27 #include "pipeline/rs_render_node.h"
28
29 namespace OHOS::Rosen {
30 namespace DrawableV2 {
31 constexpr int TRACE_LEVEL_TWO = 2;
32 // ==================== RSChildrenDrawable =====================
OnGenerate(const RSRenderNode & node)33 RSDrawable::Ptr RSChildrenDrawable::OnGenerate(const RSRenderNode& node)
34 {
35 if (auto ret = std::make_shared<RSChildrenDrawable>(); ret->OnUpdate(node)) {
36 return std::move(ret);
37 }
38 return nullptr;
39 }
40
OnUpdate(const RSRenderNode & node)41 bool RSChildrenDrawable::OnUpdate(const RSRenderNode& node)
42 {
43 childrenHasSharedTransition_ = false;
44 auto children = node.GetSortedChildren();
45 // Regenerate children drawables
46 needSync_ = true;
47 stagingChildrenDrawableVec_.clear();
48
49 if (LIKELY(!node.GetRenderProperties().GetUseShadowBatching())) {
50 // Non-ShadowBatching mode (default), draw all children in order
51 for (const auto& child : *children) {
52 if (UNLIKELY(child->GetSharedTransitionParam()) && OnSharedTransition(child)) {
53 continue;
54 }
55 auto childDrawable = RSRenderNodeDrawableAdapter::OnGenerate(child);
56 if (!childDrawable) {
57 continue;
58 }
59 if (childDrawable->GetSkipType() == SkipType::SKIP_SHADOW) {
60 childDrawable->SetSkip(SkipType::NONE);
61 }
62 stagingChildrenDrawableVec_.push_back(std::move(childDrawable));
63 }
64 } else {
65 // ShadowBatching mode, draw all shadows, then draw all children
66 decltype(stagingChildrenDrawableVec_) pendingChildren;
67 for (const auto& child : *children) {
68 if (UNLIKELY(child->GetSharedTransitionParam()) && OnSharedTransition(child)) {
69 continue;
70 }
71 auto childDrawable = RSRenderNodeDrawableAdapter::OnGenerate(child);
72 if (!childDrawable) {
73 continue;
74 }
75 auto shadowDrawable = RSRenderNodeDrawableAdapter::OnGenerateShadowDrawable(child, childDrawable);
76 if (!shadowDrawable) {
77 continue;
78 }
79 stagingChildrenDrawableVec_.push_back(std::move(shadowDrawable));
80 pendingChildren.push_back(std::move(childDrawable));
81 }
82 // merge two vectors, shadow drawables first, render node drawables second
83 stagingChildrenDrawableVec_.insert(
84 stagingChildrenDrawableVec_.end(), pendingChildren.begin(), pendingChildren.end());
85 }
86 const_cast<RSRenderNode&>(node).SetChildrenHasSharedTransition(childrenHasSharedTransition_);
87 return !stagingChildrenDrawableVec_.empty();
88 }
89
OnSharedTransition(const RSRenderNode::SharedPtr & node)90 bool RSChildrenDrawable::OnSharedTransition(const RSRenderNode::SharedPtr& node)
91 {
92 auto nodeId = node->GetId();
93 const auto& sharedTransitionParam = node->GetSharedTransitionParam();
94
95 auto pairedNode = sharedTransitionParam->GetPairedNode(nodeId);
96 if (!pairedNode || !pairedNode->IsOnTheTree()) {
97 sharedTransitionParam->paired_ = false;
98 return false;
99 }
100
101 childrenHasSharedTransition_ = true;
102 // Skip if the shared transition is not paired (Note: this may cause the lower node to be drawn twice)
103 if (!sharedTransitionParam->paired_) {
104 return false;
105 }
106
107 // Relation will be set in QuickPrepare
108 if (!sharedTransitionParam->HasRelation()) {
109 sharedTransitionParam->SetNeedGenerateDrawable(true);
110 return true;
111 }
112
113 // Test if this node is lower in the hierarchy
114 bool isLower = sharedTransitionParam->IsLower(nodeId);
115 if (isLower) {
116 // for lower hierarchy node, we skip it here
117 return true;
118 } else {
119 // for higher hierarchy node, we add paired node (lower in hierarchy) first, then add it
120 if (auto childDrawable = RSRenderNodeDrawableAdapter::OnGenerate(pairedNode)) {
121 stagingChildrenDrawableVec_.push_back(std::move(childDrawable));
122 }
123 sharedTransitionParam->SetNeedGenerateDrawable(false);
124 return false;
125 }
126 }
127
OnSync()128 void RSChildrenDrawable::OnSync()
129 {
130 if (!needSync_) {
131 return;
132 }
133 std::swap(stagingChildrenDrawableVec_, childrenDrawableVec_);
134 RSRenderNodeDrawableAdapter::AddToClearDrawables(stagingChildrenDrawableVec_);
135 needSync_ = false;
136 }
137
CreateDrawFunc() const138 Drawing::RecordingCanvas::DrawFunc RSChildrenDrawable::CreateDrawFunc() const
139 {
140 auto ptr = std::static_pointer_cast<const RSChildrenDrawable>(shared_from_this());
141 return [ptr](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
142 for (size_t i = 0; i < ptr->childrenDrawableVec_.size(); i++) {
143 #ifdef RS_ENABLE_PREFETCH
144 size_t prefetchIndex = i + 2;
145 if (prefetchIndex < ptr->childrenDrawableVec_.size()) {
146 __builtin_prefetch(&(ptr->childrenDrawableVec_[prefetchIndex]), 0, 1);
147 }
148 #endif
149 const auto& drawable = ptr->childrenDrawableVec_[i];
150 drawable->Draw(*canvas);
151 }
152 };
153 }
154
155 // ==================== RSCustomModifierDrawable ===================
OnGenerate(const RSRenderNode & node,ModifierNG::RSModifierType type)156 RSDrawable::Ptr RSCustomModifierDrawable::OnGenerate(const RSRenderNode& node, ModifierNG::RSModifierType type)
157 {
158 if (auto ret = std::make_shared<RSCustomModifierDrawable>(type); ret->OnUpdate(node)) {
159 if (node.GetType() == RSRenderNodeType::CANVAS_DRAWING_NODE) {
160 ret->needClearOp_ = true;
161 }
162 return std::move(ret);
163 }
164 return nullptr;
165 }
166
OnUpdate(const RSRenderNode & node)167 bool RSCustomModifierDrawable::OnUpdate(const RSRenderNode& node)
168 {
169 auto customModifiers = node.GetModifiersNG(modifierTypeNG_);
170 if (customModifiers.empty()) {
171 return false;
172 }
173 std::stable_sort(
174 customModifiers.begin(), customModifiers.end(), [](const auto& modifierA, const auto& modifierB) -> bool {
175 return modifierA->template Getter<int16_t>(ModifierNG::RSPropertyType::CUSTOM_INDEX, 0) <
176 modifierB->template Getter<int16_t>(ModifierNG::RSPropertyType::CUSTOM_INDEX, 0);
177 });
178
179 stagingGravity_ = node.GetRenderProperties().GetFrameGravity();
180 stagingIsCanvasNode_ = node.IsInstanceOf<RSCanvasRenderNode>() && !node.IsInstanceOf<RSCanvasDrawingRenderNode>();
181 // regenerate stagingDrawCmdList_
182 needSync_ = true;
183 stagingDrawCmdListVec_.clear();
184 if (node.GetType() == RSRenderNodeType::CANVAS_DRAWING_NODE &&
185 modifierTypeNG_ == ModifierNG::RSModifierType::CONTENT_STYLE) {
186 auto& drawingNode = static_cast<const RSCanvasDrawingRenderNode&>(node);
187 auto& cmdLists = drawingNode.GetDrawCmdListsNG();
188 auto itr = cmdLists.find(modifierTypeNG_);
189 if (itr == cmdLists.end() || itr->second.empty()) {
190 return false;
191 }
192 for (auto& cmd : itr->second) {
193 stagingDrawCmdListVec_.emplace_back(cmd);
194 }
195 } else {
196 for (const auto& modifier : customModifiers) {
197 auto propertyType = ModifierNG::ModifierTypeConvertor::GetPropertyType(modifierTypeNG_);
198 auto drawCmdList = modifier->Getter<Drawing::DrawCmdListPtr>(propertyType, nullptr);
199 if (drawCmdList == nullptr || drawCmdList->IsEmpty()) {
200 continue;
201 }
202 if (drawCmdList->GetWidth() > 0 && drawCmdList->GetHeight() > 0) {
203 stagingDrawCmdListVec_.push_back(drawCmdList);
204 }
205 }
206 }
207 return !stagingDrawCmdListVec_.empty();
208 }
209
OnSync()210 void RSCustomModifierDrawable::OnSync()
211 {
212 if (!needSync_) {
213 return;
214 }
215 gravity_ = stagingGravity_;
216 isCanvasNode_ = stagingIsCanvasNode_;
217 std::swap(stagingDrawCmdListVec_, drawCmdListVec_);
218 RSRenderNodeDrawableAdapter::AddToClearCmdList(stagingDrawCmdListVec_);
219 needSync_ = false;
220 }
221
OnPurge()222 void RSCustomModifierDrawable::OnPurge()
223 {
224 for (auto &drawCmdList : drawCmdListVec_) {
225 if (drawCmdList) {
226 drawCmdList->Purge();
227 }
228 }
229 }
230
CreateDrawFunc() const231 Drawing::RecordingCanvas::DrawFunc RSCustomModifierDrawable::CreateDrawFunc() const
232 {
233 auto ptr = std::static_pointer_cast<const RSCustomModifierDrawable>(shared_from_this());
234 return [ptr](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
235 #ifdef RS_ENABLE_GPU
236 RSTagTracker tagTracker(canvas ? canvas->GetGPUContext() : nullptr,
237 RSTagTracker::SOURCETYPE::SOURCE_RSCUSTOMMODIFIERDRAWABLE);
238 #endif
239 for (size_t i = 0; i < ptr->drawCmdListVec_.size(); i++) {
240 #ifdef RS_ENABLE_PREFETCH
241 size_t prefetchIndex = i + 2;
242 if (prefetchIndex < ptr->drawCmdListVec_.size()) {
243 __builtin_prefetch(&(ptr->drawCmdListVec_[prefetchIndex]), 0, 1);
244 }
245 #endif
246 const auto& drawCmdList = ptr->drawCmdListVec_[i];
247 Drawing::Matrix mat;
248 if (ptr->isCanvasNode_ &&
249 RSPropertyDrawableUtils::GetGravityMatrix(ptr->gravity_, *rect, drawCmdList->GetWidth(),
250 drawCmdList->GetHeight(), mat)) {
251 canvas->ConcatMatrix(mat);
252 }
253 drawCmdList->Playback(*canvas, rect);
254 if (ptr->needClearOp_ && ptr->modifierTypeNG_ == ModifierNG::RSModifierType::CONTENT_STYLE) {
255 RS_PROFILER_DRAWING_NODE_ADD_CLEAROP(drawCmdList);
256 }
257 }
258 };
259 }
260
261 // ============================================================================
262 // Save and Restore
RSSaveDrawable(std::shared_ptr<uint32_t> content)263 RSSaveDrawable::RSSaveDrawable(std::shared_ptr<uint32_t> content) : content_(std::move(content)) {}
CreateDrawFunc() const264 Drawing::RecordingCanvas::DrawFunc RSSaveDrawable::CreateDrawFunc() const
265 {
266 return [content = content_](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
267 // Save and return save count
268 *content = canvas->Save();
269 };
270 }
271
RSRestoreDrawable(std::shared_ptr<uint32_t> content)272 RSRestoreDrawable::RSRestoreDrawable(std::shared_ptr<uint32_t> content) : content_(std::move(content)) {}
CreateDrawFunc() const273 Drawing::RecordingCanvas::DrawFunc RSRestoreDrawable::CreateDrawFunc() const
274 {
275 return [content = content_](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
276 // return to previous save count
277 canvas->RestoreToCount(*content);
278 };
279 }
280
RSCustomSaveDrawable(std::shared_ptr<RSPaintFilterCanvas::SaveStatus> content,RSPaintFilterCanvas::SaveType type)281 RSCustomSaveDrawable::RSCustomSaveDrawable(
282 std::shared_ptr<RSPaintFilterCanvas::SaveStatus> content, RSPaintFilterCanvas::SaveType type)
283 : content_(std::move(content)), type_(type)
284 {}
CreateDrawFunc() const285 Drawing::RecordingCanvas::DrawFunc RSCustomSaveDrawable::CreateDrawFunc() const
286 {
287 return [content = content_, type = type_](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
288 auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(canvas);
289 // Save and return save count
290 *content = paintFilterCanvas->SaveAllStatus(type);
291 };
292 }
293
RSCustomRestoreDrawable(std::shared_ptr<RSPaintFilterCanvas::SaveStatus> content)294 RSCustomRestoreDrawable::RSCustomRestoreDrawable(std::shared_ptr<RSPaintFilterCanvas::SaveStatus> content)
295 : content_(std::move(content))
296 {}
CreateDrawFunc() const297 Drawing::RecordingCanvas::DrawFunc RSCustomRestoreDrawable::CreateDrawFunc() const
298 {
299 return [content = content_](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
300 auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(canvas);
301 // return to previous save count
302 paintFilterCanvas->RestoreStatus(*content);
303 };
304 }
305
OnGenerate(const RSRenderNode & node)306 RSDrawable::Ptr RSBeginBlenderDrawable::OnGenerate(const RSRenderNode& node)
307 {
308 if (auto ret = std::make_shared<RSBeginBlenderDrawable>(); ret->OnUpdate(node)) {
309 return std::move(ret);
310 }
311 return nullptr;
312 }
313
PostUpdate(const RSRenderNode & node)314 void RSBeginBlenderDrawable::PostUpdate(const RSRenderNode& node)
315 {
316 enableEDREffect_ = node.GetRenderProperties().GetFgBrightnessEnableEDR();
317 if (enableEDREffect_) {
318 screenNodeId_ = node.GetScreenNodeId();
319 }
320 }
321
OnUpdate(const RSRenderNode & node)322 bool RSBeginBlenderDrawable::OnUpdate(const RSRenderNode& node)
323 {
324 // the order of blender and blendMode cannot be considered currently
325 const RSProperties& properties = node.GetRenderProperties();
326 auto blendMode = properties.GetColorBlendMode();
327 stagingBlendApplyType_ = properties.GetColorBlendApplyType();
328 // NOTE: stagingIsDangerous_ should be set true when adding a blender that may generate transparent pixels
329 if (properties.IsFgBrightnessValid()) {
330 if (Rosen::RSSystemProperties::GetDebugTraceLevel() >= TRACE_LEVEL_TWO) {
331 stagingPropertyDescription_ = properties.GetFgBrightnessDescription();
332 }
333 stagingBlender_ = RSPropertyDrawableUtils::MakeDynamicBrightnessBlender(
334 properties.GetFgBrightnessParams().value());
335 stagingIsDangerous_ = false;
336 } else if (blendMode && blendMode != static_cast<int>(RSColorBlendMode::NONE)) {
337 if (Rosen::RSSystemProperties::GetDebugTraceLevel() >= TRACE_LEVEL_TWO) {
338 stagingPropertyDescription_ = "BlendMode, blendMode: " + std::to_string(blendMode) +
339 " blendApplyType: " + std::to_string(stagingBlendApplyType_);
340 }
341 // map blendMode to Drawing::BlendMode and convert to Blender
342 stagingBlender_ = Drawing::Blender::CreateWithBlendMode(static_cast<Drawing::BlendMode>(blendMode - 1));
343 stagingIsDangerous_ = RSPropertyDrawableUtils::IsDangerousBlendMode(blendMode - 1, stagingBlendApplyType_);
344 } else if (properties.IsShadowBlenderValid()) {
345 if (Rosen::RSSystemProperties::GetDebugTraceLevel() >= TRACE_LEVEL_TWO) {
346 stagingPropertyDescription_ = properties.GetShadowBlenderDescription();
347 }
348 stagingBlender_ = RSPropertyDrawableUtils::MakeShadowBlender(properties.GetShadowBlenderParams().value());
349 stagingIsDangerous_ = false;
350 } else {
351 return false;
352 }
353
354 needSync_ = true;
355 PostUpdate(node);
356
357 return true;
358 }
359
OnSync()360 void RSBeginBlenderDrawable::OnSync()
361 {
362 if (needSync_ == false) {
363 return;
364 }
365 blender_ = stagingBlender_;
366 blendApplyType_ = stagingBlendApplyType_;
367 propertyDescription_ = stagingPropertyDescription_;
368 stagingPropertyDescription_.clear();
369 needSync_ = false;
370 }
371
CreateDrawFunc() const372 Drawing::RecordingCanvas::DrawFunc RSBeginBlenderDrawable::CreateDrawFunc() const
373 {
374 auto ptr = std::static_pointer_cast<const RSBeginBlenderDrawable>(shared_from_this());
375 return [ptr](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
376 if (canvas->GetDrawingType() != Drawing::DrawingType::PAINT_FILTER) {
377 return;
378 }
379 auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(canvas);
380 #ifdef RS_ENABLE_GPU
381 RSTagTracker tagTracker(paintFilterCanvas->GetGPUContext(),
382 RSTagTracker::SOURCETYPE::SOURCE_RSBEGINBLENDERDRAWABLE);
383 #endif
384 RS_OPTIONAL_TRACE_NAME_FMT_LEVEL(TRACE_LEVEL_TWO, "RSBeginBlenderDrawable:: %s, bounds: %s",
385 ptr->propertyDescription_.c_str(), rect->ToString().c_str());
386 RSPropertyDrawableUtils::BeginBlender(*paintFilterCanvas, ptr->blender_, ptr->blendApplyType_,
387 ptr->isDangerous_);
388 };
389 }
390
OnGenerate(const RSRenderNode & node)391 RSDrawable::Ptr RSEndBlenderDrawable::OnGenerate(const RSRenderNode& node)
392 {
393 if (auto ret = std::make_shared<RSEndBlenderDrawable>(); ret->OnUpdate(node)) {
394 return std::move(ret);
395 }
396 return nullptr;
397 };
398
OnUpdate(const RSRenderNode & node)399 bool RSEndBlenderDrawable::OnUpdate(const RSRenderNode& node)
400 {
401 const RSProperties& properties = node.GetRenderProperties();
402 if (properties.GetColorBlendMode() == static_cast<int>(RSColorBlendMode::NONE) ||
403 properties.GetColorBlendApplyType() == static_cast<int>(RSColorBlendApplyType::FAST)) {
404 // no blend
405 return false;
406 }
407
408 stagingBlendApplyType_ = properties.GetColorBlendApplyType();
409 needSync_ = true;
410
411 return true;
412 }
413
OnSync()414 void RSEndBlenderDrawable::OnSync()
415 {
416 if (needSync_ == false) {
417 return;
418 }
419 blendApplyType_ = stagingBlendApplyType_;
420 needSync_ = false;
421 }
422
CreateDrawFunc() const423 Drawing::RecordingCanvas::DrawFunc RSEndBlenderDrawable::CreateDrawFunc() const
424 {
425 auto ptr = std::static_pointer_cast<const RSEndBlenderDrawable>(shared_from_this());
426 return [ptr](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
427 auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(canvas);
428 RSPropertyDrawableUtils::EndBlender(*paintFilterCanvas, ptr->blendApplyType_);
429 };
430 }
431
432 // ============================================================================
433 // EnvFGColor
OnGenerate(const RSRenderNode & node)434 RSDrawable::Ptr RSEnvFGColorDrawable::OnGenerate(const RSRenderNode& node)
435 {
436 if (auto ret = std::make_shared<RSEnvFGColorDrawable>(); ret->OnUpdate(node)) {
437 return std::move(ret);
438 }
439 return nullptr;
440 }
441
OnUpdate(const RSRenderNode & node)442 bool RSEnvFGColorDrawable::OnUpdate(const RSRenderNode& node)
443 {
444 auto modifier = node.GetModifierNG(ModifierNG::RSModifierType::ENV_FOREGROUND_COLOR);
445 if (modifier == nullptr) {
446 return false;
447 }
448 if (!modifier->HasProperty(ModifierNG::RSPropertyType::ENV_FOREGROUND_COLOR)) {
449 return false;
450 }
451 stagingEnvFGColor_ = modifier->Getter<Color>(ModifierNG::RSPropertyType::ENV_FOREGROUND_COLOR, Color());
452 needSync_ = true;
453 return true;
454 }
455
OnSync()456 void RSEnvFGColorDrawable::OnSync()
457 {
458 if (!needSync_) {
459 return;
460 }
461 envFGColor_ = stagingEnvFGColor_;
462 needSync_ = false;
463 }
464
CreateDrawFunc() const465 Drawing::RecordingCanvas::DrawFunc RSEnvFGColorDrawable::CreateDrawFunc() const
466 {
467 auto ptr = std::static_pointer_cast<const RSEnvFGColorDrawable>(shared_from_this());
468 return [ptr](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
469 auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(canvas);
470 // planning: implement alpha offscreen
471 paintFilterCanvas->SetEnvForegroundColor(ptr->envFGColor_);
472 };
473 }
474
475 // ============================================================================
476 // EnvFGColorStrategy
OnGenerate(const RSRenderNode & node)477 RSDrawable::Ptr RSEnvFGColorStrategyDrawable::OnGenerate(const RSRenderNode& node)
478 {
479 if (auto ret = std::make_shared<RSEnvFGColorStrategyDrawable>(); ret->OnUpdate(node)) {
480 return std::move(ret);
481 }
482 return nullptr;
483 }
484
OnUpdate(const RSRenderNode & node)485 bool RSEnvFGColorStrategyDrawable::OnUpdate(const RSRenderNode& node)
486 {
487 auto modifier = node.GetModifierNG(ModifierNG::RSModifierType::ENV_FOREGROUND_COLOR);
488 if (modifier == nullptr) {
489 return false;
490 }
491 stagingEnvFGColorStrategy_ = static_cast<ForegroundColorStrategyType>(
492 modifier->Getter<int>(ModifierNG::RSPropertyType::ENV_FOREGROUND_COLOR_STRATEGY, 0));
493 const auto& renderProperties = node.GetRenderProperties();
494 stagingBackgroundColor_ = renderProperties.GetBackgroundColor();
495 stagingNeedClipToBounds_ = renderProperties.GetClipToBounds();
496 stagingBoundsRect_ = renderProperties.GetBounds();
497 needSync_ = true;
498 return true;
499 }
500
OnSync()501 void RSEnvFGColorStrategyDrawable::OnSync()
502 {
503 if (!needSync_) {
504 return;
505 }
506 envFGColorStrategy_ = stagingEnvFGColorStrategy_;
507 backgroundColor_ = stagingBackgroundColor_;
508 needClipToBounds_ = stagingNeedClipToBounds_;
509 boundsRect_ = stagingBoundsRect_;
510 needSync_ = false;
511 }
512
CreateDrawFunc() const513 Drawing::RecordingCanvas::DrawFunc RSEnvFGColorStrategyDrawable::CreateDrawFunc() const
514 {
515 auto ptr = std::static_pointer_cast<const RSEnvFGColorStrategyDrawable>(shared_from_this());
516 return [this, ptr](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
517 auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(canvas);
518 switch (envFGColorStrategy_) {
519 case ForegroundColorStrategyType::INVERT_BACKGROUNDCOLOR: {
520 // calculate the color by screebshot
521 Color color = RSPropertyDrawableUtils::GetInvertBackgroundColor(*paintFilterCanvas, needClipToBounds_,
522 boundsRect_, backgroundColor_);
523 paintFilterCanvas->SetEnvForegroundColor(color);
524 break;
525 }
526 default: {
527 break;
528 }
529 }
530 };
531 }
532
OnGenerate(const RSRenderNode & node)533 RSDrawable::Ptr RSCustomClipToFrameDrawable::OnGenerate(const RSRenderNode& node)
534 {
535 if (auto ret = std::make_shared<RSCustomClipToFrameDrawable>(); ret->OnUpdate(node)) {
536 return std::move(ret);
537 }
538 return nullptr;
539 }
540
OnUpdate(const RSRenderNode & node)541 bool RSCustomClipToFrameDrawable::OnUpdate(const RSRenderNode& node)
542 {
543 const auto modifier = node.GetModifierNG(ModifierNG::RSModifierType::CLIP_TO_FRAME);
544 if (modifier == nullptr || !modifier->HasProperty(ModifierNG::RSPropertyType::CUSTOM_CLIP_TO_FRAME)) {
545 return false;
546 }
547 const auto& clipRectV4f = modifier->Getter<Vector4f>(ModifierNG::RSPropertyType::CUSTOM_CLIP_TO_FRAME, Vector4f());
548 stagingCustomClipRect_ = Drawing::Rect(clipRectV4f.x_, clipRectV4f.y_, clipRectV4f.z_, clipRectV4f.w_);
549 needSync_ = true;
550 return true;
551 }
552
OnSync()553 void RSCustomClipToFrameDrawable::OnSync()
554 {
555 if (!needSync_) {
556 return;
557 }
558 customClipRect_ = stagingCustomClipRect_;
559 needSync_ = false;
560 }
561
CreateDrawFunc() const562 Drawing::RecordingCanvas::DrawFunc RSCustomClipToFrameDrawable::CreateDrawFunc() const
563 {
564 auto ptr = std::static_pointer_cast<const RSCustomClipToFrameDrawable>(shared_from_this());
565 return [ptr](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
566 canvas->ClipRect(ptr->customClipRect_);
567 };
568 }
569
570 } // namespace DrawableV2
571 } // namespace OHOS::Rosen
572