1 /*
2  * Copyright (c) 2021-2022 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 "pipeline/rs_paint_filter_canvas.h"
17 
18 #include <algorithm>
19 
20 #include "draw/canvas.h"
21 
22 #include "platform/common/rs_log.h"
23 
24 namespace OHOS {
25 namespace Rosen {
26 
27 using namespace Drawing;
28 
RSPaintFilterCanvasBase(Drawing::Canvas * canvas)29 RSPaintFilterCanvasBase::RSPaintFilterCanvasBase(Drawing::Canvas* canvas)
30     : Canvas(canvas ? canvas->GetWidth() : 0, canvas ? canvas->GetHeight() : 0), canvas_(canvas)
31 {
32 }
33 
GetTotalMatrix() const34 Drawing::Matrix RSPaintFilterCanvasBase::GetTotalMatrix() const
35 {
36     return canvas_->GetTotalMatrix();
37 }
38 
GetLocalClipBounds() const39 Drawing::Rect RSPaintFilterCanvasBase::GetLocalClipBounds() const
40 {
41     return canvas_->GetLocalClipBounds();
42 }
43 
GetDeviceClipBounds() const44 Drawing::RectI RSPaintFilterCanvasBase::GetDeviceClipBounds() const
45 {
46     return canvas_->GetDeviceClipBounds();
47 }
48 
GetRoundInDeviceClipBounds() const49 Drawing::RectI RSPaintFilterCanvasBase::GetRoundInDeviceClipBounds() const
50 {
51     return canvas_->GetRoundInDeviceClipBounds();
52 }
53 
GetSaveCount() const54 uint32_t RSPaintFilterCanvasBase::GetSaveCount() const
55 {
56     return canvas_->GetSaveCount();
57 }
58 
59 #ifdef RS_ENABLE_GPU
GetGPUContext()60 std::shared_ptr<Drawing::GPUContext> RSPaintFilterCanvasBase::GetGPUContext()
61 {
62     return canvas_ != nullptr ? canvas_->GetGPUContext() : nullptr;
63 }
64 #endif
65 
DrawPoint(const Point & point)66 void RSPaintFilterCanvasBase::DrawPoint(const Point& point)
67 {
68     if (canvas_ != nullptr && OnFilter()) {
69         canvas_->DrawPoint(point);
70     }
71 }
72 
DrawSdf(const SDFShapeBase & shape)73 void RSPaintFilterCanvasBase::DrawSdf(const SDFShapeBase& shape)
74 {
75     if (canvas_ != nullptr && OnFilter()) {
76         canvas_->DrawSdf(shape);
77     }
78 }
79 
DrawPoints(PointMode mode,size_t count,const Point pts[])80 void RSPaintFilterCanvasBase::DrawPoints(PointMode mode, size_t count, const Point pts[])
81 {
82     if (canvas_ != nullptr && OnFilter()) {
83         canvas_->DrawPoints(mode, count, pts);
84     }
85 }
86 
DrawLine(const Point & startPt,const Point & endPt)87 void RSPaintFilterCanvasBase::DrawLine(const Point& startPt, const Point& endPt)
88 {
89     if (canvas_ != nullptr && OnFilter()) {
90         canvas_->DrawLine(startPt, endPt);
91     }
92 }
93 
DrawRect(const Rect & rect)94 void RSPaintFilterCanvasBase::DrawRect(const Rect& rect)
95 {
96     if (canvas_ != nullptr && OnFilter()) {
97         canvas_->DrawRect(rect);
98     }
99 }
100 
DrawRoundRect(const RoundRect & roundRect)101 void RSPaintFilterCanvasBase::DrawRoundRect(const RoundRect& roundRect)
102 {
103     if (canvas_ != nullptr && OnFilter()) {
104         canvas_->DrawRoundRect(roundRect);
105     }
106 }
107 
DrawNestedRoundRect(const RoundRect & outer,const RoundRect & inner)108 void RSPaintFilterCanvasBase::DrawNestedRoundRect(const RoundRect& outer, const RoundRect& inner)
109 {
110     if (canvas_ != nullptr && OnFilter()) {
111         canvas_->DrawNestedRoundRect(outer, inner);
112     }
113 }
114 
DrawArc(const Rect & oval,scalar startAngle,scalar sweepAngle)115 void RSPaintFilterCanvasBase::DrawArc(const Rect& oval, scalar startAngle, scalar sweepAngle)
116 {
117     if (canvas_ != nullptr && OnFilter()) {
118         canvas_->DrawArc(oval, startAngle, sweepAngle);
119     }
120 }
121 
DrawPie(const Rect & oval,scalar startAngle,scalar sweepAngle)122 void RSPaintFilterCanvasBase::DrawPie(const Rect& oval, scalar startAngle, scalar sweepAngle)
123 {
124     if (canvas_ != nullptr && OnFilter()) {
125         canvas_->DrawPie(oval, startAngle, sweepAngle);
126     }
127 }
128 
DrawOval(const Rect & oval)129 void RSPaintFilterCanvasBase::DrawOval(const Rect& oval)
130 {
131     if (canvas_ != nullptr && OnFilter()) {
132         canvas_->DrawOval(oval);
133     }
134 }
135 
DrawCircle(const Point & centerPt,scalar radius)136 void RSPaintFilterCanvasBase::DrawCircle(const Point& centerPt, scalar radius)
137 {
138     if (canvas_ != nullptr && OnFilter()) {
139         canvas_->DrawCircle(centerPt, radius);
140     }
141 }
142 
DrawPath(const Path & path)143 void RSPaintFilterCanvasBase::DrawPath(const Path& path)
144 {
145     if (canvas_ != nullptr && OnFilter()) {
146         canvas_->DrawPath(path);
147     }
148 }
149 
DrawBackground(const Brush & brush)150 void RSPaintFilterCanvasBase::DrawBackground(const Brush& brush)
151 {
152     Brush b(brush);
153     if (canvas_ != nullptr && OnFilterWithBrush(b)) {
154         canvas_->DrawBackground(b);
155     }
156 }
157 
DrawShadow(const Path & path,const Point3 & planeParams,const Point3 & devLightPos,scalar lightRadius,Color ambientColor,Color spotColor,ShadowFlags flag)158 void RSPaintFilterCanvasBase::DrawShadow(const Path& path, const Point3& planeParams, const Point3& devLightPos,
159     scalar lightRadius, Color ambientColor, Color spotColor, ShadowFlags flag)
160 {
161     if (canvas_ != nullptr && OnFilter()) {
162         canvas_->DrawShadow(path, planeParams, devLightPos, lightRadius, ambientColor, spotColor, flag);
163     }
164 }
165 
DrawShadowStyle(const Path & path,const Point3 & planeParams,const Point3 & devLightPos,scalar lightRadius,Color ambientColor,Color spotColor,ShadowFlags flag,bool isLimitElevation)166 void RSPaintFilterCanvasBase::DrawShadowStyle(const Path& path, const Point3& planeParams, const Point3& devLightPos,
167     scalar lightRadius, Color ambientColor, Color spotColor, ShadowFlags flag, bool isLimitElevation)
168 {
169     if (canvas_ != nullptr && OnFilter()) {
170         canvas_->DrawShadowStyle(
171             path, planeParams, devLightPos, lightRadius, ambientColor, spotColor, flag, isLimitElevation);
172     }
173 }
174 
DrawColor(Drawing::ColorQuad color,Drawing::BlendMode mode)175 void RSPaintFilterCanvasBase::DrawColor(Drawing::ColorQuad color, Drawing::BlendMode mode)
176 {
177     if (canvas_ != nullptr && OnFilter()) {
178         canvas_->DrawColor(color, mode);
179     }
180 }
181 
DrawRegion(const Drawing::Region & region)182 void RSPaintFilterCanvasBase::DrawRegion(const Drawing::Region& region)
183 {
184     if (canvas_ != nullptr && OnFilter()) {
185         canvas_->DrawRegion(region);
186     }
187 }
188 
DrawPatch(const Drawing::Point cubics[12],const Drawing::ColorQuad colors[4],const Drawing::Point texCoords[4],Drawing::BlendMode mode)189 void RSPaintFilterCanvasBase::DrawPatch(const Drawing::Point cubics[12], const Drawing::ColorQuad colors[4],
190     const Drawing::Point texCoords[4], Drawing::BlendMode mode)
191 {
192     if (canvas_ != nullptr && OnFilter()) {
193         canvas_->DrawPatch(cubics, colors, texCoords, mode);
194     }
195 }
196 
DrawVertices(const Drawing::Vertices & vertices,Drawing::BlendMode mode)197 void RSPaintFilterCanvasBase::DrawVertices(const Drawing::Vertices& vertices, Drawing::BlendMode mode)
198 {
199     if (canvas_ != nullptr && OnFilter()) {
200         canvas_->DrawVertices(vertices, mode);
201     }
202 }
203 
OpCalculateBefore(const Matrix & matrix)204 bool RSPaintFilterCanvasBase::OpCalculateBefore(const Matrix& matrix)
205 {
206     if (canvas_ != nullptr && OnFilter()) {
207         return canvas_->OpCalculateBefore(matrix);
208     }
209     return false;
210 }
211 
OpCalculateAfter(const Drawing::Rect & bound)212 std::shared_ptr<Drawing::OpListHandle> RSPaintFilterCanvasBase::OpCalculateAfter(const Drawing::Rect& bound)
213 {
214     if (canvas_ != nullptr && OnFilter()) {
215         return canvas_->OpCalculateAfter(bound);
216     }
217     return nullptr;
218 }
219 
DrawAtlas(const Drawing::Image * atlas,const Drawing::RSXform xform[],const Drawing::Rect tex[],const Drawing::ColorQuad colors[],int count,Drawing::BlendMode mode,const Drawing::SamplingOptions & sampling,const Drawing::Rect * cullRect)220 void RSPaintFilterCanvasBase::DrawAtlas(const Drawing::Image* atlas, const Drawing::RSXform xform[],
221     const Drawing::Rect tex[], const Drawing::ColorQuad colors[], int count, Drawing::BlendMode mode,
222     const Drawing::SamplingOptions& sampling, const Drawing::Rect* cullRect)
223 {
224     if (canvas_ != nullptr && OnFilter()) {
225         canvas_->DrawAtlas(atlas, xform, tex, colors, count, mode, sampling, cullRect);
226     }
227 }
228 
DrawBitmap(const Bitmap & bitmap,const scalar px,const scalar py)229 void RSPaintFilterCanvasBase::DrawBitmap(const Bitmap& bitmap, const scalar px, const scalar py)
230 {
231     if (canvas_ != nullptr && OnFilter()) {
232         canvas_->DrawBitmap(bitmap, px, py);
233     }
234 }
235 
DrawImageNine(const Drawing::Image * image,const Drawing::RectI & center,const Drawing::Rect & dst,Drawing::FilterMode filter,const Drawing::Brush * brush)236 void RSPaintFilterCanvasBase::DrawImageNine(const Drawing::Image* image, const Drawing::RectI& center,
237     const Drawing::Rect& dst, Drawing::FilterMode filter, const Drawing::Brush* brush)
238 {
239     if (canvas_ != nullptr && OnFilter()) {
240         if (brush) {
241             Drawing::Brush b(*brush);
242             OnFilterWithBrush(b);
243             canvas_->DrawImageNine(image, center, dst, filter, &b);
244         } else {
245             canvas_->DrawImageNine(image, center, dst, filter, GetFilteredBrush());
246         }
247     }
248 }
249 
DrawImageLattice(const Drawing::Image * image,const Drawing::Lattice & lattice,const Drawing::Rect & dst,Drawing::FilterMode filter)250 void RSPaintFilterCanvasBase::DrawImageLattice(const Drawing::Image* image, const Drawing::Lattice& lattice,
251     const Drawing::Rect& dst, Drawing::FilterMode filter)
252 {
253     if (canvas_ != nullptr && OnFilter()) {
254         canvas_->DrawImageLattice(image, lattice, dst, filter);
255     }
256 }
257 
DrawImage(const Image & image,const scalar px,const scalar py,const SamplingOptions & sampling)258 void RSPaintFilterCanvasBase::DrawImage(
259     const Image& image, const scalar px, const scalar py, const SamplingOptions& sampling)
260 {
261     if (canvas_ != nullptr && OnFilter()) {
262         canvas_->DrawImage(image, px, py, sampling);
263     }
264 }
265 
DrawImageRect(const Image & image,const Rect & src,const Rect & dst,const SamplingOptions & sampling,SrcRectConstraint constraint)266 void RSPaintFilterCanvasBase::DrawImageRect(const Image& image, const Rect& src, const Rect& dst,
267     const SamplingOptions& sampling, SrcRectConstraint constraint)
268 {
269     if (canvas_ != nullptr && OnFilter()) {
270         canvas_->DrawImageRect(image, src, dst, sampling, constraint);
271     }
272 }
273 
DrawImageRect(const Image & image,const Rect & dst,const SamplingOptions & sampling)274 void RSPaintFilterCanvasBase::DrawImageRect(const Image& image, const Rect& dst, const SamplingOptions& sampling)
275 {
276     if (canvas_ != nullptr && OnFilter()) {
277         canvas_->DrawImageRect(image, dst, sampling);
278     }
279 }
280 
DrawPicture(const Picture & picture)281 void RSPaintFilterCanvasBase::DrawPicture(const Picture& picture)
282 {
283     if (canvas_ != nullptr && OnFilter()) {
284         canvas_->DrawPicture(picture);
285     }
286 }
287 
DrawTextBlob(const Drawing::TextBlob * blob,const Drawing::scalar x,const Drawing::scalar y)288 void RSPaintFilterCanvasBase::DrawTextBlob(
289     const Drawing::TextBlob* blob, const Drawing::scalar x, const Drawing::scalar y)
290 {
291     if (canvas_ != nullptr && OnFilter()) {
292         canvas_->DrawTextBlob(blob, x, y);
293     }
294 }
295 
ClipRect(const Drawing::Rect & rect,Drawing::ClipOp op,bool doAntiAlias)296 void RSPaintFilterCanvasBase::ClipRect(const Drawing::Rect& rect, Drawing::ClipOp op, bool doAntiAlias)
297 {
298     if (canvas_ != nullptr) {
299         canvas_->ClipRect(rect, op, doAntiAlias);
300     }
301 }
302 
ClipIRect(const Drawing::RectI & rect,Drawing::ClipOp op)303 void RSPaintFilterCanvasBase::ClipIRect(const Drawing::RectI& rect, Drawing::ClipOp op)
304 {
305     if (canvas_ != nullptr) {
306         canvas_->ClipIRect(rect, op);
307     }
308 }
309 
ClipRoundRect(const RoundRect & roundRect,ClipOp op,bool doAntiAlias)310 void RSPaintFilterCanvasBase::ClipRoundRect(const RoundRect& roundRect, ClipOp op, bool doAntiAlias)
311 {
312     if (canvas_ != nullptr) {
313         canvas_->ClipRoundRect(roundRect, op, doAntiAlias);
314     }
315 }
316 
ClipRoundRect(const Drawing::Rect & rect,std::vector<Drawing::Point> & pts,bool doAntiAlias)317 void RSPaintFilterCanvasBase::ClipRoundRect(const Drawing::Rect& rect,
318     std::vector<Drawing::Point>& pts, bool doAntiAlias)
319 {
320     if (canvas_ != nullptr) {
321         canvas_->ClipRoundRect(rect, pts, doAntiAlias);
322     }
323 }
324 
ClipPath(const Path & path,ClipOp op,bool doAntiAlias)325 void RSPaintFilterCanvasBase::ClipPath(const Path& path, ClipOp op, bool doAntiAlias)
326 {
327     if (canvas_ != nullptr) {
328         canvas_->ClipPath(path, op, doAntiAlias);
329     }
330 }
331 
ClipRegion(const Region & region,ClipOp op)332 void RSPaintFilterCanvasBase::ClipRegion(const Region& region, ClipOp op)
333 {
334     if (canvas_ != nullptr) {
335         canvas_->ClipRegion(region, op);
336     }
337 }
338 
SetMatrix(const Matrix & matrix)339 void RSPaintFilterCanvasBase::SetMatrix(const Matrix& matrix)
340 {
341     if (canvas_ != nullptr) {
342         canvas_->SetMatrix(matrix);
343     }
344 }
345 
ResetMatrix()346 void RSPaintFilterCanvasBase::ResetMatrix()
347 {
348     if (canvas_ != nullptr) {
349         canvas_->ResetMatrix();
350     }
351 }
352 
ConcatMatrix(const Matrix & matrix)353 void RSPaintFilterCanvasBase::ConcatMatrix(const Matrix& matrix)
354 {
355     if (canvas_ != nullptr) {
356         canvas_->ConcatMatrix(matrix);
357     }
358 }
359 
Translate(scalar dx,scalar dy)360 void RSPaintFilterCanvasBase::Translate(scalar dx, scalar dy)
361 {
362     if (canvas_ != nullptr) {
363         canvas_->Translate(dx, dy);
364     }
365 }
366 
Scale(scalar sx,scalar sy)367 void RSPaintFilterCanvasBase::Scale(scalar sx, scalar sy)
368 {
369     if (canvas_ != nullptr) {
370         canvas_->Scale(sx, sy);
371     }
372 }
373 
Rotate(scalar deg,scalar sx,scalar sy)374 void RSPaintFilterCanvasBase::Rotate(scalar deg, scalar sx, scalar sy)
375 {
376     if (canvas_ != nullptr) {
377         canvas_->Rotate(deg, sx, sy);
378     }
379 }
380 
Shear(scalar sx,scalar sy)381 void RSPaintFilterCanvasBase::Shear(scalar sx, scalar sy)
382 {
383     if (canvas_ != nullptr) {
384         canvas_->Shear(sx, sy);
385     }
386 }
387 
Flush()388 void RSPaintFilterCanvasBase::Flush()
389 {
390     if (canvas_ != nullptr) {
391         canvas_->Flush();
392     }
393 }
394 
Clear(ColorQuad color)395 void RSPaintFilterCanvasBase::Clear(ColorQuad color)
396 {
397     if (canvas_ != nullptr) {
398         canvas_->Clear(color);
399     }
400 }
401 
Save()402 uint32_t RSPaintFilterCanvasBase::Save()
403 {
404     if (canvas_ != nullptr) {
405         return canvas_->Save();
406     }
407     return 0;
408 }
409 
SaveLayer(const SaveLayerOps & saveLayerRec)410 void RSPaintFilterCanvasBase::SaveLayer(const SaveLayerOps& saveLayerRec)
411 {
412     if (canvas_ == nullptr) {
413         return;
414     }
415     Brush brush;
416     if (saveLayerRec.GetBrush() != nullptr) {
417         brush = *saveLayerRec.GetBrush();
418         OnFilterWithBrush(brush);
419     }
420     SaveLayerOps slo(saveLayerRec.GetBounds(), &brush, saveLayerRec.GetSaveLayerFlags());
421     canvas_->SaveLayer(slo);
422 }
423 
Restore()424 void RSPaintFilterCanvasBase::Restore()
425 {
426     if (canvas_ != nullptr) {
427         canvas_->Restore();
428     }
429 }
430 
Discard()431 void RSPaintFilterCanvasBase::Discard()
432 {
433     if (canvas_ != nullptr) {
434         canvas_->Discard();
435     }
436 }
437 
AttachPen(const Pen & pen)438 CoreCanvas& RSPaintFilterCanvasBase::AttachPen(const Pen& pen)
439 {
440     if (canvas_ != nullptr) {
441         canvas_->AttachPen(pen);
442     }
443     return *this;
444 }
445 
AttachBrush(const Brush & brush)446 CoreCanvas& RSPaintFilterCanvasBase::AttachBrush(const Brush& brush)
447 {
448     if (canvas_ != nullptr) {
449         canvas_->AttachBrush(brush);
450     }
451     return *this;
452 }
453 
AttachPaint(const Drawing::Paint & paint)454 CoreCanvas& RSPaintFilterCanvasBase::AttachPaint(const Drawing::Paint& paint)
455 {
456     if (canvas_ != nullptr) {
457         canvas_->AttachPaint(paint);
458     }
459     return *this;
460 }
461 
DetachPen()462 CoreCanvas& RSPaintFilterCanvasBase::DetachPen()
463 {
464     if (canvas_ != nullptr) {
465         canvas_->DetachPen();
466     }
467     return *this;
468 }
469 
DetachBrush()470 CoreCanvas& RSPaintFilterCanvasBase::DetachBrush()
471 {
472     if (canvas_ != nullptr) {
473         canvas_->DetachBrush();
474     }
475     return *this;
476 }
477 
DetachPaint()478 CoreCanvas& RSPaintFilterCanvasBase::DetachPaint()
479 {
480     if (canvas_ != nullptr) {
481         canvas_->DetachPaint();
482     }
483     return *this;
484 }
485 
DrawBlurImage(const Drawing::Image & image,const Drawing::HpsBlurParameter & blurParams)486 bool RSPaintFilterCanvasBase::DrawBlurImage(const Drawing::Image& image, const Drawing::HpsBlurParameter& blurParams)
487 {
488     bool result = false;
489     if (canvas_ != nullptr) {
490         result = canvas_->DrawBlurImage(image, blurParams);
491     }
492     return result;
493 }
494 
CalcHpsBluredImageDimension(const Drawing::HpsBlurParameter & blurParams)495 std::array<int, 2> RSPaintFilterCanvasBase::CalcHpsBluredImageDimension(const Drawing::HpsBlurParameter& blurParams)
496 {
497     std::array<int, 2> result = {0, 0}; // There are 2 variables
498     if (canvas_ != nullptr) {
499         result = canvas_->CalcHpsBluredImageDimension(blurParams);
500     }
501     return result;
502 }
503 
RSPaintFilterCanvas(Drawing::Canvas * canvas,float alpha)504 RSPaintFilterCanvas::RSPaintFilterCanvas(Drawing::Canvas* canvas, float alpha)
505     : RSPaintFilterCanvasBase(canvas), alphaStack_({ 1.0f }),
506       envStack_({ Env { .envForegroundColor_ = RSColor(0xFF000000), .hasOffscreenLayer_ = false } })
507 {
508     (void)alpha; // alpha is no longer used, but we keep it for backward compatibility
509 }
510 
RSPaintFilterCanvas(Drawing::Surface * surface,float alpha)511 RSPaintFilterCanvas::RSPaintFilterCanvas(Drawing::Surface* surface, float alpha)
512     : RSPaintFilterCanvasBase(surface ? surface->GetCanvas().get() : nullptr), surface_(surface), alphaStack_({ 1.0f }),
513       envStack_({ Env { .envForegroundColor_ = RSColor(0xFF000000), .hasOffscreenLayer_ = false } })
514 {
515     (void)alpha; // alpha is no longer used, but we keep it for backward compatibility
516 }
517 
GetSurface() const518 Drawing::Surface* RSPaintFilterCanvas::GetSurface() const
519 {
520     return surface_;
521 }
522 
AttachPen(const Pen & pen)523 CoreCanvas& RSPaintFilterCanvas::AttachPen(const Pen& pen)
524 {
525     if (canvas_ == nullptr) {
526         return *this;
527     }
528 
529     Pen p(pen);
530     if (p.GetColor() == 0x00000001) { // foreground color and foreground color strategy identification
531         p.SetColor(envStack_.top().envForegroundColor_.AsArgbInt());
532     }
533 
534     // use alphaStack_.top() to multiply alpha
535     if (alphaStack_.top() < 1 && alphaStack_.top() > 0) {
536         p.SetAlpha(p.GetAlpha() * alphaStack_.top());
537     }
538 
539     // use envStack_.top().blender_ to set blender
540     if (auto& blender = envStack_.top().blender_) {
541         if (p.GetBlenderEnabled()) {
542             p.SetBlender(blender);
543         }
544     }
545 
546     canvas_->AttachPen(p);
547     return *this;
548 }
549 
AttachBrush(const Brush & brush)550 CoreCanvas& RSPaintFilterCanvas::AttachBrush(const Brush& brush)
551 {
552     if (canvas_ == nullptr) {
553         return *this;
554     }
555 
556     Brush b(brush);
557     if (b.GetColor() == 0x00000001) { // foreground color and foreground color strategy identification
558         b.SetColor(envStack_.top().envForegroundColor_.AsArgbInt());
559     }
560 
561     // use alphaStack_.top() to multiply alpha
562     if (alphaStack_.top() < 1 && alphaStack_.top() > 0) {
563         b.SetAlpha(b.GetAlpha() * alphaStack_.top());
564     }
565 
566     // use envStack_.top().blender_ to set blender
567     if (auto& blender = envStack_.top().blender_) {
568         if (b.GetBlenderEnabled()) {
569             b.SetBlender(blender);
570         }
571     }
572 
573     canvas_->AttachBrush(b);
574     return *this;
575 }
576 
AttachPaint(const Drawing::Paint & paint)577 CoreCanvas& RSPaintFilterCanvas::AttachPaint(const Drawing::Paint& paint)
578 {
579     if (canvas_ == nullptr) {
580         return *this;
581     }
582 
583     Paint p(paint);
584     if (p.GetColor() == 0x00000001) { // foreground color and foreground color strategy identification
585         p.SetColor(envStack_.top().envForegroundColor_.AsArgbInt());
586     }
587 
588     // use alphaStack_.top() to multiply alpha
589     if (alphaStack_.top() < 1 && alphaStack_.top() > 0) {
590         p.SetAlpha(p.GetAlpha() * alphaStack_.top());
591     }
592 
593     // use envStack_.top().blender_ to set blender
594     if (auto& blender = envStack_.top().blender_) {
595         if (p.GetBlenderEnabled()) {
596             p.SetBlender(blender);
597         }
598     }
599 
600     canvas_->AttachPaint(p);
601     return *this;
602 }
603 
OnFilter() const604 bool RSPaintFilterCanvas::OnFilter() const
605 {
606     return alphaStack_.top() > 0.f;
607 }
608 
GetRecordingCanvas() const609 Drawing::Canvas* RSPaintFilterCanvas::GetRecordingCanvas() const
610 {
611     return recordingState_ ? canvas_ : nullptr;
612 }
613 
GetRecordingState() const614 bool RSPaintFilterCanvas::GetRecordingState() const
615 {
616     return recordingState_;
617 }
618 
SetRecordingState(bool flag)619 void RSPaintFilterCanvas::SetRecordingState(bool flag)
620 {
621     recordingState_ = flag;
622 }
623 
MultiplyAlpha(float alpha)624 void RSPaintFilterCanvas::MultiplyAlpha(float alpha)
625 {
626     // multiply alpha to top of stack
627     alphaStack_.top() *= std::clamp(alpha, 0.f, 1.f);
628 }
629 
SetAlpha(float alpha)630 void RSPaintFilterCanvas::SetAlpha(float alpha)
631 {
632     alphaStack_.top() = std::clamp(alpha, 0.f, 1.f);
633 }
634 
SaveAlpha()635 int RSPaintFilterCanvas::SaveAlpha()
636 {
637     // make a copy of top of stack
638     alphaStack_.push(alphaStack_.top());
639     // return prev stack height
640     return alphaStack_.size() - 1;
641 }
642 
GetAlpha() const643 float RSPaintFilterCanvas::GetAlpha() const
644 {
645     // return top of stack
646     return alphaStack_.top();
647 }
648 
RestoreAlpha()649 void RSPaintFilterCanvas::RestoreAlpha()
650 {
651     // sanity check, stack should not be empty
652     if (alphaStack_.size() <= 1u) {
653         return;
654     }
655     alphaStack_.pop();
656 }
657 
GetAlphaSaveCount() const658 int RSPaintFilterCanvas::GetAlphaSaveCount() const
659 {
660     return alphaStack_.size();
661 }
662 
RestoreAlphaToCount(int count)663 void RSPaintFilterCanvas::RestoreAlphaToCount(int count)
664 {
665     // sanity check, stack should not be empty
666     if (count < 1) {
667         count = 1;
668     }
669     // poo stack until stack height equals count
670     int n = static_cast<int>(alphaStack_.size()) - count;
671     for (int i = 0; i < n; ++i) {
672         alphaStack_.pop();
673     }
674 }
675 
SetBlendMode(std::optional<int> blendMode)676 void RSPaintFilterCanvas::SetBlendMode(std::optional<int> blendMode)
677 {
678     std::shared_ptr<Drawing::Blender> blender = nullptr;
679     if (blendMode) {
680         // map blendMode to Drawing::BlendMode and convert to Blender
681         blender = Drawing::Blender::CreateWithBlendMode(static_cast<Drawing::BlendMode>(*blendMode));
682     }
683     RSPaintFilterCanvas::SetBlender(blender);
684 }
685 
SetBlender(std::shared_ptr<Drawing::Blender> blender)686 void RSPaintFilterCanvas::SetBlender(std::shared_ptr<Drawing::Blender> blender)
687 {
688     envStack_.top().blender_ = blender;
689 }
690 
SaveEnv()691 int RSPaintFilterCanvas::SaveEnv()
692 {
693     // make a copy of top of stack
694     envStack_.push(envStack_.top());
695     // return prev stack height
696     return envStack_.size() - 1;
697 }
698 
RestoreEnv()699 void RSPaintFilterCanvas::RestoreEnv()
700 {
701     // sanity check, stack should not be empty
702     if (envStack_.size() <= 1) {
703         return;
704     }
705     envStack_.pop();
706 }
707 
RestoreEnvToCount(int count)708 void RSPaintFilterCanvas::RestoreEnvToCount(int count)
709 {
710     // sanity check, stack should not be empty
711     if (count < 1) {
712         count = 1;
713     }
714     // poo stack until stack height equals count
715     int n = static_cast<int>(envStack_.size()) - count;
716     for (int i = 0; i < n; ++i) {
717         envStack_.pop();
718     }
719 }
720 
GetEnvSaveCount() const721 int RSPaintFilterCanvas::GetEnvSaveCount() const
722 {
723     return envStack_.size();
724 }
725 
SetEnvForegroundColor(Rosen::RSColor color)726 void RSPaintFilterCanvas::SetEnvForegroundColor(Rosen::RSColor color)
727 {
728     // sanity check, stack should not be empty
729     if (envStack_.empty()) {
730         return;
731     }
732     envStack_.top().envForegroundColor_ = color;
733 }
734 
GetEnvForegroundColor() const735 Drawing::ColorQuad RSPaintFilterCanvas::GetEnvForegroundColor() const
736 {
737     // sanity check, stack should not be empty
738     if (envStack_.empty()) {
739         return Drawing::Color::COLOR_BLACK; // 0xFF000000 is default value -- black
740     }
741     return envStack_.top().envForegroundColor_.AsArgbInt();
742 }
743 
SaveAllStatus(SaveType type)744 RSPaintFilterCanvas::SaveStatus RSPaintFilterCanvas::SaveAllStatus(SaveType type)
745 {
746     // save and return status on demand
747     return { (RSPaintFilterCanvas::kCanvas & type) ? Save() : GetSaveCount(),
748         (RSPaintFilterCanvas::kAlpha & type) ? SaveAlpha() : GetAlphaSaveCount(),
749         (RSPaintFilterCanvas::kEnv & type) ? SaveEnv() : GetEnvSaveCount() };
750 }
751 
GetSaveStatus() const752 RSPaintFilterCanvas::SaveStatus RSPaintFilterCanvas::GetSaveStatus() const
753 {
754     return { GetSaveCount(), GetAlphaSaveCount(), GetEnvSaveCount() };
755 }
756 
RestoreStatus(const SaveStatus & status)757 void RSPaintFilterCanvas::RestoreStatus(const SaveStatus& status)
758 {
759     // simultaneously restore canvas and alpha
760     RestoreToCount(status.canvasSaveCount);
761     RestoreAlphaToCount(status.alphaSaveCount);
762     RestoreEnvToCount(status.envSaveCount);
763 }
764 
PushDirtyRegion(Drawing::Region & resultRegion)765 void RSPaintFilterCanvas::PushDirtyRegion(Drawing::Region& resultRegion)
766 {
767     dirtyRegionStack_.push(std::move(resultRegion));
768 }
769 
PopDirtyRegion()770 void RSPaintFilterCanvas::PopDirtyRegion()
771 {
772     if (dirtyRegionStack_.empty()) {
773         RS_LOGW("PopDirtyRegion dirtyRegionStack_ is empty");
774         return;
775     }
776     dirtyRegionStack_.pop();
777 }
778 
GetCurDirtyRegion()779 Drawing::Region& RSPaintFilterCanvas::GetCurDirtyRegion()
780 {
781     return dirtyRegionStack_.top();
782 }
783 
IsDirtyRegionStackEmpty()784 bool RSPaintFilterCanvas::IsDirtyRegionStackEmpty()
785 {
786     return dirtyRegionStack_.empty();
787 }
788 
CopyHDRConfiguration(const RSPaintFilterCanvas & other)789 void RSPaintFilterCanvas::CopyHDRConfiguration(const RSPaintFilterCanvas& other)
790 {
791     brightnessRatio_ = other.brightnessRatio_;
792     screenId_ = other.screenId_;
793     targetColorGamut_ = other.targetColorGamut_;
794 }
795 
CopyConfigurationToOffscreenCanvas(const RSPaintFilterCanvas & other)796 void RSPaintFilterCanvas::CopyConfigurationToOffscreenCanvas(const RSPaintFilterCanvas& other)
797 {
798     // Note:
799     // 1. we don't need to copy alpha status, alpha will be applied when drawing cache.
800     // 2. This function should only be called when creating offscreen canvas.
801     // copy high contrast flag
802     isHighContrastEnabled_.store(other.isHighContrastEnabled_.load());
803     // copy env
804     envStack_.top() = other.envStack_.top();
805     // update effect matrix
806     auto effectData = other.envStack_.top().effectData_;
807     if (effectData != nullptr) {
808         // make a deep copy of effect data, and calculate the mapping matrix from
809         // local coordinate system to global coordinate system.
810         auto copiedEffectData = std::make_shared<CachedEffectData>(*effectData);
811         if (copiedEffectData == nullptr) {
812             ROSEN_LOGE("RSPaintFilterCanvas::CopyConfigurationToOffscreenCanvas fail to create effectData");
813             return;
814         }
815         Drawing::Matrix inverse;
816         if (other.GetTotalMatrix().Invert(inverse)) {
817             copiedEffectData->cachedMatrix_.PostConcat(inverse);
818         } else {
819             ROSEN_LOGE("RSPaintFilterCanvas::CopyConfigurationToOffscreenCanvas get invert matrix failed!");
820         }
821         envStack_.top().effectData_ = copiedEffectData;
822     }
823     // cache related
824     if (other.isHighContrastEnabled()) {
825         // explicit disable cache for high contrast mode
826         SetCacheType(RSPaintFilterCanvas::CacheType::DISABLED);
827     } else {
828         // planning: maybe we should copy source cache status
829         SetCacheType(other.GetCacheType());
830     }
831     isParallelCanvas_ = other.isParallelCanvas_;
832     disableFilterCache_ = other.disableFilterCache_;
833     threadIndex_ = other.threadIndex_;
834 }
835 
SetHighContrast(bool enabled)836 void RSPaintFilterCanvas::SetHighContrast(bool enabled)
837 {
838     isHighContrastEnabled_ = enabled;
839 }
isHighContrastEnabled() const840 bool RSPaintFilterCanvas::isHighContrastEnabled() const
841 {
842     return isHighContrastEnabled_;
843 }
844 
SetCacheType(CacheType type)845 void RSPaintFilterCanvas::SetCacheType(CacheType type)
846 {
847     cacheType_ = type;
848 }
GetCacheType() const849 Drawing::CacheType RSPaintFilterCanvas::GetCacheType() const
850 {
851     return cacheType_;
852 }
853 
SetVisibleRect(Drawing::Rect visibleRect)854 void RSPaintFilterCanvas::SetVisibleRect(Drawing::Rect visibleRect)
855 {
856     visibleRect_ = visibleRect;
857 }
858 
GetVisibleRect() const859 Drawing::Rect RSPaintFilterCanvas::GetVisibleRect() const
860 {
861     return visibleRect_;
862 }
863 
GetLocalClipBounds(const Drawing::Canvas & canvas,const Drawing::RectI * clipRect)864 std::optional<Drawing::Rect> RSPaintFilterCanvas::GetLocalClipBounds(const Drawing::Canvas& canvas,
865     const Drawing::RectI* clipRect)
866 {
867     // if clipRect is explicitly specified, use it as the device clip bounds
868     Drawing::Rect bounds = Rect((clipRect != nullptr) ? *clipRect : canvas.GetDeviceClipBounds());
869 
870     if (!bounds.IsValid()) {
871         return std::nullopt;
872     }
873 
874     Drawing::Matrix inverse;
875     // if we can't invert the CTM, we can't return local clip bounds
876     if (!(canvas.GetTotalMatrix().Invert(inverse))) {
877         return std::nullopt;
878     }
879     // return the inverse of the CTM applied to the device clip bounds as local clip bounds
880     Drawing::Rect dst;
881     inverse.MapRect(dst, bounds);
882     return dst;
883 }
884 
885 
SetEffectData(const std::shared_ptr<RSPaintFilterCanvas::CachedEffectData> & effectData)886 void RSPaintFilterCanvas::SetEffectData(const std::shared_ptr<RSPaintFilterCanvas::CachedEffectData>& effectData)
887 {
888     envStack_.top().effectData_ = effectData;
889 }
890 
GetEffectData() const891 const std::shared_ptr<RSPaintFilterCanvas::CachedEffectData>& RSPaintFilterCanvas::GetEffectData() const
892 {
893     return envStack_.top().effectData_;
894 }
895 
SetBehindWindowData(const std::shared_ptr<RSPaintFilterCanvas::CachedEffectData> & behindWindowData)896 void RSPaintFilterCanvas::SetBehindWindowData(
897     const std::shared_ptr<RSPaintFilterCanvas::CachedEffectData>& behindWindowData)
898 {
899     envStack_.top().behindWindowData_ = behindWindowData;
900 }
901 
GetBehindWindowData() const902 const std::shared_ptr<RSPaintFilterCanvas::CachedEffectData>& RSPaintFilterCanvas::GetBehindWindowData() const
903 {
904     return envStack_.top().behindWindowData_;
905 }
906 
ReplaceMainScreenData(std::shared_ptr<Drawing::Surface> & offscreenSurface,std::shared_ptr<RSPaintFilterCanvas> & offscreenCanvas)907 void RSPaintFilterCanvas::ReplaceMainScreenData(std::shared_ptr<Drawing::Surface>& offscreenSurface,
908     std::shared_ptr<RSPaintFilterCanvas>& offscreenCanvas)
909 {
910     if (offscreenSurface != nullptr && offscreenCanvas != nullptr) {
911         storeMainScreenSurface_.push(surface_);
912         storeMainScreenCanvas_.push(canvas_);
913         surface_ = offscreenSurface.get();
914         canvas_ = offscreenCanvas.get();
915         OffscreenData offscreenData = {offscreenSurface, offscreenCanvas};
916         offscreenDataList_.push(offscreenData);
917     }
918 }
919 
SwapBackMainScreenData()920 void RSPaintFilterCanvas::SwapBackMainScreenData()
921 {
922     if (!storeMainScreenSurface_.empty() && !storeMainScreenCanvas_.empty() && !offscreenDataList_.empty()) {
923         surface_ = storeMainScreenSurface_.top();
924         canvas_ = storeMainScreenCanvas_.top();
925         storeMainScreenSurface_.pop();
926         storeMainScreenCanvas_.pop();
927         offscreenDataList_.pop();
928     }
929 }
930 
SavePCanvasList()931 void RSPaintFilterCanvas::SavePCanvasList()
932 {
933     storedPCanvasList_.push_back(pCanvasList_);
934 }
935 
RestorePCanvasList()936 void RSPaintFilterCanvas::RestorePCanvasList()
937 {
938     if (!storedPCanvasList_.empty()) {
939         auto item = storedPCanvasList_.back();
940         pCanvasList_.swap(item);
941         storedPCanvasList_.pop_back();
942     }
943 }
944 
SetCanvasStatus(const CanvasStatus & status)945 void RSPaintFilterCanvas::SetCanvasStatus(const CanvasStatus& status)
946 {
947     SetAlpha(status.alpha_);
948     SetMatrix(status.matrix_);
949     SetEffectData(status.effectData_);
950 }
951 
GetCanvasStatus() const952 RSPaintFilterCanvas::CanvasStatus RSPaintFilterCanvas::GetCanvasStatus() const
953 {
954     return { GetAlpha(), GetTotalMatrix(), GetEffectData() };
955 }
956 
CachedEffectData(std::shared_ptr<Drawing::Image> && image,const Drawing::RectI & rect)957 RSPaintFilterCanvas::CachedEffectData::CachedEffectData(std::shared_ptr<Drawing::Image>&& image,
958     const Drawing::RectI& rect)
959     : cachedImage_(image), cachedRect_(rect), cachedMatrix_(Drawing::Matrix())
960 {}
961 
SetIsParallelCanvas(bool isParallel)962 void RSPaintFilterCanvas::SetIsParallelCanvas(bool isParallel)
963 {
964     isParallelCanvas_ = isParallel;
965 }
966 
GetIsParallelCanvas() const967 bool RSPaintFilterCanvas::GetIsParallelCanvas() const
968 {
969     return isParallelCanvas_;
970 }
971 
972 // UNI_MAIN_THREAD_INDEX, UNI_RENDER_THREAD_INDEX, subthread 0 1 2.
SetParallelThreadIdx(uint32_t idx)973 void RSPaintFilterCanvas::SetParallelThreadIdx(uint32_t idx)
974 {
975     threadIndex_ = idx;
976 }
977 
GetParallelThreadIdx() const978 uint32_t RSPaintFilterCanvas::GetParallelThreadIdx() const
979 {
980     return threadIndex_;
981 }
982 
SetDisableFilterCache(bool disable)983 void RSPaintFilterCanvas::SetDisableFilterCache(bool disable)
984 {
985     disableFilterCache_ = disable;
986 }
987 
GetDisableFilterCache() const988 bool RSPaintFilterCanvas::GetDisableFilterCache() const
989 {
990     return disableFilterCache_;
991 }
992 
SetRecordDrawable(bool enable)993 void RSPaintFilterCanvas::SetRecordDrawable(bool enable)
994 {
995     recordDrawable_ = enable;
996 }
997 
GetRecordDrawable() const998 bool RSPaintFilterCanvas::GetRecordDrawable() const
999 {
1000     return recordDrawable_;
1001 }
HasOffscreenLayer() const1002 bool RSPaintFilterCanvas::HasOffscreenLayer() const
1003 {
1004     return envStack_.top().hasOffscreenLayer_;
1005 }
SaveLayer(const Drawing::SaveLayerOps & saveLayerOps)1006 void RSPaintFilterCanvas::SaveLayer(const Drawing::SaveLayerOps& saveLayerOps)
1007 {
1008     envStack_.top().hasOffscreenLayer_ = true;
1009     RSPaintFilterCanvasBase::SaveLayer(saveLayerOps);
1010 }
1011 
IsCapture() const1012 bool RSPaintFilterCanvas::IsCapture() const
1013 {
1014     return isCapture_;
1015 }
SetCapture(bool isCapture)1016 void RSPaintFilterCanvas::SetCapture(bool isCapture)
1017 {
1018     isCapture_ = isCapture;
1019 }
1020 
GetScreenId() const1021 ScreenId RSPaintFilterCanvas::GetScreenId() const
1022 {
1023     return screenId_;
1024 }
1025 
SetScreenId(ScreenId screenId)1026 void RSPaintFilterCanvas::SetScreenId(ScreenId screenId)
1027 {
1028     screenId_ = screenId;
1029 }
1030 
GetTargetColorGamut() const1031 GraphicColorGamut RSPaintFilterCanvas::GetTargetColorGamut() const
1032 {
1033     return targetColorGamut_;
1034 }
1035 
SetTargetColorGamut(GraphicColorGamut colorGamut)1036 void RSPaintFilterCanvas::SetTargetColorGamut(GraphicColorGamut colorGamut)
1037 {
1038     targetColorGamut_ = colorGamut;
1039 }
1040 
GetBrightnessRatio() const1041 float RSPaintFilterCanvas::GetBrightnessRatio() const
1042 {
1043     return brightnessRatio_;
1044 }
1045 
SetBrightnessRatio(float brightnessRatio)1046 void RSPaintFilterCanvas::SetBrightnessRatio(float brightnessRatio)
1047 {
1048     brightnessRatio_ = brightnessRatio;
1049 }
1050 } // namespace Rosen
1051 } // namespace OHOS
1052