1 /*
2  * Copyright (c) 2022-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 "platform/ohos/overdraw/rs_gpu_overdraw_canvas_listener.h"
17 
18 #include "draw/blend_mode.h"
19 #include "draw/color.h"
20 #include "effect/color_matrix.h"
21 #include "image/bitmap.h"
22 
23 #include "platform/ohos/overdraw/rs_overdraw_controller.h"
24 
25 namespace OHOS {
26 namespace Rosen {
RSGPUOverdrawCanvasListener(Drawing::Canvas & canvas)27 RSGPUOverdrawCanvasListener::RSGPUOverdrawCanvasListener(Drawing::Canvas& canvas)
28     : RSCanvasListener(canvas)
29 {
30     auto gpuContext = canvas.GetGPUContext();
31     if (gpuContext == nullptr) {
32         ROSEN_LOGE("RSGPUOverdrawCanvasListener, construction failed: need gpu canvas");
33         return;
34     }
35 
36     Drawing::BitmapFormat format = { Drawing::ColorType::COLORTYPE_BGRA_8888, Drawing::AlphaType::ALPHATYPE_PREMUL };
37     auto width = canvas.GetWidth();
38     auto height = canvas.GetHeight();
39     Drawing::Bitmap bitmap;
40     bitmap.Build(width, height, format);
41     Drawing::Image image;
42     image.BuildFromBitmap(*gpuContext, bitmap);
43 
44     auto surface = std::make_shared<Drawing::Surface>();
45     surface->Bind(image);
46     listenedSurface_ = surface;
47     overdrawCanvas_ = std::make_shared<Drawing::OverDrawCanvas>(surface->GetCanvas());
48 }
49 
~RSGPUOverdrawCanvasListener()50 RSGPUOverdrawCanvasListener::~RSGPUOverdrawCanvasListener()
51 {
52 }
53 
Draw()54 void RSGPUOverdrawCanvasListener::Draw()
55 {
56     auto image = listenedSurface_->GetImageSnapshot();
57     if (image == nullptr) {
58         ROSEN_LOGE("image is nullptr");
59         return;
60     }
61     Drawing::Brush brush;
62     auto overdrawColors = RSOverdrawController::GetInstance().GetColorArray();
63     auto colorFilter = Drawing::ColorFilter::CreateOverDrawColorFilter(overdrawColors.data());
64     Drawing::Filter filter;
65     filter.SetColorFilter(colorFilter);
66     brush.SetFilter(filter);
67     canvas_.AttachBrush(brush);
68     canvas_.DrawImage(*image, 0, 0, Drawing::SamplingOptions());
69     canvas_.DetachBrush();
70 }
71 
IsValid() const72 bool RSGPUOverdrawCanvasListener::IsValid() const
73 {
74     return listenedSurface_ != nullptr;
75 }
76 
DrawPoint(const Drawing::Point & point)77 void RSGPUOverdrawCanvasListener::DrawPoint(const Drawing::Point& point)
78 {
79     DrawRect(Drawing::Rect(point.GetX(), point.GetY(), 1 + point.GetX(), 1 + point.GetY()));
80 }
81 
DrawLine(const Drawing::Point & startPt,const Drawing::Point & endPt)82 void RSGPUOverdrawCanvasListener::DrawLine(const Drawing::Point& startPt, const Drawing::Point& endPt)
83 {
84     if (overdrawCanvas_ == nullptr) {
85         ROSEN_LOGE("overdrawCanvas_ is nullptr");
86         return;
87     }
88 
89     Drawing::Path path;
90     path.MoveTo(startPt.GetX(), startPt.GetY());
91     path.LineTo(endPt.GetX(), endPt.GetY());
92     overdrawCanvas_->DrawPath(path);
93 }
94 
DrawRect(const Drawing::Rect & rect)95 void RSGPUOverdrawCanvasListener::DrawRect(const Drawing::Rect& rect)
96 {
97     if (overdrawCanvas_ == nullptr) {
98         ROSEN_LOGE("overdrawCanvas_ is nullptr");
99         return;
100     }
101     overdrawCanvas_->DrawRect(rect);
102 }
103 
DrawRoundRect(const Drawing::RoundRect & roundRect)104 void RSGPUOverdrawCanvasListener::DrawRoundRect(const Drawing::RoundRect& roundRect)
105 {
106     if (overdrawCanvas_ == nullptr) {
107         ROSEN_LOGE("overdrawCanvas_ is nullptr");
108         return;
109     }
110     overdrawCanvas_->DrawRoundRect(roundRect);
111 }
112 
DrawNestedRoundRect(const Drawing::RoundRect & outer,const Drawing::RoundRect & inner)113 void RSGPUOverdrawCanvasListener::DrawNestedRoundRect(const Drawing::RoundRect& outer, const Drawing::RoundRect& inner)
114 {
115     if (overdrawCanvas_ == nullptr) {
116         ROSEN_LOGE("overdrawCanvas_ is nullptr");
117         return;
118     }
119     overdrawCanvas_->DrawNestedRoundRect(outer, inner);
120 }
121 
DrawArc(const Drawing::Rect & oval,Drawing::scalar startAngle,Drawing::scalar sweepAngle)122 void RSGPUOverdrawCanvasListener::DrawArc(
123     const Drawing::Rect& oval, Drawing::scalar startAngle, Drawing::scalar sweepAngle)
124 {
125     if (overdrawCanvas_ == nullptr) {
126         ROSEN_LOGE("overdrawCanvas_ is nullptr");
127         return;
128     }
129     Drawing::Path path;
130     path.AddArc(oval, startAngle, sweepAngle);
131     overdrawCanvas_->DrawPath(path);
132 }
133 
DrawPie(const Drawing::Rect & oval,Drawing::scalar startAngle,Drawing::scalar sweepAngle)134 void RSGPUOverdrawCanvasListener::DrawPie(
135     const Drawing::Rect& oval, Drawing::scalar startAngle, Drawing::scalar sweepAngle)
136 {
137     if (overdrawCanvas_ == nullptr) {
138         ROSEN_LOGE("overdrawCanvas_ is nullptr");
139         return;
140     }
141     Drawing::Path path;
142     path.AddArc(oval, startAngle, sweepAngle);
143     overdrawCanvas_->DrawPath(path);
144 }
145 
DrawOval(const Drawing::Rect & oval)146 void RSGPUOverdrawCanvasListener::DrawOval(const Drawing::Rect& oval)
147 {
148     if (overdrawCanvas_ == nullptr) {
149         ROSEN_LOGE("overdrawCanvas_ is nullptr");
150         return;
151     }
152     Drawing::Path path;
153     path.AddOval(oval);
154     overdrawCanvas_->DrawPath(path);
155 }
156 
DrawCircle(const Drawing::Point & centerPt,Drawing::scalar radius)157 void RSGPUOverdrawCanvasListener::DrawCircle(const Drawing::Point& centerPt, Drawing::scalar radius)
158 {
159     if (overdrawCanvas_ == nullptr) {
160         ROSEN_LOGE("overdrawCanvas_ is nullptr");
161         return;
162     }
163     Drawing::Path path;
164     path.AddCircle(centerPt.GetX(), centerPt.GetY(), radius);
165     overdrawCanvas_->DrawPath(path);
166 }
167 
DrawPath(const Drawing::Path & path)168 void RSGPUOverdrawCanvasListener::DrawPath(const Drawing::Path& path)
169 {
170     if (overdrawCanvas_ == nullptr) {
171         ROSEN_LOGE("overdrawCanvas_ is nullptr");
172         return;
173     }
174     overdrawCanvas_->DrawPath(path);
175 }
176 
DrawBackground(const Drawing::Brush & brush)177 void RSGPUOverdrawCanvasListener::DrawBackground(const Drawing::Brush& brush)
178 {
179     // need know canvas rect region
180 }
181 
DrawShadow(const Drawing::Path & path,const Drawing::Point3 & planeParams,const Drawing::Point3 & devLightPos,Drawing::scalar lightRadius,Drawing::Color ambientColor,Drawing::Color spotColor,Drawing::ShadowFlags flag)182 void RSGPUOverdrawCanvasListener::DrawShadow(const Drawing::Path& path, const Drawing::Point3& planeParams,
183     const Drawing::Point3& devLightPos, Drawing::scalar lightRadius, Drawing::Color ambientColor,
184     Drawing::Color spotColor, Drawing::ShadowFlags flag)
185 {
186     // need know shadow rect region
187 }
188 
DrawShadowStyle(const Drawing::Path & path,const Drawing::Point3 & planeParams,const Drawing::Point3 & devLightPos,Drawing::scalar lightRadius,Drawing::Color ambientColor,Drawing::Color spotColor,Drawing::ShadowFlags flag,bool isLimitElevation)189 void RSGPUOverdrawCanvasListener::DrawShadowStyle(const Drawing::Path& path, const Drawing::Point3& planeParams,
190     const Drawing::Point3& devLightPos, Drawing::scalar lightRadius, Drawing::Color ambientColor,
191     Drawing::Color spotColor, Drawing::ShadowFlags flag, bool isLimitElevation)
192 {
193     // need know shadow rect region
194 }
195 
DrawRegion(const Drawing::Region & region)196 void RSGPUOverdrawCanvasListener::DrawRegion(const Drawing::Region& region)
197 {
198     // need know region path region
199 }
200 
DrawBitmap(const Drawing::Bitmap & bitmap,const Drawing::scalar px,const Drawing::scalar py)201 void RSGPUOverdrawCanvasListener::DrawBitmap(
202     const Drawing::Bitmap& bitmap, const Drawing::scalar px, const Drawing::scalar py)
203 {
204     if (overdrawCanvas_ == nullptr) {
205         ROSEN_LOGE("overdrawCanvas_ is nullptr");
206         return;
207     }
208     overdrawCanvas_->DrawRect(Drawing::Rect(px, py, bitmap.GetWidth() + px, bitmap.GetHeight() + py));
209 }
210 
DrawImage(const Drawing::Image & image,const Drawing::scalar px,const Drawing::scalar py,const Drawing::SamplingOptions & sampling)211 void RSGPUOverdrawCanvasListener::DrawImage(const Drawing::Image& image, const Drawing::scalar px,
212     const Drawing::scalar py, const Drawing::SamplingOptions& sampling)
213 {
214     if (overdrawCanvas_ == nullptr) {
215         ROSEN_LOGE("overdrawCanvas_ is nullptr");
216         return;
217     }
218     overdrawCanvas_->DrawRect(Drawing::Rect(px, py, image.GetWidth() + px, image.GetHeight() + py));
219 }
220 
DrawImageRect(const Drawing::Image & image,const Drawing::Rect & src,const Drawing::Rect & dst,const Drawing::SamplingOptions & sampling,Drawing::SrcRectConstraint constraint)221 void RSGPUOverdrawCanvasListener::DrawImageRect(const Drawing::Image& image, const Drawing::Rect& src,
222     const Drawing::Rect& dst, const Drawing::SamplingOptions& sampling, Drawing::SrcRectConstraint constraint)
223 {
224     if (overdrawCanvas_ == nullptr) {
225         ROSEN_LOGE("overdrawCanvas_ is nullptr");
226         return;
227     }
228     overdrawCanvas_->DrawRect(dst);
229 }
230 
DrawImageRect(const Drawing::Image & image,const Drawing::Rect & dst,const Drawing::SamplingOptions & sampling)231 void RSGPUOverdrawCanvasListener::DrawImageRect(
232     const Drawing::Image& image, const Drawing::Rect& dst, const Drawing::SamplingOptions& sampling)
233 {
234     if (overdrawCanvas_ == nullptr) {
235         ROSEN_LOGE("overdrawCanvas_ is nullptr");
236         return;
237     }
238     overdrawCanvas_->DrawRect(dst);
239 }
240 
DrawPicture(const Drawing::Picture & picture)241 void RSGPUOverdrawCanvasListener::DrawPicture(const Drawing::Picture& picture)
242 {
243     // need know picture rect region
244 }
245 
Clear(Drawing::ColorQuad color)246 void RSGPUOverdrawCanvasListener::Clear(Drawing::ColorQuad color)
247 {
248     // need know canvas rect region
249 }
250 
AttachPen(const Drawing::Pen & pen)251 void RSGPUOverdrawCanvasListener::AttachPen(const Drawing::Pen& pen)
252 {
253     if (overdrawCanvas_ == nullptr) {
254         ROSEN_LOGE("RSGPUOverdrawCanvasListener::AttachPen overdrawCanvas_ is nullptr");
255         return;
256     }
257     overdrawCanvas_->AttachPen(pen);
258 }
259 
AttachBrush(const Drawing::Brush & brush)260 void RSGPUOverdrawCanvasListener::AttachBrush(const Drawing::Brush& brush)
261 {
262     if (overdrawCanvas_ == nullptr) {
263         ROSEN_LOGE("RSGPUOverdrawCanvasListener::AttachBrush overdrawCanvas_ is nullptr");
264         return;
265     }
266     overdrawCanvas_->AttachBrush(brush);
267 }
268 
DetachPen()269 void RSGPUOverdrawCanvasListener::DetachPen()
270 {
271     if (overdrawCanvas_ == nullptr) {
272         ROSEN_LOGE("RSGPUOverdrawCanvasListener::DetachPen overdrawCanvas_ is nullptr");
273         return;
274     }
275     overdrawCanvas_->DetachPen();
276 }
277 
DetachBrush()278 void RSGPUOverdrawCanvasListener::DetachBrush()
279 {
280     if (overdrawCanvas_ == nullptr) {
281         ROSEN_LOGE("RSGPUOverdrawCanvasListener::DetachBrush overdrawCanvas_ is nullptr");
282         return;
283     }
284     overdrawCanvas_->DetachBrush();
285 }
286 
287 } // namespace Rosen
288 } // namespace OHOS
289