1 /*
2 * Copyright (c) 2021-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 "ui/rs_canvas_node.h"
17
18 #include <algorithm>
19 #include <string>
20
21 #include "common/rs_obj_abs_geometry.h"
22 #include "command/rs_canvas_node_command.h"
23 #include "command/rs_node_command.h"
24 #include "platform/common/rs_log.h"
25 #include "common/rs_obj_geometry.h"
26 #include "pipeline/rs_draw_cmd_list.h"
27 #include "pipeline/rs_node_map.h"
28 #include "transaction/rs_transaction_proxy.h"
29
30 namespace OHOS {
31 namespace Rosen {
Create(bool isRenderServiceNode,bool isTextureExportNode)32 RSCanvasNode::SharedPtr RSCanvasNode::Create(bool isRenderServiceNode, bool isTextureExportNode)
33 {
34 SharedPtr node(new RSCanvasNode(isRenderServiceNode, isTextureExportNode));
35 RSNodeMap::MutableInstance().RegisterNode(node);
36
37 auto transactionProxy = RSTransactionProxy::GetInstance();
38 if (transactionProxy == nullptr) {
39 return node;
40 }
41 std::unique_ptr<RSCommand> command = std::make_unique<RSCanvasNodeCreate>(node->GetId(), isTextureExportNode);
42 transactionProxy->AddCommand(command, node->IsRenderServiceNode());
43 return node;
44 }
45
RSCanvasNode(bool isRenderServiceNode,bool isTextureExportNode)46 RSCanvasNode::RSCanvasNode(bool isRenderServiceNode, bool isTextureExportNode)
47 : RSNode(isRenderServiceNode, isTextureExportNode) {}
48
~RSCanvasNode()49 RSCanvasNode::~RSCanvasNode() {}
50
51 #ifndef USE_ROSEN_DRAWING
BeginRecording(int width,int height)52 SkCanvas* RSCanvasNode::BeginRecording(int width, int height)
53 {
54 recordingCanvas_ = new RSRecordingCanvas(width, height);
55 static_cast<RSRecordingCanvas*>(recordingCanvas_)->SetIsCustomTextType(isCustomTextType_);
56 #else
57 ExtendRecordingCanvas* RSCanvasNode::BeginRecording(int width, int height)
58 {
59 recordingCanvas_ = new ExtendRecordingCanvas(width, height);
60 recordingCanvas_->SetIsCustomTextType(isCustomTextType_);
61 #endif
62 auto transactionProxy = RSTransactionProxy::GetInstance();
63 if (transactionProxy == nullptr) {
64 return recordingCanvas_;
65 }
66 if (!recordingUpdated_) {
67 return recordingCanvas_;
68 }
69 recordingUpdated_ = false;
70 std::unique_ptr<RSCommand> command = std::make_unique<RSCanvasNodeClearRecording>(GetId());
71 transactionProxy->AddCommand(command, IsRenderServiceNode());
72 return recordingCanvas_;
73 }
74
75 bool RSCanvasNode::IsRecording() const
76 {
77 return recordingCanvas_ != nullptr;
78 }
79
80 void RSCanvasNode::FinishRecording()
81 {
82 if (!IsRecording()) {
83 return;
84 }
85 #ifndef USE_ROSEN_DRAWING
86 auto recording = static_cast<RSRecordingCanvas*>(recordingCanvas_)->GetDrawCmdList();
87 #else
88 auto recording = recordingCanvas_->GetDrawCmdList();
89 #endif
90 delete recordingCanvas_;
91 recordingCanvas_ = nullptr;
92 #ifndef USE_ROSEN_DRAWING
93 if (recording && recording->GetSize() == 0) {
94 #else
95 if (recording && recording->IsEmpty()) {
96 #endif
97 return;
98 }
99 if (recording != nullptr && RSSystemProperties::GetDrawTextAsBitmap()) {
100 // replace drawOpItem with cached one (generated by CPU)
101 recording->GenerateCache();
102 }
103 auto transactionProxy = RSTransactionProxy::GetInstance();
104 if (transactionProxy == nullptr) {
105 return;
106 }
107 std::unique_ptr<RSCommand> command = std::make_unique<RSCanvasNodeUpdateRecording>(GetId(), recording,
108 drawContentLast_ ? static_cast<uint16_t>(RSModifierType::FOREGROUND_STYLE)
109 : static_cast<uint16_t>(RSModifierType::CONTENT_STYLE));
110 transactionProxy->AddCommand(command, IsRenderServiceNode());
111 recordingUpdated_ = true;
112 }
113
114 void RSCanvasNode::DrawOnNode(RSModifierType type, DrawFunc func)
115 {
116 #ifndef USE_ROSEN_DRAWING
117 auto recordingCanvas = std::make_shared<RSRecordingCanvas>(GetPaintWidth(), GetPaintHeight());
118 recordingCanvas->SetIsCustomTextType(isCustomTextType_);
119 #else
120 auto recordingCanvas = std::make_shared<ExtendRecordingCanvas>(GetPaintWidth(), GetPaintHeight());
121 recordingCanvas->SetIsCustomTextType(isCustomTextType_);
122 #endif
123 func(recordingCanvas);
124 auto transactionProxy = RSTransactionProxy::GetInstance();
125 if (transactionProxy == nullptr) {
126 return;
127 }
128 auto recording = recordingCanvas->GetDrawCmdList();
129 #ifndef USE_ROSEN_DRAWING
130 if (recording && recording->GetSize() == 0) {
131 #else
132 if (recording && recording->IsEmpty()) {
133 #endif
134 return;
135 }
136 if (recording != nullptr && RSSystemProperties::GetDrawTextAsBitmap()) {
137 // replace drawOpItem with cached one (generated by CPU)
138 recording->GenerateCache();
139 }
140 std::unique_ptr<RSCommand> command =
141 std::make_unique<RSCanvasNodeUpdateRecording>(GetId(), recording, static_cast<uint16_t>(type));
142 transactionProxy->AddCommand(command, IsRenderServiceNode());
143 recordingUpdated_ = true;
144 }
145
146 float RSCanvasNode::GetPaintWidth() const
147 {
148 auto frame = GetStagingProperties().GetFrame();
149 return frame.z_ <= 0.f ? GetStagingProperties().GetBounds().z_ : frame.z_;
150 }
151
152 float RSCanvasNode::GetPaintHeight() const
153 {
154 auto frame = GetStagingProperties().GetFrame();
155 return frame.w_ <= 0.f ? GetStagingProperties().GetBounds().w_ : frame.w_;
156 }
157
158 void RSCanvasNode::SetFreeze(bool isFreeze)
159 {
160 if (!IsUniRenderEnabled()) {
161 ROSEN_LOGE("SetFreeze is not supported in separate render");
162 return;
163 }
164 std::unique_ptr<RSCommand> command = std::make_unique<RSSetFreeze>(GetId(), isFreeze);
165 auto transactionProxy = RSTransactionProxy::GetInstance();
166 if (transactionProxy != nullptr) {
167 transactionProxy->AddCommand(command, true);
168 }
169 }
170
171 void RSCanvasNode::OnBoundsSizeChanged() const
172 {
173 auto bounds = GetStagingProperties().GetBounds();
174 std::lock_guard<std::mutex> lock(mutex_);
175 if (boundsChangedCallback_) {
176 boundsChangedCallback_(bounds);
177 }
178 }
179
180 void RSCanvasNode::SetBoundsChangedCallback(BoundsChangedCallback callback)
181 {
182 std::lock_guard<std::mutex> lock(mutex_);
183 boundsChangedCallback_ = callback;
184 }
185
186 } // namespace Rosen
187 } // namespace OHOS
188