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