• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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