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