• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef USE_ROSEN_DRAWING
21 #include "include/core/SkColorFilter.h"
22 #endif
23 
24 namespace OHOS {
25 namespace Rosen {
26 
27 #ifdef USE_ROSEN_DRAWING
28 using namespace Drawing;
29 
RSPaintFilterCanvasBase(Drawing::Canvas * canvas)30 RSPaintFilterCanvasBase::RSPaintFilterCanvasBase(Drawing::Canvas* canvas)
31     : Canvas(canvas->GetWidth(), canvas->GetHeight()), canvas_(canvas)
32 {
33     if (canvas_) {
34         auto rectI = canvas_->GetDeviceClipBounds();
35         this->ClipRect({ rectI.GetLeft(), rectI.GetTop(), rectI.GetRight(), rectI.GetBottom() },
36             Drawing::ClipOp::INTERSECT, false);
37         this->SetMatrix(canvas_->GetTotalMatrix());
38     }
39 }
40 
41 #ifdef ACE_ENABLE_GPU
GetGPUContext() const42 std::shared_ptr<Drawing::GPUContext> RSPaintFilterCanvasBase::GetGPUContext() const
43 {
44     return canvas_ != nullptr ? canvas_->GetGPUContext() : nullptr;
45 }
46 #endif
47 
DrawPoint(const Point & point)48 void RSPaintFilterCanvasBase::DrawPoint(const Point& point)
49 {
50     if (canvas_ != nullptr && OnFilter()) {
51         canvas_->DrawPoint(point);
52     }
53 }
54 
DrawLine(const Point & startPt,const Point & endPt)55 void RSPaintFilterCanvasBase::DrawLine(const Point& startPt, const Point& endPt)
56 {
57     if (canvas_ != nullptr && OnFilter()) {
58         canvas_->DrawLine(startPt, endPt);
59     }
60 }
61 
DrawRect(const Rect & rect)62 void RSPaintFilterCanvasBase::DrawRect(const Rect& rect)
63 {
64     if (canvas_ != nullptr && OnFilter()) {
65         canvas_->DrawRect(rect);
66     }
67 }
68 
DrawRoundRect(const RoundRect & roundRect)69 void RSPaintFilterCanvasBase::DrawRoundRect(const RoundRect& roundRect)
70 {
71     if (canvas_ != nullptr && OnFilter()) {
72         canvas_->DrawRoundRect(roundRect);
73     }
74 }
75 
DrawNestedRoundRect(const RoundRect & outer,const RoundRect & inner)76 void RSPaintFilterCanvasBase::DrawNestedRoundRect(const RoundRect& outer, const RoundRect& inner)
77 {
78     if (canvas_ != nullptr && OnFilter()) {
79         canvas_->DrawNestedRoundRect(outer, inner);
80     }
81 }
82 
DrawArc(const Rect & oval,scalar startAngle,scalar sweepAngle)83 void RSPaintFilterCanvasBase::DrawArc(const Rect& oval, scalar startAngle, scalar sweepAngle)
84 {
85     if (canvas_ != nullptr && OnFilter()) {
86         canvas_->DrawArc(oval, startAngle, sweepAngle);
87     }
88 }
89 
DrawPie(const Rect & oval,scalar startAngle,scalar sweepAngle)90 void RSPaintFilterCanvasBase::DrawPie(const Rect& oval, scalar startAngle, scalar sweepAngle)
91 {
92     if (canvas_ != nullptr && OnFilter()) {
93         canvas_->DrawPie(oval, startAngle, sweepAngle);
94     }
95 }
96 
DrawOval(const Rect & oval)97 void RSPaintFilterCanvasBase::DrawOval(const Rect& oval)
98 {
99     if (canvas_ != nullptr && OnFilter()) {
100         canvas_->DrawOval(oval);
101     }
102 }
103 
DrawCircle(const Point & centerPt,scalar radius)104 void RSPaintFilterCanvasBase::DrawCircle(const Point& centerPt, scalar radius)
105 {
106     if (canvas_ != nullptr && OnFilter()) {
107         canvas_->DrawCircle(centerPt, radius);
108     }
109 }
110 
DrawPath(const Path & path)111 void RSPaintFilterCanvasBase::DrawPath(const Path& path)
112 {
113     if (canvas_ != nullptr && OnFilter()) {
114         canvas_->DrawPath(path);
115     }
116 }
117 
DrawBackground(const Brush & brush)118 void RSPaintFilterCanvasBase::DrawBackground(const Brush& brush)
119 {
120     if (canvas_ != nullptr && OnFilter()) {
121         canvas_->DrawBackground(brush);
122     }
123 }
124 
DrawShadow(const Path & path,const Point3 & planeParams,const Point3 & devLightPos,scalar lightRadius,Color ambientColor,Color spotColor,ShadowFlags flag)125 void RSPaintFilterCanvasBase::DrawShadow(const Path& path, const Point3& planeParams, const Point3& devLightPos,
126     scalar lightRadius, Color ambientColor, Color spotColor, ShadowFlags flag)
127 {
128     if (canvas_ != nullptr && OnFilter()) {
129         canvas_->DrawShadow(path, planeParams, devLightPos, lightRadius, ambientColor, spotColor, flag);
130     }
131 }
132 
DrawRegion(const Drawing::Region & region)133 void RSPaintFilterCanvasBase::DrawRegion(const Drawing::Region& region)
134 {
135     if (canvas_ != nullptr && OnFilter()) {
136         canvas_->DrawRegion(region);
137     }
138 }
139 
DrawBitmap(const Bitmap & bitmap,const scalar px,const scalar py)140 void RSPaintFilterCanvasBase::DrawBitmap(const Bitmap& bitmap, const scalar px, const scalar py)
141 {
142     if (canvas_ != nullptr && OnFilter()) {
143         canvas_->DrawBitmap(bitmap, px, py);
144     }
145 }
146 
DrawBitmap(Media::PixelMap & pixelMap,const scalar px,const scalar py)147 void RSPaintFilterCanvasBase::DrawBitmap(Media::PixelMap& pixelMap, const scalar px, const scalar py)
148 {
149     if (canvas_ != nullptr && OnFilter()) {
150         canvas_->DrawBitmap(pixelMap, px, py);
151     }
152 }
153 
DrawImage(const Image & image,const scalar px,const scalar py,const SamplingOptions & sampling)154 void RSPaintFilterCanvasBase::DrawImage(
155     const Image& image, const scalar px, const scalar py, const SamplingOptions& sampling)
156 {
157     if (canvas_ != nullptr && OnFilter()) {
158         canvas_->DrawImage(image, px, py, sampling);
159     }
160 }
161 
DrawImageRect(const Image & image,const Rect & src,const Rect & dst,const SamplingOptions & sampling,SrcRectConstraint constraint)162 void RSPaintFilterCanvasBase::DrawImageRect(const Image& image, const Rect& src, const Rect& dst,
163     const SamplingOptions& sampling, SrcRectConstraint constraint)
164 {
165     if (canvas_ != nullptr && OnFilter()) {
166         canvas_->DrawImageRect(image, src, dst, sampling, constraint);
167     }
168 }
169 
DrawImageRect(const Image & image,const Rect & dst,const SamplingOptions & sampling)170 void RSPaintFilterCanvasBase::DrawImageRect(const Image& image, const Rect& dst, const SamplingOptions& sampling)
171 {
172     if (canvas_ != nullptr && OnFilter()) {
173         canvas_->DrawImageRect(image, dst, sampling);
174     }
175 }
176 
DrawPicture(const Picture & picture)177 void RSPaintFilterCanvasBase::DrawPicture(const Picture& picture)
178 {
179     if (canvas_ != nullptr && OnFilter()) {
180         canvas_->DrawPicture(picture);
181     }
182 }
183 
ClipRect(const Drawing::Rect & rect,Drawing::ClipOp op,bool doAntiAlias)184 void RSPaintFilterCanvasBase::ClipRect(const Drawing::Rect& rect, Drawing::ClipOp op, bool doAntiAlias)
185 {
186     Canvas::ClipRect(rect, op, doAntiAlias);
187     if (canvas_ != nullptr) {
188         canvas_->ClipRect(rect, op, doAntiAlias);
189     }
190 }
191 
ClipRoundRect(const RoundRect & roundRect,ClipOp op,bool doAntiAlias)192 void RSPaintFilterCanvasBase::ClipRoundRect(const RoundRect& roundRect, ClipOp op, bool doAntiAlias)
193 {
194     Canvas::ClipRoundRect(roundRect, op, doAntiAlias);
195     if (canvas_ != nullptr) {
196         canvas_->ClipRoundRect(roundRect, op, doAntiAlias);
197     }
198 }
199 
ClipPath(const Path & path,ClipOp op,bool doAntiAlias)200 void RSPaintFilterCanvasBase::ClipPath(const Path& path, ClipOp op, bool doAntiAlias)
201 {
202     Canvas::ClipPath(path, op, doAntiAlias);
203     if (canvas_ != nullptr) {
204         canvas_->ClipPath(path, op, doAntiAlias);
205     }
206 }
207 
SetMatrix(const Matrix & matrix)208 void RSPaintFilterCanvasBase::SetMatrix(const Matrix& matrix)
209 {
210     Canvas::SetMatrix(matrix);
211     if (canvas_ != nullptr) {
212         canvas_->SetMatrix(matrix);
213     }
214 }
215 
ResetMatrix()216 void RSPaintFilterCanvasBase::ResetMatrix()
217 {
218     Canvas::ResetMatrix();
219     if (canvas_ != nullptr) {
220         canvas_->ResetMatrix();
221     }
222 }
223 
ConcatMatrix(const Matrix & matrix)224 void RSPaintFilterCanvasBase::ConcatMatrix(const Matrix& matrix)
225 {
226     Canvas::ConcatMatrix(matrix);
227     if (canvas_ != nullptr) {
228         canvas_->ConcatMatrix(matrix);
229     }
230 }
231 
Translate(scalar dx,scalar dy)232 void RSPaintFilterCanvasBase::Translate(scalar dx, scalar dy)
233 {
234     Canvas::Translate(dx, dy);
235     if (canvas_ != nullptr) {
236         canvas_->Translate(dx, dy);
237     }
238 }
239 
Scale(scalar sx,scalar sy)240 void RSPaintFilterCanvasBase::Scale(scalar sx, scalar sy)
241 {
242     Canvas::Scale(sx, sy);
243     if (canvas_ != nullptr) {
244         canvas_->Scale(sx, sy);
245     }
246 }
247 
Rotate(scalar deg,scalar sx,scalar sy)248 void RSPaintFilterCanvasBase::Rotate(scalar deg, scalar sx, scalar sy)
249 {
250     Canvas::Rotate(deg, sx, sy);
251     if (canvas_ != nullptr) {
252         canvas_->Rotate(deg, sx, sy);
253     }
254 }
255 
Shear(scalar sx,scalar sy)256 void RSPaintFilterCanvasBase::Shear(scalar sx, scalar sy)
257 {
258     Canvas::Shear(sx, sy);
259     if (canvas_ != nullptr) {
260         canvas_->Shear(sx, sy);
261     }
262 }
263 
Flush()264 void RSPaintFilterCanvasBase::Flush()
265 {
266     if (canvas_ != nullptr) {
267         canvas_->Flush();
268     }
269 }
270 
Clear(ColorQuad color)271 void RSPaintFilterCanvasBase::Clear(ColorQuad color)
272 {
273     if (canvas_ != nullptr) {
274         canvas_->Clear(color);
275     }
276 }
277 
Save()278 void RSPaintFilterCanvasBase::Save()
279 {
280     Canvas::Save();
281     if (canvas_ != nullptr) {
282         canvas_->Save();
283     }
284 }
285 
SaveLayer(const SaveLayerOps & saveLayerRec)286 void RSPaintFilterCanvasBase::SaveLayer(const SaveLayerOps& saveLayerRec)
287 {
288     Canvas::SaveLayer(saveLayerRec);
289     if (canvas_ != nullptr) {
290         canvas_->SaveLayer(saveLayerRec);
291     }
292 }
293 
Restore()294 void RSPaintFilterCanvasBase::Restore()
295 {
296     Canvas::Restore();
297     if (canvas_ != nullptr) {
298         canvas_->Restore();
299     }
300 }
301 
AttachPen(const Pen & pen)302 CoreCanvas& RSPaintFilterCanvasBase::AttachPen(const Pen& pen)
303 {
304     if (canvas_ != nullptr) {
305         canvas_->AttachPen(pen);
306     }
307     return *this;
308 }
309 
AttachBrush(const Brush & brush)310 CoreCanvas& RSPaintFilterCanvasBase::AttachBrush(const Brush& brush)
311 {
312     if (canvas_ != nullptr) {
313         canvas_->AttachBrush(brush);
314     }
315     return *this;
316 }
317 
DetachPen()318 CoreCanvas& RSPaintFilterCanvasBase::DetachPen()
319 {
320     if (canvas_ != nullptr) {
321         canvas_->DetachPen();
322     }
323     return *this;
324 }
325 
DetachBrush()326 CoreCanvas& RSPaintFilterCanvasBase::DetachBrush()
327 {
328     if (canvas_ != nullptr) {
329         canvas_->DetachBrush();
330     }
331     return *this;
332 }
333 #endif
334 
335 #ifndef USE_ROSEN_DRAWING
RSPaintFilterCanvas(SkCanvas * canvas,float alpha)336 RSPaintFilterCanvas::RSPaintFilterCanvas(SkCanvas* canvas, float alpha)
337     : SkPaintFilterCanvas(canvas),
338       alphaStack_({ std::clamp(alpha, 0.f, 1.f) }), // construct stack with given alpha
339       // Temporary fix, this default color should be 0x000000FF, fix this after foreground color refactor
340       envStack_({ Env({ Color(0xFF000000) }) }), // construct stack with default foreground color
341       effectStack_({ CachedEffectData {} })
342 {}
343 
RSPaintFilterCanvas(SkSurface * skSurface,float alpha)344 RSPaintFilterCanvas::RSPaintFilterCanvas(SkSurface* skSurface, float alpha)
345     : SkPaintFilterCanvas(skSurface ? skSurface->getCanvas() : nullptr), skSurface_(skSurface),
346       alphaStack_({ std::clamp(alpha, 0.f, 1.f) }), // construct stack with given alpha
347       // Temporary fix, this default color should be 0x000000FF, fix this after foreground color refactor
348       envStack_({ Env({ Color(0xFF000000) }) }), // construct stack with default foreground color
349       effectStack_({ CachedEffectData {} })
350 {}
351 
GetSurface() const352 SkSurface* RSPaintFilterCanvas::GetSurface() const
353 {
354     return skSurface_;
355 }
356 
onFilter(SkPaint & paint) const357 bool RSPaintFilterCanvas::onFilter(SkPaint& paint) const
358 {
359     if (paint.getColor() == 0x00000001) { // foreground color and foreground color strategy identification
360         paint.setColor(envStack_.top().envForegroundColor.AsArgbInt());
361     }
362 
363     if (alphaStack_.top() >= 1.f) {
364         return true;
365     } else if (alphaStack_.top() <= 0.f) {
366         return false;
367     }
368     // use alphaStack_.top() to multiply alpha
369     paint.setAlphaf(paint.getAlphaf() * alphaStack_.top());
370     return true;
371 }
372 
onDrawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)373 void RSPaintFilterCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint)
374 {
375     SkPaint filteredPaint(paint ? *paint : SkPaint());
376     if (this->onFilter(filteredPaint)) {
377         this->SkCanvas::onDrawPicture(picture, matrix, &filteredPaint);
378     }
379 }
380 #else
RSPaintFilterCanvas(Drawing::Canvas * canvas,float alpha)381 RSPaintFilterCanvas::RSPaintFilterCanvas(Drawing::Canvas* canvas, float alpha)
382     : RSPaintFilterCanvasBase(canvas), alphaStack_({ std::clamp(alpha, 0.f, 1.f) }), // construct stack with given alpha
383       // Temporary fix, this default color should be 0x000000FF, fix this after foreground color refactor
384       envStack_({ Env({ RSColor(0xFF000000) }) }) // construct stack with default foreground color
385 {}
386 
RSPaintFilterCanvas(Drawing::Surface * surface,float alpha)387 RSPaintFilterCanvas::RSPaintFilterCanvas(Drawing::Surface* surface, float alpha)
388     : RSPaintFilterCanvasBase(surface ? surface->GetCanvas().get() : nullptr), surface_(surface),
389       alphaStack_({ std::clamp(alpha, 0.f, 1.f) }), // construct stack with given alpha
390       // Temporary fix, this default color should be 0x000000FF, fix this after foreground color refactor
391       envStack_({ Env({ RSColor(0xFF000000) }) }) // construct stack with default foreground color
392 {}
393 
GetSurface() const394 Drawing::Surface* RSPaintFilterCanvas::GetSurface() const
395 {
396     return surface_;
397 }
398 
AttachPen(const Pen & pen)399 CoreCanvas& RSPaintFilterCanvas::AttachPen(const Pen& pen)
400 {
401     if (canvas_ == nullptr) {
402         return *this;
403     }
404 
405     Pen p(pen);
406     if (p.GetColor() == 0x00000001) { // foreground color and foreground color strategy identification
407         p.SetColor(envStack_.top().envForegroundColor.AsArgbInt());
408     }
409 
410     // use alphaStack_.top() to multiply alpha
411     if (alphaStack_.top() < 1 && alphaStack_.top() > 0) {
412         p.SetAlpha(p.GetAlpha() * alphaStack_.top());
413     }
414 
415     canvas_->AttachPen(p);
416     return *this;
417 }
418 
AttachBrush(const Brush & brush)419 CoreCanvas& RSPaintFilterCanvas::AttachBrush(const Brush& brush)
420 {
421     if (canvas_ == nullptr) {
422         return *this;
423     }
424 
425     Brush b(brush);
426     if (b.GetColor() == 0x00000001) { // foreground color and foreground color strategy identification
427         b.SetColor(envStack_.top().envForegroundColor.AsArgbInt());
428     }
429 
430     // use alphaStack_.top() to multiply alpha
431     if (alphaStack_.top() < 1 && alphaStack_.top() > 0) {
432         b.SetAlpha(b.GetAlpha() * alphaStack_.top());
433     }
434 
435     canvas_->AttachBrush(b);
436     return *this;
437 }
438 
OnFilter() const439 bool RSPaintFilterCanvas::OnFilter() const
440 {
441     return alphaStack_.top() > 0.f;
442 }
443 #endif // USE_ROSEN_DRAWING
444 
MultiplyAlpha(float alpha)445 void RSPaintFilterCanvas::MultiplyAlpha(float alpha)
446 {
447     // multiply alpha to top of stack
448     alphaStack_.top() *= std::clamp(alpha, 0.f, 1.f);
449 }
450 
SetAlpha(float alpha)451 void RSPaintFilterCanvas::SetAlpha(float alpha)
452 {
453     alphaStack_.top() = std::clamp(alpha, 0.f, 1.f);
454 }
455 
SaveAlpha()456 int RSPaintFilterCanvas::SaveAlpha()
457 {
458     // make a copy of top of stack
459     alphaStack_.push(alphaStack_.top());
460     // return prev stack height
461     return alphaStack_.size() - 1;
462 }
463 
GetAlpha() const464 float RSPaintFilterCanvas::GetAlpha() const
465 {
466     // return top of stack
467     return alphaStack_.top();
468 }
469 
RestoreAlpha()470 void RSPaintFilterCanvas::RestoreAlpha()
471 {
472     // sanity check, stack should not be empty
473     if (alphaStack_.size() <= 1u) {
474         return;
475     }
476     alphaStack_.pop();
477 }
478 
GetAlphaSaveCount() const479 int RSPaintFilterCanvas::GetAlphaSaveCount() const
480 {
481     return alphaStack_.size();
482 }
483 
RestoreAlphaToCount(int count)484 void RSPaintFilterCanvas::RestoreAlphaToCount(int count)
485 {
486     // sanity check, stack should not be empty
487     if (count < 1) {
488         count = 1;
489     }
490     // poo stack until stack height equals count
491     int n = static_cast<int>(alphaStack_.size()) - count;
492     for (int i = 0; i < n; ++i) {
493         alphaStack_.pop();
494     }
495 }
496 
SaveEnv()497 int RSPaintFilterCanvas::SaveEnv()
498 {
499     // make a copy of top of stack
500     envStack_.push(envStack_.top());
501     // return prev stack height
502     return envStack_.size() - 1;
503 }
504 
RestoreEnv()505 void RSPaintFilterCanvas::RestoreEnv()
506 {
507     // sanity check, stack should not be empty
508     if (envStack_.size() <= 1) {
509         return;
510     }
511     envStack_.pop();
512 }
513 
RestoreEnvToCount(int count)514 void RSPaintFilterCanvas::RestoreEnvToCount(int count)
515 {
516     // sanity check, stack should not be empty
517     if (count < 1) {
518         count = 1;
519     }
520     // poo stack until stack height equals count
521     int n = static_cast<int>(envStack_.size()) - count;
522     for (int i = 0; i < n; ++i) {
523         envStack_.pop();
524     }
525 }
526 
GetEnvSaveCount() const527 int RSPaintFilterCanvas::GetEnvSaveCount() const
528 {
529     return envStack_.size();
530 }
531 
532 #ifndef USE_ROSEN_DRAWING
SetEnvForegroundColor(Color color)533 void RSPaintFilterCanvas::SetEnvForegroundColor(Color color)
534 #else
535 void RSPaintFilterCanvas::SetEnvForegroundColor(Rosen::RSColor color)
536 #endif
537 {
538     // sanity check, stack should not be empty
539     if (envStack_.empty()) {
540         return;
541     }
542     envStack_.top().envForegroundColor = color;
543 }
544 
545 #ifndef USE_ROSEN_DRAWING
GetEnvForegroundColor() const546 Color RSPaintFilterCanvas::GetEnvForegroundColor() const
547 {
548     // sanity check, stack should not be empty
549     if (envStack_.empty()) {
550         return Color { 0xFF000000 }; // 0xFF000000 is default value -- black
551     }
552     return envStack_.top().envForegroundColor;
553 }
554 #else
GetEnvForegroundColor() const555 RSColor RSPaintFilterCanvas::GetEnvForegroundColor() const
556 {
557     // sanity check, stack should not be empty
558     if (envStack_.empty()) {
559         return RSColor { 0xFF000000 }; // 0xFF000000 is default value -- black
560     }
561     return envStack_.top().envForegroundColor;
562 }
563 #endif
564 
565 #ifndef USE_ROSEN_DRAWING
Save()566 RSPaintFilterCanvas::SaveStatus RSPaintFilterCanvas::Save()
567 {
568     // simultaneously save canvas and alpha
569     return { save(), SaveAlpha(), SaveEnv() };
570 }
571 #else
SaveAllStatus()572 RSPaintFilterCanvas::SaveStatus RSPaintFilterCanvas::SaveAllStatus()
573 {
574     // simultaneously save canvas and alpha
575     int canvasSaveCount = GetSaveCount();
576     Save();
577     return { canvasSaveCount, SaveAlpha(), SaveEnv() };
578 }
579 #endif
580 
GetSaveStatus() const581 RSPaintFilterCanvas::SaveStatus RSPaintFilterCanvas::GetSaveStatus() const
582 {
583 #ifndef USE_ROSEN_DRAWING
584     return { getSaveCount(), GetAlphaSaveCount(), GetEnvSaveCount() };
585 #else
586     return { GetSaveCount(), GetAlphaSaveCount(), GetEnvSaveCount() };
587 #endif
588 }
589 
RestoreStatus(const SaveStatus & status)590 void RSPaintFilterCanvas::RestoreStatus(const SaveStatus& status)
591 {
592     // simultaneously restore canvas and alpha
593 #ifndef USE_ROSEN_DRAWING
594     restoreToCount(status.canvasSaveCount);
595 #else
596     RestoreToCount(status.canvasSaveCount);
597 #endif
598     RestoreAlphaToCount(status.alphaSaveCount);
599     RestoreEnvToCount(status.envSaveCount);
600 }
601 
CopyConfiguration(const RSPaintFilterCanvas & other)602 void RSPaintFilterCanvas::CopyConfiguration(const RSPaintFilterCanvas& other)
603 {
604     // Note:
605     // 1. we don't need to copy alpha status, alpha will be applied when drawing cache.
606     // copy high contrast flag
607     isHighContrastEnabled_.store(other.isHighContrastEnabled_.load());
608     // copy env
609     envStack_.top() = other.envStack_.top();
610     // cache related
611     if (other.isHighContrastEnabled()) {
612         // explicit disable cache for high contrast mode
613         SetCacheType(RSPaintFilterCanvas::CacheType::DISABLED);
614     } else {
615         // planning: maybe we should copy source cache status
616         SetCacheType(other.GetCacheType());
617     }
618 }
619 
RSColorFilterCanvas(RSPaintFilterCanvas * canvas)620 RSColorFilterCanvas::RSColorFilterCanvas(RSPaintFilterCanvas* canvas)
621     : RSPaintFilterCanvas(canvas)
622 {}
623 
624 #ifndef USE_ROSEN_DRAWING
onFilter(SkPaint & paint) const625 bool RSColorFilterCanvas::onFilter(SkPaint& paint) const
626 {
627     // foreground color and foreground color strategy identification
628     if (paint.getColor() == 0x00000001) {
629         // creates a color filter that blends the foreground color with the destination color
630         paint.setColorFilter(SkColorFilters::Blend(GetEnvForegroundColor().AsArgbInt(), SkBlendMode::kDstIn));
631     }
632 
633     return RSPaintFilterCanvas::onFilter(paint);
634 }
635 #else
AttachPen(const Pen & pen)636 CoreCanvas& RSColorFilterCanvas::AttachPen(const Pen& pen)
637 {
638     if (canvas_ == nullptr) {
639         return *this;
640     }
641 
642     Pen p(pen);
643     if (p.GetColor() == 0x00000001) { // foreground color and foreground color strategy identification
644         p.SetColor(GetEnvStack().top().envForegroundColor.AsArgbInt());
645         // creates a color filter that blends the foreground color with the destination color
646         Drawing::Filter filter;
647         filter.SetColorFilter(Drawing::ColorFilter::CreateBlendModeColorFilter(
648             GetEnvForegroundColor().AsArgbInt(), Drawing::BlendMode::DST_IN));
649         p.SetFilter(filter);
650     }
651 
652     // use alphaStack_.top() to multiply alpha
653     if (GetAlphaStack().top() < 1 && GetAlphaStack().top() > 0) {
654         p.SetAlpha(p.GetAlpha() * GetAlphaStack().top());
655     }
656 
657     canvas_->AttachPen(p);
658     return *this;
659 }
660 
AttachBrush(const Brush & brush)661 CoreCanvas& RSColorFilterCanvas::AttachBrush(const Brush& brush)
662 {
663     if (canvas_ == nullptr) {
664         return *this;
665     }
666 
667     Brush b(brush);
668     if (b.GetColor() == 0x00000001) { // foreground color and foreground color strategy identification
669         b.SetColor(GetEnvStack().top().envForegroundColor.AsArgbInt());
670         // creates a color filter that blends the foreground color with the destination color
671         Drawing::Filter filter;
672         filter.SetColorFilter(Drawing::ColorFilter::CreateBlendModeColorFilter(
673             GetEnvForegroundColor().AsArgbInt(), Drawing::BlendMode::DST_IN));
674         b.SetFilter(filter);
675     }
676 
677     // use alphaStack_.top() to multiply alpha
678     if (GetAlphaStack().top() < 1 && GetAlphaStack().top() > 0) {
679         b.SetAlpha(b.GetAlpha() * GetAlphaStack().top());
680     }
681 
682     canvas_->AttachBrush(b);
683     return *this;
684 }
685 #endif
686 
RSAutoCanvasRestore(RSPaintFilterCanvas * canvas,SaveType type)687 RSAutoCanvasRestore::RSAutoCanvasRestore(RSPaintFilterCanvas* canvas, SaveType type) : canvas_(canvas)
688 {
689     if (canvas_) {
690         saveCount_ = canvas->GetSaveStatus();
691         if (SaveType::kCanvas & type) {
692 #ifndef USE_ROSEN_DRAWING
693             canvas->save();
694 #else
695             canvas->Save();
696 #endif
697         }
698         if (SaveType::kAlpha & type) {
699             canvas->SaveAlpha();
700         }
701         if (SaveType::kEnv & type) {
702             canvas->SaveEnv();
703         }
704     }
705 }
706 
SetHighContrast(bool enabled)707 void RSPaintFilterCanvas::SetHighContrast(bool enabled)
708 {
709     isHighContrastEnabled_ = enabled;
710 }
isHighContrastEnabled() const711 bool RSPaintFilterCanvas::isHighContrastEnabled() const
712 {
713     return isHighContrastEnabled_;
714 }
715 
SetCacheType(CacheType type)716 void RSPaintFilterCanvas::SetCacheType(CacheType type)
717 {
718     cacheType_ = type;
719 }
GetCacheType() const720 RSPaintFilterCanvas::CacheType RSPaintFilterCanvas::GetCacheType() const
721 {
722     return cacheType_;
723 }
724 
725 #ifndef USE_ROSEN_DRAWING
SetVisibleRect(SkRect visibleRect)726 void RSPaintFilterCanvas::SetVisibleRect(SkRect visibleRect)
727 {
728     visibleRect_ = visibleRect;
729 }
730 
GetVisibleRect() const731 SkRect RSPaintFilterCanvas::GetVisibleRect() const
732 {
733     return visibleRect_;
734 }
735 #else
SetVisibleRect(Drawing::Rect visibleRect)736 void RSPaintFilterCanvas::SetVisibleRect(Drawing::Rect visibleRect)
737 {
738     visibleRect_ = visibleRect;
739 }
740 
GetVisibleRect() const741 Drawing::Rect RSPaintFilterCanvas::GetVisibleRect() const
742 {
743     return visibleRect_;
744 }
745 #endif
746 
747 #ifndef USE_ROSEN_DRAWING
GetLocalClipBounds(const SkCanvas & canvas,const SkIRect * clipRect)748 std::optional<SkRect> RSPaintFilterCanvas::GetLocalClipBounds(const SkCanvas& canvas, const SkIRect* clipRect)
749 {
750     // if clipRect is explicitly specified, use it as the device clip bounds
751     SkRect bounds = SkRect::Make((clipRect != nullptr) ? *clipRect : canvas.getDeviceClipBounds());
752     if (bounds.isEmpty()) {
753         return std::nullopt;
754     }
755     SkMatrix inverse;
756     // if we can't invert the CTM, we can't return local clip bounds
757     if (!(canvas.getTotalMatrix().invert(&inverse))) {
758         return std::nullopt;
759     }
760     // return the inverse of the CTM applied to the device clip bounds as local clip bounds
761     return inverse.mapRect(bounds);
762 }
763 #else
GetLocalClipBounds(const Drawing::Canvas & canvas,const Drawing::RectI * clipRect)764 std::optional<Drawing::Rect> RSPaintFilterCanvas::GetLocalClipBounds(const Drawing::Canvas& canvas,
765     const Drawing::RectI* clipRect)
766 {
767     // if clipRect is explicitly specified, use it as the device clip bounds
768     auto tmpRect = (clipRect != nullptr) ? *clipRect : canvas.GetDeviceClipBounds();
769     Drawing::Rect bounds(static_cast<scalar>(tmpRect.GetLeft()), static_cast<scalar>(tmpRect.GetTop()),
770         static_cast<scalar>(tmpRect.GetRight()), static_cast<scalar>(tmpRect.GetBottom()));
771 
772     if (!bounds.IsValid()) {
773         return std::nullopt;
774     }
775 
776     Drawing::Matrix inverse;
777     // if we can't invert the CTM, we can't return local clip bounds
778     if (!(canvas.GetTotalMatrix().Invert(inverse))) {
779         return std::nullopt;
780     }
781     // return the inverse of the CTM applied to the device clip bounds as local clip bounds
782     Drawing::Rect dst;
783     inverse.MapRect(dst, bounds);
784     return dst;
785 }
786 
GetAlphaStack()787 std::stack<float> RSPaintFilterCanvas::GetAlphaStack()
788 {
789     return alphaStack_;
790 }
791 
GetEnvStack()792 std::stack<RSPaintFilterCanvas::Env> RSPaintFilterCanvas::GetEnvStack()
793 {
794     return envStack_;
795 }
796 #endif
797 
798 #ifndef USE_ROSEN_DRAWING
getSaveLayerStrategy(const SaveLayerRec & rec)799 SkCanvas::SaveLayerStrategy RSPaintFilterCanvas::getSaveLayerStrategy(const SaveLayerRec& rec)
800 {
801     SkPaint p = rec.fPaint ? *rec.fPaint : SkPaint();
802     SaveLayerRec tmpRec = rec;
803     if (onFilter(p)) {
804         tmpRec.fPaint = &p;
805     }
806     return SkPaintFilterCanvas::getSaveLayerStrategy(tmpRec);
807 }
808 #endif
809 
810 #ifndef USE_ROSEN_DRAWING
SetEffectData(const CachedEffectData & effectData)811 void RSPaintFilterCanvas::SetEffectData(const CachedEffectData& effectData)
812 {
813     effectStack_.top() = effectData;
814 }
815 
SetChildrenPath(const SkPath & childrenPath)816 void RSPaintFilterCanvas::SetChildrenPath(const SkPath& childrenPath)
817 {
818     effectStack_.top().childrenPath_ = childrenPath;
819 }
820 
GetEffectData() const821 const CachedEffectData& RSPaintFilterCanvas::GetEffectData() const
822 {
823     return effectStack_.top();
824 }
825 
SaveEffectData()826 void RSPaintFilterCanvas::SaveEffectData()
827 {
828     effectStack_.push({});
829 }
830 
RestoreEffectData()831 void RSPaintFilterCanvas::RestoreEffectData()
832 {
833     if (effectStack_.size() < 1u) {
834         return;
835     }
836     effectStack_.pop();
837 }
838 #endif
839 } // namespace Rosen
840 } // namespace OHOS
841