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