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 "property/rs_property_drawable_utilities.h"
17 #include "pipeline/rs_render_node.h"
18 #include "pipeline/rs_single_frame_composer.h"
19 #include "property/rs_properties.h"
20 #include "property/rs_properties_painter.h"
21 
22 namespace OHOS::Rosen {
23 // ============================================================================
24 // alias (reference or soft link) of another drawable
RSAliasDrawable(RSPropertyDrawableSlot slot)25 RSAliasDrawable::RSAliasDrawable(RSPropertyDrawableSlot slot) : slot_(slot) {}
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const26 void RSAliasDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
27 {
28     content.DrawPropertyDrawable(slot_, canvas);
29 }
30 
31 // ============================================================================
32 // Save and Restore
RSSaveDrawable(std::shared_ptr<uint32_t> content)33 RSSaveDrawable::RSSaveDrawable(std::shared_ptr<uint32_t> content) : content_(std::move(content)) {}
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const34 void RSSaveDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
35 {
36     *content_ = canvas.Save();
37 }
38 
RSRestoreDrawable(std::shared_ptr<uint32_t> content)39 RSRestoreDrawable::RSRestoreDrawable(std::shared_ptr<uint32_t> content) : content_(std::move(content)) {}
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const40 void RSRestoreDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
41 {
42     canvas.RestoreToCount(*content_);
43 }
44 
RSCustomSaveDrawable(std::shared_ptr<RSPaintFilterCanvas::SaveStatus> content,RSPaintFilterCanvas::SaveType type)45 RSCustomSaveDrawable::RSCustomSaveDrawable(
46     std::shared_ptr<RSPaintFilterCanvas::SaveStatus> content, RSPaintFilterCanvas::SaveType type)
47     : content_(std::move(content)), type_(type)
48 {}
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const49 void RSCustomSaveDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
50 {
51     *content_ = canvas.SaveAllStatus(type_);
52 }
53 
RSCustomRestoreDrawable(std::shared_ptr<RSPaintFilterCanvas::SaveStatus> content)54 RSCustomRestoreDrawable::RSCustomRestoreDrawable(std::shared_ptr<RSPaintFilterCanvas::SaveStatus> content)
55     : content_(std::move(content))
56 {}
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const57 void RSCustomRestoreDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
58 {
59     canvas.RestoreStatus(*content_);
60 }
61 
62 // ============================================================================
63 // Adapter for RSRenderModifier
RSModifierDrawable(RSModifierType type)64 RSModifierDrawable::RSModifierDrawable(RSModifierType type) : type_(type) {}
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const65 void RSModifierDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
66 {
67     // single-frame-compose needs to access render node & mutable draw cmd list during the render process
68     // PLANNING: this is a temporarily workaround, should refactor later
69     auto nodePtr = content.GetRenderProperties().backref_.lock();
70     if (nodePtr == nullptr) {
71         return;
72     }
73     auto& drawCmdModifiers = const_cast<RSRenderContent::DrawCmdContainer&>(content.drawCmdModifiers_);
74     auto itr = drawCmdModifiers.find(type_);
75     if (itr == drawCmdModifiers.end() || itr->second.empty()) {
76         return;
77     }
78     // temporary fix, will refactor RSRenderModifier::Apply to workaround this issue
79     RSModifierContext context = { const_cast<RSRenderContent&>(content).renderProperties_, &canvas };
80     if (RSSystemProperties::GetSingleFrameComposerEnabled()) {
81         bool needSkip = false;
82         if (nodePtr->GetNodeIsSingleFrameComposer() && nodePtr->singleFrameComposer_ != nullptr) {
83             needSkip = nodePtr->singleFrameComposer_->SingleFrameModifierAddToList(type_, itr->second);
84         }
85         for (const auto& modifier : itr->second) {
86             if (nodePtr->singleFrameComposer_ != nullptr &&
87                 nodePtr->singleFrameComposer_->SingleFrameIsNeedSkip(needSkip, modifier)) {
88                 continue;
89             }
90             modifier->Apply(context);
91         }
92     } else {
93         for (const auto& modifier : itr->second) {
94             if (modifier) {
95                 modifier->Apply(context);
96             }
97         }
98     }
99 }
100 
101 // ============================================================================
102 // Alpha
RSAlphaDrawable(float alpha)103 RSAlphaDrawable::RSAlphaDrawable(float alpha) : RSPropertyDrawable(), alpha_(alpha) {}
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const104 void RSAlphaDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
105 {
106     canvas.MultiplyAlpha(alpha_);
107 }
Generate(const RSRenderContent & content)108 RSPropertyDrawable::DrawablePtr RSAlphaDrawable::Generate(const RSRenderContent& content)
109 {
110     auto alpha = content.GetRenderProperties().GetAlpha();
111     if (alpha == 1) {
112         return nullptr;
113     }
114     return content.GetRenderProperties().GetAlphaOffscreen() ? std::make_unique<RSAlphaOffscreenDrawable>(alpha)
115                                                    : std::make_unique<RSAlphaDrawable>(alpha);
116 }
117 
RSAlphaOffscreenDrawable(float alpha)118 RSAlphaOffscreenDrawable::RSAlphaOffscreenDrawable(float alpha) : RSAlphaDrawable(alpha) {}
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const119 void RSAlphaOffscreenDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
120 {
121     auto rect = RSPropertiesPainter::Rect2DrawingRect(content.GetRenderProperties().GetBoundsRect());
122     Drawing::Brush brush;
123     brush.SetAlpha(std::clamp(alpha_, 0.f, 1.f) * UINT8_MAX);
124     Drawing::SaveLayerOps slr(&rect, &brush);
125     canvas.SaveLayer(slr);
126 }
127 } // namespace OHOS::Rosen
128